int main(int argc, char* argv[]) { // Load the mesh Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize the shapeset and the cache H1Shapeset shapeset; PrecalcShapeset pss(&shapeset); // Create finite element space H1Space space(&mesh, &shapeset); space.set_bc_types(bc_types); space.set_bc_values(bc_values); space.set_uniform_order(P_INIT); // Enumerate basis functions space.assign_dofs(); // Initialize the weak formulation WeakForm wf(1); wf.add_biform(0, 0, bilinear_form, bilinear_form_ord, SYM); wf.add_liform(0, linear_form, linear_form_ord); wf.add_liform_surf(0, linear_form_surf, linear_form_surf_ord, 2); // Visualize solution and mesh ScalarView sview("Coarse solution", 0, 100, 798, 700); OrderView oview("Polynomial orders", 800, 100, 798, 700); // Matrix solver UmfpackSolver solver; // Time measurement double cpu = 0; begin_time(); // Solve the problem Solution sln; LinSystem ls(&wf, &solver); ls.set_spaces(1, &space); ls.set_pss(1, &pss); ls.assemble(); ls.solve(1, &sln); // Time measurement cpu += end_time(); // View the solution and mesh sview.show(&sln); oview.show(&space); // Print timing information verbose("Total running time: %g sec", cpu); // wait for all views to be closed View::wait("Waiting for all views to be closed."); return 0; }
int main(int argc, char* argv[]) { // load the mesh file Mesh mesh; H2DReader mloader; mloader.load("square.mesh", &mesh); // initial mesh refinements for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(1,INIT_BDY_REF_NUM); // initialize the shapeset and the cache H1Shapeset shapeset; PrecalcShapeset pss(&shapeset); // create an H1 space H1Space space(&mesh, &shapeset); space.set_bc_types(bc_types); space.set_uniform_order(P_INIT); space.assign_dofs(); // previous solution for the Newton's iteration Solution u_prev; // initialize the weak formulation WeakForm wf(1); wf.add_biform(0, 0, callback(jac), UNSYM, ANY, 1, &u_prev); wf.add_liform(0, callback(res), ANY, 1, &u_prev); // initialize the nonlinear system and solver UmfpackSolver umfpack; NonlinSystem nls(&wf, &umfpack); nls.set_spaces(1, &space); nls.set_pss(1, &pss); // use a constant function as the initial guess u_prev.set_const(&mesh, 3.0); nls.set_ic(&u_prev, &u_prev, PROJ_TYPE); // Newton's loop if (!nls.solve_newton_1(&u_prev, NEWTON_TOL, NEWTON_MAX_ITER)) error("Newton's method did not converge."); // visualise the solution and mesh ScalarView sview("Solution", 0, 0, 800, 600); OrderView oview("Mesh", 820, 0, 800, 600); char title[100]; sprintf(title, "Solution"); sview.set_title(title); sview.show(&u_prev); sprintf(title, "Mesh"); oview.set_title(title); oview.show(&space); // wait for keyboard or mouse input View::wait(); return 0; }
int main(int argc, char* argv[]) { // load the mesh Mesh mesh; H2DReader mloader; mloader.load("motor.mesh", &mesh); // initialize the shapeset and the cache H1Shapeset shapeset; PrecalcShapeset pss(&shapeset); // create finite element space H1Space space(&mesh, &shapeset); space.set_bc_types(bc_types); space.set_bc_values(bc_values); space.set_uniform_order(P_INIT); // enumerate basis functions space.assign_dofs(); // initialize the weak formulation WeakForm wf(1); wf.add_biform(0, 0, callback(biform1), SYM, 1); wf.add_biform(0, 0, callback(biform2), SYM, 2); // visualize solution, gradient, and mesh ScalarView sview("Coarse solution", 0, 0, 600, 1000); VectorView gview("Gradient", 610, 0, 600, 1000); OrderView oview("Polynomial orders", 1220, 0, 600, 1000); //gview.set_min_max_range(0.0, 400.0); // matrix solver UmfpackSolver solver; // DOF and CPU convergence graphs SimpleGraph graph_dof, graph_cpu; // adaptivity loop int it = 1, ndofs; bool done = false; double cpu = 0.0; Solution sln_coarse, sln_fine; do { info("\n---- Adaptivity step %d ---------------------------------------------\n", it++); // time measurement begin_time(); // solve the coarse mesh problem LinSystem ls(&wf, &solver); ls.set_spaces(1, &space); ls.set_pss(1, &pss); ls.assemble(); ls.solve(1, &sln_coarse); // time measurement cpu += end_time(); // view the solution -- this can be slow; for illustration only sview.show(&sln_coarse); gview.show(&sln_coarse, &sln_coarse, EPS_NORMAL, FN_DX_0, FN_DY_0); oview.show(&space); // time measurement begin_time(); // solve the fine mesh problem RefSystem rs(&ls); rs.assemble(); rs.solve(1, &sln_fine); // calculate element errors and total error estimate H1OrthoHP hp(1, &space); double err_est = hp.calc_error(&sln_coarse, &sln_fine) * 100; info("Error estimate: %g%%", err_est); // time measurement cpu += end_time(); // add entry to DOF convergence graph graph_dof.add_values(space.get_num_dofs(), err_est); graph_dof.save("conv_dof.dat"); // add entry to CPU convergence graph graph_cpu.add_values(cpu, err_est); graph_cpu.save("conv_cpu.dat"); // if err_est too large, adapt the mesh if (err_est < ERR_STOP) done = true; else { hp.adapt(THRESHOLD, STRATEGY, ADAPT_TYPE, ISO_ONLY, MESH_REGULARITY); ndofs = space.assign_dofs(); if (ndofs >= NDOF_STOP) done = true; } } while (done == false); verbose("Total running time: %g sec", cpu); // show the fine solution - this is the final result sview.set_title("Final solution"); sview.show(&sln_fine); gview.show(&sln_fine, &sln_fine, EPS_HIGH, FN_DX_0, FN_DY_0); // wait for all views to be closed View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("square.mesh", &mesh); // Initial mesh refinements. for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(BDY_DIRICHLET, INIT_BDY_REF_NUM); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(BDY_DIRICHLET); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_function(BDY_DIRICHLET, essential_bc_values); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d.", ndof); // Solution for the previous time level. Solution u_prev_time; // Initialize the weak formulation. WeakForm wf; if (TIME_INTEGRATION == 1) { wf.add_matrix_form(jac_euler, jac_ord, HERMES_NONSYM, HERMES_ANY, &u_prev_time); wf.add_vector_form(res_euler, res_ord, HERMES_ANY, &u_prev_time); } else { wf.add_matrix_form(jac_cranic, jac_ord, HERMES_NONSYM, HERMES_ANY, &u_prev_time); wf.add_vector_form(res_cranic, res_ord, HERMES_ANY, &u_prev_time); } // Project the function init_cond() on the FE space // to obtain initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[Space::get_num_dofs(&space)]; info("Projecting initial condition to obtain initial vector for the Newton's method."); OGProjection::project_global(&space, init_cond, coeff_vec, matrix_solver); Solution::vector_to_solution(coeff_vec, &space, &u_prev_time); // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 500, 400)); OrderView oview("Mesh", new WinGeom(520, 0, 450, 400)); oview.show(&space); sview.show(&u_prev_time); // Time stepping loop: double current_time = 0.0; int t_step = 1; do { info("---- Time step %d, t = %g s.", t_step, current_time); t_step++; // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Perform Newton's iteration. bool verbose = true; if (!solve_newton(coeff_vec, &dp, solver, matrix, rhs, NEWTON_TOL, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution::vector_to_solution(coeff_vec, &space, &u_prev_time); // Cleanup. delete matrix; delete rhs; delete solver; // Update time. current_time += TAU; // Show the new time level solution. char title[100]; sprintf(title, "Solution, t = %g", current_time); sview.set_title(title); sview.show(&u_prev_time); } while (current_time < T_FINAL); delete [] coeff_vec; // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("cathedral.mesh", &mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(bdy_air, INIT_REF_NUM_BDY); // Initialize an H1 space with default shepeset. H1Space space(&mesh, bc_types, essential_bc_values, P_INIT); int ndof = get_num_dofs(&space); info("ndof = %d.", ndof); // Set initial condition. Solution tsln; tsln.set_const(&mesh, T_INIT); // Initialize weak formulation. WeakForm wf; wf.add_matrix_form(bilinear_form<double, double>, bilinear_form<Ord, Ord>); wf.add_matrix_form_surf(bilinear_form_surf<double, double>, bilinear_form_surf<Ord, Ord>, bdy_air); wf.add_vector_form(linear_form<double, double>, linear_form<Ord, Ord>, H2D_ANY, &tsln); wf.add_vector_form_surf(linear_form_surf<double, double>, linear_form_surf<Ord, Ord>, bdy_air); // Initialize the linear problem. LinearProblem lp(&wf, &space); // Initialize matrix solver. Matrix* mat; Vector* rhs; CommonSolver* solver; init_matrix_solver(matrix_solver, ndof, mat, rhs, solver); // Time stepping: int nsteps = (int)(FINAL_TIME/TAU + 0.5); bool rhsonly = false; for(int ts = 1; ts <= nsteps; ts++) { info("---- Time step %d, time %3.5f, ext_temp %g", ts, TIME, temp_ext(TIME)); // Assemble stiffness matrix and rhs. lp.assemble(mat, rhs, rhsonly); rhsonly = true; // Solve the matrix problem. if (!solver->solve(mat, rhs)) error ("Matrix solver failed.\n"); // Update tsln. tsln.set_fe_solution(&space, rhs); if (ts % OUTPUT_FREQUENCY == 0) { Linearizer lin; int item = H2D_FN_VAL_0; double eps = H2D_EPS_NORMAL; double max_abs = -1.0; MeshFunction* xdisp = NULL; MeshFunction* ydisp = NULL; double dmult = 1.0; lin.process_solution(&tsln, item, eps, max_abs, xdisp, ydisp, dmult); char* filename = new char[100]; sprintf(filename, "tsln_%d.lin", ts); // Save Linearizer data. lin.save_data(filename); info("Linearizer data saved to file %s.", filename); // Save complete Solution. sprintf(filename, "tsln_%d.dat", ts); bool compress = false; // Gzip compression not used as it only works on Linux. tsln.save(filename, compress); info("Complete Solution saved to file %s.", filename); } // Update the time variable. TIME += TAU; } info("Let's assume that the remote computation has finished and you fetched the *.lin files."); info("Visualizing Linearizer data from file tsln_40.lin."); // First use ScalarView to read and show the Linearizer data. WinGeom* win_geom_1 = new WinGeom(0, 0, 450, 600); ScalarView sview_1("Saved Linearizer data", win_geom_1); sview_1.lin.load_data("tsln_40.lin"); sview_1.set_min_max_range(0,20); sview_1.fix_scale_width(3); sview_1.show_linearizer_data(); info("Visualizing Solution from file tsln_60.dat."); Solution sln_from_file; sln_from_file.load("tsln_60.dat"); WinGeom* win_geom_2 = new WinGeom(460, 0, 450, 600); ScalarView sview_2("Saved Solution data", win_geom_2); sview_2.set_min_max_range(0,20); sview_2.fix_scale_width(3); sview_2.show(&sln_from_file); info("Visualizing Mesh and Orders extracted from the Solution."); int p_init = 1; // The NULLs are for bc_types() and essential_bc_values(). H1Space space_from_file(sln_from_file.get_mesh(), NULL, NULL, p_init); space_from_file.set_element_orders(sln_from_file.get_element_orders()); WinGeom* win_geom_3 = new WinGeom(920, 0, 450, 600); OrderView oview("Saved Solution -> Space", win_geom_3); oview.show(&space_from_file); // Wait for the view to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); // Perform initial mesh refinements. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Create an H1 space with default shapeset. H1Space space(&mesh, bc_types, essential_bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d", ndof); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(bilinear_form, bilinear_form_ord, HERMES_SYM); wf.add_vector_form(linear_form, linear_form_ord); wf.add_vector_form_surf(linear_form_surf, linear_form_surf_ord, BDY_VERTICAL); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); initialize_solution_environment(matrix_solver, argc, argv); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Initialize the solution. Solution sln; // Assemble the stiffness matrix and right-hand side vector. info("Assembling the stiffness matrix and right-hand side vector."); dp.assemble(matrix, rhs); // Solve the linear system and if successful, obtain the solution. info("Solving the matrix problem."); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Clean up. delete solver; delete matrix; delete rhs; finalize_solution_environment(matrix_solver); // View the solution and mesh. ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); sview.show(&sln); OrderView oview("Polynomial orders", new WinGeom(450, 0, 400, 350)); oview.show(&space); // Skip visualization time. cpu_time.tick(HERMES_SKIP); // Print timing information. verbose("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("square.mesh", &mesh); // Initial mesh refinements. for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(1, INIT_BDY_REF_NUM); // Create an H1 space with default shapeset. H1Space space(&mesh, bc_types, essential_bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d.", ndof); // Solution for the previous time level. Solution u_prev_time; // Initialize the weak formulation. WeakForm wf; if (TIME_INTEGRATION == 1) { wf.add_matrix_form(jac_euler, jac_ord, HERMES_UNSYM, HERMES_ANY, &u_prev_time); wf.add_vector_form(res_euler, res_ord, HERMES_ANY, &u_prev_time); } else { wf.add_matrix_form(jac_cranic, jac_ord, HERMES_UNSYM, HERMES_ANY, &u_prev_time); wf.add_vector_form(res_cranic, res_ord, HERMES_ANY, &u_prev_time); } // Project the function init_cond() on the FE space // to obtain initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[Space::get_num_dofs(&space)]; info("Projecting initial condition to obtain initial vector for the Newton's method."); OGProjection::project_global(&space, init_cond, coeff_vec, matrix_solver); Solution::vector_to_solution(coeff_vec, &space, &u_prev_time); // Initialize views. ScalarView sview("Solution", 0, 0, 500, 400); OrderView oview("Mesh", 520, 0, 450, 400); oview.show(&space); sview.show(&u_prev_time); // Time stepping loop: double current_time = 0.0; int t_step = 1; do { info("---- Time step %d, t = %g s.", t_step, current_time); t_step++; // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Perform Newton's iteration. int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(&space); // Assemble the Jacobian matrix and residual vector. dp.assemble(coeff_vec, matrix, rhs, false); // Multiply the residual vector with -1 since the matrix // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). for (int i = 0; i < ndof; i++) rhs->set(i, -rhs->get(i)); // Calculate the l2-norm of residual vector. double res_l2_norm = get_l2_norm(rhs); // Info for user. info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(&space), res_l2_norm); // If l2 norm of the residual vector is within tolerance, or the maximum number // of iteration has been reached, then quit. if (res_l2_norm < NEWTON_TOL || it > NEWTON_MAX_ITER) break; // Solve the linear system. if(!solver->solve()) error ("Matrix solver failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof; i++) coeff_vec[i] += solver->get_solution()[i]; if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); it++; } // Translate the resulting coefficient vector into the Solution sln. Solution::vector_to_solution(coeff_vec, &space, &u_prev_time); // Cleanup. delete matrix; delete rhs; delete solver; // Update time. current_time += TAU; // Show the new time level solution. char title[100]; sprintf(title, "Solution, t = %g", current_time); sview.set_title(title); sview.show(&u_prev_time); } while (current_time < T_FINAL); delete [] coeff_vec; // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // load the mesh Mesh mesh; H2DReader mloader; mloader.load("square_quad.mesh", &mesh); // initial mesh refinement for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // initialize the shapeset and the cache H1Shapeset shapeset; PrecalcShapeset pss(&shapeset); // create finite element space H1Space space(&mesh, &shapeset); space.set_bc_types(bc_types); space.set_bc_values(bc_values); space.set_uniform_order(P_INIT); // enumerate basis functions space.assign_dofs(); // initialize the weak formulation WeakForm wf(1); wf.add_biform(0, 0, callback(bilinear_form), SYM); wf.add_liform(0, linear_form, linear_form_ord); // visualize solution and mesh ScalarView sview("Coarse solution", 0, 100, 798, 700); OrderView oview("Polynomial orders", 800, 100, 798, 700); // matrix solver UmfpackSolver solver; // prepare selector RefinementSelectors::H1UniformHP selector(ISO_ONLY, ADAPT_TYPE, 1.0, H2DRS_DEFAULT_ORDER, &shapeset); // DOF and CPU convergence graphs SimpleGraph graph_dof_est, graph_dof_exact, graph_cpu_est, graph_cpu_exact; // adaptivity loop int it = 1, ndofs; bool done = false; double cpu = 0.0; Solution sln_coarse, sln_fine; do { info("\n---- Adaptivity step %d ---------------------------------------------\n", it++); // time measurement begin_time(); // solve the coarse mesh problem LinSystem ls(&wf, &solver); ls.set_spaces(1, &space); ls.set_pss(1, &pss); ls.assemble(); ls.solve(1, &sln_coarse); // time measurement cpu += end_time(); // calculate error wrt. exact solution ExactSolution exact(&mesh, fndd); double error = h1_error(&sln_coarse, &exact) * 100; info("\nExact solution error: %g%%", error); // view the solution sview.show(&sln_coarse); oview.show(&space); // time measurement begin_time(); // solve the fine mesh problem RefSystem rs(&ls); rs.assemble(); rs.solve(1, &sln_fine); // calculate error estimate wrt. fine mesh solution H1AdaptHP hp(1, &space); double err_est = hp.calc_error(&sln_coarse, &sln_fine) * 100; info("Estimate of error: %g%%", err_est); // add entries to DOF convergence graphs graph_dof_exact.add_values(space.get_num_dofs(), error); graph_dof_exact.save("conv_dof_exact.dat"); graph_dof_est.add_values(space.get_num_dofs(), err_est); graph_dof_est.save("conv_dof_est.dat"); // add entries to CPU convergence graphs graph_cpu_exact.add_values(cpu, error); graph_cpu_exact.save("conv_cpu_exact.dat"); graph_cpu_est.add_values(cpu, err_est); graph_cpu_est.save("conv_cpu_est.dat"); // if err_est too large, adapt the mesh if (err_est < ERR_STOP) done = true; else { hp.adapt(THRESHOLD, STRATEGY, &selector, MESH_REGULARITY); ndofs = space.assign_dofs(); if (ndofs >= NDOF_STOP) done = true; } // time measurement cpu += end_time(); //sview.wait_for_keypress(); } while (done == false); verbose("Total running time: %g sec", cpu); // show the fine solution - this is the final result sview.set_title("Final solution"); sview.show(&sln_fine); // wait for keyboard or mouse input View::wait(); return 0; }
int main(int argc, char* args[]) { // Load the mesh. MeshSharedPtr mesh(new Mesh); MeshReaderH2D mloader; mloader.load("square.mesh", mesh); // Perform initial mesh refinement. for (int i=0; i<INIT_REF; i++) mesh->refine_all_elements(); // Create an L2 space-> SpaceSharedPtr<double> space(new L2Space<double>(mesh, P_INIT)); // Initialize refinement selector. L2ProjBasedSelector<double> selector(CAND_LIST); // Display the mesh. #ifdef SHOW_OUTPUT OrderView oview("Coarse mesh", new WinGeom(0, 0, 440, 350)); oview.show(space); #endif MeshFunctionSharedPtr<double> sln(new Solution<double>); MeshFunctionSharedPtr<double> ref_sln(new Solution<double>); // Initialize the weak formulation. CustomWeakForm wf("Bdy_bottom_left", mesh); #ifdef SHOW_OUTPUT ScalarView view1("Solution", new WinGeom(900, 0, 450, 350)); view1.fix_scale_width(60); #endif // Initialize linear solver. Hermes::Hermes2D::LinearSolver<double> linear_solver(&wf, space); int as = 1; bool done = false; do { // Construct globally refined reference mesh // and setup reference space-> Mesh::ReferenceMeshCreator ref_mesh_creator(mesh); MeshSharedPtr ref_mesh = ref_mesh_creator.create_ref_mesh(); Space<double>::ReferenceSpaceCreator ref_space_creator(space, ref_mesh); SpaceSharedPtr<double> ref_space = ref_space_creator.create_ref_space(); ref_space->save("space-real.xml"); ref_space->free(); ref_space->load("space-real.xml"); #ifdef WITH_BSON ref_space->save_bson("space-real.bson"); ref_space->free(); ref_space->load_bson("space-real.bson"); #endif linear_solver.set_space(ref_space); // Solve the linear system. If successful, obtain the solution. linear_solver.solve(); Solution<double>::vector_to_solution(linear_solver.get_sln_vector(), ref_space, ref_sln); // Project the fine mesh solution onto the coarse mesh. OGProjection<double> ogProjection; ogProjection.project_global(space, ref_sln, sln, HERMES_L2_NORM); #ifdef SHOW_OUTPUT MeshFunctionSharedPtr<double> val_filter(new ValFilter(ref_sln, 0.0, 1.0)); // View the coarse mesh solution. view1.show(val_filter); oview.show(space); #endif // Calculate element errors and total error estimate. errorCalculator.calculate_errors(sln, ref_sln); double err_est_rel = errorCalculator.get_total_error_squared() * 100; adaptivity.set_space(space); #ifdef SHOW_OUTPUT std::cout << "Error: " << err_est_rel << "%." << std::endl; #endif // If err_est_rel too large, adapt the mesh-> if(err_est_rel < ERR_STOP) done = true; else done = adaptivity.adapt(&selector); as++; } while (done == false); // Wait for keyboard or mouse input. #ifdef SHOW_OUTPUT View::wait(); #endif return as; }
int main(int argc, char* argv[]) { // Load the mesh. MeshSharedPtr mesh(new Mesh); MeshReaderH2D mloader; mloader.load("domain.mesh", mesh); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); // Initialize boundary conditions. Hermes::Hermes2D::DefaultEssentialBCConst<complex> bc_essential("Dirichlet", complex(0.0, 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(); // Initialize the weak formulation. CustomWeakForm wf("Air", MU_0, "Iron", MU_IRON, GAMMA_IRON, "Wire", MU_0, complex(J_EXT, 0.0), OMEGA); // Initialize coarse and reference mesh solution. MeshFunctionSharedPtr<complex> sln(new Hermes::Hermes2D::Solution<complex>()); MeshFunctionSharedPtr<complex> ref_sln(new Hermes::Hermes2D::Solution<complex>()); // Initialize refinement selector. H1ProjBasedSelector<complex> selector(CAND_LIST); // Initialize views. #ifdef SHOW_OUTPUT Views::ScalarView sview("Solution", new Views::WinGeom(0, 0, 600, 350)); Views::ScalarView sview2("Ref. Solution", new Views::WinGeom(0, 0, 600, 350)); Views::OrderView oview("Polynomial orders", new Views::WinGeom(610, 0, 520, 350)); #endif DiscreteProblem<complex> dp(&wf, space); // Perform Newton's iteration and translate the resulting coefficient vector into a Solution. Hermes::Hermes2D::NewtonSolver<complex> newton(&dp); // Adaptivity loop: int as = 1; bool done = false; adaptivity.set_space(space); do { // Construct globally refined reference mesh and setup reference space-> Mesh::ReferenceMeshCreator ref_mesh_creator(mesh); MeshSharedPtr ref_mesh = ref_mesh_creator.create_ref_mesh(); Space<complex>::ReferenceSpaceCreator ref_space_creator(space, ref_mesh); SpaceSharedPtr<complex> ref_space = ref_space_creator.create_ref_space(); newton.set_space(ref_space); ref_space->save("space-complex.xml"); ref_space->free(); ref_space->load("space-complex.xml"); #ifdef WITH_BSON ref_space->save_bson("space-complex.bson"); ref_space->free(); ref_space->load_bson("space-complex.bson"); #endif int ndof_ref = ref_space->get_num_dofs(); // Initialize reference problem. // Initial coefficient vector for the Newton's method. complex* coeff_vec = new complex[ndof_ref]; memset(coeff_vec, 0, ndof_ref * sizeof(complex)); // Perform Newton's iteration and translate the resulting coefficient vector into a Solution. SpaceSharedPtr<complex> space_test = Space<complex>::load("space-complex.xml", ref_mesh, false, &bcs); newton.set_space(space_test); newton.solve(coeff_vec); 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; #ifdef WITH_BSON space->save_bson("space-complex-coarse.bson"); SpaceSharedPtr<complex> space_test2 = Space<complex>::load_bson("space-complex-coarse.bson", mesh, &bcs); ogProjection.project_global(space_test2, ref_sln, sln); #else space->save("space-complex-coarse.xml2"); SpaceSharedPtr<complex> space_test2 = Space<complex>::load("space-complex-coarse.xml2", mesh, false, &bcs); ogProjection.project_global(space_test2, ref_sln, sln); #endif // View the coarse mesh solution and polynomial orders. #ifdef SHOW_OUTPUT MeshFunctionSharedPtr<double> real_filter(new RealFilter(sln)); MeshFunctionSharedPtr<double> rreal_filter(new RealFilter(ref_sln)); sview2.show(rreal_filter); oview.show(space); #endif // Calculate element errors and total error estimate. errorCalculator.calculate_errors(sln, ref_sln); #ifdef SHOW_OUTPUT std::cout << "Relative error: " << errorCalculator.get_total_error_squared() * 100. << '%' << std::endl; #endif // Add entry to DOF and CPU convergence graphs. #ifdef SHOW_OUTPUT sview.show(errorCalculator.get_errorMeshFunction()); #endif // If err_est too large, adapt the mesh-> if(errorCalculator.get_total_error_squared() * 100. < ERR_STOP) done = true; else { std::cout << "Adapting..." << std::endl << std::endl; adaptivity.adapt(&selector); } // Clean up. delete [] coeff_vec; // Increase counter. as++; } while (done == false); #ifdef SHOW_OUTPUT // Show the reference solution - the final result. sview.set_title("Fine mesh solution"); MeshFunctionSharedPtr<double> real_filter(new RealFilter(ref_sln)); sview.show(real_filter); // Wait for all views to be closed. Views::View::wait(); #endif return as; }
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; }
// Main function. int main(int argc, char* argv[]) { ConstitutiveRelationsGenuchtenWithLayer constitutive_relations(CONSTITUTIVE_TABLE_METHOD, NUM_OF_INSIDE_PTS, LOW_LIMIT, TABLE_PRECISION, TABLE_LIMIT, K_S_vals, ALPHA_vals, N_vals, M_vals, THETA_R_vals, THETA_S_vals, STORATIVITY_vals); // Either use exact constitutive relations (slow) (method 0) or precalculate // their linear approximations (faster) (method 1) or // precalculate their quintic polynomial approximations (method 2) -- managed by // the following loop "Initializing polynomial approximation". if (CONSTITUTIVE_TABLE_METHOD == 1) constitutive_relations.constitutive_tables_ready = get_constitutive_tables(1, &constitutive_relations, MATERIAL_COUNT); // 1 stands for the Newton's method. // The van Genuchten + Mualem K(h) function is approximated by polynomials close // to zero in case of CONSTITUTIVE_TABLE_METHOD==1. // In case of CONSTITUTIVE_TABLE_METHOD==2, all constitutive functions are approximated by polynomials. info("Initializing polynomial approximations."); for (int i=0; i < MATERIAL_COUNT; i++) { // Points to be used for polynomial approximation of K(h). double* points = new double[NUM_OF_INSIDE_PTS]; init_polynomials(6 + NUM_OF_INSIDE_PTS, LOW_LIMIT, points, NUM_OF_INSIDE_PTS, i, &constitutive_relations, MATERIAL_COUNT, NUM_OF_INTERVALS, INTERVALS_4_APPROX); } constitutive_relations.polynomials_ready = true; if (CONSTITUTIVE_TABLE_METHOD == 2) { constitutive_relations.constitutive_tables_ready = true; //Assign table limit to global definition. constitutive_relations.table_limit = INTERVALS_4_APPROX[NUM_OF_INTERVALS-1]; } // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); if (bt.is_explicit()) info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Load the mesh. Mesh mesh, basemesh; MeshReaderH2D mloader; mloader.load(mesh_file, &basemesh); // Perform initial mesh refinements. mesh.copy(&basemesh); for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary("Top", INIT_REF_NUM_BDY_TOP); // Initialize boundary conditions. RichardsEssentialBC bc_essential("Top", H_ELEVATION, PULSE_END_TIME, H_INIT, STARTUP_TIME); 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(); info("ndof = %d.", ndof); // Convert initial condition into a Solution. ZeroSolution h_time_prev(&mesh), h_time_new(&mesh), time_error_fn(&mesh); // Initialize views. ScalarView view("Initial condition", new WinGeom(0, 0, 600, 500)); view.fix_scale_width(80); // Visualize the initial condition. view.show(&h_time_prev); // Initialize the weak formulation. CustomWeakFormRichardsRK wf(&constitutive_relations); // Visualize the projection and mesh. ScalarView sview("Initial condition", new WinGeom(0, 0, 400, 350)); sview.fix_scale_width(50); sview.show(&h_time_prev, HERMES_EPS_VERYHIGH); ScalarView eview("Temporal error", new WinGeom(405, 0, 400, 350)); eview.fix_scale_width(50); eview.show(&time_error_fn, HERMES_EPS_VERYHIGH); OrderView oview("Initial mesh", new WinGeom(810, 0, 350, 350)); oview.show(&space); // Graph for time step history. SimpleGraph time_step_graph; info("Time step history will be saved to file time_step_history.dat."); // Initialize Runge-Kutta time stepping. RungeKutta<double> runge_kutta(&wf, &space, &bt, matrix_solver); // Time stepping: double current_time = 0; int ts = 1; do { info("---- Time step %d, time %3.5f s", ts, current_time); Space<double>::update_essential_bc_values(&space, current_time); // Perform one Runge-Kutta time step according to the selected Butcher's table. info("Runge-Kutta time step (t = %g s, time step = %g s, stages: %d).", current_time, time_step, bt.get_size()); bool freeze_jacobian = false; bool block_diagonal_jacobian = false; bool verbose = true; double damping_coeff = 1.0; double max_allowed_residual_norm = 1e10; try { runge_kutta.rk_time_step_newton(current_time, time_step, &h_time_prev, &h_time_new, &time_error_fn, freeze_jacobian, block_diagonal_jacobian, verbose, NEWTON_TOL, NEWTON_MAX_ITER, damping_coeff, max_allowed_residual_norm); } catch(Exceptions::Exception& e) { info("Runge-Kutta time step failed, decreasing time step size from %g to %g days.", time_step, time_step * time_step_dec); time_step *= time_step_dec; if (time_step < time_step_min) error("Time step became too small."); continue; } // Copy solution for the new time step. h_time_prev.copy(&h_time_new); // Show error function. char title[100]; sprintf(title, "Temporal error, t = %g", current_time); eview.set_title(title); eview.show(&time_error_fn, HERMES_EPS_VERYHIGH); // Calculate relative time stepping error and decide whether the // time step can be accepted. If not, then the time step size is // reduced and the entire time step repeated. If yes, then another // check is run, and if the relative error is very low, time step // is increased. double rel_err_time = Global<double>::calc_norm(&time_error_fn, HERMES_H1_NORM) / Global<double>::calc_norm(&h_time_new, HERMES_H1_NORM) * 100; info("rel_err_time = %g%%", rel_err_time); if (rel_err_time > time_tol_upper) { info("rel_err_time above upper limit %g%% -> decreasing time step from %g to %g days and repeating time step.", time_tol_upper, time_step, time_step * time_step_dec); time_step *= time_step_dec; continue; } if (rel_err_time < time_tol_lower) { info("rel_err_time = below lower limit %g%% -> increasing time step from %g to %g days", time_tol_lower, time_step, time_step * time_step_inc); time_step *= time_step_inc; } // Add entry to the timestep graph. time_step_graph.add_values(current_time, time_step); time_step_graph.save("time_step_history.dat"); // Update time. current_time += time_step; // Show the new time level solution. sprintf(title, "Solution, t = %g", current_time); sview.set_title(title); sview.show(&h_time_new, HERMES_EPS_VERYHIGH); oview.show(&space); // Save complete Solution. char filename[100]; sprintf(filename, "outputs/tsln_%f.dat", current_time); h_time_new.save(filename); info("Solution at time %g saved to file %s.", current_time, filename); // Save solution for the next time step. h_time_prev.copy(&h_time_new); // Increase time step counter. ts++; } while (current_time < T_FINAL); // Wait for the view to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); mesh.refine_all_elements(); // Initialize the shapeset and the cache H1Shapeset shapeset; PrecalcShapeset pss(&shapeset); // Create finite element space H1Space space(&mesh, &shapeset); space.set_bc_types(bc_types); space.set_bc_values(bc_values); space.set_uniform_order(P_INIT); // Enumerate basis functions space.assign_dofs(); // initialize the weak formulation WeakForm wf(1); wf.add_biform(0, 0, bilinear_form, bilinear_form_ord, SYM); wf.add_liform(0, linear_form, linear_form_ord); wf.add_liform_surf(0, linear_form_surf, linear_form_surf_ord, 2); // Visualize solution and mesh ScalarView sview("Coarse solution", 0, 100, 798, 700); OrderView oview("Polynomial orders", 800, 100, 798, 700); // Matrix solver UmfpackSolver solver; // DOF and CPU convergence graphs SimpleGraph graph_dof, graph_cpu; // Adaptivity loop int it = 1, ndofs; bool done = false; double cpu = 0.0; Solution sln_coarse, sln_fine; do { info("\n---- Adaptivity step %d ---------------------------------------------\n", it++); // Time measurement begin_time(); // Solve the coarse mesh problem LinSystem ls(&wf, &solver); ls.set_spaces(1, &space); ls.set_pss(1, &pss); ls.assemble(); ls.solve(1, &sln_coarse); // Time measurement cpu += end_time(); // View the solution and mesh sview.show(&sln_coarse); oview.show(&space); // Time measurement begin_time(); // Solve the fine mesh problem RefSystem rs(&ls); rs.assemble(); rs.solve(1, &sln_fine); // Calculate error estimate wrt. fine mesh solution H1OrthoHP hp(1, &space); double err_est = hp.calc_error(&sln_coarse, &sln_fine) * 100; info("Estimate of error: %g%%", err_est); // add entry to DOF convergence graph graph_dof.add_values(space.get_num_dofs(), err_est); graph_dof.save("conv_dof.dat"); // add entry to CPU convergence graph graph_cpu.add_values(cpu, err_est); graph_cpu.save("conv_cpu.dat"); // If err_est too large, adapt the mesh if (err_est < ERR_STOP) done = true; else { hp.adapt(THRESHOLD, STRATEGY, ADAPT_TYPE, ISO_ONLY, MESH_REGULARITY); ndofs = space.assign_dofs(); if (ndofs >= NDOF_STOP) done = true; } // Time measurement cpu += end_time(); } while (done == false); verbose("Total running time: %g sec", cpu); // Show the fine solution - this is the final result sview.set_title("Final solution"); sview.show(&sln_fine); // Wait for keyboard or mouse input View::wait("Waiting for all views to be closed."); return 0; }
int main(int argc, char* argv[]) { // load the mesh Mesh mesh; H2DReader mloader; mloader.load("square_quad.mesh", &mesh); // mloader.load("square_tri.mesh", &mesh); for (int i=0; i<INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(2, INIT_REF_NUM_BDY); // initialize the shapeset and the cache H1Shapeset shapeset; PrecalcShapeset pss(&shapeset); // create finite element space H1Space space(&mesh, &shapeset); space.set_bc_types(bc_types); space.set_bc_values(bc_values); space.set_uniform_order(P_INIT); // enumerate basis functions space.assign_dofs(); // initialize the weak formulation WeakForm wf(1); wf.add_biform(0, 0, callback(bilinear_form)); if (STABILIZATION_ON == true) { wf.add_biform(0, 0, bilinear_form_stabilization, bilinear_form_stabilization_order); } if (SHOCK_CAPTURING_ON == true) { wf.add_biform(0, 0, bilinear_form_shock_capturing, bilinear_form_shock_capturing_order); } // visualize solution and mesh OrderView oview("Coarse mesh", 0, 0, 500, 400); ScalarView sview("Coarse mesh solution", 510, 0, 500, 400); ScalarView sview2("Fine mesh solution", 1020, 0, 500, 400); // matrix solver UmfpackSolver solver; // DOF convergence graph SimpleGraph graph_dof_est, graph_cpu_est; // prepare selector RefinementSelectors::H1NonUniformHP selector(ISO_ONLY, ADAPT_TYPE, CONV_EXP, H2DRS_DEFAULT_ORDER, &shapeset); // adaptivity loop int it = 1, ndofs; bool done = false; double cpu = 0.0; Solution sln_coarse, sln_fine; do { info("\n---- Adaptivity step %d ---------------------------------------------\n", it++); // time measurement begin_time(); // solve the coarse mesh problem LinSystem ls(&wf, &solver); ls.set_spaces(1, &space); ls.set_pss(1, &pss); ls.assemble(); ls.solve(1, &sln_coarse); // solve the fine mesh problem int p_increase; if (ADAPT_TYPE == RefinementSelectors::H2DRS_CAND_HP) p_increase = 1; else p_increase = 0; RefSystem rs(&ls, p_increase, 1); // the '1' is for one level of global refinement in space rs.assemble(); rs.solve(1, &sln_fine); // time measurement cpu += end_time(); // show fine mesh solution // view the solution and mesh oview.show(&space); sview.show(&sln_coarse); sview2.show(&sln_fine); //sview.wait_for_keypress(); // time measurement begin_time(); // calculate error estimate wrt. fine mesh solution H1AdaptHP hp(1, &space); double err_est = hp.calc_error(&sln_coarse, &sln_fine) * 100; info("Estimate of error: %g%%", err_est); // add entries to DOF and CPU convergence graphs graph_dof_est.add_values(space.get_num_dofs(), err_est); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu, err_est); graph_cpu_est.save("conv_cpu_est.dat"); // if err_est too large, adapt the mesh if (err_est < ERR_STOP) done = true; else { hp.adapt(THRESHOLD, STRATEGY, &selector, MESH_REGULARITY); ndofs = space.assign_dofs(); if (ndofs >= NDOF_STOP) done = true; } // time measurement cpu += end_time(); } while (done == false); verbose("Total running time: %g sec", cpu); // show the fine solution - this is the final result sview.set_title("Final solution"); sview.show(&sln_fine); // wait for keyboard or mouse input View::wait(); return 0; }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // Load the mesh. Mesh mesh; H2DReader 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 bc_essential(Hermes::vector<std::string>("right", "top"), 0.0); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space 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 wf(regions, D_map, Sigma_a_map, Sources_map); // Initialize coarse and reference mesh solution. Solution sln, ref_sln; // Initialize refinement selector. H1ProjBasedSelector 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. TimePeriod cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = Space::construct_refined_space(&space); int ndof_ref = Space::get_num_dofs(ref_space); // Initialize the FE problem. DiscreteProblem dp(&wf, ref_space); // Initialize the FE problem. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof_ref]; memset(coeff_vec, 0, ndof_ref*sizeof(scalar)); // Perform Newton's iteration on reference emesh. info("Solving on reference mesh."); if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution::vector_to_solution(coeff_vec, ref_space, &ref_sln); // Project the fine mesh solution onto the coarse mesh. Solution sln; info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // 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_SKIP); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt* adaptivity = new Adapt(&space); double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space::get_num_dofs(&space), Space::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::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 { 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(&space) >= NDOF_STOP) done = true; // Clean up. delete [] coeff_vec; delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) delete ref_space->get_mesh(); delete ref_space; } while (done == false); verbose("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; }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); // Perform initial mesh refinements. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions CustomEssentialBCNonConst bc_essential("Boundary horizontal"); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the weak formulation. CustomWeakFormGeneral wf("Boundary horizontal"); // Initialize the FE problem. DiscreteProblem dp(&wf, &space); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof]; memset(coeff_vec, 0, ndof*sizeof(scalar)); // Perform Newton's iteration. if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution sln; Solution::vector_to_solution(coeff_vec, &space, &sln); // Time measurement. cpu_time.tick(); // Clean up. delete solver; delete matrix; delete rhs; delete [] coeff_vec; // View the solution and mesh. ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); sview.show(&sln); OrderView oview("Polynomial orders", new WinGeom(450, 0, 400, 350)); oview.show(&space); // Skip visualization time. cpu_time.tick(HERMES_SKIP); // Print timing information. verbose("Total running time: %g s", cpu_time.accumulated()); // 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. Mesh mesh; if (USE_XML_FORMAT == true) { MeshReaderH2DXML mloader; Hermes::Mixins::Loggable::Static::info("Reading mesh in XML format."); mloader.load("domain.xml", &mesh); } else { MeshReaderH2D mloader; Hermes::Mixins::Loggable::Static::info("Reading mesh in original format."); mloader.load("domain.mesh", &mesh); } // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions CustomEssentialBCNonConst bc_essential("Horizontal"); 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(); Hermes::Mixins::Loggable::Static::info("ndof = %d", ndof); // Initialize the weak formulation. CustomWeakFormGeneral wf("Horizontal"); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, &space); // Initialize Newton solver. NewtonSolver<double> newton(&dp); // Perform Newton's iteration. try { newton.solve(); } catch(std::exception& e) { std::cout << e.what(); } // Translate the resulting coefficient vector into a Solution. Solution<double> sln; Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln); // Time measurement. cpu_time.tick(); // View the solution and mesh. ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); sview.show(&sln); OrderView oview("Polynomial orders", new WinGeom(450, 0, 405, 350)); oview.show(&space); // Print timing information. Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // load the mesh file Mesh mesh; H2DReader mloader; mloader.load("square.mesh", &mesh); // initial mesh refinements for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(1,INIT_BDY_REF_NUM); // initialize the shapeset and the cache H1Shapeset shapeset; PrecalcShapeset pss(&shapeset); // create an H1 space H1Space space(&mesh, &shapeset); space.set_bc_types(bc_types); space.set_bc_values(bc_values); space.set_uniform_order(P_INIT); space.assign_dofs(); // previous solution for the Newton's iteration Solution u_prev; // initialize the weak formulation WeakForm wf(1); wf.add_biform(0, 0, callback(jac), UNSYM, ANY, 1, &u_prev); wf.add_liform(0, callback(res), ANY, 1, &u_prev); // initialize the nonlinear system and solver UmfpackSolver umfpack; NonlinSystem nls(&wf, &umfpack); nls.set_spaces(1, &space); nls.set_pss(1, &pss); // DOF and CPU convergence graphs SimpleGraph graph_dof, graph_cpu; // project the function init_cond() on the mesh // to obtain initial guess u_prev for the Newton's method nls.set_ic(init_cond, &mesh, &u_prev, PROJ_TYPE); // visualise the initial ocndition ScalarView view("Initial condition", 0, 0, 700, 600); view.show(&u_prev); OrderView oview("Initial mesh", 720, 0, 700, 600); oview.show(&space); //printf("Click into the image window and press any key to proceed.\n"); //view.wait_for_keypress(); // adaptivity loop double cpu = 0.0, err_est; int a_step = 1; bool done = false; do { a_step++; // Newton's loop on the coarse mesh int it = 1; double res_l2_norm; Solution sln_coarse; do { info("\n---- Adapt step %d, Newton iter %d (coarse mesh) ---------------------------------\n", a_step, it++); printf("ndof = %d\n", space.get_num_dofs()); // time measurement begin_time(); // assemble the Jacobian matrix and residual vector, // solve the system nls.assemble(); nls.solve(1, &sln_coarse); // calculate the l2-norm of residual vector res_l2_norm = nls.get_residuum_l2_norm(); info("Residuum L2 norm: %g\n", res_l2_norm); // time measurement cpu += end_time(); // visualise the solution char title[100]; sprintf(title, "Temperature (coarse mesh), Newton iteration %d", it-1); view.set_title(title); view.show(&sln_coarse); sprintf(title, "Coarse mesh, Newton iteration %d", it-1); oview.set_title(title); oview.show(&space); //printf("Click into the image window and press any key to proceed.\n"); //view.wait_for_keypress(); // save the new solution as "previous" for the // next Newton's iteration u_prev.copy(&sln_coarse); } while (res_l2_norm > NEWTON_TOL); // Setting initial guess for the Newton's method on the fine mesh Solution sln_fine, u_prev_fine; RefNonlinSystem rs(&nls); rs.prepare(); rs.set_ic(&u_prev, &u_prev); // Newton's loop on the fine mesh it = 1; do { info("\n---- Adapt step %d, Newton iter %d (fine mesh) ---------------------------------\n", a_step, it++); // time measurement begin_time(); // assemble the Jacobian matrix and residual vector, // solve the system rs.assemble(); rs.solve(1, &sln_fine); // calculate the l2-norm of residual vector res_l2_norm = rs.get_residuum_l2_norm(); info("Residuum L2 norm: %g\n", res_l2_norm); // time measurement cpu += end_time(); // visualise the solution char title[100]; sprintf(title, "Temperature (fine mesh), Newton iteration %d", it-1); view.set_title(title); view.show(&sln_fine); sprintf(title, "Fine mesh, Newton iteration %d", it-1); oview.set_title(title); oview.show(rs.get_ref_space(0)); //printf("Click into the image window and press any key to proceed.\n"); //view.wait_for_keypress(); u_prev.copy(&sln_fine); } while (res_l2_norm > NEWTON_TOL_REF); // time measurement begin_time(); // calculate element errors and total error estimate H1OrthoHP hp(1, &space); err_est = hp.calc_error(&sln_coarse, &sln_fine) * 100; info("Error estimate: %g%%", err_est); // add entry to DOF convergence graph graph_dof.add_values(space.get_num_dofs(), err_est); graph_dof.save("conv_dof.dat"); // add entry to CPU convergence graph graph_cpu.add_values(cpu, err_est); graph_cpu.save("conv_cpu.dat"); // if err_est too large, adapt the mesh if (err_est < ERR_STOP) done = true; else { hp.adapt(THRESHOLD, STRATEGY, ADAPT_TYPE, ISO_ONLY, MESH_REGULARITY); int ndof = space.assign_dofs(); if (ndof >= NDOF_STOP) done = true; } // time measurement cpu += end_time(); } while (!done); verbose("Total running time: %g sec", cpu); // wait for keyboard or mouse input View::wait(); return 0; }
int main(int argc, char* argv[]) { // Define problem parameters: (x_loc, y_loc) is the center of the circular wave front, R_ZERO is the distance from the // wave front to the center of the circle, and alpha gives the steepness of the wave front. double alpha, x_loc, y_loc, r_zero; switch(PARAM) { case 0: alpha = 20; x_loc = -0.05; y_loc = -0.05; r_zero = 0.7; break; case 1: alpha = 1000; x_loc = -0.05; y_loc = -0.05; r_zero = 0.7; break; case 2: alpha = 1000; x_loc = 1.5; y_loc = 0.25; r_zero = 0.92; break; case 3: alpha = 50; x_loc = 0.5; y_loc = 0.5; r_zero = 0.25; break; default: // The same as 0. alpha = 20; x_loc = -0.05; y_loc = -0.05; r_zero = 0.7; break; } // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("square_quad.mesh", &mesh); // quadrilaterals // mloader.load("square_tri.mesh", &mesh); // triangles // Perform initial mesh refinement. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Set exact solution. CustomExactSolution exact(&mesh, alpha, x_loc, y_loc, r_zero); // Define right-hand side. CustomRightHandSide rhs(alpha, x_loc, y_loc, r_zero); // Initialize the weak formulation. CustomWeakForm wf(&rhs); // Equivalent, but slower: // DefaultWeakFormPoisson<double> wf(Hermes::HERMES_ANY, HERMES_ONE, &rhs); // Initialize boundary conditions. DefaultEssentialBCNonConst<double> bc("Bdy", &exact); EssentialBCs<double> bcs(&bc); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); // Initialize approximate solution. Solution<double> sln; // Initialize views. Views::ScalarView<double> sview("Solution", new Views::WinGeom(0, 0, 440, 350)); sview.show_mesh(false); sview.fix_scale_width(50); Views::OrderView<double> oview("Polynomial orders", new Views::WinGeom(450, 0, 420, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof, graph_cpu, graph_dof_exact, graph_cpu_exact; // Time measurement. Hermes::TimePeriod cpu_time; // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d (%d DOF):", as, space.get_num_dofs()); cpu_time.tick(); // Assemble the discrete problem. DiscreteProblem<double> dp(&wf, &space); // Initial coefficient vector for the Newton's method. int ndof = space.get_num_dofs(); double* coeff_vec = new double[ndof]; memset(coeff_vec, 0, ndof * sizeof(double)); NewtonSolver<double> newton(&dp, matrix_solver_type); newton.set_verbose_output(false); if (!newton.solve(coeff_vec)) error("Newton's iteration failed."); else Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln); cpu_time.tick(); verbose("Solution: %g s", cpu_time.last()); // Calculate element errors and total error estimate. BasicKellyAdapt<double> adaptivity(&space); if (USE_ENERGY_NORM_NORMALIZATION) adaptivity.set_error_form(new EnergyErrorForm(&wf)); if (USE_RESIDUAL_ESTIMATOR) adaptivity.add_error_estimator_vol(new ResidualErrorForm(&rhs)); double err_est_rel = adaptivity.calc_err_est(&sln) * 100; double err_exact_rel = Global<double>::calc_rel_error(&sln, &exact, HERMES_H1_NORM) * 100; cpu_time.tick(); verbose("Error calculation: %g s", cpu_time.last()); info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel); if (TEST_ELEMENT_BASED_KELLY) { cpu_time.tick(); // Ensure that the two possible approaches to interface error estimators accumulation give same results. KellyTypeAdapt<double> adaptivity2(&space, false); adaptivity2.disable_aposteriori_interface_scaling(); adaptivity2.add_error_estimator_surf(new InterfaceErrorForm); if (USE_ENERGY_NORM_NORMALIZATION) adaptivity2.set_error_form(new EnergyErrorForm(&wf)); if (USE_RESIDUAL_ESTIMATOR) { adaptivity2.add_error_estimator_vol(new ResidualErrorForm(&rhs)); adaptivity2.set_volumetric_scaling_const(1./24.); } double err_est_rel2 = adaptivity2.calc_err_est(&sln) * 100; double err_exact_rel2 = adaptivity2.calc_err_exact(&sln, &exact, false) * 100; info("err_est_rel_2: %g%%, err_exact_rel_2: %g%%", err_est_rel2, err_exact_rel2); if (fabs(err_est_rel2 - err_est_rel) >= 1e-13 || fabs(err_exact_rel2 - err_exact_rel) >= 1e-13) { info("err_est_rel diff: %1.15g, err_exact_rel diff: %1.15g", std::abs(err_est_rel2 - err_est_rel), std::abs(err_exact_rel2 - err_exact_rel)); err_est_rel = err_exact_rel = 0; // Exit the adaptivity loop. } cpu_time.tick(Hermes::HERMES_SKIP); } // Report results. cpu_time.tick(); double accum_time = cpu_time.accumulated(); // View the approximate solution and polynomial orders. sview.show(&sln); oview.show(&space); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(space.get_num_dofs(), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(accum_time, err_est_rel); graph_cpu.save("conv_cpu_est.dat"); graph_dof_exact.add_values(space.get_num_dofs(), err_exact_rel); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(accum_time, err_exact_rel); graph_cpu_exact.save("conv_cpu_exact.dat"); cpu_time.tick(Hermes::HERMES_SKIP); // If err_est too large, adapt the mesh. The NDOF test must be here, so that the solution may be visualized // after ending due to this criterion. if (err_exact_rel < ERR_STOP || space.get_num_dofs() >= NDOF_STOP) done = true; else done = adaptivity.adapt(THRESHOLD, STRATEGY, MESH_REGULARITY); cpu_time.tick(); verbose("Adaptation: %g s", cpu_time.last()); // Increase the counter of performed adaptivity steps. if (done == false) as++; /* else { sview.show(&sln); oview.show(&space); info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel); } */ // Clean up. delete [] coeff_vec; } while (done == false); cpu_time.tick(); verbose("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. Views::View::wait(); return 0; }
int main(int argc, char* argv[]) { // load the mesh Mesh mesh; mesh.load("square_quad.mesh"); if(P_INIT == 1) mesh.refine_all_elements(); // this is because there are no degrees of freedom // on the coarse mesh lshape.mesh if P_INIT == 1 // initialize the shapeset and the cache H1ShapesetOrtho shapeset; PrecalcShapeset pss(&shapeset); // create finite element space H1Space space(&mesh, &shapeset); space.set_bc_values(bc_values); space.set_uniform_order(P_INIT); // enumerate basis functions space.assign_dofs(); // initialize the weak formulation WeakForm wf(1); wf.add_biform(0, 0, bilinear_form, SYM); wf.add_liform(0, linear_form); // visualize solution and mesh ScalarView sview("Coarse solution", 0, 100, 798, 700); OrderView oview("Polynomial orders", 800, 100, 798, 700); // matrix solver UmfpackSolver solver; // convergence graph wrt. the number of degrees of freedom GnuplotGraph graph; graph.set_log_y(); graph.set_captions("Error Convergence for the Inner Layer Problem", "Degrees of Freedom", "Error [%]"); graph.add_row("exact error", "k", "-", "o"); graph.add_row("error estimate", "k", "--"); // convergence graph wrt. CPU time GnuplotGraph graph_cpu; graph_cpu.set_captions("Error Convergence for the Inner Layer Problem", "CPU Time", "Error Estimate [%]"); graph_cpu.add_row("exact error", "k", "-", "o"); graph_cpu.add_row("error estimate", "k", "--"); graph_cpu.set_log_y(); // adaptivity loop int it = 1, ndofs; bool done = false; double cpu = 0.0; Solution sln_coarse, sln_fine; do { info("\n---- Adaptivity step %d ---------------------------------------------\n", it++); // time measurement begin_time(); // solve the coarse mesh problem LinSystem ls(&wf, &solver); ls.set_spaces(1, &space); ls.set_pss(1, &pss); ls.assemble(); ls.solve(1, &sln_coarse); // time measurement cpu += end_time(); // calculate error wrt. exact solution ExactSolution exact(&mesh, fndd); double error = h1_error(&sln_coarse, &exact) * 100; info("\nExact solution error: %g%%", error); // view the solution and mesh sview.show(&sln_coarse); oview.show(&space); // time measurement begin_time(); // solve the fine mesh problem RefSystem rs(&ls); rs.assemble(); rs.solve(1, &sln_fine); // calculate error estimate wrt. fine mesh solution H1OrthoHP hp(1, &space); double err_est = hp.calc_error(&sln_coarse, &sln_fine) * 100; info("Estimate of error: %g%%", err_est); // add entry to DOF convergence graph graph.add_values(0, space.get_num_dofs(), error); graph.add_values(1, space.get_num_dofs(), err_est); graph.save("conv_dof.gp"); // add entry to CPU convergence graph graph_cpu.add_values(0, cpu, error); graph_cpu.add_values(1, cpu, err_est); graph_cpu.save("conv_cpu.gp"); // if err_est too large, adapt the mesh if (err_est < ERR_STOP) done = true; else { hp.adapt(THRESHOLD, STRATEGY, ADAPT_TYPE, ISO_ONLY, MESH_REGULARITY); ndofs = space.assign_dofs(); if (ndofs >= NDOF_STOP) done = true; } // time measurement cpu += end_time(); } while (done == false); verbose("Total running time: %g sec", cpu); // show the fine solution - this is the final result sview.set_title("Final solution"); sview.show(&sln_fine); // wait for keyboard or mouse input printf("Waiting for keyboard or mouse input.\n"); View::wait(); return 0; }
int main(int argc, char* argv[]) { // Define problem parameters: (x_loc, y_loc) is the center of the circular wave front, R_ZERO is the distance from the // wave front to the center of the circle, and alpha gives the steepness of the wave front. double alpha, x_loc, y_loc, r_zero; switch(PARAM) { case 0: alpha = 20; x_loc = -0.05; y_loc = -0.05; r_zero = 0.7; break; case 1: alpha = 1000; x_loc = -0.05; y_loc = -0.05; r_zero = 0.7; break; case 2: alpha = 1000; x_loc = 1.5; y_loc = 0.25; r_zero = 0.92; break; case 3: alpha = 50; x_loc = 0.5; y_loc = 0.5; r_zero = 0.25; break; default: // The same as 0. alpha = 20; x_loc = -0.05; y_loc = -0.05; r_zero = 0.7; break; } // Set adaptivity options according to the command line argument. int refinement_mode; if (argc != 2) refinement_mode = 0; else { refinement_mode = atoi(argv[1]); if (refinement_mode < 1 || refinement_mode > 12) throw Hermes::Exceptions::Exception("Invalid run case: %d (valid range is [1,12])", refinement_mode); } double threshold = 0.3; // strategy = 0 ... Refine elements until sqrt(threshold) times total error is processed. // If more elements have similar errors, refine all to keep the mesh symmetric. int strategy = 0; // strategy = 1 ... Refine all elements whose error is larger than threshold times max. element error. // Add also the norm of the residual to the error estimate of each element. bool use_residual_estimator = false; // Use energy norm for error estimate normalization and measuring of exact error. bool use_energy_norm_normalization = false; switch (refinement_mode) { case 1: case 2: case 3: case 4: case 5: case 6: { strategy = 0; break; } case 7 : case 8 : case 9 : case 10: case 11: case 12: { strategy = 1; break; } } switch (refinement_mode) { case 1: case 2: case 3: case 7: case 8: case 9: { threshold = 0.3; break; } case 4: case 5: case 6: case 10: case 11: case 12: { threshold = 0.3*0.3; break; } } switch (refinement_mode) { case 2: case 3: case 5: case 6: case 8: case 9: case 11: case 12: { use_residual_estimator = true; break; } } switch (refinement_mode) { case 3: case 6: case 9: case 12: { use_energy_norm_normalization = true; break; } } double setup_time = 0, assemble_time = 0, solve_time = 0, adapt_time = 0; // Time measurement. Hermes::Mixins::TimeMeasurable wall_clock; // Stop counting time for adaptation. wall_clock.tick(); // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("square_quad.mesh", &mesh); // Perform initial mesh refinement. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Stop counting time for adaptation. wall_clock.tick(); adapt_time += wall_clock.last(); // Set exact solution. CustomExactSolution exact(&mesh, alpha, x_loc, y_loc, r_zero); // Define right-hand side. CustomRightHandSide rhs(alpha, x_loc, y_loc, r_zero); // Initialize the weak formulation. CustomWeakForm wf(&rhs); // Equivalent, but slower: // DefaultWeakFormPoisson<double> wf(Hermes::HERMES_ANY, HERMES_ONE, &rhs); // Initialize boundary conditions. DefaultEssentialBCNonConst<double> bc("Bdy", &exact); EssentialBCs<double> bcs(&bc); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); // Initialize approximate solution. Solution<double> sln; // Initialize views. Views::ScalarView sview("Solution", new Views::WinGeom(800, 0, 400, 400)); sview.show_mesh(false); sview.set_3d_mode(); sview.set_palette(Views::H2DV_PT_HUESCALE); sview.fix_scale_width(50); Views::OrderView oview("Mesh", new Views::WinGeom(0, 0, 800, 800)); oview.set_palette(Views::H2DV_PT_INVGRAYSCALE); // DOF and CPU convergence graphs. ConvergenceTable conv_table; conv_table.add_column(" cycle ", "%6d "); conv_table.add_column(" H1 error ", " %.4e "); conv_table.add_column(" ndof ", " %6d "); conv_table.add_column(" total time ", " %8.3f "); conv_table.add_column(" setup time ", " %8.3f "); conv_table.add_column(" assem time ", " %8.3f "); conv_table.add_column(" solve time ", " %8.3f "); conv_table.add_column(" adapt time ", " %8.3f "); wall_clock.tick(Hermes::Mixins::TimeMeasurable::HERMES_SKIP); // Adaptivity loop: int as = 0; bool done = false; do { // Start counting setup time. wall_clock.tick(); // Assemble the discrete problem. DiscreteProblem<double> dp(&wf, &space); // Actual ndof. int ndof = space.get_num_dofs(); NewtonSolver<double> newton(&dp); newton.set_verbose_output(false); // Setup time continues in NewtonSolver::solve(). try { newton.solve(); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); throw Hermes::Exceptions::Exception("Newton's iteration failed."); }; setup_time += newton.get_setup_time(); assemble_time += newton.get_assemble_time(); solve_time += newton.get_solve_time(); // Start counting time for adaptation. wall_clock.tick(); Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln); double err_exact = Global<double>::calc_abs_error(&sln, &exact, HERMES_H1_NORM); // Report results. Hermes::Mixins::Loggable::Static::info(" Cycle %d:", as); Hermes::Mixins::Loggable::Static::info(" Number of degrees of freedom: %d", ndof); Hermes::Mixins::Loggable::Static::info(" H1 error w.r.t. exact soln.: %g", err_exact); // Stop counting time for adaptation. wall_clock.tick(); double accum_time = wall_clock.accumulated(); adapt_time += wall_clock.last(); // View the approximate solution and polynomial orders. //sview.show(&sln); //oview.show(&space); //Views::View::wait(Views::HERMES_WAIT_KEYPRESS); conv_table.add_value(0, as); conv_table.add_value(1, err_exact); conv_table.add_value(2, ndof); conv_table.add_value(3, accum_time); conv_table.add_value(4, setup_time); conv_table.add_value(5, assemble_time); conv_table.add_value(6, solve_time); conv_table.add_value(7, adapt_time); // Start counting time for adaptation. wall_clock.tick(); if (err_exact < ERR_STOP) done = true; else { // Calculate element errors and total error estimate. Hermes::Hermes2D::BasicKellyAdapt<double> adaptivity(&space); unsigned int error_flags = HERMES_TOTAL_ERROR_ABS; if (use_energy_norm_normalization) { error_flags |= HERMES_ELEMENT_ERROR_REL; adaptivity.set_error_form(new EnergyErrorForm(&wf)); } else error_flags |= HERMES_ELEMENT_ERROR_ABS; if (use_residual_estimator) adaptivity.add_error_estimator_vol(new ResidualErrorForm(&rhs)); double err_est_rel = adaptivity.calc_err_est(&sln, error_flags); done = adaptivity.adapt(threshold, strategy, MESH_REGULARITY); // Stop counting time for adaptation. wall_clock.tick(); adapt_time += wall_clock.last(); } // Increase the counter of performed adaptivity steps. if (done == false) as++; else { Hermes::Mixins::Loggable::Static::info("Total running time: %g s", wall_clock.accumulated()); Hermes::Mixins::Loggable::Static::info(" Setup: %g s", setup_time); Hermes::Mixins::Loggable::Static::info(" Assemble: %g s", assemble_time); Hermes::Mixins::Loggable::Static::info(" Solve: %g s", solve_time); Hermes::Mixins::Loggable::Static::info(" Adapt: %g s", adapt_time); //sview.show(&sln); oview.show(&space); oview.save_screenshot(("final_mesh-"+itos(refinement_mode)+".bmp").c_str()); oview.close(); conv_table.save(("conv_table-"+itos(refinement_mode)+".dat").c_str()); } } while (done == false); // Wait for all views to be closed. //Views::View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); // Perform initial mesh refinements. for(int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_vertex(3, CORNER_REF_LEVEL); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(BDY_LEFT); bc_types.add_bc_neumann(Hermes::vector<int>(BDY_OUTER, BDY_INNER)); bc_types.add_bc_newton(BDY_BOTTOM); // Enter Dirichlet boudnary values. BCValues bc_values; bc_values.add_const(BDY_LEFT, T1); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d", ndof); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(bilinear_form_1), HERMES_SYM, MATERIAL_1); wf.add_matrix_form(callback(bilinear_form_2), HERMES_SYM, MATERIAL_2); wf.add_matrix_form_surf(callback(bilinear_form_surf_bottom), BDY_BOTTOM); wf.add_vector_form_surf(callback(linear_form_surf_bottom), BDY_BOTTOM); wf.add_vector_form_surf(callback(linear_form_surf_outer), BDY_OUTER); // Initialize coarse and reference mesh solution. Solution sln; // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 410, 600)); sview.fix_scale_width(50); sview.show_mesh(false); OrderView oview("Polynomial orders", new WinGeom(420, 0, 400, 600)); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Initialize matrix solver. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Assemble reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, &space, is_linear); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. // If successful, obtain the solution. if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); // 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_SKIP); // Calculate element errors and total error estimate. info("Calculating error estimate."); KellyTypeAdapt* adaptivity = new KellyTypeAdapt(&space); adaptivity->add_error_estimator_surf(callback(kelly_interface_estimator)); adaptivity->add_error_estimator_surf(callback(kelly_newton_boundary_estimator), BDY_BOTTOM); adaptivity->add_error_estimator_surf(callback(kelly_neumann_boundary_estimator), BDY_OUTER); adaptivity->add_error_estimator_surf(callback(kelly_zero_neumann_boundary_estimator), BDY_INNER); double err_est_rel = adaptivity->calc_err_est(&sln, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100; // Report results. info("ndof: %d, err_est_rel: %g%%", Space::get_num_dofs(&space), err_est_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(Space::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 { info("Adapting coarse mesh."); done = adaptivity->adapt(THRESHOLD, STRATEGY, MESH_REGULARITY); } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Increase the counter of performed adaptivity steps. if (done == false) as++; // Clean up. delete adaptivity; delete dp; } while (done == false); // Clean up. delete solver; delete matrix; delete rhs; verbose("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // load the mesh Mesh mesh; H2DReader mloader; mloader.load("domain2.mesh", &mesh); // initial uniform subdivision //mesh.refine_all_elements(); // initialize the shapeset and the cache H1Shapeset shapeset; PrecalcShapeset pss(&shapeset); // create an H1 space H1Space space(&mesh, &shapeset); space.set_bc_types(bc_types); space.set_bc_values(dir_bc_values); space.set_uniform_order(P_INIT); // enumerate basis functions space.assign_dofs(); // initialize the weak formulation WeakForm wf(1); wf.add_biform(0, 0, callback(bilinear_form_iron), SYM, 3); wf.add_biform(0, 0, callback(bilinear_form_wire), SYM, 2); wf.add_biform(0, 0, callback(bilinear_form_air), SYM, 1); wf.add_liform(0, callback(linear_form_wire), 2); // visualize solution and mesh ScalarView view("Vector potential A", 0, 0, 1000, 600); OrderView oview("Polynomial orders", 1100, 0, 900, 600); // matrix solver UmfpackSolver solver; // DOF and CPU convergence graphs SimpleGraph graph_dof_est, graph_dof_exact, graph_cpu_est, graph_cpu_exact; // adaptivity loop int it = 1, ndofs; bool done = false; double cpu = 0.0; Solution sln_coarse, sln_fine; do { info("\n---- Adaptivity step %d ---------------------------------------------\n", it++); // time measurement begin_time(); // solve the coarse mesh problem LinSystem sys(&wf, &solver); sys.set_spaces(1, &space); sys.set_pss(1, &pss); // time measurement cpu += end_time(); // assemble the stiffness matrix and solve the system sys.assemble(); sys.solve(1, &sln_coarse); // visualize the solution view.show(&sln_coarse, EPS_HIGH); oview.show(&space); // time measurement begin_time(); // solve the fine mesh problem RefSystem rs(&sys); rs.assemble(); rs.solve(1, &sln_fine); // calculate element errors and total error estimate H1OrthoHP hp(1, &space); double err_est = hp.calc_error(&sln_coarse, &sln_fine) * 100; info("Error estimate: %g%%", err_est); // add entries to DOF convergence graph graph_dof_est.add_values(space.get_num_dofs(), err_est); graph_dof_est.save("conv_dof.dat"); // add entries to CPU convergence graph graph_cpu_est.add_values(cpu, err_est); graph_cpu_est.save("conv_cpu.dat"); // if err_est too large, adapt the mesh if (err_est < ERR_STOP) done = true; else { hp.adapt(THRESHOLD, STRATEGY, ADAPT_TYPE, ISO_ONLY, MESH_REGULARITY); ndofs = space.assign_dofs(); if (ndofs >= NDOF_STOP) done = true; } // time measurement cpu += end_time(); } while (done == false); verbose("Total running time: %g sec", cpu); // show the fine solution - this is the final result view.set_title("Final solution"); view.show(&sln_fine); // wait for keyboard or mouse input View::wait("Waiting for all views to be closed."); 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[]) { // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("motor.mesh", &mesh); // Initialize the weak formulation. CustomWeakFormPoisson wf("Motor", EPS_MOTOR, "Air", EPS_AIR, &mesh); // Initialize boundary conditions DefaultEssentialBCConst<double> bc_essential_out("Outer", 0.0); DefaultEssentialBCConst<double> bc_essential_stator("Stator", VOLTAGE); EssentialBCs<double> bcs(Hermes::vector<EssentialBoundaryCondition<double> *>(&bc_essential_out, &bc_essential_stator)); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); // Initialize coarse and reference mesh solution. Solution<double> sln; // Initialize views. Views::ScalarView sview("Solution", new Views::WinGeom(0, 0, 410, 600)); sview.fix_scale_width(50); sview.show_mesh(false); Views::OrderView oview("Polynomial orders", new Views::WinGeom(420, 0, 400, 600)); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; // Adaptivity loop: int as = 1; bool done = false; do { Hermes::Mixins::Loggable::Static::info("---- Adaptivity step %d:", as); // Time measurement. cpu_time.tick(); // Initialize reference problem. Hermes::Mixins::Loggable::Static::info("Solving."); DiscreteProblem<double> dp(&wf, &space); NewtonSolver<double> newton(&dp); newton.set_verbose_output(false); // Initial ndof. int ndof = space.get_num_dofs(); // Perform Newton's iteration. try { newton.solve(); } catch(std::exception& e) { std::cout << e.what(); } // Translate the resulting coefficient vector into the instance of Solution. Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln); // Time measurement. cpu_time.tick(); // VTK output. if (VTK_VISUALIZATION) { // Output solution in VTK format. Views::Linearizer lin; char* title = new char[100]; sprintf(title, "sln-%d.vtk", as); lin.save_solution_vtk(&sln, title, "Potential", false); Hermes::Mixins::Loggable::Static::info("Solution in VTK format saved to file %s.", title); // Output mesh and element orders in VTK format. Views::Orderizer ord; sprintf(title, "ord-%d.vtk", as); ord.save_orders_vtk(&space, title); Hermes::Mixins::Loggable::Static::info("Element orders in VTK format saved to file %s.", title); } // View the coarse mesh solution and polynomial orders. if (HERMES_VISUALIZATION) { sview.show(&sln); oview.show(&space); } // Skip visualization time. cpu_time.tick(); // Calculate element errors and total error estimate. Hermes::Mixins::Loggable::Static::info("Calculating error estimate."); bool ignore_visited_segments = true; KellyTypeAdapt<double> adaptivity(&space, ignore_visited_segments, USE_EPS_IN_INTERFACE_ESTIMATOR ? new CustomInterfaceEstimatorScalingFunction("Motor", EPS_MOTOR, "Air", EPS_AIR) : new CustomInterfaceEstimatorScalingFunction); adaptivity.add_error_estimator_surf(new Hermes::Hermes2D::BasicKellyAdapt<double>::ErrorEstimatorFormKelly()); if (USE_RESIDUAL_ESTIMATOR) { adaptivity.add_error_estimator_vol(new ResidualErrorFormMotor("Motor", EPS_MOTOR)); adaptivity.add_error_estimator_vol(new ResidualErrorFormAir("Air", EPS_AIR)); } if (USE_EPS_IN_INTERFACE_ESTIMATOR) // Use normalization by energy norm. adaptivity.set_error_form(new EnergyErrorForm(&wf)); // Note that there is only one solution (the only one available) passed to BasicKellyAdapt::calc_err_est // and there is also no "solutions_for_adapt" parameter. The last parameter, "error_flags", is left // intact and has the meaning explained in P04-adaptivity/01-intro. You may however still call // adaptivity.calc_err_est with a solution, an exact solution and solutions_for_adapt=false to calculate // error wrt. an exact solution (if provided). double err_est_rel = adaptivity.calc_err_est(&sln, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100; // Report results. Hermes::Mixins::Loggable::Static::info("ndof: %d, err_est_rel: %g%%", space.get_num_dofs(), err_est_rel); // Add entry to DOF and CPU convergence graphs. cpu_time.tick(); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); graph_dof.add_values(space.get_num_dofs(), err_est_rel); graph_dof.save("conv_dof_est.dat"); // Skip the time spent to save the convergence graphs. cpu_time.tick(); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { Hermes::Mixins::Loggable::Static::info("Adapting coarse mesh."); // h-refinement is automatically selected here, no need for parameter "selector". done = adaptivity.adapt(THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (space.get_num_dofs() >= NDOF_STOP) done = true; } while (done == false); Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated()); // The final result has already been shown in the final step of the adaptivity loop, so we only // adjust the title and hide the mesh here. sview.set_title("Fine mesh solution"); sview.show_mesh(false); // Wait for all views to be closed. Views::View::wait(); return 0; }
int main(int argc, char* argv[]) { // 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; }