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("wall.mesh", basemesh); mesh->copy(basemesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); mesh->refine_towards_boundary(BDY_RIGHT, 2); mesh->refine_towards_boundary(BDY_FIRE, INIT_REF_NUM_BDY); // Initialize essential boundary conditions (none). EssentialBCs<double> bcs; // Initialize an H1 space with default shapeset. SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT)); int ndof = Space<double>::get_num_dofs(space); Hermes::Mixins::Loggable::Static::info("ndof = %d.", ndof); // Convert initial condition into a Solution. MeshFunctionSharedPtr<double> sln_prev_time(new ConstantSolution<double> (mesh, TEMP_INIT)); // Initialize the weak formulation. double current_time = 0; CustomWeakFormHeatRK wf(BDY_FIRE, BDY_AIR, ALPHA_FIRE, ALPHA_AIR, RHO, HEATCAP, TEMP_EXT_AIR, TEMP_INIT, ¤t_time); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, space); // Create a refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST); // Visualize initial condition. char title[100]; ScalarView sln_view("Initial condition", new WinGeom(0, 0, 1500, 360)); OrderView ordview("Initial mesh", new WinGeom(0, 410, 1500, 360)); ScalarView time_error_view("Temporal error", new WinGeom(0, 800, 1500, 360)); time_error_view.fix_scale_width(40); ScalarView space_error_view("Spatial error", new WinGeom(0, 1220, 1500, 360)); space_error_view.fix_scale_width(40); sln_view.show(sln_prev_time); 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."); // Class for projections. OGProjection<double> ogProjection; // Time stepping loop: 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, P_INIT); space->adjust_element_order(-1, -1, P_INIT, P_INIT); break; default: throw Hermes::Exceptions::Exception("Wrong global derefinement method."); } space->assign_dofs(); ndof = Space<double>::get_num_dofs(space); } // Spatial adaptivity loop. Note: sln_prev_time must not be // changed during spatial adaptivity. MeshFunctionSharedPtr<double> ref_sln(new Solution<double>()); MeshFunctionSharedPtr<double> time_error_fn(new Solution<double>(mesh)); 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<double>::ReferenceSpaceCreator refSpaceCreator(space, ref_mesh); SpaceSharedPtr<double> ref_space = refSpaceCreator.create_ref_space(); // Initialize Runge-Kutta time stepping on the reference mesh. RungeKutta<double> runge_kutta(&wf, ref_space, &bt); try { ogProjection.project_global(ref_space, sln_prev_time, sln_prev_time); } catch(Exceptions::Exception& e) { std::cout << e.what() << std::endl; Hermes::Mixins::Loggable::Static::error("Projection failed."); return -1; } // 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()); bool verbose = true; bool jacobian_changed = false; 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(sln_prev_time, ref_sln, bt.is_embedded() ? time_error_fn : NULL); } catch(Exceptions::Exception& e) { std::cout << e.what() << std::endl; Hermes::Mixins::Loggable::Static::error("Runge-Kutta time step failed"); return -1; } /* 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); time_error_view.show(time_error_fn); rel_err_time = Global<double>::calc_norm(time_error_fn.get(), HERMES_H1_NORM) / Global<double>::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 tau from %g to %g s and restarting time step.", time_step, time_step * TIME_STEP_DEC_RATIO); time_step *= TIME_STEP_DEC_RATIO; 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; } 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<double> sln(new Solution<double>()); Hermes::Mixins::Loggable::Static::info("Projecting fine mesh solution on coarse mesh for error estimation."); ogProjection.project_global(space, ref_sln, sln); // Show spatial error. sprintf(title, "Spatial error est, spatial adaptivity step %d", as); MeshFunctionSharedPtr<double> space_error_fn(new DiffFilter<double>(Hermes::vector<MeshFunctionSharedPtr<double> >(ref_sln, sln))); space_error_view.set_title(title); //space_error_view.show_mesh(false); MeshFunctionSharedPtr<double> abs_sef(new AbsFilter(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."); adaptivity.set_space(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<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); if (Space<double>::get_num_dofs(space) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } // Clean up. if(!done) } while (done == false); // Visualize the solution and mesh-> char title[100]; sprintf(title, "Solution, 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_prev_time sln_prev_time->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. 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_GLOB_REF_NUM; i++) mesh->refine_all_elements(); mesh->refine_towards_boundary("Top", INIT_REF_NUM_BDY); // Initialize boundary conditions. CustomEssentialBCNonConst bc_essential(Hermes::vector<std::string>("Bottom", "Right", "Top", "Left")); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT)); int ndof_coarse = Space<double>::get_num_dofs(space); adaptivity.set_space(space); Hermes::Mixins::Loggable::Static::info("ndof_coarse = %d.", ndof_coarse); // Zero initial solution. This is why we use H_OFFSET. MeshFunctionSharedPtr<double> h_time_prev(new ZeroSolution<double>(mesh)), h_time_new(new ZeroSolution<double>(mesh)); // Initialize the constitutive relations. ConstitutiveRelations* constitutive_relations; if(constitutive_relations_type == CONSTITUTIVE_GENUCHTEN) constitutive_relations = new ConstitutiveRelationsGenuchten(ALPHA, M, N, THETA_S, THETA_R, K_S, STORATIVITY); else constitutive_relations = new ConstitutiveRelationsGardner(ALPHA, THETA_S, THETA_R, K_S); // Initialize the weak formulation. CustomWeakFormRichardsRK wf(constitutive_relations); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, space); // Create a refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST); // Visualize initial condition. char title[100]; ScalarView view("Initial condition", new WinGeom(0, 0, 440, 350)); OrderView ordview("Initial mesh", new WinGeom(445, 0, 440, 350)); view.show(h_time_prev); ordview.show(space); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; cpu_time.tick(); // 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: 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."); } space->assign_dofs(); ndof_coarse = Space<double>::get_num_dofs(space); } // Spatial adaptivity loop. Note: h_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. 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 = Space<double>::get_num_dofs(ref_space); // Time measurement. cpu_time.tick(); // Initialize Runge-Kutta time stepping. RungeKutta<double> runge_kutta(&wf, ref_space, &bt); // Perform one Runge-Kutta time step according to the selected Butcher's table. Hermes::Mixins::Loggable::Static::info("Runge-Kutta time step (t = %g s, tau = %g s, stages: %d).", current_time, time_step, bt.get_size()); 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); runge_kutta.rk_time_step_newton(h_time_prev, h_time_new); } catch(Exceptions::Exception& e) { e.print_msg(); throw Hermes::Exceptions::Exception("Runge-Kutta time step failed"); } // Project the fine mesh solution onto the coarse mesh. MeshFunctionSharedPtr<double> sln_coarse(new Solution<double>); Hermes::Mixins::Loggable::Static::info("Projecting fine mesh solution on coarse mesh for error estimation."); OGProjection<double> ogProjection; ogProjection.project_global(space, h_time_new, sln_coarse); // Calculate element errors and total error estimate. Hermes::Mixins::Loggable::Static::info("Calculating error estimate."); errorCalculator.calculate_errors(sln_coarse, h_time_new, true); double err_est_rel_total = errorCalculator.get_total_error_squared() * 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); // Time measurement. cpu_time.tick(); // 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); // Increase the counter of performed adaptivity steps. as++; } } while (done == false); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(current_time, Space<double>::get_num_dofs(space)); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(current_time, cpu_time.accumulated()); graph_cpu.save("conv_cpu_est.dat"); // Visualize the solution and mesh-> char title[100]; sprintf(title, "Solution, time %g", current_time); view.set_title(title); view.show_mesh(false); view.show(h_time_new); sprintf(title, "Mesh, time %g", current_time); ordview.set_title(title); ordview.show(space); // Copy last reference solution into h_time_prev. h_time_prev->copy(h_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; }
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; }
int main(int argc, char* argv[]) { #ifdef THREAD_TESTING HermesCommonApi.set_integral_param_value(numThreads, 8); #endif // Load the mesh. MeshSharedPtr mesh(new Mesh); Hermes::vector<MeshSharedPtr> meshes; meshes.push_back(mesh); MeshReaderH2DXML mloader; mloader.load("agrosMesh.msh", meshes); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); // Initialize boundary conditions. DefaultEssentialBCConst<complex> bc_essential("4", P_SOURCE); EssentialBCs<complex> bcs(&bc_essential); // Create an H1 space with default shapeset. SpaceSharedPtr<complex> space(new H1Space<complex> (mesh, &bcs, P_INIT)); adaptivity.set_space(space); // Initialize the weak formulation. CustomWeakFormAcoustics wf("0", RHO, SOUND_SPEED, OMEGA); // Initialize coarse and reference mesh solution. MeshFunctionSharedPtr<complex> sln(new Solution<complex>), ref_sln(new Solution<complex>); // Initialize refinement selector. H1ProjBasedSelector<complex> selector(CAND_LIST); Hermes::Hermes2D::NewtonSolver<complex> newton; newton.set_weak_formulation(&wf); // 2 Adaptivity steps: int as = 1; bool done = false; 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(); // Perform Newton's iteration. try { newton.set_space(ref_space); 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. OGProjection<complex> ogProjection; ogProjection.project_global(space, ref_sln, sln); // Calculate element errors and total error estimate. errorCalculator.calculate_errors(sln, ref_sln); adaptivity.adapt(&selector); } while (as++ < 2); return 0; }
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[]) { // 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[]) { // Load the mesh. MeshSharedPtr mesh(new Mesh); MeshReaderH2D mloader; mloader.load("square_quad.mesh", mesh); // mloader.load("square_tri.mesh", mesh); // Perform initial mesh refinement. for (int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); mesh->refine_towards_boundary("Layer", INIT_REF_NUM_BDY); // Initialize the weak formulation. WeakFormSharedPtr<double> wf(new WeakFormLinearAdvectionDiffusion(STABILIZATION_ON, SHOCK_CAPTURING_ON, B1, B2, EPSILON)); // Initialize boundary conditions DefaultEssentialBCConst<double> bc_rest("Rest", 1.0); EssentialBCNonConst bc_layer("Layer"); EssentialBCs<double> bcs({ &bc_rest, &bc_layer }); // Create an H1 space with default shapeset. SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT)); WinGeom* sln_win_geom = new WinGeom(0, 0, 440, 350); WinGeom* mesh_win_geom = new WinGeom(450, 0, 400, 350); // Initialize coarse and reference mesh solution. MeshFunctionSharedPtr<double> sln(new Solution<double>), ref_sln(new Solution<double>); // Initialize refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST); // 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); // 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(); // Assemble the reference problem. Hermes::Mixins::Loggable::Static::info("Solving on reference mesh."); LinearSolver<double> solver(wf, ref_space); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. // If successful, obtain the solution. solver.solve(); Solution<double>::vector_to_solution(solver.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<double>::project_global(space, ref_sln, sln); // Time measurement. cpu_time.tick(); // View the coarse mesh solution and polynomial orders. 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."); adaptivity.set_space(space); errorCalculator.calculate_errors(sln, ref_sln); double err_est_rel = errorCalculator.get_total_error_squared() * 100; // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space<double>::get_num_dofs(space), Space<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<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); // Increase the counter of performed adaptivity steps. if (done == false) 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"); sview.show_mesh(false); sview.show(ref_sln); // Wait for all views to be closed. View::wait(); return 0; }