int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("motor.mesh", &mesh); // Initialize the weak formulation. CustomWeakFormPoisson wf("Motor", EPS_MOTOR, "Air", EPS_AIR, &mesh); // Initialize boundary conditions DefaultEssentialBCConst<double> bc_essential_out("Outer", 0.0); DefaultEssentialBCConst<double> bc_essential_stator("Stator", VOLTAGE); EssentialBCs<double> bcs(Hermes::vector<EssentialBoundaryCondition<double> *>(&bc_essential_out, &bc_essential_stator)); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); // Initialize coarse and reference mesh solution. Solution<double> sln; // Initialize views. Views::ScalarView sview("Solution", new Views::WinGeom(0, 0, 410, 600)); sview.fix_scale_width(50); sview.show_mesh(false); Views::OrderView oview("Polynomial orders", new Views::WinGeom(420, 0, 400, 600)); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; // Adaptivity loop: int as = 1; bool done = false; do { Hermes::Mixins::Loggable::Static::info("---- Adaptivity step %d:", as); // Time measurement. cpu_time.tick(); // Initialize reference problem. Hermes::Mixins::Loggable::Static::info("Solving."); DiscreteProblem<double> dp(&wf, &space); NewtonSolver<double> newton(&dp); newton.set_verbose_output(false); // Initial ndof. int ndof = space.get_num_dofs(); // Perform Newton's iteration. try { newton.solve(); } catch(std::exception& e) { std::cout << e.what(); } // Translate the resulting coefficient vector into the instance of Solution. Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln); // Time measurement. cpu_time.tick(); // VTK output. if (VTK_VISUALIZATION) { // Output solution in VTK format. Views::Linearizer lin; char* title = new char[100]; sprintf(title, "sln-%d.vtk", as); lin.save_solution_vtk(&sln, title, "Potential", false); Hermes::Mixins::Loggable::Static::info("Solution in VTK format saved to file %s.", title); // Output mesh and element orders in VTK format. Views::Orderizer ord; sprintf(title, "ord-%d.vtk", as); ord.save_orders_vtk(&space, title); Hermes::Mixins::Loggable::Static::info("Element orders in VTK format saved to file %s.", title); } // View the coarse mesh solution and polynomial orders. if (HERMES_VISUALIZATION) { sview.show(&sln); oview.show(&space); } // Skip visualization time. cpu_time.tick(); // Calculate element errors and total error estimate. Hermes::Mixins::Loggable::Static::info("Calculating error estimate."); bool ignore_visited_segments = true; KellyTypeAdapt<double> adaptivity(&space, ignore_visited_segments, USE_EPS_IN_INTERFACE_ESTIMATOR ? new CustomInterfaceEstimatorScalingFunction("Motor", EPS_MOTOR, "Air", EPS_AIR) : new CustomInterfaceEstimatorScalingFunction); adaptivity.add_error_estimator_surf(new Hermes::Hermes2D::BasicKellyAdapt<double>::ErrorEstimatorFormKelly()); if (USE_RESIDUAL_ESTIMATOR) { adaptivity.add_error_estimator_vol(new ResidualErrorFormMotor("Motor", EPS_MOTOR)); adaptivity.add_error_estimator_vol(new ResidualErrorFormAir("Air", EPS_AIR)); } if (USE_EPS_IN_INTERFACE_ESTIMATOR) // Use normalization by energy norm. adaptivity.set_error_form(new EnergyErrorForm(&wf)); // Note that there is only one solution (the only one available) passed to BasicKellyAdapt::calc_err_est // and there is also no "solutions_for_adapt" parameter. The last parameter, "error_flags", is left // intact and has the meaning explained in P04-adaptivity/01-intro. You may however still call // adaptivity.calc_err_est with a solution, an exact solution and solutions_for_adapt=false to calculate // error wrt. an exact solution (if provided). double err_est_rel = adaptivity.calc_err_est(&sln, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100; // Report results. Hermes::Mixins::Loggable::Static::info("ndof: %d, err_est_rel: %g%%", space.get_num_dofs(), err_est_rel); // Add entry to DOF and CPU convergence graphs. cpu_time.tick(); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); graph_dof.add_values(space.get_num_dofs(), err_est_rel); graph_dof.save("conv_dof_est.dat"); // Skip the time spent to save the convergence graphs. cpu_time.tick(); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { Hermes::Mixins::Loggable::Static::info("Adapting coarse mesh."); // h-refinement is automatically selected here, no need for parameter "selector". done = adaptivity.adapt(THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (space.get_num_dofs() >= NDOF_STOP) done = true; } while (done == false); Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated()); // The final result has already been shown in the final step of the adaptivity loop, so we only // adjust the title and hide the mesh here. sview.set_title("Fine mesh solution"); sview.show_mesh(false); // Wait for all views to be closed. Views::View::wait(); return 0; }
int main(int argc, char* argv[]) { // Define problem parameters: (x_loc, y_loc) is the center of the circular wave front, R_ZERO is the distance from the // wave front to the center of the circle, and alpha gives the steepness of the wave front. double alpha, x_loc, y_loc, r_zero; switch(PARAM) { case 0: alpha = 20; x_loc = -0.05; y_loc = -0.05; r_zero = 0.7; break; case 1: alpha = 1000; x_loc = -0.05; y_loc = -0.05; r_zero = 0.7; break; case 2: alpha = 1000; x_loc = 1.5; y_loc = 0.25; r_zero = 0.92; break; case 3: alpha = 50; x_loc = 0.5; y_loc = 0.5; r_zero = 0.25; break; default: // The same as 0. alpha = 20; x_loc = -0.05; y_loc = -0.05; r_zero = 0.7; break; } // Set adaptivity options according to the command line argument. int refinement_mode; if (argc != 2) refinement_mode = 0; else { refinement_mode = atoi(argv[1]); if (refinement_mode < 1 || refinement_mode > 12) throw Hermes::Exceptions::Exception("Invalid run case: %d (valid range is [1,12])", refinement_mode); } double threshold = 0.3; // strategy = 0 ... Refine elements until sqrt(threshold) times total error is processed. // If more elements have similar errors, refine all to keep the mesh symmetric. int strategy = 0; // strategy = 1 ... Refine all elements whose error is larger than threshold times max. element error. // Add also the norm of the residual to the error estimate of each element. bool use_residual_estimator = false; // Use energy norm for error estimate normalization and measuring of exact error. bool use_energy_norm_normalization = false; switch (refinement_mode) { case 1: case 2: case 3: case 4: case 5: case 6: { strategy = 0; break; } case 7 : case 8 : case 9 : case 10: case 11: case 12: { strategy = 1; break; } } switch (refinement_mode) { case 1: case 2: case 3: case 7: case 8: case 9: { threshold = 0.3; break; } case 4: case 5: case 6: case 10: case 11: case 12: { threshold = 0.3*0.3; break; } } switch (refinement_mode) { case 2: case 3: case 5: case 6: case 8: case 9: case 11: case 12: { use_residual_estimator = true; break; } } switch (refinement_mode) { case 3: case 6: case 9: case 12: { use_energy_norm_normalization = true; break; } } double setup_time = 0, assemble_time = 0, solve_time = 0, adapt_time = 0; // Time measurement. Hermes::Mixins::TimeMeasurable wall_clock; // Stop counting time for adaptation. wall_clock.tick(); // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("square_quad.mesh", &mesh); // Perform initial mesh refinement. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Stop counting time for adaptation. wall_clock.tick(); adapt_time += wall_clock.last(); // Set exact solution. CustomExactSolution exact(&mesh, alpha, x_loc, y_loc, r_zero); // Define right-hand side. CustomRightHandSide rhs(alpha, x_loc, y_loc, r_zero); // Initialize the weak formulation. CustomWeakForm wf(&rhs); // Equivalent, but slower: // DefaultWeakFormPoisson<double> wf(Hermes::HERMES_ANY, HERMES_ONE, &rhs); // Initialize boundary conditions. DefaultEssentialBCNonConst<double> bc("Bdy", &exact); EssentialBCs<double> bcs(&bc); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); // Initialize approximate solution. Solution<double> sln; // Initialize views. Views::ScalarView sview("Solution", new Views::WinGeom(800, 0, 400, 400)); sview.show_mesh(false); sview.set_3d_mode(); sview.set_palette(Views::H2DV_PT_HUESCALE); sview.fix_scale_width(50); Views::OrderView oview("Mesh", new Views::WinGeom(0, 0, 800, 800)); oview.set_palette(Views::H2DV_PT_INVGRAYSCALE); // DOF and CPU convergence graphs. ConvergenceTable conv_table; conv_table.add_column(" cycle ", "%6d "); conv_table.add_column(" H1 error ", " %.4e "); conv_table.add_column(" ndof ", " %6d "); conv_table.add_column(" total time ", " %8.3f "); conv_table.add_column(" setup time ", " %8.3f "); conv_table.add_column(" assem time ", " %8.3f "); conv_table.add_column(" solve time ", " %8.3f "); conv_table.add_column(" adapt time ", " %8.3f "); wall_clock.tick(Hermes::Mixins::TimeMeasurable::HERMES_SKIP); // Adaptivity loop: int as = 0; bool done = false; do { // Start counting setup time. wall_clock.tick(); // Assemble the discrete problem. DiscreteProblem<double> dp(&wf, &space); // Actual ndof. int ndof = space.get_num_dofs(); NewtonSolver<double> newton(&dp); newton.set_verbose_output(false); // Setup time continues in NewtonSolver::solve(). try { newton.solve(); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); throw Hermes::Exceptions::Exception("Newton's iteration failed."); }; setup_time += newton.get_setup_time(); assemble_time += newton.get_assemble_time(); solve_time += newton.get_solve_time(); // Start counting time for adaptation. wall_clock.tick(); Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln); double err_exact = Global<double>::calc_abs_error(&sln, &exact, HERMES_H1_NORM); // Report results. Hermes::Mixins::Loggable::Static::info(" Cycle %d:", as); Hermes::Mixins::Loggable::Static::info(" Number of degrees of freedom: %d", ndof); Hermes::Mixins::Loggable::Static::info(" H1 error w.r.t. exact soln.: %g", err_exact); // Stop counting time for adaptation. wall_clock.tick(); double accum_time = wall_clock.accumulated(); adapt_time += wall_clock.last(); // View the approximate solution and polynomial orders. //sview.show(&sln); //oview.show(&space); //Views::View::wait(Views::HERMES_WAIT_KEYPRESS); conv_table.add_value(0, as); conv_table.add_value(1, err_exact); conv_table.add_value(2, ndof); conv_table.add_value(3, accum_time); conv_table.add_value(4, setup_time); conv_table.add_value(5, assemble_time); conv_table.add_value(6, solve_time); conv_table.add_value(7, adapt_time); // Start counting time for adaptation. wall_clock.tick(); if (err_exact < ERR_STOP) done = true; else { // Calculate element errors and total error estimate. Hermes::Hermes2D::BasicKellyAdapt<double> adaptivity(&space); unsigned int error_flags = HERMES_TOTAL_ERROR_ABS; if (use_energy_norm_normalization) { error_flags |= HERMES_ELEMENT_ERROR_REL; adaptivity.set_error_form(new EnergyErrorForm(&wf)); } else error_flags |= HERMES_ELEMENT_ERROR_ABS; if (use_residual_estimator) adaptivity.add_error_estimator_vol(new ResidualErrorForm(&rhs)); double err_est_rel = adaptivity.calc_err_est(&sln, error_flags); done = adaptivity.adapt(threshold, strategy, MESH_REGULARITY); // Stop counting time for adaptation. wall_clock.tick(); adapt_time += wall_clock.last(); } // Increase the counter of performed adaptivity steps. if (done == false) as++; else { Hermes::Mixins::Loggable::Static::info("Total running time: %g s", wall_clock.accumulated()); Hermes::Mixins::Loggable::Static::info(" Setup: %g s", setup_time); Hermes::Mixins::Loggable::Static::info(" Assemble: %g s", assemble_time); Hermes::Mixins::Loggable::Static::info(" Solve: %g s", solve_time); Hermes::Mixins::Loggable::Static::info(" Adapt: %g s", adapt_time); //sview.show(&sln); oview.show(&space); oview.save_screenshot(("final_mesh-"+itos(refinement_mode)+".bmp").c_str()); oview.close(); conv_table.save(("conv_table-"+itos(refinement_mode)+".dat").c_str()); } } while (done == false); // Wait for all views to be closed. //Views::View::wait(); return 0; }
int main(int argc, char* argv[]) { // Define problem parameters: (x_loc, y_loc) is the center of the circular wave front, R_ZERO is the distance from the // wave front to the center of the circle, and alpha gives the steepness of the wave front. double alpha, x_loc, y_loc, r_zero; switch(PARAM) { case 0: alpha = 20; x_loc = -0.05; y_loc = -0.05; r_zero = 0.7; break; case 1: alpha = 1000; x_loc = -0.05; y_loc = -0.05; r_zero = 0.7; break; case 2: alpha = 1000; x_loc = 1.5; y_loc = 0.25; r_zero = 0.92; break; case 3: alpha = 50; x_loc = 0.5; y_loc = 0.5; r_zero = 0.25; break; default: // The same as 0. alpha = 20; x_loc = -0.05; y_loc = -0.05; r_zero = 0.7; break; } // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("square_quad.mesh", &mesh); // quadrilaterals // mloader.load("square_tri.mesh", &mesh); // triangles // Perform initial mesh refinement. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Set exact solution. CustomExactSolution exact(&mesh, alpha, x_loc, y_loc, r_zero); // Define right-hand side. CustomRightHandSide rhs(alpha, x_loc, y_loc, r_zero); // Initialize the weak formulation. CustomWeakForm wf(&rhs); // Equivalent, but slower: // DefaultWeakFormPoisson<double> wf(Hermes::HERMES_ANY, HERMES_ONE, &rhs); // Initialize boundary conditions. DefaultEssentialBCNonConst<double> bc("Bdy", &exact); EssentialBCs<double> bcs(&bc); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); // Initialize approximate solution. Solution<double> sln; // Initialize views. Views::ScalarView<double> sview("Solution", new Views::WinGeom(0, 0, 440, 350)); sview.show_mesh(false); sview.fix_scale_width(50); Views::OrderView<double> oview("Polynomial orders", new Views::WinGeom(450, 0, 420, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof, graph_cpu, graph_dof_exact, graph_cpu_exact; // Time measurement. Hermes::TimePeriod cpu_time; // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d (%d DOF):", as, space.get_num_dofs()); cpu_time.tick(); // Assemble the discrete problem. DiscreteProblem<double> dp(&wf, &space); // Initial coefficient vector for the Newton's method. int ndof = space.get_num_dofs(); double* coeff_vec = new double[ndof]; memset(coeff_vec, 0, ndof * sizeof(double)); NewtonSolver<double> newton(&dp, matrix_solver_type); newton.set_verbose_output(false); if (!newton.solve(coeff_vec)) error("Newton's iteration failed."); else Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln); cpu_time.tick(); verbose("Solution: %g s", cpu_time.last()); // Calculate element errors and total error estimate. BasicKellyAdapt<double> adaptivity(&space); if (USE_ENERGY_NORM_NORMALIZATION) adaptivity.set_error_form(new EnergyErrorForm(&wf)); if (USE_RESIDUAL_ESTIMATOR) adaptivity.add_error_estimator_vol(new ResidualErrorForm(&rhs)); double err_est_rel = adaptivity.calc_err_est(&sln) * 100; double err_exact_rel = Global<double>::calc_rel_error(&sln, &exact, HERMES_H1_NORM) * 100; cpu_time.tick(); verbose("Error calculation: %g s", cpu_time.last()); info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel); if (TEST_ELEMENT_BASED_KELLY) { cpu_time.tick(); // Ensure that the two possible approaches to interface error estimators accumulation give same results. KellyTypeAdapt<double> adaptivity2(&space, false); adaptivity2.disable_aposteriori_interface_scaling(); adaptivity2.add_error_estimator_surf(new InterfaceErrorForm); if (USE_ENERGY_NORM_NORMALIZATION) adaptivity2.set_error_form(new EnergyErrorForm(&wf)); if (USE_RESIDUAL_ESTIMATOR) { adaptivity2.add_error_estimator_vol(new ResidualErrorForm(&rhs)); adaptivity2.set_volumetric_scaling_const(1./24.); } double err_est_rel2 = adaptivity2.calc_err_est(&sln) * 100; double err_exact_rel2 = adaptivity2.calc_err_exact(&sln, &exact, false) * 100; info("err_est_rel_2: %g%%, err_exact_rel_2: %g%%", err_est_rel2, err_exact_rel2); if (fabs(err_est_rel2 - err_est_rel) >= 1e-13 || fabs(err_exact_rel2 - err_exact_rel) >= 1e-13) { info("err_est_rel diff: %1.15g, err_exact_rel diff: %1.15g", std::abs(err_est_rel2 - err_est_rel), std::abs(err_exact_rel2 - err_exact_rel)); err_est_rel = err_exact_rel = 0; // Exit the adaptivity loop. } cpu_time.tick(Hermes::HERMES_SKIP); } // Report results. cpu_time.tick(); double accum_time = cpu_time.accumulated(); // View the approximate solution and polynomial orders. sview.show(&sln); oview.show(&space); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(space.get_num_dofs(), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(accum_time, err_est_rel); graph_cpu.save("conv_cpu_est.dat"); graph_dof_exact.add_values(space.get_num_dofs(), err_exact_rel); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(accum_time, err_exact_rel); graph_cpu_exact.save("conv_cpu_exact.dat"); cpu_time.tick(Hermes::HERMES_SKIP); // If err_est too large, adapt the mesh. The NDOF test must be here, so that the solution may be visualized // after ending due to this criterion. if (err_exact_rel < ERR_STOP || space.get_num_dofs() >= NDOF_STOP) done = true; else done = adaptivity.adapt(THRESHOLD, STRATEGY, MESH_REGULARITY); cpu_time.tick(); verbose("Adaptation: %g s", cpu_time.last()); // Increase the counter of performed adaptivity steps. if (done == false) as++; /* else { sview.show(&sln); oview.show(&space); info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel); } */ // Clean up. delete [] coeff_vec; } while (done == false); cpu_time.tick(); verbose("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. Views::View::wait(); return 0; }
int main(int argc, char* argv[]) { // Initialize refinement selector. MySelector selector(hORpSelectionBasedOnDOFs); HermesCommonApi.set_integral_param_value(Hermes::showInternalWarnings, false); // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; cpu_time.tick(); // Load the mesh. MeshSharedPtr mesh(new Mesh); MeshReaderH2D mloader; mloader.load("domain.mesh", mesh); // Error calculation & adaptivity. DefaultErrorCalculator<complex, HERMES_H1_NORM> errorCalculator(RelativeErrorToGlobalNorm, 1); // Stopping criterion for an adaptivity step. AdaptStoppingCriterionSingleElement<complex> stoppingCriterion(THRESHOLD); // Adaptivity processor class. Adapt<complex> adaptivity(&errorCalculator, &stoppingCriterion); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); // Initialize boundary conditions. DefaultEssentialBCConst<complex> bc_essential("Source", P_SOURCE); EssentialBCs<complex> bcs(&bc_essential); // Create an H1 space with default shapeset. SpaceSharedPtr<complex> space(new H1Space<complex> (mesh, &bcs, P_INIT)); int ndof = Space<complex>::get_num_dofs(space); //Hermes::Mixins::Loggable::Static::info("ndof = %d", ndof); // Initialize the weak formulation. CustomWeakFormAcoustics wf("Wall", RHO, SOUND_SPEED, OMEGA); // Initialize coarse and reference mesh solution. MeshFunctionSharedPtr<complex> sln(new Solution<complex>), ref_sln(new Solution<complex>); // Initialize views. ScalarView sview("Acoustic pressure", new WinGeom(600, 0, 600, 350)); sview.show_contours(.2); ScalarView eview("Error", new WinGeom(600, 377, 600, 350)); sview.show_mesh(false); sview.fix_scale_width(50); OrderView oview("Polynomial orders", new WinGeom(1208, 0, 600, 350)); ScalarView ref_view("Refined elements", new WinGeom(1208, 377, 600, 350)); ref_view.show_scale(false); ref_view.set_min_max_range(0, 2); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; //Hermes::Mixins::Loggable::Static::info("Solving on reference mesh."); // Time measurement. cpu_time.tick(); // Perform Newton's iteration. Hermes::Hermes2D::NewtonSolver<complex> newton(&wf, space); newton.set_verbose_output(false); // Adaptivity loop: int as = 1; adaptivity.set_space(space); bool done = false; do { //Hermes::Mixins::Loggable::Static::info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Mesh::ReferenceMeshCreator refMeshCreator(mesh); MeshSharedPtr ref_mesh = refMeshCreator.create_ref_mesh(); Space<complex>::ReferenceSpaceCreator refSpaceCreator(space, ref_mesh); SpaceSharedPtr<complex> ref_space = refSpaceCreator.create_ref_space(); int ndof_ref = Space<complex>::get_num_dofs(ref_space); wf.set_verbose_output(false); newton.set_space(ref_space); // Assemble the reference problem. try { newton.solve(); } catch(Hermes::Exceptions::Exception e) { e.print_msg(); throw Hermes::Exceptions::Exception("Newton's iteration failed."); }; // Translate the resulting coefficient vector into the Solution<complex> sln-> Hermes::Hermes2D::Solution<complex>::vector_to_solution(newton.get_sln_vector(), ref_space, ref_sln); // Project the fine mesh solution onto the coarse mesh. //Hermes::Mixins::Loggable::Static::info("Projecting reference solution on coarse mesh."); OGProjection<complex> ogProjection; ogProjection.project_global(space, ref_sln, sln); // Time measurement. cpu_time.tick(); // View the coarse mesh solution and polynomial orders. MeshFunctionSharedPtr<double> acoustic_pressure(new RealFilter(sln)); sview.show(acoustic_pressure); oview.show(space); // Calculate element errors and total error estimate. //Hermes::Mixins::Loggable::Static::info("Calculating error estimate."); errorCalculator.calculate_errors(sln, ref_sln); double err_est_rel = errorCalculator.get_total_error_squared() * 100; eview.show(errorCalculator.get_errorMeshFunction()); // Report results. //Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space<complex>::get_num_dofs(space), Space<complex>::get_num_dofs(ref_space), err_est_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(Space<complex>::get_num_dofs(space), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { //Hermes::Mixins::Loggable::Static::info("Adapting coarse mesh."); done = adaptivity.adapt(&selector); ref_view.show(adaptivity.get_refinementInfoMeshFunction()); cpu_time.tick(); std::cout << "Adaptivity step: " << as << ", running CPU time: " << cpu_time.accumulated_str() << std::endl; } // Increase counter. as++; } while (done == false); //Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated()); // Show the reference solution - the final result. sview.set_title("Fine mesh solution magnitude"); MeshFunctionSharedPtr<double> ref_mag(new RealFilter(ref_sln)); sview.show(ref_mag); // Output solution in VTK format. Linearizer lin(FileExport); bool mode_3D = true; lin.save_solution_vtk(ref_mag, "sln.vtk", "Acoustic pressure", mode_3D); //Hermes::Mixins::Loggable::Static::info("Solution in VTK format saved to file %s.", "sln.vtk"); // Wait for all views to be closed. View::wait(); return 0; }
QList<SolutionArray *> SolutionAgros::solveSolutioArray(Hermes::vector<EssentialBCs> bcs) { QTime time; // solution agros array QList<SolutionArray *> solutionArrayList; // load the mesh file mesh = readMeshFromFile(tempProblemFileName() + ".mesh"); refineMesh(mesh, true, true); // create an H1 space Hermes::vector<Space *> space; // create hermes solution array Hermes::vector<Solution *> solution; // create reference solution Hermes::vector<Solution *> solutionReference; // projection norms Hermes::vector<ProjNormType> projNormType; // prepare selector Hermes::vector<RefinementSelectors::Selector *> selector; // error marker bool isError = false; RefinementSelectors::Selector *select = NULL; switch (adaptivityType) { case AdaptivityType_H: select = new RefinementSelectors::HOnlySelector(); break; case AdaptivityType_P: select = new RefinementSelectors::H1ProjBasedSelector(RefinementSelectors::H2D_P_ANISO, Util::config()->convExp, H2DRS_DEFAULT_ORDER); break; case AdaptivityType_HP: select = new RefinementSelectors::H1ProjBasedSelector(RefinementSelectors::H2D_HP_ANISO, Util::config()->convExp, H2DRS_DEFAULT_ORDER); break; } for (int i = 0; i < numberOfSolution; i++) { space.push_back(new H1Space(mesh, &bcs[i], polynomialOrder)); // set order by element for (int j = 0; j < Util::scene()->labels.count(); j++) if (Util::scene()->labels[j]->material != Util::scene()->materials[0]) space.at(i)->set_uniform_order(Util::scene()->labels[j]->polynomialOrder > 0 ? Util::scene()->labels[j]->polynomialOrder : polynomialOrder, QString::number(j).toStdString()); // solution agros array solution.push_back(new Solution()); if (adaptivityType != AdaptivityType_None) { // add norm projNormType.push_back(Util::config()->projNormType); // add refinement selector selector.push_back(select); // reference solution solutionReference.push_back(new Solution()); } } // check for DOFs if (Space::get_num_dofs(space) == 0) { m_progressItemSolve->emitMessage(QObject::tr("DOF is zero"), true); } else { for (int i = 0; i < numberOfSolution; i++) { // transient if (analysisType == AnalysisType_Transient) { // constant initial solution solution.at(i)->set_const(mesh, initialCondition); solutionArrayList.append(solutionArray(solution.at(i))); } // nonlinear if ((linearityType != LinearityType_Linear) && (analysisType != AnalysisType_Transient)) { solution.at(i)->set_const(mesh, 0.0); } } actualTime = 0.0; // update time function Util::scene()->problemInfo()->hermes()->updateTimeFunctions(actualTime); m_wf->set_current_time(actualTime); m_wf->solution = solution; m_wf->delete_all(); m_wf->registerForms(); // emit message if (adaptivityType != AdaptivityType_None) m_progressItemSolve->emitMessage(QObject::tr("Adaptivity type: %1").arg(adaptivityTypeString(adaptivityType)), false); double error = 0.0; // solution int maxAdaptivitySteps = (adaptivityType == AdaptivityType_None) ? 1 : adaptivitySteps; int actualAdaptivitySteps = -1; for (int i = 0; i<maxAdaptivitySteps; i++) { // set up the solver, matrix, and rhs according to the solver selection. SparseMatrix *matrix = create_matrix(matrixSolver); Vector *rhs = create_vector(matrixSolver); Solver *solver = create_linear_solver(matrixSolver, matrix, rhs); if (adaptivityType == AdaptivityType_None) { if (analysisType != AnalysisType_Transient) solve(space, solution, solver, matrix, rhs); } else { // construct globally refined reference mesh and setup reference space. Hermes::vector<Space *> spaceReference = *Space::construct_refined_spaces(space); // assemble reference problem. solve(spaceReference, solutionReference, solver, matrix, rhs); if (!isError) { // project the fine mesh solution onto the coarse mesh. OGProjection::project_global(space, solutionReference, solution, matrixSolver); // Calculate element errors and total error estimate. Adapt adaptivity(space, projNormType); // Calculate error estimate for each solution component and the total error estimate. error = adaptivity.calc_err_est(solution, solutionReference) * 100; // emit signal m_progressItemSolve->emitMessage(QObject::tr("Adaptivity rel. error (step: %2/%3, DOFs: %4/%5): %1%"). arg(error, 0, 'f', 3). arg(i + 1). arg(maxAdaptivitySteps). arg(Space::get_num_dofs(space)). arg(Space::get_num_dofs(spaceReference)), false, 1); // add error to the list m_progressItemSolve->addAdaptivityError(error, Space::get_num_dofs(space)); if (error < adaptivityTolerance || Space::get_num_dofs(space) >= adaptivityMaxDOFs) { break; } if (i != maxAdaptivitySteps-1) adaptivity.adapt(selector, Util::config()->threshold, Util::config()->strategy, Util::config()->meshRegularity); actualAdaptivitySteps = i+1; } if (m_progressItemSolve->isCanceled()) { isError = true; break; } // delete reference space for (int i = 0; i < spaceReference.size(); i++) { delete spaceReference.at(i)->get_mesh(); delete spaceReference.at(i); } spaceReference.clear(); } // clean up. delete solver; delete matrix; delete rhs; } // delete reference solution for (int i = 0; i < solutionReference.size(); i++) delete solutionReference.at(i); solutionReference.clear(); // delete selector if (select) delete select; selector.clear(); // timesteps if (!isError) { SparseMatrix *matrix = NULL; Vector *rhs = NULL; Solver *solver = NULL; // allocate dp for transient solution DiscreteProblem *dpTran = NULL; if (analysisType == AnalysisType_Transient) { // set up the solver, matrix, and rhs according to the solver selection. matrix = create_matrix(matrixSolver); rhs = create_vector(matrixSolver); solver = create_linear_solver(matrixSolver, matrix, rhs); // solver->set_factorization_scheme(HERMES_REUSE_FACTORIZATION_COMPLETELY); dpTran = new DiscreteProblem(m_wf, space, true); } int timesteps = (analysisType == AnalysisType_Transient) ? floor(timeTotal/timeStep) : 1; for (int n = 0; n<timesteps; n++) { // set actual time actualTime = (n+1)*timeStep; // update essential bc values Space::update_essential_bc_values(space, actualTime); // update timedep values Util::scene()->problemInfo()->hermes()->updateTimeFunctions(actualTime); m_wf->set_current_time(actualTime); m_wf->delete_all(); m_wf->registerForms(); // transient if ((timesteps > 1) && (linearityType == LinearityType_Linear)) isError = !solveLinear(dpTran, space, solution, solver, matrix, rhs); if ((timesteps > 1) && (linearityType != LinearityType_Linear)) isError = !solve(space, solution, solver, matrix, rhs); // output for (int i = 0; i < numberOfSolution; i++) { solutionArrayList.append(solutionArray(solution.at(i), space.at(i), error, actualAdaptivitySteps, (n+1)*timeStep)); } if (analysisType == AnalysisType_Transient) m_progressItemSolve->emitMessage(QObject::tr("Transient time step (%1/%2): %3 s"). arg(n+1). arg(timesteps). arg(actualTime, 0, 'e', 2), false, n+2); if (m_progressItemSolve->isCanceled()) { isError = true; break; } } // clean up if (solver) delete solver; if (matrix) delete matrix; if (rhs) delete rhs; if (dpTran) delete dpTran; } } // delete mesh delete mesh; // delete space for (unsigned int i = 0; i < space.size(); i++) { // delete space.at(i)->get_mesh(); delete space.at(i); } space.clear(); // delete last solution for (unsigned int i = 0; i < solution.size(); i++) delete solution.at(i); solution.clear(); if (isError) { for (int i = 0; i < solutionArrayList.count(); i++) delete solutionArrayList.at(i); solutionArrayList.clear(); } return solutionArrayList; }