int main(int argc, char **args) { // Test variable. int success_test = 1; // Check the number of command-line parameters. if (argc < 2) { info("Use x, y, z, xy, xz, yz, or xyz as a command-line parameter."); error("Not enough command-line parameters."); } // Determine anisotropy type from the command-line parameter. ANISO_TYPE = parse_aniso_type(args[1]); // Load the mesh. Mesh mesh; H3DReader mesh_loader; mesh_loader.load("hex-0-1.mesh3d", &mesh); // Assign the lowest possible directional polynomial degrees so that the problem's NDOF >= 1. assign_poly_degrees(); // Create an H1 space with default shapeset. info("Setting directional polynomial degrees %d, %d, %d.", P_INIT_X, P_INIT_Y, P_INIT_Z); H1Space space(&mesh, bc_types, essential_bc_values, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); // Initialize weak formulation. WeakForm wf; wf.add_matrix_form(bilinear_form<double, scalar>, bilinear_form<Ord, Ord>, HERMES_SYM, HERMES_ANY); wf.add_vector_form(linear_form<double, scalar>, linear_form<Ord, Ord>, HERMES_ANY); // Set exact solution. ExactSolution exact(&mesh, fndd); // 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 = construct_refined_space(&space, 1); // Initialize discrete problem. bool is_linear = true; DiscreteProblem dp(&wf, ref_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); // Initialize the preconditioner in the case of SOLVER_AZTECOO. if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Assemble the reference problem. info("Assembling on reference mesh (ndof: %d).", Space::get_num_dofs(ref_space)); dp.assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system on reference mesh. If successful, obtain the solution. info("Solving on reference mesh."); Solution ref_sln(ref_space->get_mesh()); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else { error ("Matrix solver failed.\n"); success_test = 0; } // Time measurement. cpu_time.tick(); // Project the reference solution on the coarse mesh. Solution sln(space.get_mesh()); info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Time measurement. cpu_time.tick(); // Output solution and mesh with polynomial orders. if (solution_output) { out_fn_vtk(&sln, "sln", as); out_orders_vtk(&space, "order", as); } // Skip the visualization time. cpu_time.tick(HERMES_SKIP); // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); Adapt *adaptivity = new Adapt(&space, HERMES_H1_NORM); bool solutions_for_adapt = true; double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt) * 100; // Calculate exact error. solutions_for_adapt = false; double err_exact_rel = adaptivity->calc_err_exact(&sln, &exact, solutions_for_adapt) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d.", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space)); info("err_est_rel: %g%%, err_exact_rel: %g%%.", err_est_rel, err_exact_rel); // If err_est_rel is too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); adaptivity->adapt(THRESHOLD); } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete ref_space->get_mesh(); delete ref_space; delete matrix; delete rhs; delete solver; delete adaptivity; // Increase the counter of performed adaptivity steps. as++; } while (!done); // This is the actual test. #define ERROR_SUCCESS 0 #define ERROR_FAILURE -1 int ndof_allowed; switch (ANISO_TYPE) { case ANISO_X: ndof_allowed = 28; break; case ANISO_Y: ndof_allowed = 28; break; case ANISO_Z: ndof_allowed = 28; break; case ANISO_X | ANISO_Y: ndof_allowed = 98; break; case ANISO_X | ANISO_Z: ndof_allowed = 98; break; case ANISO_Y | ANISO_Z: ndof_allowed = 98; break; case ANISO_X | ANISO_Y | ANISO_Z: ndof_allowed = 343; break; default: error("Admissible command-line options are x, y, x, xy, xz, yz, xyz."); } int ndof = Space::get_num_dofs(&space); info("ndof_actual = %d", ndof); info("ndof_allowed = %d", ndof_allowed); if (ndof > ndof_allowed) success_test = 0; if (success_test) { info("Success!"); return ERR_SUCCESS; } else { info("Failure!"); return ERR_FAILURE; } }
int main(int argc, char **args) { // Load the mesh. Mesh mesh; H3DReader mesh_loader; mesh_loader.load("fichera-corner.mesh3d", &mesh); // Perform initial mesh refinement. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(H3D_H3D_H3D_REFT_HEX_XYZ); // Create an H1 space with default shapeset. H1Space space(&mesh, bc_types, essential_bc_values, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); // Initialize weak formulation. WeakForm wf; wf.add_matrix_form(bilinear_form<double, double>, bilinear_form<Ord, Ord>, HERMES_SYM, HERMES_ANY); wf.add_vector_form(linear_form<double, double>, linear_form<Ord, Ord>, HERMES_ANY); // Set exact solution. ExactSolution exact(&mesh, fndd); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est, graph_dof_exact, graph_cpu_exact; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Initialize the solver in the case of SOLVER_PETSC or SOLVER_MUMPS. initialize_solution_environment(matrix_solver, argc, args); // 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 = construct_refined_space(&space,1 , H3D_H3D_H3D_REFT_HEX_XYZ); // Initialize discrete problem. bool is_linear = true; DiscreteProblem dp(&wf, ref_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); // Initialize the preconditioner in the case of SOLVER_AZTECOO. if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Assemble the reference problem. info("Assembling on reference mesh (ndof: %d).", Space::get_num_dofs(ref_space)); dp.assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system on reference mesh. If successful, obtain the solution. info("Solving on reference mesh."); Solution ref_sln(ref_space->get_mesh()); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Project the reference solution on the coarse mesh. Solution sln(space.get_mesh()); info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Time measurement. cpu_time.tick(); // Output solution and mesh with polynomial orders. if (solution_output) { out_fn_vtk(&sln, "sln", as); out_orders_vtk(&space, "order", as); } // Skip the visualization time. cpu_time.tick(HERMES_SKIP); // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); Adapt *adaptivity = new Adapt(&space, HERMES_H1_NORM); bool solutions_for_adapt = true; double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt) * 100; // Calculate exact error. solutions_for_adapt = false; double err_exact_rel = adaptivity->calc_err_exact(&sln, &exact, solutions_for_adapt) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d.", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space)); info("err_est_rel: %g%%, err_exact_rel: %g%%.", err_est_rel, err_exact_rel); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu_est.save("conv_cpu_est.dat"); graph_dof_exact.add_values(Space::get_num_dofs(&space), err_exact_rel); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel); graph_cpu_exact.save("conv_cpu_exact.dat"); // If err_est_rel is too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); adaptivity->adapt(THRESHOLD); } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete ref_space->get_mesh(); delete ref_space; delete matrix; delete rhs; delete solver; delete adaptivity; // Increase the counter of performed adaptivity steps. as++; } while (!done); // Properly terminate the solver in the case of SOLVER_PETSC or SOLVER_MUMPS. finalize_solution_environment(matrix_solver); return 1; }
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)); // 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); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; 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); 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. try { newton.solve(coeff_vec); } catch(Hermes::Exceptions::Exception& e) { e.print_msg(); } Hermes::Hermes2D::Solution<complex>::vector_to_solution(newton.get_sln_vector(), ref_space, ref_sln); // Project the fine mesh solution onto the coarse mesh. OGProjection<complex> ogProjection; ogProjection.project_global(space, ref_sln, sln); // Calculate element errors and total error estimate. errorCalculator.calculate_errors(sln, ref_sln); // If err_est too large, adapt the mesh-> if(errorCalculator.get_total_error_squared() * 100. < ERR_STOP) done = true; else { adaptivity.adapt(&selector); } // Clean up. delete [] coeff_vec; // Increase counter. as++; } while (done == false); complex sum = 0; for (int i = 0; i < space->get_num_dofs(); i++) sum += newton.get_sln_vector()[i]; printf("coefficient sum = %f\n", sum); complex expected_sum; expected_sum.real(1.4685364e-005); expected_sum.imag(-5.45632171e-007); bool success = true; if(std::abs(sum - expected_sum) > 1e-6) success = false; int ndof = space->get_num_dofs(); if(ndof != 82) // Tested value as of May 2013. success = false; if(success) { printf("Success!\n"); return 0; } else { printf("Failure!\n"); return -1; } }
int main(int argc, char **args) { // Test variable. int success_test = 1; if (argc < 5) error("Not enough parameters."); // Load the mesh. Mesh mesh; H3DReader mloader; if (!mloader.load(args[1], &mesh)) error("Loading mesh file '%s'.", args[1]); // Initialize the space according to the // command-line parameters passed. sscanf(args[2], "%d", &P_INIT_X); sscanf(args[3], "%d", &P_INIT_Y); sscanf(args[4], "%d", &P_INIT_Z); Ord3 order(P_INIT_X, P_INIT_Y, P_INIT_Z); H1Space space(&mesh, bc_types, essential_bc_values, order); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(bilinear_form<double, scalar>, bilinear_form<Ord, Ord>, HERMES_SYM, HERMES_ANY); wf.add_vector_form(linear_form<double, scalar>, linear_form<Ord, Ord>, HERMES_ANY); // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Initialize the solver in the case of SOLVER_PETSC or SOLVER_MUMPS. initialize_solution_environment(matrix_solver, argc, args); // 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 = construct_refined_space(&space,1 , H3D_H3D_H3D_REFT_HEX_XYZ); out_orders_vtk(ref_space, "space", as); // Initialize the FE problem. bool is_linear = true; DiscreteProblem lp(&wf, ref_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); // Initialize the preconditioner in the case of SOLVER_AZTECOO. if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Assemble the reference problem. info("Assembling on reference mesh (ndof: %d).", Space::get_num_dofs(ref_space)); lp.assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system on reference mesh. If successful, obtain the solution. info("Solving on reference mesh."); Solution ref_sln(ref_space->get_mesh()); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else { printf("Matrix solver failed.\n"); success_test = 0; } // Time measurement. cpu_time.tick(); // Project the reference solution on the coarse mesh. Solution sln(space.get_mesh()); info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Time measurement. cpu_time.tick(); // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); Adapt *adaptivity = new Adapt(&space, HERMES_H1_NORM); bool solutions_for_adapt = true; double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d.", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space)); info("err_est_rel: %g%%.", err_est_rel); // If err_est_rel is too large, adapt the mesh. if (err_est_rel < ERR_STOP) { done = true; ExactSolution ex_sln(&mesh, exact_solution); // Calculate exact error. info("Calculating exact error."); Adapt *adaptivity = new Adapt(&space, HERMES_H1_NORM); bool solutions_for_adapt = false; double err_exact = adaptivity->calc_err_exact(&sln, &ex_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_ABS); if (err_exact > EPS) // Calculated solution is not precise enough. success_test = 0; break; } else { info("Adapting coarse mesh."); adaptivity->adapt(THRESHOLD); } // If we reached the maximum allowed number of degrees of freedom, set the return flag to failure. if (Space::get_num_dofs(&space) >= NDOF_STOP) { done = true; success_test = 0; } // Clean up. delete ref_space->get_mesh(); delete ref_space; delete matrix; delete rhs; delete solver; delete adaptivity; // Increase the counter of performed adaptivity steps. as++; } while (!done); // Properly terminate the solver in the case of SOLVER_PETSC or SOLVER_MUMPS. finalize_solution_environment(matrix_solver); if (success_test) { info("Success!"); return ERR_SUCCESS; } else { info("Failure!"); return ERR_FAILURE; } }
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[]) { // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); if (bt.is_explicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Turn off adaptive time stepping if R-K method is not embedded. if (bt.is_embedded() == false && ADAPTIVE_TIME_STEP_ON == true) { Hermes::Mixins::Loggable::Static::warn("R-K method not embedded, turning off adaptive time stepping."); ADAPTIVE_TIME_STEP_ON = false; } // Load the mesh. MeshSharedPtr mesh(new Mesh), basemesh(new Mesh); MeshReaderH2D mloader; mloader.load("wall.mesh", basemesh); mesh->copy(basemesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); mesh->refine_towards_boundary(BDY_RIGHT, 2); mesh->refine_towards_boundary(BDY_FIRE, INIT_REF_NUM_BDY); // Initialize essential boundary conditions (none). EssentialBCs<double> bcs; // Initialize an H1 space with default shapeset. SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT)); int ndof = Space<double>::get_num_dofs(space); Hermes::Mixins::Loggable::Static::info("ndof = %d.", ndof); // Convert initial condition into a Solution. MeshFunctionSharedPtr<double> sln_prev_time(new ConstantSolution<double> (mesh, TEMP_INIT)); // Initialize the weak formulation. double current_time = 0; CustomWeakFormHeatRK wf(BDY_FIRE, BDY_AIR, ALPHA_FIRE, ALPHA_AIR, RHO, HEATCAP, TEMP_EXT_AIR, TEMP_INIT, ¤t_time); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, space); // Create a refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST); // Visualize initial condition. char title[100]; ScalarView sln_view("Initial condition", new WinGeom(0, 0, 1500, 360)); OrderView ordview("Initial mesh", new WinGeom(0, 410, 1500, 360)); ScalarView time_error_view("Temporal error", new WinGeom(0, 800, 1500, 360)); time_error_view.fix_scale_width(40); ScalarView space_error_view("Spatial error", new WinGeom(0, 1220, 1500, 360)); space_error_view.fix_scale_width(40); sln_view.show(sln_prev_time); ordview.show(space); // Graph for time step history. SimpleGraph time_step_graph; if (ADAPTIVE_TIME_STEP_ON) Hermes::Mixins::Loggable::Static::info("Time step history will be saved to file time_step_history.dat."); // Class for projections. OGProjection<double> ogProjection; // Time stepping loop: int ts = 1; do { Hermes::Mixins::Loggable::Static::info("Begin time step %d.", ts); // Periodic global derefinement. if (ts > 1 && ts % UNREF_FREQ == 0) { Hermes::Mixins::Loggable::Static::info("Global mesh derefinement."); switch (UNREF_METHOD) { case 1: mesh->copy(basemesh); space->set_uniform_order(P_INIT); break; case 2: space->unrefine_all_mesh_elements(); space->set_uniform_order(P_INIT); break; case 3: space->unrefine_all_mesh_elements(); //space->adjust_element_order(-1, P_INIT); space->adjust_element_order(-1, -1, P_INIT, P_INIT); break; default: throw Hermes::Exceptions::Exception("Wrong global derefinement method."); } space->assign_dofs(); ndof = Space<double>::get_num_dofs(space); } // Spatial adaptivity loop. Note: sln_prev_time must not be // changed during spatial adaptivity. MeshFunctionSharedPtr<double> ref_sln(new Solution<double>()); MeshFunctionSharedPtr<double> time_error_fn(new Solution<double>(mesh)); bool done = false; int as = 1; double err_est; do { // Construct globally refined reference mesh and setup reference space. Mesh::ReferenceMeshCreator refMeshCreator(mesh); MeshSharedPtr ref_mesh = refMeshCreator.create_ref_mesh(); Space<double>::ReferenceSpaceCreator refSpaceCreator(space, ref_mesh); SpaceSharedPtr<double> ref_space = refSpaceCreator.create_ref_space(); // Initialize Runge-Kutta time stepping on the reference mesh. RungeKutta<double> runge_kutta(&wf, ref_space, &bt); try { ogProjection.project_global(ref_space, sln_prev_time, sln_prev_time); } catch(Exceptions::Exception& e) { std::cout << e.what() << std::endl; Hermes::Mixins::Loggable::Static::error("Projection failed."); return -1; } // Runge-Kutta step on the fine mesh-> Hermes::Mixins::Loggable::Static::info("Runge-Kutta time step on fine mesh (t = %g s, tau = %g s, stages: %d).", current_time, time_step, bt.get_size()); bool verbose = true; bool jacobian_changed = false; try { runge_kutta.set_time(current_time); runge_kutta.set_time_step(time_step); runge_kutta.set_max_allowed_iterations(NEWTON_MAX_ITER); runge_kutta.set_tolerance(NEWTON_TOL_FINE); runge_kutta.rk_time_step_newton(sln_prev_time, ref_sln, bt.is_embedded() ? time_error_fn : NULL); } catch(Exceptions::Exception& e) { std::cout << e.what() << std::endl; Hermes::Mixins::Loggable::Static::error("Runge-Kutta time step failed"); return -1; } /* If ADAPTIVE_TIME_STEP_ON == true, estimate temporal error. If too large or too small, then adjust it and restart the time step. */ double rel_err_time = 0; if (bt.is_embedded() == true) { Hermes::Mixins::Loggable::Static::info("Calculating temporal error estimate."); // Show temporal error. char title[100]; sprintf(title, "Temporal error est, spatial adaptivity step %d", as); time_error_view.set_title(title); //time_error_view.show_mesh(false); time_error_view.show(time_error_fn); rel_err_time = Global<double>::calc_norm(time_error_fn.get(), HERMES_H1_NORM) / Global<double>::calc_norm(ref_sln.get(), HERMES_H1_NORM) * 100; if (ADAPTIVE_TIME_STEP_ON == false) Hermes::Mixins::Loggable::Static::info("rel_err_time: %g%%", rel_err_time); } if (ADAPTIVE_TIME_STEP_ON) { if (rel_err_time > TIME_ERR_TOL_UPPER) { Hermes::Mixins::Loggable::Static::info("rel_err_time %g%% is above upper limit %g%%", rel_err_time, TIME_ERR_TOL_UPPER); Hermes::Mixins::Loggable::Static::info("Decreasing tau from %g to %g s and restarting time step.", time_step, time_step * TIME_STEP_DEC_RATIO); time_step *= TIME_STEP_DEC_RATIO; continue; } else if (rel_err_time < TIME_ERR_TOL_LOWER) { Hermes::Mixins::Loggable::Static::info("rel_err_time = %g%% is below lower limit %g%%", rel_err_time, TIME_ERR_TOL_LOWER); Hermes::Mixins::Loggable::Static::info("Increasing tau from %g to %g s.", time_step, time_step * TIME_STEP_INC_RATIO); time_step *= TIME_STEP_INC_RATIO; } else { Hermes::Mixins::Loggable::Static::info("rel_err_time = %g%% is in acceptable interval (%g%%, %g%%)", rel_err_time, TIME_ERR_TOL_LOWER, TIME_ERR_TOL_UPPER); } // Add entry to time step history graph. time_step_graph.add_values(current_time, time_step); time_step_graph.save("time_step_history.dat"); } /* Estimate spatial errors and perform mesh refinement */ Hermes::Mixins::Loggable::Static::info("Spatial adaptivity step %d.", as); // Project the fine mesh solution onto the coarse mesh. MeshFunctionSharedPtr<double> sln(new Solution<double>()); Hermes::Mixins::Loggable::Static::info("Projecting fine mesh solution on coarse mesh for error estimation."); ogProjection.project_global(space, ref_sln, sln); // Show spatial error. sprintf(title, "Spatial error est, spatial adaptivity step %d", as); MeshFunctionSharedPtr<double> space_error_fn(new DiffFilter<double>(Hermes::vector<MeshFunctionSharedPtr<double> >(ref_sln, sln))); space_error_view.set_title(title); //space_error_view.show_mesh(false); MeshFunctionSharedPtr<double> abs_sef(new AbsFilter(space_error_fn)); space_error_view.show(abs_sef); // Calculate element errors and spatial error estimate. Hermes::Mixins::Loggable::Static::info("Calculating spatial error estimate."); adaptivity.set_space(space); double err_rel_space = errorCalculator.get_total_error_squared() * 100; // Report results. Hermes::Mixins::Loggable::Static::info("ndof: %d, ref_ndof: %d, err_rel_space: %g%%", Space<double>::get_num_dofs(space), Space<double>::get_num_dofs(ref_space), err_rel_space); // If err_est too large, adapt the mesh. if (err_rel_space < SPACE_ERR_TOL) done = true; else { Hermes::Mixins::Loggable::Static::info("Adapting the coarse mesh."); done = adaptivity.adapt(&selector); if (Space<double>::get_num_dofs(space) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } // Clean up. if(!done) } while (done == false); // Visualize the solution and mesh-> char title[100]; sprintf(title, "Solution, time %g s", current_time); sln_view.set_title(title); //sln_view.show_mesh(false); sln_view.show(ref_sln); sprintf(title, "Mesh, time %g s", current_time); ordview.set_title(title); ordview.show(space); // Copy last reference solution into sln_prev_time sln_prev_time->copy(ref_sln); // Increase current time and counter of time steps. current_time += time_step; ts++; } while (current_time < T_FINAL); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* 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[]) { #ifdef THREAD_TESTING HermesCommonApi.set_integral_param_value(numThreads, 8); #endif // Load the mesh. MeshSharedPtr mesh(new Mesh); Hermes::vector<MeshSharedPtr> meshes; meshes.push_back(mesh); MeshReaderH2DXML mloader; mloader.load("agrosMesh.msh", meshes); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); // Initialize boundary conditions. DefaultEssentialBCConst<complex> bc_essential("4", P_SOURCE); EssentialBCs<complex> bcs(&bc_essential); // Create an H1 space with default shapeset. SpaceSharedPtr<complex> space(new H1Space<complex> (mesh, &bcs, P_INIT)); adaptivity.set_space(space); // Initialize the weak formulation. CustomWeakFormAcoustics wf("0", RHO, SOUND_SPEED, OMEGA); // Initialize coarse and reference mesh solution. MeshFunctionSharedPtr<complex> sln(new Solution<complex>), ref_sln(new Solution<complex>); // Initialize refinement selector. H1ProjBasedSelector<complex> selector(CAND_LIST); Hermes::Hermes2D::NewtonSolver<complex> newton; newton.set_weak_formulation(&wf); // 2 Adaptivity steps: int as = 1; bool done = false; do { // Construct globally refined reference mesh and setup reference space. Mesh::ReferenceMeshCreator refMeshCreator(mesh); MeshSharedPtr ref_mesh = refMeshCreator.create_ref_mesh(); Space<complex>::ReferenceSpaceCreator refSpaceCreator(space, ref_mesh); SpaceSharedPtr<complex> ref_space = refSpaceCreator.create_ref_space(); // Perform Newton's iteration. try { newton.set_space(ref_space); newton.solve(); } catch(Hermes::Exceptions::Exception& e) { e.print_msg(); throw Hermes::Exceptions::Exception("Newton's iteration failed."); }; // Translate the resulting coefficient vector into the Solution<complex> sln-> Hermes::Hermes2D::Solution<complex>::vector_to_solution(newton.get_sln_vector(), ref_space, ref_sln); // Project the fine mesh solution onto the coarse mesh. OGProjection<complex> ogProjection; ogProjection.project_global(space, ref_sln, sln); // Calculate element errors and total error estimate. errorCalculator.calculate_errors(sln, ref_sln); adaptivity.adapt(&selector); } while (as++ < 2); return 0; }
int main(int argc, char* argv[]) { // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); if (bt.is_explicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Turn off adaptive time stepping if R-K method is not embedded. if (bt.is_embedded() == false && ADAPTIVE_TIME_STEP_ON == true) { Hermes::Mixins::Loggable::Static::warn("R-K method not embedded, turning off adaptive time stepping."); ADAPTIVE_TIME_STEP_ON = false; } // Load the mesh. MeshSharedPtr mesh(new Mesh), basemesh(new Mesh); MeshReaderH2D mloader; mloader.load("square.mesh", basemesh); mesh->copy(basemesh); // Initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); // Convert initial condition into a Solution<complex>. MeshFunctionSharedPtr<complex> psi_time_prev(new CustomInitialCondition(mesh)); // Initialize the weak formulation. double current_time = 0; // Initialize weak formulation. CustomWeakFormGPRK wf(h, m, g, omega); // Initialize boundary conditions. DefaultEssentialBCConst<complex> bc_essential("Bdy", 0.0); EssentialBCs<complex> bcs(&bc_essential); // Create an H1 space with default shapeset. SpaceSharedPtr<complex> space(new H1Space<complex> (mesh, &bcs, P_INIT)); int ndof = space->get_num_dofs(); Hermes::Mixins::Loggable::Static::info("ndof = %d", ndof); // Initialize the FE problem. DiscreteProblem<complex> dp(&wf, space); // Create a refinement selector. H1ProjBasedSelector<complex> selector(CAND_LIST); // Visualize initial condition. char title[100]; ScalarView sview_real("Initial condition - real part", new WinGeom(0, 0, 600, 500)); ScalarView sview_imag("Initial condition - imaginary part", new WinGeom(610, 0, 600, 500)); sview_real.show_mesh(false); sview_imag.show_mesh(false); sview_real.fix_scale_width(50); sview_imag.fix_scale_width(50); OrderView ord_view("Initial mesh", new WinGeom(445, 0, 440, 350)); ord_view.fix_scale_width(50); ScalarView time_error_view("Temporal error", new WinGeom(0, 400, 440, 350)); time_error_view.fix_scale_width(50); time_error_view.fix_scale_width(60); ScalarView space_error_view("Spatial error", new WinGeom(445, 400, 440, 350)); space_error_view.fix_scale_width(50); MeshFunctionSharedPtr<double> real(new RealFilter(psi_time_prev)); MeshFunctionSharedPtr<double> imag(new ImagFilter(psi_time_prev)); sview_real.show(real); sview_imag.show(imag); ord_view.show(space); // Graph for time step history. SimpleGraph time_step_graph; if (ADAPTIVE_TIME_STEP_ON) Hermes::Mixins::Loggable::Static::info("Time step history will be saved to file time_step_history.dat."); // Time stepping: int num_time_steps = (int)(T_FINAL/time_step + 0.5); for(int ts = 1; ts <= num_time_steps; ts++) // Time stepping loop. double current_time = 0.0; int ts = 1; do { Hermes::Mixins::Loggable::Static::info("Begin time step %d.", ts); // Periodic global derefinement. if (ts > 1 && ts % UNREF_FREQ == 0) { Hermes::Mixins::Loggable::Static::info("Global mesh derefinement."); switch (UNREF_METHOD) { case 1: mesh->copy(basemesh); space->set_uniform_order(P_INIT); break; case 2: space->unrefine_all_mesh_elements(); space->set_uniform_order(P_INIT); break; case 3: space->unrefine_all_mesh_elements(); space->adjust_element_order(-1, -1, P_INIT, P_INIT); break; default: throw Hermes::Exceptions::Exception("Wrong global derefinement method."); } ndof = Space<complex>::get_num_dofs(space); } Hermes::Mixins::Loggable::Static::info("ndof: %d", ndof); // Spatial adaptivity loop. Note: psi_time_prev must not be // changed during spatial adaptivity. MeshFunctionSharedPtr<complex> ref_sln(new Solution<complex>()); MeshFunctionSharedPtr<complex> time_error_fn(new Solution<complex>); bool done = false; int as = 1; double err_est; do { // Construct globally refined reference mesh and setup reference space. Mesh::ReferenceMeshCreator refMeshCreator(mesh); MeshSharedPtr ref_mesh = refMeshCreator.create_ref_mesh(); Space<complex>::ReferenceSpaceCreator refSpaceCreator(space, ref_mesh); SpaceSharedPtr<complex> ref_space = refSpaceCreator.create_ref_space(); // Initialize discrete problem on reference mesh. DiscreteProblem<complex>* ref_dp = new DiscreteProblem<complex>(&wf, ref_space); RungeKutta<complex> runge_kutta(&wf, ref_space, &bt); // Runge-Kutta step on the fine mesh-> Hermes::Mixins::Loggable::Static::info("Runge-Kutta time step on fine mesh (t = %g s, time step = %g s, stages: %d).", current_time, time_step, bt.get_size()); bool verbose = true; try { runge_kutta.set_time(current_time); runge_kutta.set_time_step(time_step); runge_kutta.set_max_allowed_iterations(NEWTON_MAX_ITER); runge_kutta.set_tolerance(NEWTON_TOL_FINE); runge_kutta.rk_time_step_newton(psi_time_prev, ref_sln, time_error_fn); } catch(Exceptions::Exception& e) { e.print_msg(); throw Hermes::Exceptions::Exception("Runge-Kutta time step failed"); } /* If ADAPTIVE_TIME_STEP_ON == true, estimate temporal error. If too large or too small, then adjust it and restart the time step. */ double rel_err_time = 0; if (bt.is_embedded() == true) { Hermes::Mixins::Loggable::Static::info("Calculating temporal error estimate."); // Show temporal error. char title[100]; sprintf(title, "Temporal error est, spatial adaptivity step %d", as); time_error_view.set_title(title); time_error_view.show_mesh(false); MeshFunctionSharedPtr<double> abs_time(new RealFilter(time_error_fn)); MeshFunctionSharedPtr<double> abs_tef(new AbsFilter(abs_time)); time_error_view.show(abs_tef); rel_err_time = Global<complex>::calc_norm(time_error_fn.get(), HERMES_H1_NORM) / Global<complex>::calc_norm(ref_sln.get(), HERMES_H1_NORM) * 100; if (ADAPTIVE_TIME_STEP_ON == false) Hermes::Mixins::Loggable::Static::info("rel_err_time: %g%%", rel_err_time); } if (ADAPTIVE_TIME_STEP_ON) { if (rel_err_time > TIME_ERR_TOL_UPPER) { Hermes::Mixins::Loggable::Static::info("rel_err_time %g%% is above upper limit %g%%", rel_err_time, TIME_ERR_TOL_UPPER); Hermes::Mixins::Loggable::Static::info("Decreasing time step from %g to %g s and restarting time step.", time_step, time_step * TIME_STEP_DEC_RATIO); time_step *= TIME_STEP_DEC_RATIO; delete ref_dp; continue; } else if (rel_err_time < TIME_ERR_TOL_LOWER) { Hermes::Mixins::Loggable::Static::info("rel_err_time = %g%% is below lower limit %g%%", rel_err_time, TIME_ERR_TOL_LOWER); Hermes::Mixins::Loggable::Static::info("Increasing time step from %g to %g s.", time_step, time_step * TIME_STEP_INC_RATIO); time_step *= TIME_STEP_INC_RATIO; delete ref_dp; continue; } else { Hermes::Mixins::Loggable::Static::info("rel_err_time = %g%% is in acceptable interval (%g%%, %g%%)", rel_err_time, TIME_ERR_TOL_LOWER, TIME_ERR_TOL_UPPER); } // Add entry to time step history graph. time_step_graph.add_values(current_time, time_step); time_step_graph.save("time_step_history.dat"); } /* Estimate spatial errors and perform mesh refinement */ Hermes::Mixins::Loggable::Static::info("Spatial adaptivity step %d.", as); // Project the fine mesh solution onto the coarse mesh. MeshFunctionSharedPtr<complex> sln(new Solution<complex>); Hermes::Mixins::Loggable::Static::info("Projecting fine mesh solution on coarse mesh for error estimation."); OGProjection<complex> ogProjection; ogProjection.project_global(space, ref_sln, sln); // Show spatial error. sprintf(title, "Spatial error est, spatial adaptivity step %d", as); MeshFunctionSharedPtr<complex> space_error_fn(new DiffFilter<complex>(Hermes::vector<MeshFunctionSharedPtr<complex> >(ref_sln, sln))); space_error_view.set_title(title); space_error_view.show_mesh(false); MeshFunctionSharedPtr<double> abs_space(new RealFilter(space_error_fn)); MeshFunctionSharedPtr<double> abs_sef(new AbsFilter(abs_space)); space_error_view.show(abs_sef); // Calculate element errors and spatial error estimate. Hermes::Mixins::Loggable::Static::info("Calculating spatial error estimate."); Adapt<complex> adaptivity(space); double err_rel_space = errorCalculator.get_total_error_squared() * 100; // Report results. Hermes::Mixins::Loggable::Static::info("ndof: %d, ref_ndof: %d, err_rel_space: %g%%", Space<complex>::get_num_dofs(space), Space<complex>::get_num_dofs(ref_space), err_rel_space); // If err_est too large, adapt the mesh. if (err_rel_space < SPACE_ERR_TOL) done = true; else { Hermes::Mixins::Loggable::Static::info("Adapting the coarse mesh."); done = adaptivity.adapt(&selector); // Increase the counter of performed adaptivity steps. as++; } // Clean up. delete ref_dp; } while (done == false); // Visualize the solution and mesh-> char title[100]; sprintf(title, "Solution - real part, Time %3.2f s", current_time); sview_real.set_title(title); sprintf(title, "Solution - imaginary part, Time %3.2f s", current_time); sview_imag.set_title(title); MeshFunctionSharedPtr<double> real(new RealFilter(ref_sln)); MeshFunctionSharedPtr<double> imag(new ImagFilter(ref_sln)); sview_real.show(real); sview_imag.show(imag); sprintf(title, "Mesh, time %g s", current_time); ord_view.set_title(title); ord_view.show(space); // Copy last reference solution into psi_time_prev. psi_time_prev->copy(ref_sln); // Increase current time and counter of time steps. current_time += time_step; ts++; } while (current_time < T_FINAL); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. MeshSharedPtr mesh(new Mesh); MeshReaderH2D mloader; mloader.load("square_quad.mesh", mesh); // mloader.load("square_tri.mesh", mesh); // Perform initial mesh refinement. for (int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); mesh->refine_towards_boundary("Layer", INIT_REF_NUM_BDY); // Initialize the weak formulation. WeakFormSharedPtr<double> wf(new WeakFormLinearAdvectionDiffusion(STABILIZATION_ON, SHOCK_CAPTURING_ON, B1, B2, EPSILON)); // Initialize boundary conditions DefaultEssentialBCConst<double> bc_rest("Rest", 1.0); EssentialBCNonConst bc_layer("Layer"); EssentialBCs<double> bcs({ &bc_rest, &bc_layer }); // Create an H1 space with default shapeset. SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT)); WinGeom* sln_win_geom = new WinGeom(0, 0, 440, 350); WinGeom* mesh_win_geom = new WinGeom(450, 0, 400, 350); // Initialize coarse and reference mesh solution. MeshFunctionSharedPtr<double> sln(new Solution<double>), ref_sln(new Solution<double>); // Initialize refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST); // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); sview.fix_scale_width(50); sview.show_mesh(false); OrderView oview("Polynomial orders", new WinGeom(450, 0, 400, 350)); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { Hermes::Mixins::Loggable::Static::info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Mesh::ReferenceMeshCreator refMeshCreator(mesh); MeshSharedPtr ref_mesh = refMeshCreator.create_ref_mesh(); Space<double>::ReferenceSpaceCreator refSpaceCreator(space, ref_mesh); SpaceSharedPtr<double> ref_space = refSpaceCreator.create_ref_space(); // Assemble the reference problem. Hermes::Mixins::Loggable::Static::info("Solving on reference mesh."); LinearSolver<double> solver(wf, ref_space); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. // If successful, obtain the solution. solver.solve(); Solution<double>::vector_to_solution(solver.get_sln_vector(), ref_space, ref_sln); // Project the fine mesh solution onto the coarse mesh. Hermes::Mixins::Loggable::Static::info("Projecting reference solution on coarse mesh."); OGProjection<double>::project_global(space, ref_sln, sln); // Time measurement. cpu_time.tick(); // View the coarse mesh solution and polynomial orders. sview.show(sln); oview.show(space); // Skip visualization time. cpu_time.tick(Hermes::Mixins::TimeMeasurable::HERMES_SKIP); // Calculate element errors and total error estimate. Hermes::Mixins::Loggable::Static::info("Calculating error estimate."); adaptivity.set_space(space); errorCalculator.calculate_errors(sln, ref_sln); double err_est_rel = errorCalculator.get_total_error_squared() * 100; // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space<double>::get_num_dofs(space), Space<double>::get_num_dofs(ref_space), err_est_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(Space<double>::get_num_dofs(space), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { Hermes::Mixins::Loggable::Static::info("Adapting coarse mesh."); done = adaptivity.adapt(&selector); // Increase the counter of performed adaptivity steps. if (done == false) as++; } } while (done == false); Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated()); // Show the reference solution - the final result. sview.set_title("Fine mesh solution"); sview.show_mesh(false); sview.show(ref_sln); // Wait for all views to be closed. View::wait(); return 0; }