int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; MeshReaderH2D mloader; if (ALIGN_MESH) mloader.load("oven_load_circle.mesh", &mesh); else mloader.load("oven_load_square.mesh", &mesh); // Perform initial mesh refinemets. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions DefaultEssentialBCConst<std::complex<double> > bc_essential(BDY_PERFECT_CONDUCTOR, std::complex<double>(0.0, 0.0)); EssentialBCs<std::complex<double> > bcs(&bc_essential); // Create an Hcurl space with default shapeset. HcurlSpace<std::complex<double> > space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); Hermes::Mixins::Loggable::Static::info("ndof = %d", ndof); // Initialize the weak formulation. CustomWeakForm wf(e_0, mu_0, mu_r, kappa, omega, J, ALIGN_MESH, &mesh, BDY_CURRENT); // Initialize coarse and reference mesh solution. Solution<std::complex<double> > sln, ref_sln; // Initialize refinements selector. HcurlProjBasedSelector<std::complex<double> > selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView eview("Electric field", new WinGeom(0, 0, 580, 400)); OrderView oview("Polynomial orders", new WinGeom(590, 0, 550, 400)); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; 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); Mesh* ref_mesh = refMeshCreator.create_ref_mesh(); Space<std::complex<double> >::ReferenceSpaceCreator refSpaceCreator(&space, ref_mesh); Space<std::complex<double> >* ref_space = refSpaceCreator.create_ref_space(); int ndof_ref = Space<std::complex<double> >::get_num_dofs(ref_space); // Initialize reference problem. Hermes::Mixins::Loggable::Static::info("Solving on reference mesh."); DiscreteProblem<std::complex<double> > dp(&wf, ref_space); // Time measurement. cpu_time.tick(); // Perform Newton's iteration. Hermes::Hermes2D::NewtonSolver<std::complex<double> > newton(&dp); try { newton.set_newton_max_iter(NEWTON_MAX_ITER); newton.set_newton_tol(NEWTON_TOL); 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<std::complex<double> > sln. Hermes::Hermes2D::Solution<std::complex<double> >::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<std::complex<double> > ogProjection; ogProjection.project_global(&space, &ref_sln, &sln); // View the coarse mesh solution and polynomial orders. RealFilter real(&sln); MagFilter<double> magn(&real); ValFilter limited_magn(&magn, 0.0, 4e3); char title[100]; sprintf(title, "Electric field, adaptivity step %d", as); eview.set_title(title); //eview.set_min_max_range(0.0, 4e3); eview.show(&limited_magn); sprintf(title, "Polynomial orders, adaptivity step %d", as); oview.set_title(title); oview.show(&space); // Calculate element errors and total error estimate. Hermes::Mixins::Loggable::Static::info("Calculating error estimate."); Adapt<std::complex<double> >* adaptivity = new Adapt<std::complex<double> >(&space); // Set custom error form and calculate error estimate. CustomErrorForm cef(kappa); adaptivity->set_error_form(0, 0, &cef); double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space<std::complex<double> >::get_num_dofs(&space), Space<std::complex<double> >::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<std::complex<double> >::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, THRESHOLD, STRATEGY, MESH_REGULARITY); } if (space.get_num_dofs() >= NDOF_STOP) done = true; delete adaptivity; if(!done) { delete ref_space->get_mesh(); delete ref_space; } // Increase counter. as++; } while (done == false); Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated()); RealFilter ref_real(&sln); MagFilter<double> ref_magn(&ref_real); ValFilter ref_limited_magn(&ref_magn, 0.0, 4e3); eview.set_title("Fine mesh solution - magnitude"); eview.show(&ref_limited_magn); // Output solution in VTK format. Linearizer lin; bool mode_3D = true; lin.save_solution_vtk(&ref_limited_magn, "sln.vtk", "Magnitude of E", 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; }
int main(int argc, char* argv[]) { // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; cpu_time.tick(); // Load the mesh. MeshSharedPtr u_mesh(new Mesh), v_mesh(new Mesh); MeshReaderH2D mloader; mloader.load("domain.mesh", u_mesh); if (MULTI == false) u_mesh->refine_towards_boundary("Bdy", INIT_REF_BDY); // Create initial mesh (master mesh). v_mesh->copy(u_mesh); // Initial mesh refinements in the v_mesh towards the boundary. if (MULTI == true) v_mesh->refine_towards_boundary("Bdy", INIT_REF_BDY); // Set exact solutions. MeshFunctionSharedPtr<double> exact_u(new ExactSolutionFitzHughNagumo1(u_mesh)); MeshFunctionSharedPtr<double> exact_v(new ExactSolutionFitzHughNagumo2(MULTI ? v_mesh : u_mesh, K)); // Define right-hand sides. CustomRightHandSide1 g1(K, D_u, SIGMA); CustomRightHandSide2 g2(K, D_v); // Initialize the weak formulation. WeakFormSharedPtr<double> wf(new CustomWeakForm(&g1, &g2)); // Initialize boundary conditions DefaultEssentialBCConst<double> bc_u("Bdy", 0.0); EssentialBCs<double> bcs_u(&bc_u); DefaultEssentialBCConst<double> bc_v("Bdy", 0.0); EssentialBCs<double> bcs_v(&bc_v); // Create H1 spaces with default shapeset for both displacement components. SpaceSharedPtr<double> u_space(new H1Space<double>(u_mesh, &bcs_u, P_INIT_U)); SpaceSharedPtr<double> v_space(new H1Space<double>(MULTI ? v_mesh : u_mesh, &bcs_v, P_INIT_V)); // Initialize coarse and reference mesh solutions. MeshFunctionSharedPtr<double> u_sln(new Solution<double>()), v_sln(new Solution<double>()), u_ref_sln(new Solution<double>()), v_ref_sln(new Solution<double>()); std::vector<MeshFunctionSharedPtr<double> > slns({ u_sln, v_sln }); std::vector<MeshFunctionSharedPtr<double> > ref_slns({ u_ref_sln, v_ref_sln }); std::vector<MeshFunctionSharedPtr<double> > exact_slns({ exact_u, exact_v }); // Initialize refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST); //HOnlySelector<double> selector; // Initialize views. Views::ScalarView s_view_0("Solution[0]", new Views::WinGeom(0, 0, 440, 350)); s_view_0.show_mesh(false); Views::OrderView o_view_0("Mesh[0]", new Views::WinGeom(450, 0, 420, 350)); Views::ScalarView s_view_1("Solution[1]", new Views::WinGeom(880, 0, 440, 350)); s_view_1.show_mesh(false); Views::OrderView o_view_1("Mesh[1]", new Views::WinGeom(1330, 0, 420, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est; SimpleGraph graph_dof_exact, graph_cpu_exact; NewtonSolver<double> newton; newton.set_weak_formulation(wf); // Adaptivity loop: int as = 1; bool done = false; do { Hermes::Mixins::Loggable::Static::info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space-> Mesh::ReferenceMeshCreator u_ref_mesh_creator(u_mesh); MeshSharedPtr u_ref_mesh = u_ref_mesh_creator.create_ref_mesh(); Mesh::ReferenceMeshCreator v_ref_mesh_creator(v_mesh); MeshSharedPtr v_ref_mesh = v_ref_mesh_creator.create_ref_mesh(); Space<double>::ReferenceSpaceCreator u_ref_space_creator(u_space, u_ref_mesh); SpaceSharedPtr<double> u_ref_space = u_ref_space_creator.create_ref_space(); Space<double>::ReferenceSpaceCreator v_ref_space_creator(v_space, MULTI ? v_ref_mesh : u_ref_mesh); SpaceSharedPtr<double> v_ref_space = v_ref_space_creator.create_ref_space(); newton.set_spaces({ u_ref_space, v_ref_space }); int ndof_ref = Space<double>::get_num_dofs({ u_ref_space, v_ref_space }); // Initialize reference problem. Hermes::Mixins::Loggable::Static::info("Solving on reference mesh."); // Time measurement. cpu_time.tick(); // Perform Newton's iteration. try { newton.solve(); } catch (Hermes::Exceptions::Exception& e) { std::cout << e.info(); } catch (std::exception& e) { std::cout << e.what(); } // Translate the resulting coefficient vector into the instance of Solution. Solution<double>::vector_to_solutions(newton.get_sln_vector(), { u_ref_space, v_ref_space }, { u_ref_sln, v_ref_sln }); // Project the fine mesh solution onto the coarse mesh. Hermes::Mixins::Loggable::Static::info("Projecting reference solution on coarse mesh."); OGProjection<double> ogProjection; ogProjection.project_global({ u_space, v_space }, ref_slns, slns); cpu_time.tick(); // View the coarse mesh solution and polynomial orders. s_view_0.show(u_sln); o_view_0.show(u_space); s_view_1.show(v_sln); o_view_1.show(v_space); // Calculate element errors. Hermes::Mixins::Loggable::Static::info("Calculating error estimate and exact error."); errorCalculator.calculate_errors(slns, exact_slns, false); double err_exact_rel_total = errorCalculator.get_total_error_squared() * 100; std::vector<double> err_exact_rel; err_exact_rel.push_back(errorCalculator.get_error_squared(0) * 100); err_exact_rel.push_back(errorCalculator.get_error_squared(1) * 100); errorCalculator.calculate_errors(slns, ref_slns, true); double err_est_rel_total = errorCalculator.get_total_error_squared() * 100; std::vector<double> err_est_rel; err_est_rel.push_back(errorCalculator.get_error_squared(0) * 100); err_est_rel.push_back(errorCalculator.get_error_squared(1) * 100); adaptivity.set_spaces({ u_space, v_space }); // Time measurement. cpu_time.tick(); // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse[0]: %d, ndof_fine[0]: %d", u_space->get_num_dofs(), u_ref_space->get_num_dofs()); Hermes::Mixins::Loggable::Static::info("err_est_rel[0]: %g%%, err_exact_rel[0]: %g%%", err_est_rel[0], err_exact_rel[0]); Hermes::Mixins::Loggable::Static::info("ndof_coarse[1]: %d, ndof_fine[1]: %d", v_space->get_num_dofs(), v_ref_space->get_num_dofs()); Hermes::Mixins::Loggable::Static::info("err_est_rel[1]: %g%%, err_exact_rel[1]: %g%%", err_est_rel[1], err_exact_rel[1]); Hermes::Mixins::Loggable::Static::info("ndof_coarse_total: %d, ndof_fine_total: %d", Space<double>::get_num_dofs({ u_space, v_space }), Space<double>::get_num_dofs({ u_ref_space, v_ref_space })); Hermes::Mixins::Loggable::Static::info("err_est_rel_total: %g%%, err_est_exact_total: %g%%", err_est_rel_total, err_exact_rel_total); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space<double>::get_num_dofs({ u_space, v_space }), err_est_rel_total); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel_total); graph_cpu_est.save("conv_cpu_est.dat"); graph_dof_exact.add_values(Space<double>::get_num_dofs({ u_space, v_space }), err_exact_rel_total); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel_total); graph_cpu_exact.save("conv_cpu_exact.dat"); // If err_est too large, adapt the mesh-> if (err_est_rel_total < ERR_STOP) done = true; else { Hermes::Mixins::Loggable::Static::info("Adapting coarse mesh."); done = adaptivity.adapt({ &selector, &selector }); } // Increase counter. as++; } while (done == false); Hermes::Mixins::Loggable::Static::info("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[]) { // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("domain.mesh", &mesh); // Initialize the weak formulation. CustomWeakFormPoisson wf("Motor", EPS_MOTOR, "Air", EPS_AIR); // 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 fine mesh solution. Solution<double> sln, ref_sln; // Initialize refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // 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; DiscreteProblem<double> dp(&wf, &space); NewtonSolver<double> newton(&dp); newton.set_verbose_output(true); // Adaptivity loop: int as = 1; bool done = false; do { Hermes::Mixins::Loggable::Static::info("---- Adaptivity step %d:", as); // Time measurement. cpu_time.tick(); // Construct globally refined mesh and setup fine mesh space. Mesh::ReferenceMeshCreator ref_mesh_creator(&mesh); Mesh* ref_mesh = ref_mesh_creator.create_ref_mesh(); Space<double>::ReferenceSpaceCreator ref_space_creator(&space, ref_mesh); Space<double>* ref_space = ref_space_creator.create_ref_space(); int ndof_ref = ref_space->get_num_dofs(); // Initialize fine mesh problem. Hermes::Mixins::Loggable::Static::info("Solving on fine mesh."); newton.set_space(ref_space); // 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(), ref_space, &ref_sln); // Project the fine mesh solution onto the coarse mesh. Hermes::Mixins::Loggable::Static::info("Projecting fine mesh solution on coarse mesh."); OGProjection<double> ogProjection; ogProjection.project_global(&space, &ref_sln, &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."); Adapt<double> adaptivity(&space); bool solutions_for_adapt = true; // In the following function, the Boolean parameter "solutions_for_adapt" determines whether // the calculated errors are intended for use with adaptivity (this may not be the case, for example, // when error wrt. an exact solution is calculated). The default value is solutions_for_adapt = true, // The last parameter "error_flags" determine whether the total and element errors are treated as // absolute or relative. Its default value is error_flags = HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL. // In subsequent examples and benchmarks, these two parameters will be often used with // their default values, and thus they will not be present in the code explicitly. double err_est_rel = adaptivity.calc_err_est(&sln, &ref_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100; // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", space.get_num_dofs(), ref_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."); done = adaptivity.adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (space.get_num_dofs() >= NDOF_STOP) done = true; // Keep the mesh from final step to allow further work with the final fine mesh solution. if(done == false) delete ref_space->get_mesh(); delete ref_space; } while (done == false); Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated()); // Show the fine mesh solution - final result. sview.set_title("Fine mesh solution"); sview.show_mesh(false); sview.show(&ref_sln); // Wait for all views to be closed. Views::View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. MeshSharedPtr mesh(new 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(); // Set exact solution. MeshFunctionSharedPtr<double> exact_sln(new CustomExactSolution(mesh, K, alpha)); // Define right-hand side. CustomRightHandSide f(K, alpha); // Initialize weak formulation. Hermes1DFunction<double> lambda(1.0); WeakFormsH1::DefaultWeakFormPoisson<double> wf(HERMES_ANY, &lambda, &f); // Initialize boundary conditions DefaultEssentialBCNonConst<double> bc_essential("Bdy_dirichlet_rest", exact_sln); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT)); // Initialize approximate solution. MeshFunctionSharedPtr<double> sln(new Solution<double>()); // Initialize refinement selector. MySelector selector(CAND_LIST); // Initialize views. Views::ScalarView sview("Solution", new Views::WinGeom(0, 0, 440, 350)); sview.show_mesh(false); sview.fix_scale_width(50); Views::OrderView oview("Polynomial orders", new Views::WinGeom(450, 0, 420, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est, graph_dof_exact, graph_cpu_exact; // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; // Adaptivity loop: int as = 1; bool done = false; do { cpu_time.tick(); // Construct globally refined reference mesh and setup reference space-> Mesh::ReferenceMeshCreator refMeshCreator(mesh); MeshSharedPtr ref_mesh = refMeshCreator.create_ref_mesh(); Space<double>::ReferenceSpaceCreator refSpaceCreator(space, ref_mesh); SpaceSharedPtr<double> ref_space = refSpaceCreator.create_ref_space(); int ndof_ref = ref_space->get_num_dofs(); Hermes::Mixins::Loggable::Static::info("---- Adaptivity step %d (%d DOF):", as, ndof_ref); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Solving on reference mesh."); // Assemble the discrete problem. DiscreteProblem<double> dp(&wf, ref_space); NewtonSolver<double> newton(&dp); MeshFunctionSharedPtr<double> ref_sln(new Solution<double>()); 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 instance of Solution. Solution<double>::vector_to_solution(newton.get_sln_vector(), ref_space, ref_sln); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Solution: %g s", cpu_time.last()); // Project the fine mesh solution onto the coarse mesh. Hermes::Mixins::Loggable::Static::info("Calculating error estimate and exact error."); OGProjection<double> ogProjection; ogProjection.project_global(space, ref_sln, sln); // Calculate element errors and total error estimate. DefaultErrorCalculator<double, HERMES_H1_NORM> error_calculator(errorType, 1); error_calculator.calculate_errors(sln, exact_sln); double err_exact_rel = error_calculator.get_total_error_squared() * 100.0; error_calculator.calculate_errors(sln, ref_sln); double err_est_rel = error_calculator.get_total_error_squared() * 100.0; Adapt<double> adaptivity(space, &error_calculator); adaptivity.set_strategy(&stoppingCriterion); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Error calculation: %g s", cpu_time.last()); // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_fine: %d", space->get_num_dofs(), ref_space->get_num_dofs()); Hermes::Mixins::Loggable::Static::info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel); // Time measurement. cpu_time.tick(); double accum_time = cpu_time.accumulated(); // View the coarse mesh solution and polynomial orders. sview.show(sln); oview.show(space); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(space->get_num_dofs(), err_est_rel); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(accum_time, err_est_rel); graph_cpu_est.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::Mixins::TimeMeasurable::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) done = true; else done = adaptivity.adapt(&selector); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Adaptation: %g s", cpu_time.last()); // Increase the counter of adaptivity steps. if (done == false) as++; } while (done == false); Hermes::Mixins::Loggable::Static::info("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[]) { // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("domain.mesh", &mesh); // Perform initial mesh refinemets. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions. DefaultEssentialBCConst<double> left_t("Left", 1.0); EssentialBCs<double> bcs_t(&left_t); DefaultEssentialBCConst<double> left_c("Left", 0.0); EssentialBCs<double> bcs_c(&left_c); // Create H1 spaces with default shapesets. H1Space<double>* t_space = new H1Space<double>(&mesh, &bcs_t, P_INIT); H1Space<double>* c_space = new H1Space<double>(&mesh, &bcs_c, P_INIT); int ndof = Space<double>::get_num_dofs(Hermes::vector<const Space<double>*>(t_space, c_space)); Hermes::Mixins::Loggable::Static::info("ndof = %d.", ndof); // Define initial conditions. InitialSolutionTemperature t_prev_time_1(&mesh, x1); InitialSolutionConcentration c_prev_time_1(&mesh, x1, Le); InitialSolutionTemperature t_prev_time_2(&mesh, x1); InitialSolutionConcentration c_prev_time_2(&mesh, x1, Le); Solution<double> t_prev_newton; Solution<double> c_prev_newton; // Filters for the reaction rate omega and its derivatives. CustomFilter omega(Hermes::vector<Solution<double>*>(&t_prev_time_1, &c_prev_time_1), Le, alpha, beta, kappa, x1, TAU); CustomFilterDt omega_dt(Hermes::vector<Solution<double>*>(&t_prev_time_1, &c_prev_time_1), Le, alpha, beta, kappa, x1, TAU); CustomFilterDc omega_dc(Hermes::vector<Solution<double>*>(&t_prev_time_1, &c_prev_time_1), Le, alpha, beta, kappa, x1, TAU); // Initialize visualization. ScalarView rview("Reaction rate", new WinGeom(0, 0, 800, 230)); // Initialize weak formulation. CustomWeakForm wf(Le, alpha, beta, kappa, x1, TAU, TRILINOS_JFNK, PRECOND, &omega, &omega_dt, &omega_dc, &t_prev_time_1, &c_prev_time_1, &t_prev_time_2, &c_prev_time_2); // Project the functions "t_prev_time_1" and "c_prev_time_1" on the FE space // in order to obtain initial vector for NOX. Hermes::Mixins::Loggable::Static::info("Projecting initial solutions on the FE meshes."); double* coeff_vec = new double[ndof]; OGProjection<double> ogProjection; ogProjection.project_global(Hermes::vector<const Space<double> *>(t_space, c_space), Hermes::vector<MeshFunction<double>*>(&t_prev_time_1, &c_prev_time_1), coeff_vec); // Measure the projection time. double proj_time = cpu_time.tick().last(); // Initialize finite element problem. DiscreteProblem<double> dp(&wf, Hermes::vector<const Space<double>*>(t_space, c_space)); // Initialize NOX solver and preconditioner. NewtonSolverNOX<double> solver(&dp); MlPrecond<double> pc("sa"); if (PRECOND) { if (TRILINOS_JFNK) solver.set_precond(pc); else solver.set_precond("New Ifpack"); } if (TRILINOS_OUTPUT) solver.set_output_flags(NOX::Utils::Error | NOX::Utils::OuterIteration | NOX::Utils::OuterIterationStatusTest | NOX::Utils::LinearSolverDetails); // Time stepping loop: double total_time = 0.0; cpu_time.tick_reset(); for (int ts = 1; total_time <= T_FINAL; ts++) { Hermes::Mixins::Loggable::Static::info("---- Time step %d, t = %g s", ts, total_time + TAU); cpu_time.tick(); try { solver.solve(coeff_vec); } catch(std::exception& e) { std::cout << e.what(); } Solution<double>::vector_to_solutions(solver.get_sln_vector(), Hermes::vector<const Space<double> *>(t_space, c_space), Hermes::vector<Solution<double> *>(&t_prev_newton, &c_prev_newton)); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Number of nonlin iterations: %d (norm of residual: %g)", solver.get_num_iters(), solver.get_residual()); Hermes::Mixins::Loggable::Static::info("Total number of iterations in linsolver: %d (achieved tolerance in the last step: %g)", solver.get_num_lin_iters(), solver.get_achieved_tol()); // Time measurement. cpu_time.tick(); // Skip visualization time. cpu_time.tick(); // Update global time. total_time += TAU; // Saving solutions for the next time step. if(ts > 1) { t_prev_time_2.copy(&t_prev_time_1); c_prev_time_2.copy(&c_prev_time_1); } t_prev_time_1.copy(&t_prev_newton); c_prev_time_1.copy(&c_prev_newton); // Visualization. rview.set_min_max_range(0.0,2.0); rview.show(&omega); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Total running time for time level %d: %g s.", ts, cpu_time.tick().last()); } // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("domain.mesh", &mesh); // Perform initial uniform mesh refinement. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Set essential boundary conditions. DefaultEssentialBCConst<double> bc_essential(Hermes::vector<std::string>("right", "top"), 0.0); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); // Associate element markers (corresponding to physical regions) // with material properties (diffusion coefficient, absorption // cross-section, external sources). Hermes::vector<std::string> regions("e1", "e2", "e3", "e4", "e5"); Hermes::vector<double> D_map(D_1, D_2, D_3, D_4, D_5); Hermes::vector<double> Sigma_a_map(SIGMA_A_1, SIGMA_A_2, SIGMA_A_3, SIGMA_A_4, SIGMA_A_5); Hermes::vector<double> Sources_map(Q_EXT_1, 0.0, Q_EXT_3, 0.0, 0.0); // Initialize the weak formulation. WeakFormsNeutronics::Monoenergetic::Diffusion::DefaultWeakFormFixedSource<double> wf(regions, D_map, Sigma_a_map, Sources_map); // Initialize coarse and reference mesh solution. Solution<double> sln, ref_sln; // Initialize refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); sview.fix_scale_width(50); sview.show_mesh(false); OrderView oview("Polynomial orders", new WinGeom(450, 0, 400, 350)); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { Hermes::Mixins::Loggable::Static::info("---- Adaptivity step %d:", as); // Time measurement. cpu_time.tick(); // Construct globally refined mesh and setup fine mesh space. Space<double>* ref_space = Space<double>::construct_refined_space(&space); int ndof_ref = ref_space->get_num_dofs(); // Initialize fine mesh problem. Hermes::Mixins::Loggable::Static::info("Solving on fine mesh."); DiscreteProblem<double> dp(&wf, ref_space); NewtonSolver<double> newton(&dp); newton.set_verbose_output(false); // Perform Newton's iteration. try { newton.solve(); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); throw Hermes::Exceptions::Exception("Newton's iteration failed."); } // Translate the resulting coefficient vector into the instance of Solution. Solution<double>::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 fine mesh solution on coarse mesh."); OGProjection<double> ogProjection; ogProjection.project_global(&space, &ref_sln, &sln); // Time measurement. cpu_time.tick(); // Visualize the solution and mesh. sview.show(&sln); oview.show(&space); // Skip visualization time. cpu_time.tick(Hermes::Mixins::TimeMeasurable::HERMES_SKIP); // Calculate element errors and total error estimate. Hermes::Mixins::Loggable::Static::info("Calculating error estimate."); Adapt<double> adaptivity(&space); bool solutions_for_adapt = true; double err_est_rel = adaptivity.calc_err_est(&sln, &ref_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100; // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", space.get_num_dofs(), ref_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(Hermes::Mixins::TimeMeasurable::HERMES_SKIP); // 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, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (space.get_num_dofs() >= NDOF_STOP) done = true; // Keep the mesh from final step to allow further work with the final fine mesh solution. if(done == false) { delete ref_space->get_mesh(); delete ref_space; } } while (done == false); Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated()); // Show the fine mesh solution - final result. sview.set_title("Fine mesh solution"); sview.show_mesh(false); sview.show(&ref_sln); // Wait for all views to be closed. Views::View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("lshape.mesh", &mesh); // Perform initial mesh refinement. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Set exact solution. CustomExactSolution exact_sln(&mesh, alpha_w, alpha_p, x_w, y_w, r_0, omega_c, epsilon, x_p, y_p); // Define right-hand side. CustomRightHandSide f(alpha_w, alpha_p, x_w, y_w, r_0, omega_c, epsilon, x_p, y_p); // Initialize the weak formulation. Hermes1DFunction<double> lambda(1.0); WeakFormsH1::DefaultWeakFormPoisson<double> wf(HERMES_ANY, &lambda, &f); // Initialize boundary conditions DefaultEssentialBCNonConst<double> bc_essential("Bdy", &exact_sln); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); // Initialize approximate solution. Solution<double> sln; // Initialize refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. Views::ScalarView sview("Solution", new Views::WinGeom(0, 0, 440, 350)); sview.show_mesh(false); sview.fix_scale_width(50); Views::OrderView oview("Polynomial orders", new Views::WinGeom(450, 0, 420, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est, graph_dof_exact, graph_cpu_exact; // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; // Adaptivity loop: int as = 1; bool done = false; do { cpu_time.tick(); // Construct globally refined reference mesh and setup reference space. Space<double>* ref_space = Space<double>::construct_refined_space(&space, 1); int ndof_ref = ref_space->get_num_dofs(); Hermes::Mixins::Loggable::Static::info("---- Adaptivity step %d (%d DOF):", as, ndof_ref); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Solving on reference mesh."); // Assemble the discrete problem. DiscreteProblem<double> dp(&wf, ref_space); NewtonSolver<double> newton(&dp); newton.set_verbose_output(false); Solution<double> ref_sln; try { newton.solve(); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); throw Hermes::Exceptions::Exception("Newton's iteration failed."); }; // Translate the resulting coefficient vector into the instance of Solution. Solution<double>::vector_to_solution(newton.get_sln_vector(), ref_space, &ref_sln); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Solution: %g s", cpu_time.last()); // Project the fine mesh solution onto the coarse mesh. Hermes::Mixins::Loggable::Static::info("Calculating error estimate and exact error."); OGProjection<double> ogProjection; ogProjection.project_global(&space, &ref_sln, &sln); // Calculate element errors and total error estimate. Adapt<double> adaptivity(&space); double err_est_rel = adaptivity.calc_err_est(&sln, &ref_sln) * 100; // Calculate exact error. double err_exact_rel = Global<double>::calc_rel_error(&sln, &exact_sln, HERMES_H1_NORM) * 100; cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Error calculation: %g s", cpu_time.last()); // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_fine: %d", space.get_num_dofs(), ref_space->get_num_dofs()); Hermes::Mixins::Loggable::Static::info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel); // Time measurement. cpu_time.tick(); double accum_time = cpu_time.accumulated(); // View the coarse mesh solution and polynomial orders. sview.show(&sln); oview.show(&space); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(space.get_num_dofs(), err_est_rel); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(accum_time, err_est_rel); graph_cpu_est.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::Mixins::TimeMeasurable::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(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Adaptation: %g s", cpu_time.last()); // Increase the counter of adaptivity steps. if (done == false) as++; delete ref_space->get_mesh(); delete ref_space; } while (done == false); Hermes::Mixins::Loggable::Static::info("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[]) { // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); if (bt.is_explicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Turn off adaptive time stepping if R-K method is not embedded. if (bt.is_embedded() == false && ADAPTIVE_TIME_STEP_ON == true) { Hermes::Mixins::Loggable::Static::warn("R-K method not embedded, turning off adaptive time stepping."); ADAPTIVE_TIME_STEP_ON = false; } // Load the mesh. MeshSharedPtr mesh(new Mesh), basemesh(new Mesh); MeshReaderH2D mloader; mloader.load("square.mesh", basemesh); mesh->copy(basemesh); // Initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); // Convert initial condition into a Solution<complex>. MeshFunctionSharedPtr<complex> psi_time_prev(new CustomInitialCondition(mesh)); // Initialize the weak formulation. double current_time = 0; // Initialize weak formulation. CustomWeakFormGPRK wf(h, m, g, omega); // Initialize boundary conditions. DefaultEssentialBCConst<complex> bc_essential("Bdy", 0.0); 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->get_num_dofs(); Hermes::Mixins::Loggable::Static::info("ndof = %d", ndof); // Initialize the FE problem. DiscreteProblem<complex> dp(&wf, space); // Create a refinement selector. H1ProjBasedSelector<complex> selector(CAND_LIST); // Visualize initial condition. char title[100]; ScalarView sview_real("Initial condition - real part", new WinGeom(0, 0, 600, 500)); ScalarView sview_imag("Initial condition - imaginary part", new WinGeom(610, 0, 600, 500)); sview_real.show_mesh(false); sview_imag.show_mesh(false); sview_real.fix_scale_width(50); sview_imag.fix_scale_width(50); OrderView ord_view("Initial mesh", new WinGeom(445, 0, 440, 350)); ord_view.fix_scale_width(50); ScalarView time_error_view("Temporal error", new WinGeom(0, 400, 440, 350)); time_error_view.fix_scale_width(50); time_error_view.fix_scale_width(60); ScalarView space_error_view("Spatial error", new WinGeom(445, 400, 440, 350)); space_error_view.fix_scale_width(50); MeshFunctionSharedPtr<double> real(new RealFilter(psi_time_prev)); MeshFunctionSharedPtr<double> imag(new ImagFilter(psi_time_prev)); sview_real.show(real); sview_imag.show(imag); ord_view.show(space); // Graph for time step history. SimpleGraph time_step_graph; if (ADAPTIVE_TIME_STEP_ON) Hermes::Mixins::Loggable::Static::info("Time step history will be saved to file time_step_history.dat."); // Time stepping: int num_time_steps = (int)(T_FINAL/time_step + 0.5); for(int ts = 1; ts <= num_time_steps; ts++) // Time stepping loop. double current_time = 0.0; int ts = 1; do { Hermes::Mixins::Loggable::Static::info("Begin time step %d.", ts); // Periodic global derefinement. if (ts > 1 && ts % UNREF_FREQ == 0) { Hermes::Mixins::Loggable::Static::info("Global mesh derefinement."); switch (UNREF_METHOD) { case 1: mesh->copy(basemesh); space->set_uniform_order(P_INIT); break; case 2: space->unrefine_all_mesh_elements(); space->set_uniform_order(P_INIT); break; case 3: space->unrefine_all_mesh_elements(); space->adjust_element_order(-1, -1, P_INIT, P_INIT); break; default: throw Hermes::Exceptions::Exception("Wrong global derefinement method."); } ndof = Space<complex>::get_num_dofs(space); } Hermes::Mixins::Loggable::Static::info("ndof: %d", ndof); // Spatial adaptivity loop. Note: psi_time_prev must not be // changed during spatial adaptivity. MeshFunctionSharedPtr<complex> ref_sln(new Solution<complex>()); MeshFunctionSharedPtr<complex> time_error_fn(new Solution<complex>); bool done = false; int as = 1; double err_est; do { // 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(); // Initialize discrete problem on reference mesh. DiscreteProblem<complex>* ref_dp = new DiscreteProblem<complex>(&wf, ref_space); RungeKutta<complex> runge_kutta(&wf, ref_space, &bt); // Runge-Kutta step on the fine mesh-> Hermes::Mixins::Loggable::Static::info("Runge-Kutta time step on fine mesh (t = %g s, time step = %g s, stages: %d).", current_time, time_step, bt.get_size()); bool verbose = true; try { runge_kutta.set_time(current_time); runge_kutta.set_time_step(time_step); runge_kutta.set_max_allowed_iterations(NEWTON_MAX_ITER); runge_kutta.set_tolerance(NEWTON_TOL_FINE); runge_kutta.rk_time_step_newton(psi_time_prev, ref_sln, time_error_fn); } catch(Exceptions::Exception& e) { e.print_msg(); throw Hermes::Exceptions::Exception("Runge-Kutta time step failed"); } /* If ADAPTIVE_TIME_STEP_ON == true, estimate temporal error. If too large or too small, then adjust it and restart the time step. */ double rel_err_time = 0; if (bt.is_embedded() == true) { Hermes::Mixins::Loggable::Static::info("Calculating temporal error estimate."); // Show temporal error. char title[100]; sprintf(title, "Temporal error est, spatial adaptivity step %d", as); time_error_view.set_title(title); time_error_view.show_mesh(false); MeshFunctionSharedPtr<double> abs_time(new RealFilter(time_error_fn)); MeshFunctionSharedPtr<double> abs_tef(new AbsFilter(abs_time)); time_error_view.show(abs_tef); rel_err_time = Global<complex>::calc_norm(time_error_fn.get(), HERMES_H1_NORM) / Global<complex>::calc_norm(ref_sln.get(), HERMES_H1_NORM) * 100; if (ADAPTIVE_TIME_STEP_ON == false) Hermes::Mixins::Loggable::Static::info("rel_err_time: %g%%", rel_err_time); } if (ADAPTIVE_TIME_STEP_ON) { if (rel_err_time > TIME_ERR_TOL_UPPER) { Hermes::Mixins::Loggable::Static::info("rel_err_time %g%% is above upper limit %g%%", rel_err_time, TIME_ERR_TOL_UPPER); Hermes::Mixins::Loggable::Static::info("Decreasing time step from %g to %g s and restarting time step.", time_step, time_step * TIME_STEP_DEC_RATIO); time_step *= TIME_STEP_DEC_RATIO; delete ref_dp; continue; } else if (rel_err_time < TIME_ERR_TOL_LOWER) { Hermes::Mixins::Loggable::Static::info("rel_err_time = %g%% is below lower limit %g%%", rel_err_time, TIME_ERR_TOL_LOWER); Hermes::Mixins::Loggable::Static::info("Increasing time step from %g to %g s.", time_step, time_step * TIME_STEP_INC_RATIO); time_step *= TIME_STEP_INC_RATIO; delete ref_dp; continue; } else { Hermes::Mixins::Loggable::Static::info("rel_err_time = %g%% is in acceptable interval (%g%%, %g%%)", rel_err_time, TIME_ERR_TOL_LOWER, TIME_ERR_TOL_UPPER); } // Add entry to time step history graph. time_step_graph.add_values(current_time, time_step); time_step_graph.save("time_step_history.dat"); } /* Estimate spatial errors and perform mesh refinement */ Hermes::Mixins::Loggable::Static::info("Spatial adaptivity step %d.", as); // Project the fine mesh solution onto the coarse mesh. MeshFunctionSharedPtr<complex> sln(new Solution<complex>); Hermes::Mixins::Loggable::Static::info("Projecting fine mesh solution on coarse mesh for error estimation."); OGProjection<complex> ogProjection; ogProjection.project_global(space, ref_sln, sln); // Show spatial error. sprintf(title, "Spatial error est, spatial adaptivity step %d", as); MeshFunctionSharedPtr<complex> space_error_fn(new DiffFilter<complex>(Hermes::vector<MeshFunctionSharedPtr<complex> >(ref_sln, sln))); space_error_view.set_title(title); space_error_view.show_mesh(false); MeshFunctionSharedPtr<double> abs_space(new RealFilter(space_error_fn)); MeshFunctionSharedPtr<double> abs_sef(new AbsFilter(abs_space)); space_error_view.show(abs_sef); // Calculate element errors and spatial error estimate. Hermes::Mixins::Loggable::Static::info("Calculating spatial error estimate."); Adapt<complex> adaptivity(space); double err_rel_space = errorCalculator.get_total_error_squared() * 100; // Report results. Hermes::Mixins::Loggable::Static::info("ndof: %d, ref_ndof: %d, err_rel_space: %g%%", Space<complex>::get_num_dofs(space), Space<complex>::get_num_dofs(ref_space), err_rel_space); // If err_est too large, adapt the mesh. if (err_rel_space < SPACE_ERR_TOL) done = true; else { Hermes::Mixins::Loggable::Static::info("Adapting the coarse mesh."); done = adaptivity.adapt(&selector); // Increase the counter of performed adaptivity steps. as++; } // Clean up. delete ref_dp; } while (done == false); // Visualize the solution and mesh-> char title[100]; sprintf(title, "Solution - real part, Time %3.2f s", current_time); sview_real.set_title(title); sprintf(title, "Solution - imaginary part, Time %3.2f s", current_time); sview_imag.set_title(title); MeshFunctionSharedPtr<double> real(new RealFilter(ref_sln)); MeshFunctionSharedPtr<double> imag(new ImagFilter(ref_sln)); sview_real.show(real); sview_imag.show(imag); sprintf(title, "Mesh, time %g s", current_time); ord_view.set_title(title); ord_view.show(space); // Copy last reference solution into psi_time_prev. psi_time_prev->copy(ref_sln); // Increase current time and counter of time steps. current_time += time_step; ts++; } while (current_time < T_FINAL); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { #ifdef WITH_PARALUTION HermesCommonApi.set_integral_param_value(matrixSolverType, SOLVER_PARALUTION_ITERATIVE); // Load the mesh. MeshSharedPtr mesh(new Mesh); MeshReaderH2D mloader; mloader.load("square.mesh", mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh->refine_all_elements(); mesh->refine_towards_boundary("Bdy", INIT_BDY_REF_NUM); // Initialize boundary conditions. CustomEssentialBCNonConst bc_essential("Bdy"); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT)); int ndof = space->get_num_dofs(); // Initialize the weak formulation CustomNonlinearity lambda(alpha); Hermes2DFunction<double> src(-heat_src); DefaultWeakFormPoisson<double> wf(HERMES_ANY, &lambda, &src); #ifdef SHOW_OUTPUT ScalarView s_view("Solution"); #endif double* coeff_vec = new double[ndof]; MeshFunctionSharedPtr<double> init_sln(new CustomInitialCondition(mesh)); OGProjection<double> ogProjection; ogProjection.project_global(space, init_sln, coeff_vec); MeshFunctionSharedPtr<double> sln(new Solution<double>); // Testing is happening here. Hermes::vector<int> numbers_of_nonlinear_iterations; Hermes::vector<int> numbers_of_linear_iterations_in_last_nonlinear_step; // Iterative - original initial guess. HermesCommonApi.set_integral_param_value(matrixSolverType, SOLVER_PARALUTION_ITERATIVE); { // Initialize Newton solver. NewtonSolver<double> newton(&wf, space); newton.set_tolerance(NEWTON_TOL, ResidualNormAbsolute); newton.set_max_steps_with_reused_jacobian(0); newton.get_linear_matrix_solver()->as_IterSolver()->set_solver_type(Solvers::GMRES); newton.get_linear_matrix_solver()->as_IterSolver()->set_tolerance(1e-5); // Perform Newton's iteration. newton.solve(coeff_vec); numbers_of_nonlinear_iterations.push_back(newton.get_num_iters()); numbers_of_linear_iterations_in_last_nonlinear_step.push_back(newton.get_linear_matrix_solver()->as_IterSolver()->get_num_iters()); // Translate the resulting coefficient vector into a Solution. Solution<double>::vector_to_solution(newton.get_sln_vector(), space, sln); #ifdef SHOW_OUTPUT s_view.show(sln); #endif } // Iterative - "exact" initial guess. { // Initialize Newton solver. NewtonSolver<double> newton(&wf, space); newton.set_tolerance(NEWTON_TOL, ResidualNormAbsolute); newton.get_linear_matrix_solver()->as_IterSolver()->set_solver_type(Solvers::GMRES); // Perform Newton's iteration. newton.solve(sln); numbers_of_nonlinear_iterations.push_back(newton.get_num_iters()); numbers_of_linear_iterations_in_last_nonlinear_step.push_back(newton.get_linear_matrix_solver()->as_IterSolver()->get_num_iters()); // Translate the resulting coefficient vector into a Solution. Solution<double>::vector_to_solution(newton.get_sln_vector(), space, sln); #ifdef SHOW_OUTPUT s_view.show(sln); #endif } bool success = true; success = Hermes::Testing::test_value(numbers_of_nonlinear_iterations[0], 10, "Nonlinear iterations[0]", 1) && success; success = Hermes::Testing::test_value(numbers_of_nonlinear_iterations[1], 1, "Nonlinear iterations[1]", 1) && success; success = Hermes::Testing::test_value(numbers_of_linear_iterations_in_last_nonlinear_step[0], 5, "Linear iterations[0]", 1) && success; success = Hermes::Testing::test_value(numbers_of_linear_iterations_in_last_nonlinear_step[1], 7, "Linear iterations[1]", 1) && success; if(success == true) { printf("Success!\n"); return 0; } else { printf("Failure!\n"); return -1; } #endif return 0; }
int main(int argc, char* argv[]) { // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); if (bt.is_explicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Turn off adaptive time stepping if R-K method is not embedded. if (bt.is_embedded() == false && ADAPTIVE_TIME_STEP_ON == true) { throw Hermes::Exceptions::Exception("R-K method not embedded, turning off adaptive time stepping."); ADAPTIVE_TIME_STEP_ON = false; } // Load the mesh. Mesh mesh, basemesh; MeshReaderH2D mloader; mloader.load("square.mesh", &basemesh); mesh.copy(&basemesh); // Initial mesh refinements. for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary("Bdy", INIT_BDY_REF_NUM); // Initialize boundary conditions. EssentialBCNonConst bc_essential("Bdy"); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); // Convert initial condition into a Solution. CustomInitialCondition sln_time_prev(&mesh); // Initialize the weak formulation CustomNonlinearity lambda(alpha); Hermes2DFunction<double> f(heat_src); WeakFormsH1::DefaultWeakFormPoisson<double> wf(HERMES_ANY, &lambda, &f); // Initialize the discrete problem. DiscreteProblem<double> dp(&wf, &space); // Create a refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Visualize initial condition. char title[100]; ScalarView sln_view("Initial condition", new WinGeom(0, 0, 440, 350)); sln_view.show_mesh(false); OrderView ordview("Initial mesh", new WinGeom(445, 0, 440, 350)); ScalarView time_error_view("Temporal error", new WinGeom(0, 400, 440, 350)); time_error_view.fix_scale_width(60); ScalarView space_error_view("Spatial error", new WinGeom(445, 400, 440, 350)); space_error_view.fix_scale_width(60); sln_view.show(&sln_time_prev); ordview.show(&space); // Graph for time step history. SimpleGraph time_step_graph; if (ADAPTIVE_TIME_STEP_ON) Hermes::Mixins::Loggable::Static::info("Time step history will be saved to file time_step_history.dat."); // Time stepping loop. double current_time = 0.0; int ts = 1; do { Hermes::Mixins::Loggable::Static::info("Begin time step %d.", ts); // Periodic global derefinement. if (ts > 1 && ts % UNREF_FREQ == 0) { Hermes::Mixins::Loggable::Static::info("Global mesh derefinement."); switch (UNREF_METHOD) { case 1: mesh.copy(&basemesh); space.set_uniform_order(P_INIT); break; case 2: mesh.unrefine_all_elements(); space.set_uniform_order(P_INIT); break; case 3: mesh.unrefine_all_elements(); space.adjust_element_order(-1, -1, P_INIT, P_INIT); break; } ndof = Space<double>::get_num_dofs(&space); } Hermes::Mixins::Loggable::Static::info("ndof: %d", ndof); // Spatial adaptivity loop. Note: sln_time_prev must not be // changed during spatial adaptivity. Solution<double> ref_sln; Solution<double>* time_error_fn; if (bt.is_embedded() == true) time_error_fn = new Solution<double>(&mesh); else time_error_fn = NULL; bool done = false; int as = 1; double err_est; do { // Construct globally refined reference mesh and setup reference space. Space<double>* ref_space = Space<double>::construct_refined_space(&space); RungeKutta<double> runge_kutta(&wf, ref_space, &bt); // Runge-Kutta step on the fine mesh. Hermes::Mixins::Loggable::Static::info("Runge-Kutta time step on fine mesh (t = %g s, tau = %g s, stages: %d).", current_time, time_step, bt.get_size()); try { runge_kutta.setTime(current_time); runge_kutta.setTimeStep(time_step); runge_kutta.set_newton_max_iter(NEWTON_MAX_ITER); runge_kutta.set_newton_tol(NEWTON_TOL_FINE); runge_kutta.rk_time_step_newton(&sln_time_prev, &ref_sln, time_error_fn); } catch(Exceptions::Exception& e) { std::cout << e.what(); } /* If ADAPTIVE_TIME_STEP_ON == true, estimate temporal error. If too large or too small, then adjust it and restart the time step. */ double rel_err_time = 0; if (bt.is_embedded() == true) { Hermes::Mixins::Loggable::Static::info("Calculating temporal error estimate."); // Show temporal error. char title[100]; sprintf(title, "Temporal error est, spatial adaptivity step %d", as); time_error_view.set_title(title); time_error_view.show_mesh(false); AbsFilter abs_tef(time_error_fn); time_error_view.show(&abs_tef); rel_err_time = Global<double>::calc_norm(time_error_fn, HERMES_H1_NORM) / Global<double>::calc_norm(&ref_sln, HERMES_H1_NORM) * 100; if (ADAPTIVE_TIME_STEP_ON == false) Hermes::Mixins::Loggable::Static::info("rel_err_time: %g%%", rel_err_time); } if (ADAPTIVE_TIME_STEP_ON) { if (rel_err_time > TIME_ERR_TOL_UPPER) { Hermes::Mixins::Loggable::Static::info("rel_err_time %g%% is above upper limit %g%%", rel_err_time, TIME_ERR_TOL_UPPER); Hermes::Mixins::Loggable::Static::info("Decreasing tau from %g to %g s and restarting time step.", time_step, time_step * TIME_STEP_DEC_RATIO); time_step *= TIME_STEP_DEC_RATIO; delete ref_space->get_mesh(); delete ref_space; continue; } else if (rel_err_time < TIME_ERR_TOL_LOWER) { Hermes::Mixins::Loggable::Static::info("rel_err_time = %g%% is below lower limit %g%%", rel_err_time, TIME_ERR_TOL_LOWER); Hermes::Mixins::Loggable::Static::info("Increasing tau from %g to %g s.", time_step, time_step * TIME_STEP_INC_RATIO); time_step *= TIME_STEP_INC_RATIO; delete ref_space->get_mesh(); delete ref_space; continue; } else { Hermes::Mixins::Loggable::Static::info("rel_err_time = %g%% is in acceptable interval (%g%%, %g%%)", rel_err_time, TIME_ERR_TOL_LOWER, TIME_ERR_TOL_UPPER); } // Add entry to time step history graph. time_step_graph.add_values(current_time, time_step); time_step_graph.save("time_step_history.dat"); } /* Estimate spatial errors and perform mesh refinement */ Hermes::Mixins::Loggable::Static::info("Spatial adaptivity step %d.", as); // Project the fine mesh solution onto the coarse mesh. Solution<double> sln; Hermes::Mixins::Loggable::Static::info("Projecting fine mesh solution on coarse mesh for error estimation."); OGProjection<double> ogProjection; ogProjection.project_global(&space, &ref_sln, &sln); // Show spatial error. sprintf(title, "Spatial error est, spatial adaptivity step %d", as); DiffFilter<double>* space_error_fn = new DiffFilter<double>(Hermes::vector<MeshFunction<double>*>(&ref_sln, &sln)); space_error_view.set_title(title); space_error_view.show_mesh(false); AbsFilter abs_sef(space_error_fn); space_error_view.show(&abs_sef); // Calculate element errors and spatial error estimate. Hermes::Mixins::Loggable::Static::info("Calculating spatial error estimate."); Adapt<double>* adaptivity = new Adapt<double>(&space); double err_rel_space = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Report results. Hermes::Mixins::Loggable::Static::info("ndof: %d, ref_ndof: %d, err_rel_space: %g%%", Space<double>::get_num_dofs(&space), Space<double>::get_num_dofs(ref_space), err_rel_space); // If err_est too large, adapt the mesh. if (err_rel_space < SPACE_ERR_TOL) done = true; else { Hermes::Mixins::Loggable::Static::info("Adapting the coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); if (Space<double>::get_num_dofs(&space) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } // Clean up. delete adaptivity; if(!done) { delete ref_space->get_mesh(); delete ref_space; } delete space_error_fn; } while (done == false); // Clean up. if (time_error_fn != NULL) delete time_error_fn; // Visualize the solution and mesh. char title[100]; sprintf(title, "Solution<double>, time %g s", current_time); sln_view.set_title(title); sln_view.show_mesh(false); sln_view.show(&ref_sln); sprintf(title, "Mesh, time %g s", current_time); ordview.set_title(title); ordview.show(&space); // Copy last reference solution into sln_time_prev. sln_time_prev.copy(&ref_sln); // Increase current time and counter of time steps. current_time += time_step; ts++; } while (current_time < T_FINAL); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); if (bt.is_explicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Load the mesh. Mesh mesh, basemesh; MeshReaderH2D mloader; mloader.load("square.mesh", &basemesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) basemesh.refine_all_elements(0, true); mesh.copy(&basemesh); // Initialize boundary conditions. EssentialBCNonConst bc_essential("Bdy"); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); int ndof_coarse = space.get_num_dofs(); // Previous time level solution (initialized by initial condition). CustomInitialCondition sln_time_prev(&mesh); // Initialize the weak formulation CustomNonlinearity lambda(alpha); Hermes2DFunction<double> f(heat_src); WeakFormsH1::DefaultWeakFormPoisson<double> wf(HERMES_ANY, &lambda, &f); // Next time level solution. Solution<double> sln_time_new(&mesh); // Create a refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Visualize initial condition. char title[100]; ScalarView view("Initial condition", new WinGeom(0, 0, 440, 350)); OrderView ordview("Initial mesh", new WinGeom(445, 0, 410, 350)); view.show(&sln_time_prev); ordview.show(&space); // Initialize Runge-Kutta time stepping. RungeKutta<double> runge_kutta(&wf, &space, &bt); // Time stepping loop. double current_time = 0; int ts = 1; do { // Periodic global derefinement. if (ts > 1 && ts % UNREF_FREQ == 0) { Hermes::Mixins::Loggable::Static::info("Global mesh derefinement."); switch (UNREF_METHOD) { case 1: mesh.copy(&basemesh); space.set_uniform_order(P_INIT); break; case 2: mesh.unrefine_all_elements(); space.set_uniform_order(P_INIT); break; case 3: mesh.unrefine_all_elements(); space.adjust_element_order(-1, -1, P_INIT, P_INIT); break; } ndof_coarse = Space<double>::get_num_dofs(&space); } // Spatial adaptivity loop. Note: sln_time_prev must not be changed // during spatial adaptivity. bool done = false; int as = 1; double err_est; do { Hermes::Mixins::Loggable::Static::info("Time step %d, adaptivity step %d:", ts, as); // Construct globally refined reference mesh and setup reference space. Space<double>* ref_space = Space<double>::construct_refined_space(&space); int ndof_ref = Space<double>::get_num_dofs(ref_space); // Perform one Runge-Kutta time step according to the selected Butcher's table. try { runge_kutta.set_space(ref_space); runge_kutta.set_verbose_output(true); runge_kutta.setTime(current_time); runge_kutta.setTimeStep(time_step); runge_kutta.rk_time_step_newton(&sln_time_prev, &sln_time_new); } catch(Exceptions::Exception& e) { std::cout << e.what(); } // Project the fine mesh solution onto the coarse mesh. Solution<double> sln_coarse; Hermes::Mixins::Loggable::Static::info("Projecting fine mesh solution on coarse mesh for error estimation."); OGProjection<double> ogProjection; ogProjection.project_global(&space, &sln_time_new, &sln_coarse); // Calculate element errors and total error estimate. Hermes::Mixins::Loggable::Static::info("Calculating error estimate."); Adapt<double>* adaptivity = new Adapt<double>(&space); double err_est_rel_total = adaptivity->calc_err_est(&sln_coarse, &sln_time_new) * 100; // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_ref: %d, err_est_rel: %g%%", Space<double>::get_num_dofs(&space), Space<double>::get_num_dofs(ref_space), err_est_rel_total); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { Hermes::Mixins::Loggable::Static::info("Adapting the coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); if (Space<double>::get_num_dofs(&space) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } // Visualize the solution and mesh. char title[100]; sprintf(title, "Solution<double>, time %g", current_time); view.set_title(title); view.show_mesh(false); view.show(&sln_time_new); sprintf(title, "Mesh, time %g", current_time); ordview.set_title(title); ordview.show(&space); // Clean up. delete adaptivity; if(!done) { delete ref_space; delete sln_time_new.get_mesh(); } } while (done == false); sln_time_prev.copy(&sln_time_new); // Increase current time and counter of time steps. current_time += time_step; ts++; } while (current_time < T_FINAL); // Wait for all views to be closed. View::wait(); return 0; }