int main(int argc, char* argv[]) { // Load the mesh. MeshSharedPtr mesh(new Mesh); MeshReaderH2D mloader; mloader.load("square.mesh", mesh); // Perform uniform mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); // Create an L2 space with default shapeset. SpaceSharedPtr<double> space(new L2Space<double>(mesh, P_INIT)); // View basis functions. BaseView<double> bview("BaseView", new WinGeom(0, 0, 600, 500)); bview.show(space); // View::wait(H2DV_WAIT_KEYPRESS); // Initialize the exact and projected solution. MeshFunctionSharedPtr<double> sln(new Solution<double>); MeshFunctionSharedPtr<double> sln_exact(new CustomExactSolution(mesh)); // Project the exact function on the FE space. OGProjection<double> ogProjection; ogProjection.project_global(space, sln_exact, sln); // Visualize the projection. ScalarView view1("Projection", new WinGeom(610, 0, 600, 500)); view1.show(sln); // 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("square_2_elem.mesh", &mesh); // Perform initial mesh refinements. for(int i = 0; i < UNIFORM_REF_LEVEL; i++) mesh.refine_all_elements(); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, P_INIT); int ndof = Space<double>::get_num_dofs(&space); info("ndof = %d", ndof); // Initialize the right-hand side. CustomRightHandSide rhs_value(K); // Initialize the weak formulation. CustomWeakForm wf(&rhs_value, BDY_LEFT_RIGHT, K); Solution<double> sln; // NON-ADAPTIVE VERSION // Initialize the linear problem. DiscreteProblem<double> dp(&wf, &space); // Select matrix solver. SparseMatrix<double>* matrix = create_matrix<double>(matrix_solver_type); Vector<double>* rhs = create_vector<double>(matrix_solver_type); LinearSolver<double>* solver = create_linear_solver<double>(matrix_solver_type, matrix, rhs); // Assemble stiffness matrix and rhs. dp.assemble(matrix, rhs); // Solve the linear system of the reference problem. If successful, obtain the solutions. if(solver->solve()) Solution<double>::vector_to_solution(solver->get_sln_vector(), &space, &sln); else error ("Matrix solver failed.\n"); // Visualize the solution. ScalarView view("Solution", new WinGeom(0, 0, 440, 350)); view.show(&sln); // Calculate error wrt. exact solution. CustomExactSolution sln_exact(&mesh, K); double err = Global<double>::calc_abs_error(&sln, &sln_exact, HERMES_H1_NORM); printf("err = %g, err_squared = %g\n\n", err, err*err); // 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("square.mesh", &mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary("Bdy", INIT_BDY_REF_NUM); // Initialize boundary conditions. CustomEssentialBCNonConst bc_essential("Bdy"); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); // Initialize previous iteration solution for the Picard's method. CustomInitialCondition sln_prev_iter(&mesh, INIT_COND_CONST); // Initialize the weak formulation. CustomNonlinearity lambda(alpha,beta); CustomNonlinearBulk ksi(gama,delta); Hermes2DFunction<double> src(-heat_src); CustomWeakFormPicard wf(&sln_prev_iter, &lambda, &ksi, &src); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, &space); // Initialize the Picard solver. PicardSolver<double> picard(&dp, &sln_prev_iter, matrix_solver); // Perform the Picard's iteration (Anderson acceleration on by default). if (!picard.solve(PICARD_TOL, PICARD_MAX_ITER, PICARD_NUM_LAST_ITER_USED, PICARD_ANDERSON_BETA)) error("Picard's iteration failed."); // Translate the coefficient vector into a Solution. Solution<double> sln; Solution<double>::vector_to_solution(picard.get_sln_vector(), &space, &sln); // Visualise the solution and mesh. ScalarView s_view("Solution", new WinGeom(0, 0, 440, 350)); s_view.show_mesh(false); s_view.show(&sln_prev_iter); OrderView o_view("Mesh", new WinGeom(450, 0, 420, 350)); o_view.show(&space); // 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(mesh_file, mesh); // Perform initial mesh refinements (optional). for (int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); // Show the mesh. Views::MeshView mview("Nurbs", new Views::WinGeom(0, 0, 350, 350)); mview.show(mesh); // Wait for the view 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.mesh", mesh); // Initial mesh refinement. for (int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); // Create an Hcurl space with default shapeset. SpaceSharedPtr<double> space(new HcurlSpace<double>(mesh, P_INIT)); // Visualize FE basis. VectorBaseView<double> bview("VectorBaseView", new WinGeom(0, 0, 700, 600)); bview.show(space); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. MeshSharedPtr mesh(new Mesh); if (USE_XML_FORMAT == true) { MeshReaderH2DXML mloader; Hermes::Mixins::Loggable::Static::info("Reading mesh in XML format."); try { mloader.load("domain.xml", mesh); } catch(Hermes::Exceptions::Exception& e) { e.print_msg(); } } else { MeshReaderH2D mloader; Hermes::Mixins::Loggable::Static::info("Reading mesh in original format."); mloader.load("domain.mesh", mesh); } // Perform initial mesh refinements (optional). for (int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); // Initialize the weak formulation. CustomWeakFormPoisson wf("Aluminum", new Hermes1DFunction<double>(LAMBDA_AL), "Copper", new Hermes1DFunction<double>(LAMBDA_CU), new Hermes2DFunction<double>(-VOLUME_HEAT_SRC)); // Initialize essential boundary conditions. DefaultEssentialBCConst<double> bc_essential( Hermes::vector<std::string>("Bottom", "Inner", "Outer", "Left"), FIXED_BDY_TEMP); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT)); int ndof = space->get_num_dofs(); Hermes::Mixins::Loggable::Static::info("ndof = %d", ndof); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, space); // Initialize Newton solver. NewtonSolver<double> newton(&dp); // Perform Newton's iteration. try { // When newton.solve() is used without any parameters, this means that the initial coefficient // vector will be the zero vector, tolerance will be 1e-8, maximum allowed number of iterations // will be 100, and residual will be measured using Euclidean vector norm. newton.solve(); } catch(std::exception& e) { std::cout << e.what(); } // Translate the resulting coefficient vector into a Solution. MeshFunctionSharedPtr<double> sln(new Solution<double>); Solution<double>::vector_to_solution(newton.get_sln_vector(), space, sln); // VTK output. if (VTK_VISUALIZATION) { // Output solution in VTK format. Linearizer lin; bool mode_3D = true; lin.save_solution_vtk(sln, "sln.vtk", "Temperature", mode_3D); Hermes::Mixins::Loggable::Static::info("Solution in VTK format saved to file %s.", "sln.vtk"); // Output mesh and element orders in VTK format. Orderizer ord; ord.save_orders_vtk(space, "ord.vtk"); Hermes::Mixins::Loggable::Static::info("Element orders in VTK format saved to file %s.", "ord.vtk"); } // Visualize the solution. if (HERMES_VISUALIZATION) { ScalarView view("Solution", new WinGeom(0, 0, 440, 350)); // Hermes uses adaptive FEM to approximate higher-order FE solutions with linear // triangles for OpenGL. The second parameter of View::show() sets the error // tolerance for that. Options are HERMES_EPS_LOW, HERMES_EPS_NORMAL (default), // HERMES_EPS_HIGH and HERMES_EPS_VERYHIGH. The size of the graphics file grows // considerably with more accurate representation, so use it wisely. view.show(sln, HERMES_EPS_HIGH); View::wait(); } return 0; }
int main(int argc, char* argv[]) { // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); // Initialize the time. double current_time = 0; // mesh-> MeshSharedPtr mesh(new Mesh); // Init mesh-> MeshReaderH2D 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("Boundary_air", INIT_REF_NUM_BDY); mesh->refine_towards_boundary("Boundary_ground", INIT_REF_NUM_BDY); // Initialize boundary conditions. Hermes::Hermes2D::DefaultEssentialBCConst<double> bc_essential("Boundary_ground", TEMP_INIT); Hermes::Hermes2D::EssentialBCs<double> bcs(&bc_essential); // space-> SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT)); // Solution pointer. MeshFunctionSharedPtr<double> sln_time_prev(new ConstantSolution<double>(mesh, TEMP_INIT)); MeshFunctionSharedPtr<double> sln_time_new(new Solution<double>(mesh)); WeakFormSharedPtr<double> wf(new CustomWeakFormHeatRK("Boundary_air", ALPHA, LAMBDA, HEATCAP, RHO, ¤t_time, TEMP_INIT, T_FINAL)); // Initialize views. Hermes::Hermes2D::Views::ScalarView Tview("Temperature", new Hermes::Hermes2D::Views::WinGeom(0, 0, 450, 600)); Tview.set_min_max_range(0, 20); Tview.fix_scale_width(30); // Initialize Runge-Kutta time stepping. RungeKutta<double> runge_kutta(wf, space, &bt); runge_kutta.set_tolerance(NEWTON_TOL); runge_kutta.set_verbose_output(true); runge_kutta.set_time_step(time_step); // Iteration number. int iteration = 0; // Time stepping loop: do { // Perform one Runge-Kutta time step according to the selected Butcher's table. try { runge_kutta.set_time(current_time); runge_kutta.rk_time_step_newton(sln_time_prev, sln_time_new); } catch (Exceptions::Exception& e) { e.print_msg(); } // Show the new_ time level solution. char title[100]; sprintf(title, "Time %3.2f s", current_time); Tview.set_title(title); Tview.show(sln_time_new); // Copy solution for the new_ time step. sln_time_prev->copy(sln_time_new); // Increase current time and time step counter. current_time += time_step; iteration++; } while (current_time < T_FINAL); // Wait for the view to be closed. Hermes::Hermes2D::Views::View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. MeshSharedPtr mesh(new Mesh); MeshReaderH2D mloader; mloader.load("domain.mesh", mesh); // Define exact solution. MeshFunctionSharedPtr<double> exact_sln(new CustomExactSolution(mesh)); // Initialize the weak formulation. CustomWeakForm wf("Right"); // Initialize boundary conditions. DefaultEssentialBCConst<double> bc_essential("Left", 0.0); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT)); // Set the space to adaptivity. adaptivity.set_space(space); // Initialize approximate solution. MeshFunctionSharedPtr<double> sln(new Solution<double>()); // Initialize refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST); // Initialize views. Views::ScalarView sview("Solution", new Views::WinGeom(0, 0, 440, 350)); sview.show_mesh(false); sview.fix_scale_width(50); Views::OrderView oview("Polynomial orders", new Views::WinGeom(450, 0, 420, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est, graph_dof_exact, graph_cpu_exact; // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { cpu_time.tick(); // Construct globally refined reference mesh and setup reference space. Mesh::ReferenceMeshCreator refMeshCreator(mesh); MeshSharedPtr ref_mesh = refMeshCreator.create_ref_mesh(); Space<double>::ReferenceSpaceCreator refSpaceCreator(space, ref_mesh); SpaceSharedPtr<double> ref_space = refSpaceCreator.create_ref_space(); int ndof_ref = ref_space->get_num_dofs(); Hermes::Mixins::Loggable::Static::info("---- Adaptivity step %d (%d DOF):", as, ndof_ref); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Solving on reference mesh."); // Assemble the discrete problem. DiscreteProblem<double> dp(&wf, ref_space); NewtonSolver<double> newton(&dp); //newton.set_verbose_output(false); MeshFunctionSharedPtr<double> ref_sln(new Solution<double>()); try { newton.solve(); } catch(Hermes::Exceptions::Exception e) { e.print_msg(); throw Hermes::Exceptions::Exception("Newton's iteration failed."); }; // Translate the resulting coefficient vector into the instance of Solution. Solution<double>::vector_to_solution(newton.get_sln_vector(), ref_space, ref_sln); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Solution: %g s", cpu_time.last()); // Project the fine mesh solution onto the coarse mesh. Hermes::Mixins::Loggable::Static::info("Calculating error estimate and exact error."); OGProjection<double> ogProjection; ogProjection.project_global(space, ref_sln, sln); // Calculate element errors and total error estimate. errorCalculator.calculate_errors(sln, exact_sln, false); double err_exact_rel = errorCalculator.get_total_error_squared() * 100; errorCalculator.calculate_errors(sln, ref_sln, true); double err_est_rel = errorCalculator.get_total_error_squared() * 100; cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Error calculation: %g s", cpu_time.last()); // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_fine: %d", space->get_num_dofs(), ref_space->get_num_dofs()); Hermes::Mixins::Loggable::Static::info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel); // Time measurement. cpu_time.tick(); double accum_time = cpu_time.accumulated(); // View the coarse mesh solution and polynomial orders. sview.show(sln); oview.show(space); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(space->get_num_dofs(), err_est_rel); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(accum_time, err_est_rel); graph_cpu_est.save("conv_cpu_est.dat"); graph_dof_exact.add_values(space->get_num_dofs(), err_exact_rel); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(accum_time, err_exact_rel); graph_cpu_exact.save("conv_cpu_exact.dat"); cpu_time.tick(Hermes::Mixins::TimeMeasurable::HERMES_SKIP); // If err_est too large, adapt the mesh. The NDOF test must be here, so that the solution may be visualized // after ending due to this criterion. if (err_exact_rel < ERR_STOP) done = true; else done = adaptivity.adapt(&selector); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Adaptation: %g s", cpu_time.last()); // Increase the counter of adaptivity steps. if (done == false) as++; } while (done == false); Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. Views::View::wait(); }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load(mesh_file.c_str(), &mesh); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Solution variables. Solution<double> sln1, sln2, sln3, sln4; Hermes::vector<Solution<double>*> solutions(&sln1, &sln2, &sln3, &sln4); // Define initial conditions. Hermes::Mixins::Loggable::Static::info("Setting initial conditions."); ConstantSolution<double> iter1(&mesh, 1.00), iter2(&mesh, 1.00), iter3(&mesh, 1.00), iter4(&mesh, 1.00); Hermes::vector<MeshFunction<double>*> iterates(&iter1, &iter2, &iter3, &iter4); // Create H1 spaces with default shapesets. H1Space<double> space1(&mesh, P_INIT_1); H1Space<double> space2(&mesh, P_INIT_2); H1Space<double> space3(&mesh, P_INIT_3); H1Space<double> space4(&mesh, P_INIT_4); Hermes::vector<const Space<double>* > spaces(&space1, &space2, &space3, &space4); int ndof = Space<double>::get_num_dofs(spaces); Hermes::Mixins::Loggable::Static::info("ndof = %d", ndof); // Initialize views. ScalarView view1("Neutron flux 1", new WinGeom(0, 0, 320, 600)); ScalarView view2("Neutron flux 2", new WinGeom(350, 0, 320, 600)); ScalarView view3("Neutron flux 3", new WinGeom(700, 0, 320, 600)); ScalarView view4("Neutron flux 4", new WinGeom(1050, 0, 320, 600)); // Do not show meshes, set 3D mode. view1.show_mesh(false); view1.set_3d_mode(true); view2.show_mesh(false); view2.set_3d_mode(true); view3.show_mesh(false); view3.set_3d_mode(true); view4.show_mesh(false); view4.set_3d_mode(true); // Load physical data of the problem for the 4 energy groups. Hermes::Hermes2D::WeakFormsNeutronics::Multigroup::MaterialProperties::Diffusion::MaterialPropertyMaps matprop(4); matprop.set_D(D); matprop.set_Sigma_r(Sr); matprop.set_Sigma_s(Ss); matprop.set_Sigma_a(Sa); matprop.set_Sigma_f(Sf); matprop.set_nu(nu); matprop.set_chi(chi); matprop.validate(); // Printing table of material properties. std::cout << matprop; // Initialize the weak formulation. CustomWeakForm wf(matprop, iterates, k_eff, bdy_vacuum); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, spaces); // Initialize Newton solver. NewtonSolver<double> newton(&dp); // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; // Main power iteration loop: int it = 1; bool done = false; do { Hermes::Mixins::Loggable::Static::info("------------ Power iteration %d:", it); Hermes::Mixins::Loggable::Static::info("Newton's method."); // Perform Newton's iteration. try { newton.set_newton_max_iter(NEWTON_MAX_ITER); newton.set_newton_tol(NEWTON_TOL); newton.solve_keep_jacobian(); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); throw Hermes::Exceptions::Exception("Newton's iteration failed."); } // Debug. //printf("\n=================================================\n"); //for (int d = 0; d < ndof; d++) printf("%g ", newton.get_sln_vector()[d]); // Translate the resulting coefficient vector into a Solution. Solution<double>::vector_to_solutions(newton.get_sln_vector(), spaces, solutions); // Show intermediate solutions. view1.show(&sln1); view2.show(&sln2); view3.show(&sln3); view4.show(&sln4); // Compute eigenvalue. SourceFilter source(solutions, &matprop, core); SourceFilter source_prev(iterates, &matprop, core); double k_new = k_eff * (integrate(&source, core) / integrate(&source_prev, core)); Hermes::Mixins::Loggable::Static::info("Largest eigenvalue: %.8g, rel. difference from previous it.: %g", k_new, fabs((k_eff - k_new) / k_new)); // Stopping criterion. if (fabs((k_eff - k_new) / k_new) < ERROR_STOP) done = true; // Update eigenvalue. k_eff = k_new; wf.update_keff(k_eff); if (!done) { // Save solutions for the next iteration. iter1.copy(&sln1); iter2.copy(&sln2); iter3.copy(&sln3); iter4.copy(&sln4); it++; } } while (!done); // Time measurement. cpu_time.tick(); // Show solutions. view1.show(&sln1); view2.show(&sln2); view3.show(&sln3); view4.show(&sln4); // Skip visualization time. cpu_time.tick(Hermes::Mixins::TimeMeasurable::HERMES_SKIP); // 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[]) { // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; cpu_time.tick(); // Load physical data of the problem. MaterialPropertyMaps matprop(N_GROUPS); matprop.set_D(D); matprop.set_Sigma_r(Sr); matprop.set_Sigma_s(Ss); matprop.set_Sigma_a(Sa); matprop.set_Sigma_f(Sf); matprop.set_nu(nu); matprop.set_chi(chi); matprop.validate(); std::cout << matprop; // Use multimesh, i.e. create one mesh for each energy group. Hermes::vector<Mesh *> meshes; for (unsigned int g = 0; g < matprop.get_G(); g++) meshes.push_back(new Mesh()); // Load the mesh for the 1st group. MeshReaderH2D mloader; mloader.load(mesh_file.c_str(), meshes[0]); for (unsigned int g = 1; g < matprop.get_G(); g++) { // Obtain meshes for the 2nd to 4th group by cloning the mesh loaded for the 1st group. meshes[g]->copy(meshes[0]); // Initial uniform refinements. for (int i = 0; i < INIT_REF_NUM[g]; i++) meshes[g]->refine_all_elements(); } for (int i = 0; i < INIT_REF_NUM[0]; i++) meshes[0]->refine_all_elements(); // Create pointers to solutions on coarse and fine meshes and from the latest power iteration, respectively. Hermes::vector<Solution<double>*> coarse_solutions, fine_solutions; Hermes::vector<MeshFunction<double>*> power_iterates; // Initialize all the new solution variables. for (unsigned int g = 0; g < matprop.get_G(); g++) { coarse_solutions.push_back(new Solution<double>()); fine_solutions.push_back(new Solution<double>()); power_iterates.push_back(new ConstantSolution<double>(meshes[g], 1.0)); } // Create the approximation spaces with the default shapeset. H1Space<double> space1(meshes[0], P_INIT[0]); H1Space<double> space2(meshes[1], P_INIT[1]); H1Space<double> space3(meshes[2], P_INIT[2]); H1Space<double> space4(meshes[3], P_INIT[3]); Hermes::vector<const Space<double>*> const_spaces(&space1, &space2, &space3, &space4); Hermes::vector<Space<double>*> spaces(&space1, &space2, &space3, &space4); // Initialize the weak formulation. CustomWeakForm wf(matprop, power_iterates, k_eff, bdy_vacuum); // Initialize the discrete algebraic representation of the problem and its solver. // // Create the matrix and right-hand side vector for the solver. SparseMatrix<double>* mat = create_matrix<double>(); Vector<double>* rhs = create_vector<double>(); // Instantiate the solver itself. LinearMatrixSolver<double>* solver = create_linear_solver<double>( mat, rhs); // Initialize views. /* for 1280x800 display */ ScalarView view1("Neutron flux 1", new WinGeom(0, 0, 320, 400)); ScalarView view2("Neutron flux 2", new WinGeom(330, 0, 320, 400)); ScalarView view3("Neutron flux 3", new WinGeom(660, 0, 320, 400)); ScalarView view4("Neutron flux 4", new WinGeom(990, 0, 320, 400)); OrderView oview1("Mesh for group 1", new WinGeom(0, 450, 320, 500)); OrderView oview2("Mesh for group 2", new WinGeom(330, 450, 320, 500)); OrderView oview3("Mesh for group 3", new WinGeom(660, 450, 320, 500)); OrderView oview4("Mesh for group 4", new WinGeom(990, 450, 320, 500)); /* for adjacent 1280x800 and 1680x1050 displays ScalarView view1("Neutron flux 1", new WinGeom(0, 0, 640, 480)); ScalarView view2("Neutron flux 2", new WinGeom(650, 0, 640, 480)); ScalarView view3("Neutron flux 3", new WinGeom(1300, 0, 640, 480)); ScalarView view4("Neutron flux 4", new WinGeom(1950, 0, 640, 480)); OrderView oview1("Mesh for group 1", new WinGeom(1300, 500, 340, 500)); OrderView oview2("Mesh for group 2", new WinGeom(1650, 500, 340, 500)); OrderView oview3("Mesh for group 3", new WinGeom(2000, 500, 340, 500)); OrderView oview4("Mesh for group 4", new WinGeom(2350, 500, 340, 500)); */ Hermes::vector<ScalarView *> sviews(&view1, &view2, &view3, &view4); Hermes::vector<OrderView *> oviews(&oview1, &oview2, &oview3, &oview4); for (unsigned int g = 0; g < matprop.get_G(); g++) { sviews[g]->show_mesh(false); sviews[g]->set_3d_mode(true); } // DOF and CPU convergence graphs GnuplotGraph graph_dof("Error convergence", "NDOF", "log(error)"); graph_dof.add_row("H1 err. est. [%]", "r", "-", "o"); graph_dof.add_row("L2 err. est. [%]", "g", "-", "s"); graph_dof.add_row("Keff err. est. [milli-%]", "b", "-", "d"); graph_dof.set_log_y(); graph_dof.show_legend(); graph_dof.show_grid(); GnuplotGraph graph_dof_evol("Evolution of NDOF", "Adaptation step", "NDOF"); graph_dof_evol.add_row("group 1", "r", "-", "o"); graph_dof_evol.add_row("group 2", "g", "-", "x"); graph_dof_evol.add_row("group 3", "b", "-", "+"); graph_dof_evol.add_row("group 4", "m", "-", "*"); graph_dof_evol.set_log_y(); graph_dof_evol.set_legend_pos("bottom right"); graph_dof_evol.show_grid(); GnuplotGraph graph_cpu("Error convergence", "CPU time [s]", "log(error)"); graph_cpu.add_row("H1 err. est. [%]", "r", "-", "o"); graph_cpu.add_row("L2 err. est. [%]", "g", "-", "s"); graph_cpu.add_row("Keff err. est. [milli-%]", "b", "-", "d"); graph_cpu.set_log_y(); graph_cpu.show_legend(); graph_cpu.show_grid(); // Initialize the refinement selectors. H1ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); Hermes::vector<RefinementSelectors::Selector<double>*> selectors; for (unsigned int g = 0; g < matprop.get_G(); g++) selectors.push_back(&selector); Hermes::vector<MatrixFormVol<double>*> projection_jacobian; Hermes::vector<VectorFormVol<double>*> projection_residual; for (unsigned int g = 0; g < matprop.get_G(); g++) { projection_jacobian.push_back(new H1AxisymProjectionJacobian(g)); projection_residual.push_back(new H1AxisymProjectionResidual(g, power_iterates[g])); } Hermes::vector<ProjNormType> proj_norms_h1, proj_norms_l2; for (unsigned int g = 0; g < matprop.get_G(); g++) { proj_norms_h1.push_back(HERMES_H1_NORM); proj_norms_l2.push_back(HERMES_L2_NORM); } // Initial power iteration to obtain a coarse estimate of the eigenvalue and the fission source. Hermes::Mixins::Loggable::Static::info("Coarse mesh power iteration, %d + %d + %d + %d = %d ndof:", report_num_dofs(spaces)); power_iteration(matprop, const_spaces, &wf, power_iterates, core, TOL_PIT_CM, matrix_solver); // Adaptivity loop: int as = 1; bool done = false; do { Hermes::Mixins::Loggable::Static::info("---- Adaptivity step %d:", as); // Construct globally refined meshes and setup reference spaces on them. Hermes::vector<const Space<double>*> ref_spaces_const; Hermes::vector<Mesh *> ref_meshes; for (unsigned int g = 0; g < matprop.get_G(); g++) { ref_meshes.push_back(new Mesh()); Mesh *ref_mesh = ref_meshes.back(); ref_mesh->copy(spaces[g]->get_mesh()); ref_mesh->refine_all_elements(); int order_increase = 1; ref_spaces_const.push_back(spaces[g]->dup(ref_mesh, order_increase)); } #ifdef WITH_PETSC // PETSc assembling is currently slow for larger matrices, so we switch to // UMFPACK when matrices of order >8000 start to appear. if (Space<double>::get_num_dofs(ref_spaces_const) > 8000 && matrix_solver == SOLVER_PETSC) { // Delete the old solver. delete mat; delete rhs; delete solver; // Create a new one. matrix_solver = SOLVER_UMFPACK; mat = create_matrix<double>(); rhs = create_vector<double>(); solver = create_linear_solver<double>( mat, rhs); } #endif // Solve the fine mesh problem. Hermes::Mixins::Loggable::Static::info("Fine mesh power iteration, %d + %d + %d + %d = %d ndof:", report_num_dofs(ref_spaces_const)); power_iteration(matprop, ref_spaces_const, &wf, power_iterates, core, TOL_PIT_RM, matrix_solver); // Store the results. for (unsigned int g = 0; g < matprop.get_G(); g++) fine_solutions[g]->copy((static_cast<Solution<double>*>(power_iterates[g]))); Hermes::Mixins::Loggable::Static::info("Projecting fine mesh solutions on coarse meshes."); // This is commented out as the appropriate method was deleted in the commit // "Cleaning global projections" (b282194946225014faa1de37f20112a5a5d7ab5a). //OGProjection<double> ogProjection; ogProjection.project_global(spaces, projection_jacobian, projection_residual, coarse_solutions); // Time measurement. cpu_time.tick(); // View the coarse mesh solution and meshes. for (unsigned int g = 0; g < matprop.get_G(); g++) { sviews[g]->show(coarse_solutions[g]); oviews[g]->show(spaces[g]); } // Skip visualization time. cpu_time.tick(Hermes::Mixins::TimeMeasurable::HERMES_SKIP); // Report the number of negative eigenfunction values. Hermes::Mixins::Loggable::Static::info("Num. of negative values: %d, %d, %d, %d", get_num_of_neg(coarse_solutions[0]), get_num_of_neg(coarse_solutions[1]), get_num_of_neg(coarse_solutions[2]), get_num_of_neg(coarse_solutions[3])); // Calculate element errors and total error estimate. Adapt<double> adapt_h1(spaces); Adapt<double> adapt_l2(spaces); for (unsigned int g = 0; g < matprop.get_G(); g++) { adapt_h1.set_error_form(g, g, new ErrorForm(proj_norms_h1[g])); adapt_l2.set_error_form(g, g, new ErrorForm(proj_norms_l2[g])); } // Calculate element errors and error estimates in H1 and L2 norms. Use the H1 estimate to drive adaptivity. Hermes::Mixins::Loggable::Static::info("Calculating errors."); Hermes::vector<double> h1_group_errors, l2_group_errors; double h1_err_est = adapt_h1.calc_err_est(coarse_solutions, fine_solutions, &h1_group_errors) * 100; double l2_err_est = adapt_l2.calc_err_est(coarse_solutions, fine_solutions, &l2_group_errors, false) * 100; // Time measurement. cpu_time.tick(); double cta = cpu_time.accumulated(); // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d + %d + %d + %d = %d", report_num_dofs(spaces)); // Millipercent eigenvalue error w.r.t. the reference value (see physical_parameters.cpp). double keff_err = 1e5*fabs(wf.get_keff() - REF_K_EFF)/REF_K_EFF; Hermes::Mixins::Loggable::Static::info("per-group err_est_coarse (H1): %g%%, %g%%, %g%%, %g%%", report_errors(h1_group_errors)); Hermes::Mixins::Loggable::Static::info("per-group err_est_coarse (L2): %g%%, %g%%, %g%%, %g%%", report_errors(l2_group_errors)); Hermes::Mixins::Loggable::Static::info("total err_est_coarse (H1): %g%%", h1_err_est); Hermes::Mixins::Loggable::Static::info("total err_est_coarse (L2): %g%%", l2_err_est); Hermes::Mixins::Loggable::Static::info("k_eff err: %g milli-percent", keff_err); // Add entry to DOF convergence graph. int ndof_coarse = spaces[0]->get_num_dofs() + spaces[1]->get_num_dofs() + spaces[2]->get_num_dofs() + spaces[3]->get_num_dofs(); graph_dof.add_values(0, ndof_coarse, h1_err_est); graph_dof.add_values(1, ndof_coarse, l2_err_est); graph_dof.add_values(2, ndof_coarse, keff_err); // Add entry to CPU convergence graph. graph_cpu.add_values(0, cta, h1_err_est); graph_cpu.add_values(1, cta, l2_err_est); graph_cpu.add_values(2, cta, keff_err); for (unsigned int g = 0; g < matprop.get_G(); g++) graph_dof_evol.add_values(g, as, Space<double>::get_num_dofs(spaces[g])); cpu_time.tick(Hermes::Mixins::TimeMeasurable::HERMES_SKIP); // If err_est too large, adapt the mesh (L2 norm chosen since (weighted integrals of) solution values // are more important for further analyses than the derivatives. if (l2_err_est < ERR_STOP) done = true; else { Hermes::Mixins::Loggable::Static::info("Adapting the coarse mesh."); done = adapt_h1.adapt(selectors, THRESHOLD, STRATEGY, MESH_REGULARITY); if (spaces[0]->get_num_dofs() + spaces[1]->get_num_dofs() + spaces[2]->get_num_dofs() + spaces[3]->get_num_dofs() >= NDOF_STOP) done = true; } // Free reference meshes and spaces. for (unsigned int g = 0; g < matprop.get_G(); g++) { delete ref_spaces_const[g]; delete ref_meshes[g]; } as++; if (as >= MAX_ADAPT_NUM) done = true; } while(done == false); Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated()); for (unsigned int g = 0; g < matprop.get_G(); g++) { delete spaces[g]; delete meshes[g]; delete coarse_solutions[g], delete fine_solutions[g]; delete power_iterates[g]; } delete mat; delete rhs; delete solver; graph_dof.save("conv_dof.gp"); graph_cpu.save("conv_cpu.gp"); graph_dof_evol.save("dof_evol.gp"); // 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("domain.mesh", mesh); // Initial mesh refinements. mesh->refine_towards_boundary(BDY_OBSTACLE, 2, false); mesh->refine_towards_boundary(BDY_TOP, 2, true); // '4' is the number of levels, mesh->refine_towards_boundary(BDY_BOTTOM, 2, true); // 'true' stands for anisotropic refinements. mesh->refine_all_elements(); // Initialize boundary conditions. EssentialBCNonConst bc_left_vel_x(BDY_LEFT, VEL_INLET, H, STARTUP_TIME); Hermes::Hermes2D::DefaultEssentialBCConst<double> bc_other_vel_x(Hermes::vector<std::string>(BDY_BOTTOM, BDY_TOP, BDY_OBSTACLE), 0.0); Hermes::Hermes2D::EssentialBCs<double> bcs_vel_x(Hermes::vector<EssentialBoundaryCondition<double> *>(&bc_left_vel_x, &bc_other_vel_x)); Hermes::Hermes2D::DefaultEssentialBCConst<double> bc_vel_y(Hermes::vector<std::string>(BDY_LEFT, BDY_BOTTOM, BDY_TOP, BDY_OBSTACLE), 0.0); Hermes::Hermes2D::EssentialBCs<double> bcs_vel_y(&bc_vel_y); Hermes::Hermes2D::EssentialBCs<double> bcs_pressure; // Spaces for velocity components and pressure. SpaceSharedPtr<double> xvel_space(new H1Space<double>(mesh, &bcs_vel_x, P_INIT_VEL)); SpaceSharedPtr<double> yvel_space(new H1Space<double>(mesh, &bcs_vel_y, P_INIT_VEL)); #ifdef PRESSURE_IN_L2 SpaceSharedPtr<double> p_space(new L2Space<double> (mesh, P_INIT_PRESSURE)); #else SpaceSharedPtr<double> p_space(new H1Space<double> (mesh, &bcs_pressure, P_INIT_PRESSURE)); #endif // Calculate and report the number of degrees of freedom. int ndof = Space<double>::get_num_dofs(Hermes::vector<SpaceSharedPtr<double> >(xvel_space, yvel_space, p_space)); // Define projection norms. NormType vel_proj_norm = HERMES_H1_NORM; #ifdef PRESSURE_IN_L2 NormType p_proj_norm = HERMES_L2_NORM; #else NormType p_proj_norm = HERMES_H1_NORM; #endif // Solutions for the Newton's iteration and time stepping. MeshFunctionSharedPtr<double> xvel_prev_time(new ConstantSolution<double> (mesh, 0.0)); MeshFunctionSharedPtr<double> yvel_prev_time(new ConstantSolution<double> (mesh, 0.0)); MeshFunctionSharedPtr<double> p_prev_time(new ConstantSolution<double> (mesh, 0.0)); // Initialize weak formulation. WeakFormNSNewton wf(STOKES, RE, TAU, xvel_prev_time, yvel_prev_time); UExtFunctionSharedPtr<double> fn_0(new CustomUExtFunction(0)); UExtFunctionSharedPtr<double> fn_1(new CustomUExtFunction(1)); wf.set_ext(Hermes::vector<MeshFunctionSharedPtr<double> >(xvel_prev_time, yvel_prev_time)); wf.set_u_ext_fn(Hermes::vector<UExtFunctionSharedPtr<double> >(fn_0, fn_1)); // Initialize the Newton solver. Hermes::Hermes2D::NewtonSolver<double> newton; newton.set_weak_formulation(&wf); Hermes::vector<SpaceSharedPtr<double> > spaces(xvel_space, yvel_space, p_space); newton.set_spaces(spaces); // Initialize views. Views::VectorView vview("velocity[m/s]", new Views::WinGeom(0, 0, 750, 240)); Views::ScalarView pview("pressure[Pa]", new Views::WinGeom(0, 290, 750, 240)); vview.set_min_max_range(0, 1.6); vview.fix_scale_width(80); //pview.set_min_max_range(-0.9, 1.0); pview.fix_scale_width(80); if(HERMES_VISUALIZATION) pview.show_mesh(true); // Project the initial condition on the FE space to obtain initial // coefficient vector for the Newton's method. double* coeff_vec = new double[Space<double>::get_num_dofs(Hermes::vector<SpaceSharedPtr<double> >(xvel_space, yvel_space, p_space))]; OGProjection<double> ogProjection; ogProjection.project_global(Hermes::vector<SpaceSharedPtr<double> >(xvel_space, yvel_space, p_space), Hermes::vector<MeshFunctionSharedPtr<double> >(xvel_prev_time, yvel_prev_time, p_prev_time), coeff_vec, Hermes::vector<NormType>(vel_proj_norm, vel_proj_norm, p_proj_norm)); newton.set_max_allowed_iterations(max_allowed_iterations); newton.set_tolerance(NEWTON_TOL, Hermes::Solvers::ResidualNormAbsolute); newton.set_sufficient_improvement_factor_jacobian(1e-2); //newton.set_jacobian_constant(); // Time-stepping loop: char title[100]; int num_time_steps = T_FINAL / TAU; for (int ts = 1; ts <= num_time_steps; ts++) { current_time += TAU; Hermes::Mixins::Loggable::Static::info("Time step %i, time %f.", ts, current_time); // Update time-dependent essential BCs. newton.set_time(current_time); // Perform Newton's iteration and translate the resulting coefficient vector into previous time level solutions. try { newton.solve(coeff_vec); } catch(Hermes::Exceptions::Exception& e) { e.print_msg(); } Hermes::vector<MeshFunctionSharedPtr<double> > tmp(xvel_prev_time, yvel_prev_time, p_prev_time); Hermes::Hermes2D::Solution<double>::vector_to_solutions(newton.get_sln_vector(), Hermes::vector<SpaceSharedPtr<double> >(xvel_space, yvel_space, p_space), tmp); // Show the solution at the end of time step. if(HERMES_VISUALIZATION) { sprintf(title, "Velocity, time %g", current_time); vview.set_title(title); vview.show(xvel_prev_time, yvel_prev_time); sprintf(title, "Pressure, time %g", current_time); pview.set_title(title); pview.show(p_prev_time); } } delete [] coeff_vec; return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("domain.mesh", &mesh); // Initial mesh refinements. mesh.refine_all_elements(); mesh.refine_towards_boundary(BDY_OBSTACLE, 4, false); mesh.refine_towards_boundary(BDY_TOP, 4, true); // '4' is the number of levels, mesh.refine_towards_boundary(BDY_BOTTOM, 4, true); // 'true' stands for anisotropic refinements. // Initialize boundary conditions. EssentialBCNonConst bc_left_vel_x(BDY_LEFT, VEL_INLET, H, STARTUP_TIME); DefaultEssentialBCConst<double> bc_other_vel_x(Hermes::vector<std::string>(BDY_BOTTOM, BDY_TOP, BDY_OBSTACLE), 0.0); EssentialBCs<double> bcs_vel_x(Hermes::vector<EssentialBoundaryCondition<double> *>(&bc_left_vel_x, &bc_other_vel_x)); DefaultEssentialBCConst<double> bc_vel_y(Hermes::vector<std::string>(BDY_LEFT, BDY_BOTTOM, BDY_TOP, BDY_OBSTACLE), 0.0); EssentialBCs<double> bcs_vel_y(&bc_vel_y); // Spaces for velocity components and pressure. H1Space<double> xvel_space(&mesh, &bcs_vel_x, P_INIT_VEL); H1Space<double> yvel_space(&mesh, &bcs_vel_y, P_INIT_VEL); #ifdef PRESSURE_IN_L2 L2Space<double> p_space(&mesh, P_INIT_PRESSURE); #else H1Space<double> p_space(&mesh, P_INIT_PRESSURE); #endif // Calculate and report the number of degrees of freedom. int ndof = Space<double>::get_num_dofs(Hermes::vector<Space<double>*>(&xvel_space, &yvel_space, &p_space)); info("ndof = %d.", ndof); // Define projection norms. ProjNormType vel_proj_norm = HERMES_H1_NORM; #ifdef PRESSURE_IN_L2 ProjNormType p_proj_norm = HERMES_L2_NORM; #else ProjNormType p_proj_norm = HERMES_H1_NORM; #endif // Solutions for the Newton's iteration and time stepping. info("Setting initial conditions."); ZeroSolution xvel_prev_time(&mesh); ZeroSolution yvel_prev_time(&mesh); ZeroSolution p_prev_time(&mesh); // Initialize weak formulation. WeakForm<double>* wf; if (NEWTON) wf = new WeakFormNSNewton(STOKES, RE, TAU, &xvel_prev_time, &yvel_prev_time); else wf = new WeakFormNSSimpleLinearization(STOKES, RE, TAU, &xvel_prev_time, &yvel_prev_time); // Initialize the FE problem. DiscreteProblem<double> dp(wf, Hermes::vector<Space<double>*>(&xvel_space, &yvel_space, &p_space)); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix<double>* matrix = create_matrix<double>(matrix_solver_type); Vector<double>* rhs = create_vector<double>(matrix_solver_type); LinearSolver<double>* solver = create_linear_solver<double>(matrix_solver_type, matrix, rhs); // Initialize views. VectorView vview("velocity [m/s]", new WinGeom(0, 0, 750, 240)); ScalarView pview("pressure [Pa]", new WinGeom(0, 290, 750, 240)); vview.set_min_max_range(0, 1.6); vview.fix_scale_width(80); //pview.set_min_max_range(-0.9, 1.0); pview.fix_scale_width(80); pview.show_mesh(true); // Project the initial condition on the FE space to obtain initial // coefficient vector for the Newton's method. double* coeff_vec = new double[Space<double>::get_num_dofs(Hermes::vector<Space<double>*>(&xvel_space, &yvel_space, &p_space))]; if (NEWTON) { info("Projecting initial condition to obtain initial vector for the Newton's method."); OGProjection<double>::project_global(Hermes::vector<Space<double>*>(&xvel_space, &yvel_space, &p_space), Hermes::vector<MeshFunction<double>*>(&xvel_prev_time, &yvel_prev_time, &p_prev_time), coeff_vec, matrix_solver_type, Hermes::vector<ProjNormType>(vel_proj_norm, vel_proj_norm, p_proj_norm)); } // Time-stepping loop: char title[100]; int num_time_steps = T_FINAL / TAU; for (int ts = 1; ts <= num_time_steps; ts++) { current_time += TAU; info("---- Time step %d, time = %g:", ts, current_time); // Update time-dependent essential BCs. if (current_time <= STARTUP_TIME) { info("Updating time-dependent essential BC."); Space<double>::update_essential_bc_values(Hermes::vector<Space<double>*>(&xvel_space, &yvel_space, &p_space), current_time); } if (NEWTON) { // Perform Newton's iteration. info("Solving nonlinear problem:"); Hermes::Hermes2D::NewtonSolver<double> newton(&dp, matrix_solver_type); try { newton.solve(coeff_vec, NEWTON_TOL, NEWTON_MAX_ITER); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); error("Newton's iteration failed."); }; // Update previous time level solutions. Solution<double>::vector_to_solutions(coeff_vec, Hermes::vector<Space<double>*>(&xvel_space, &yvel_space, &p_space), Hermes::vector<Solution<double>*>(&xvel_prev_time, &yvel_prev_time, &p_prev_time)); } else { // Linear solve. info("Assembling and solving linear problem."); dp.assemble(matrix, rhs, false); if(solver->solve()) Solution<double>::vector_to_solutions(solver->get_sln_vector(), Hermes::vector<Space<double>*>(&xvel_space, &yvel_space, &p_space), Hermes::vector<Solution<double>*>(&xvel_prev_time, &yvel_prev_time, &p_prev_time)); else error ("Matrix solver failed.\n"); } // Show the solution at the end of time step. sprintf(title, "Velocity, time %g", current_time); vview.set_title(title); vview.show(&xvel_prev_time, &yvel_prev_time, HERMES_EPS_LOW); sprintf(title, "Pressure, time %g", current_time); pview.set_title(title); pview.show(&p_prev_time); } delete [] coeff_vec; delete matrix; delete rhs; delete solver; // Wait for all views 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 xmesh, ymesh, tmesh; MeshReaderH2D mloader; mloader.load("domain.mesh", &xmesh); // Master mesh. // Initialize multimesh hp-FEM. ymesh.copy(&xmesh); // Ydisp will share master mesh with xdisp. tmesh.copy(&xmesh); // Temp will share master mesh with xdisp. // Initialize boundary conditions. BCTypes bc_types_x_y; bc_types_x_y.add_bc_dirichlet(BDY_BOTTOM); bc_types_x_y.add_bc_neumann(Hermes::vector<int>(BDY_SIDES, BDY_TOP, BDY_HOLES)); BCTypes bc_types_t; bc_types_t.add_bc_dirichlet(BDY_HOLES); bc_types_t.add_bc_neumann(Hermes::vector<int>(BDY_SIDES, BDY_TOP, BDY_BOTTOM)); // Enter Dirichlet boundary values. BCValues bc_values_x_y; bc_values_x_y.add_zero(BDY_BOTTOM); BCValues bc_values_t; bc_values_t.add_const(BDY_HOLES, TEMP_INNER); // Create H1 spaces with default shapesets. H1Space<double> xdisp(&xmesh, &bc_types_x_y, &bc_values_x_y, P_INIT_DISP); H1Space<double> ydisp(MULTI ? &ymesh : &xmesh, &bc_types_x_y, &bc_values_x_y, P_INIT_DISP); H1Space<double> temp(MULTI ? &tmesh : &xmesh, &bc_types_t, &bc_values_t, P_INIT_TEMP); // Initialize the weak formulation. WeakForm wf(3); wf.add_matrix_form(0, 0, callback(bilinear_form_0_0)); wf.add_matrix_form(0, 1, callback(bilinear_form_0_1), HERMES_SYM); wf.add_matrix_form(0, 2, callback(bilinear_form_0_2)); wf.add_matrix_form(1, 1, callback(bilinear_form_1_1)); wf.add_matrix_form(1, 2, callback(bilinear_form_1_2)); wf.add_matrix_form(2, 2, callback(bilinear_form_2_2)); wf.add_vector_form(1, callback(linear_form_1)); wf.add_vector_form(2, callback(linear_form_2)); wf.add_vector_form_surf(2, callback(linear_form_surf_2)); // Initialize coarse and reference mesh solutions. Solution<double> xdisp_sln, ydisp_sln, temp_sln, ref_xdisp_sln, ref_ydisp_sln, ref_temp_sln; // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView s_view_0("Solution[xdisp]", new WinGeom(0, 0, 450, 350)); s_view_0.show_mesh(false); ScalarView s_view_1("Solution[ydisp]", new WinGeom(460, 0, 450, 350)); s_view_1.show_mesh(false); ScalarView s_view_2("Solution[temp]", new WinGeom(920, 0, 450, 350)); s_view_1.show_mesh(false); OrderView o_view_0("Mesh[xdisp]", new WinGeom(0, 360, 450, 350)); OrderView o_view_1("Mesh[ydisp]", new WinGeom(460, 360, 450, 350)); OrderView o_view_2("Mesh[temp]", new WinGeom(920, 360, 450, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est; // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Hermes::vector<Space<double> *>* ref_spaces = Space<double>::construct_refined_spaces(Hermes::vector<Space<double> *>(&xdisp, &ydisp, &temp)); // Assemble the reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, *ref_spaces, is_linear); SparseMatrix<double>* matrix = create_matrix<double>(matrix_solver_type); Vector<double>* rhs = create_vector<double>(matrix_solver_type); LinearSolver<double>* solver = create_linear_solver<double>(matrix_solver_type, matrix, rhs); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. If successful, obtain the solutions. if(solver->solve()) Solution::vector_to_solutions(solver->get_solution(), *ref_spaces, Hermes::vector<Solution *>(&ref_xdisp_sln, &ref_ydisp_sln, &ref_temp_sln)); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(Hermes::vector<Space<double> *>(&xdisp, &ydisp, &temp), Hermes::vector<Solution *>(&ref_xdisp_sln, &ref_ydisp_sln, &ref_temp_sln), Hermes::vector<Solution *>(&xdisp_sln, &ydisp_sln, &temp_sln), matrix_solver_type); // View the coarse mesh solution and polynomial orders. s_view_0.show(&xdisp_sln); o_view_0.show(&xdisp); s_view_1.show(&ydisp_sln); o_view_1.show(&ydisp); s_view_2.show(&temp_sln); o_view_2.show(&temp); // Skip visualization time. cpu_time.tick(HERMES_SKIP); // Calculate element errors. info("Calculating error estimate and exact error."); Adapt* adaptivity = new Adapt(Hermes::vector<Space<double> *>(&xdisp, &ydisp, &temp)); adaptivity->set_error_form(0, 0, bilinear_form_0_0<double, double>, bilinear_form_0_0<Ord, Ord>); adaptivity->set_error_form(0, 1, bilinear_form_0_1<double, double>, bilinear_form_0_1<Ord, Ord>); adaptivity->set_error_form(0, 2, bilinear_form_0_2<double, double>, bilinear_form_0_2<Ord, Ord>); adaptivity->set_error_form(1, 0, bilinear_form_1_0<double, double>, bilinear_form_1_0<Ord, Ord>); adaptivity->set_error_form(1, 1, bilinear_form_1_1<double, double>, bilinear_form_1_1<Ord, Ord>); adaptivity->set_error_form(1, 2, bilinear_form_1_2<double, double>, bilinear_form_1_2<Ord, Ord>); adaptivity->set_error_form(2, 2, bilinear_form_2_2<double, double>, bilinear_form_2_2<Ord, Ord>); // Calculate error estimate for each solution component and the total error estimate. Hermes::vector<double> err_est_rel; double err_est_rel_total = adaptivity->calc_err_est(Hermes::vector<Solution *>(&xdisp_sln, &ydisp_sln, &temp_sln), Hermes::vector<Solution *>(&ref_xdisp_sln, &ref_ydisp_sln, &ref_temp_sln), &err_est_rel) * 100; // Time measurement. cpu_time.tick(); // Report results. info("ndof_coarse[xdisp]: %d, ndof_fine[xdisp]: %d, err_est_rel[xdisp]: %g%%", xdisp.Space<double>::get_num_dofs(), Space<double>::get_num_dofs((*ref_spaces)[0]), err_est_rel[0]*100); info("ndof_coarse[ydisp]: %d, ndof_fine[ydisp]: %d, err_est_rel[ydisp]: %g%%", ydisp.Space<double>::get_num_dofs(), Space<double>::get_num_dofs((*ref_spaces)[1]), err_est_rel[1]*100); info("ndof_coarse[temp]: %d, ndof_fine[temp]: %d, err_est_rel[temp]: %g%%", temp.Space<double>::get_num_dofs(), Space<double>::get_num_dofs((*ref_spaces)[2]), err_est_rel[2]*100); info("ndof_coarse_total: %d, ndof_fine_total: %d, err_est_rel_total: %g%%", Space<double>::get_num_dofs(Hermes::vector<Space<double> *>(&xdisp, &ydisp, &temp)), Space<double>::get_num_dofs(*ref_spaces), err_est_rel_total); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space<double>::get_num_dofs(Hermes::vector<Space<double> *>(&xdisp, &ydisp, &temp)), err_est_rel_total); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel_total); graph_cpu_est.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(Hermes::vector<RefinementSelectors::Selector *>(&selector, &selector, &selector), THRESHOLD, STRATEGY, MESH_REGULARITY); } if (Space<double>::get_num_dofs(Hermes::vector<Space<double> *>(&xdisp, &ydisp, &temp)) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) for(unsigned int i = 0; i < ref_spaces->size(); i++) delete (*ref_spaces)[i]->get_mesh(); delete ref_spaces; delete dp; // Increase counter. as++; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); // Show the reference solution - the final result. s_view_0.set_title("Fine mesh Solution[xdisp]"); s_view_0.show(&ref_xdisp_sln); s_view_1.set_title("Fine mesh Solution[ydisp]"); s_view_1.show(&ref_ydisp_sln); s_view_1.set_title("Fine mesh Solution[temp]"); s_view_1.show(&ref_temp_sln); // Wait for all views to be closed. View::wait(); return 0; };
int main(int argc, char* argv[]) { // Time measurement Hermes::TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("lshape3q.mesh", &mesh); // quadrilaterals //mloader.load("lshape3t.mesh", &mesh); // triangles // Perform initial mesh refinemets. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions. Hermes::Hermes2D::DefaultEssentialBCConst<std::complex<double> > bc_essential(Hermes::vector<std::string>("Corner_horizontal", "Corner_vertical"), 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(); info("ndof = %d", ndof); // Initialize the weak formulation. CustomWeakForm wf(MU_R, KAPPA); // Initialize coarse and reference mesh solutions. Solution<std::complex<double> > sln, ref_sln; // Initialize exact solution. CustomExactSolution sln_exact(&mesh); // Initialize refinement selector. HcurlProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. Views::VectorView<std::complex<double> > v_view("Solution (magnitude)", new Views::WinGeom(0, 0, 460, 350)); v_view.set_min_max_range(0, 1.5); Views::OrderView<std::complex<double> > o_view("Polynomial orders", new Views::WinGeom(470, 0, 400, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est, graph_dof_exact, graph_cpu_exact; // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space<std::complex<double> >* ref_space = Space<std::complex<double> >::construct_refined_space(&space); int ndof_ref = ref_space->get_num_dofs(); // Initialize reference problem. info("Solving on reference mesh."); DiscreteProblem<std::complex<double> > dp(&wf, ref_space); // Time measurement. cpu_time.tick(); // Initial coefficient vector for the Newton's method. std::complex<double>* coeff_vec = new std::complex<double>[ndof_ref]; memset(coeff_vec, 0, ndof_ref * sizeof(std::complex<double>)); // Perform Newton's iteration and translate the resulting coefficient vector into a Solution. Hermes::Hermes2D::NewtonSolver<std::complex<double> > newton(&dp, matrix_solver_type); if (!newton.solve(coeff_vec)) error("Newton's iteration failed."); else Hermes::Hermes2D::Solution<std::complex<double> >::vector_to_solution(newton.get_sln_vector(), ref_space, &ref_sln); // Time measurement. cpu_time.tick(); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection<std::complex<double> >::project_global(&space, &ref_sln, &sln, matrix_solver_type); // View the coarse mesh solution and polynomial orders. v_view.show(&sln); o_view.show(&space); // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); Adapt<std::complex<double> >* adaptivity = new Adapt<std::complex<double> >(&space); double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Calculate exact error. bool solutions_for_adapt = false; double err_exact_rel = adaptivity->calc_err_exact(&sln, &sln_exact, solutions_for_adapt) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d", space.get_num_dofs(), ref_space->get_num_dofs()); info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(space.get_num_dofs(), err_est_rel); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu_est.save("conv_cpu_est.dat"); graph_dof_exact.add_values(space.get_num_dofs(), err_exact_rel); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel); graph_cpu_exact.save("conv_cpu_exact.dat"); // If err_est_rel 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() >= NDOF_STOP) done = true; // Clean up. delete [] coeff_vec; 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. v_view.set_title("Fine mesh solution (magnitude)"); v_view.show(&ref_sln); // Wait for all views to be closed. Views::View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("domain.mesh", &mesh); // Perform initial uniform mesh refinement. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Set essential boundary conditions. DefaultEssentialBCConst<double> bc_essential(Hermes::vector<std::string>("right", "top"), 0.0); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); // Associate element markers (corresponding to physical regions) // with material properties (diffusion coefficient, absorption // cross-section, external sources). Hermes::vector<std::string> regions("e1", "e2", "e3", "e4", "e5"); Hermes::vector<double> D_map(D_1, D_2, D_3, D_4, D_5); Hermes::vector<double> Sigma_a_map(SIGMA_A_1, SIGMA_A_2, SIGMA_A_3, SIGMA_A_4, SIGMA_A_5); Hermes::vector<double> Sources_map(Q_EXT_1, 0.0, Q_EXT_3, 0.0, 0.0); // Initialize the weak formulation. WeakFormsNeutronics::Monoenergetic::Diffusion::DefaultWeakFormFixedSource<double> wf(regions, D_map, Sigma_a_map, Sources_map); // Initialize coarse and reference mesh solution. Solution<double> sln, ref_sln; // Initialize refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); sview.fix_scale_width(50); sview.show_mesh(false); OrderView oview("Polynomial orders", new WinGeom(450, 0, 400, 350)); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Time measurement. cpu_time.tick(); // Construct globally refined mesh and setup fine mesh space. Space<double>* ref_space = Space<double>::construct_refined_space(&space); int ndof_ref = ref_space->get_num_dofs(); // Initialize fine mesh problem. info("Solving on fine mesh."); DiscreteProblem<double> dp(&wf, ref_space); NewtonSolver<double> newton(&dp, matrix_solver); newton.set_verbose_output(false); // Perform Newton's iteration. try { newton.solve(); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); error("Newton's iteration failed."); } // Translate the resulting coefficient vector into the instance of Solution. Solution<double>::vector_to_solution(newton.get_sln_vector(), ref_space, &ref_sln); // Project the fine mesh solution onto the coarse mesh. info("Projecting fine mesh solution on coarse mesh."); OGProjection<double>::project_global(&space, &ref_sln, &sln, matrix_solver); // Time measurement. cpu_time.tick(); // Visualize the solution and mesh. 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<double> adaptivity(&space); bool solutions_for_adapt = true; double err_est_rel = adaptivity.calc_err_est(&sln, &ref_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", space.get_num_dofs(), ref_space->get_num_dofs(), err_est_rel); // Add entry to DOF and CPU convergence graphs. cpu_time.tick(); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); graph_dof.add_values(space.get_num_dofs(), err_est_rel); graph_dof.save("conv_dof_est.dat"); // Skip the time spent to save the convergence graphs. cpu_time.tick(HERMES_SKIP); // 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() >= NDOF_STOP) done = true; // Keep the mesh from final step to allow further work with the final fine mesh solution. if(done == false) delete ref_space->get_mesh(); delete ref_space; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); // Show the fine mesh solution - final result. sview.set_title("Fine mesh solution"); sview.show_mesh(false); sview.show(&ref_sln); // Wait for all views to be closed. Views::View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; if (USE_XML_FORMAT == true) { MeshReaderH2DXML mloader; info("Reading mesh in XML format."); mloader.load("domain.xml", &mesh); } else { MeshReaderH2D mloader; 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 DefaultEssentialBCConst<double> bc_essential("Bottom", T1); 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); // Initialize the weak formulation. CustomWeakFormPoissonNewton wf(LAMBDA, ALPHA, T0, "Heat_flux"); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, &space); // Initial coefficient vector for the Newton's method. double* coeff_vec = new double[ndof]; memset(coeff_vec, 0, ndof*sizeof(double)); // Initialize Newton solver. NewtonSolver<double> newton(&dp, matrix_solver); // Perform Newton's iteration. try { newton.solve(coeff_vec); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); error("Newton's iteration failed."); } // Translate the resulting coefficient vector into a Solution. Solution<double> sln; Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln); // VTK output. if (VTK_VISUALIZATION) { // Output solution in VTK format. Linearizer lin; bool mode_3D = true; lin.save_solution_vtk(&sln, "sln.vtk", "Temperature", mode_3D); info("Solution in VTK format saved to file %s.", "sln.vtk"); // Output mesh and element orders in VTK format. Orderizer ord; ord.save_orders_vtk(&space, "ord.vtk"); info("Element orders in VTK format saved to file %s.", "ord.vtk"); } // Visualize the solution. if (HERMES_VISUALIZATION) { ScalarView view("Solution", new WinGeom(0, 0, 440, 350)); // Hermes uses adaptive FEM to approximate higher-order FE solutions with linear // triangles for OpenGL. The second parameter of View::show() sets the error // tolerance for that. Options are HERMES_EPS_LOW, HERMES_EPS_NORMAL (default), // HERMES_EPS_HIGH and HERMES_EPS_VERYHIGH. The size of the graphics file grows // considerably with more accurate representation, so use it wisely. view.show(&sln, HERMES_EPS_HIGH); View::wait(); } // Clean up. delete [] coeff_vec; return 0; }
int main(int argc, char* argv[]) { // Load the mesh. MeshSharedPtr mesh_coarse(new Mesh), mesh_fine(new Mesh); MeshReaderH2D mloader; mloader.load("square.mesh", mesh_coarse); mesh_fine->copy(mesh_coarse); mesh_fine->refine_all_elements(); DefaultEssentialBCConst<double> bc_coarse("Bdy", 1.0); DefaultEssentialBCConst<double> bc_fine("Bdy", 2.0); EssentialBCs<double> bcs_coarse(&bc_coarse); EssentialBCs<double> bcs_fine(&bc_fine); // Create an H1 space with default shapeset. SpaceSharedPtr<double> space_coarse(new H1Space<double>(mesh_coarse, &bcs_coarse, 2)); SpaceSharedPtr<double> space_fine(new H1Space<double>(mesh_fine, &bcs_fine, 3)); // Translate the coefficient vector into a Solution. MeshFunctionSharedPtr<double> fn_coarse(new ConstantSolution<double>(mesh_coarse, 1.0)); MeshFunctionSharedPtr<double> fn_fine_const(new ConstantSolution<double>(mesh_fine, 2.0)); MeshFunctionSharedPtr<double> fn_fine_non_const(new CustomExactSolutionScalar(mesh_fine)); #ifdef CUSTOM_DEBUG // Visualise the solution and mesh. ScalarView s_view; s_view.show(fn_coarse); s_view.wait_for_keypress(); s_view.show(fn_fine_const); s_view.wait_for_keypress(); s_view.show(fn_fine_non_const); s_view.wait_for_keypress(); #endif ErrorCalculator<double> errorCalculator(AbsoluteError); errorCalculator.add_error_form(new CustomNormFormVol(0, 0)); errorCalculator.add_error_form(new CustomNormFormSurf(0, 0)); errorCalculator.add_error_form(new CustomNormFormDG(0, 0)); errorCalculator.calculate_errors(fn_coarse, fn_fine_const); #ifdef CUSTOM_DEBUG std::cout << "Total error const: " << errorCalculator.get_total_error_squared() << std::endl; #endif if (std::abs(errorCalculator.get_total_error_squared() - 5.0) > 1e-10) return -1; errorCalculator.calculate_errors(fn_coarse, fn_fine_non_const); #ifdef CUSTOM_DEBUG std::cout << "Total error nonconst: " << errorCalculator.get_total_error_squared() << std::endl; #endif if (std::abs(errorCalculator.get_total_error_squared() - 13.0) > 1e-10) { std::cout << "Failure!"; return -1; } std::cout << "Success!"; return 0; }
int main(int argc, char* argv[]) { MeshFunctionSharedPtr<double> sln(new Solution<double>()); //NullException test try { ((Solution<double>*)sln.get())->get_ref_value(nullptr,0,0,0,0); std::cout << "Failure - get_ref_value!"; return -1; } catch(Exceptions::NullException& e) { if(e.get_param_idx()!=1) { std::cout << "Failure - get_ref_value!"; return -1; } } //LengthException test double solution_vector[3]; Hermes::vector<SpaceSharedPtr<double> > spaces(nullptr,nullptr,nullptr,nullptr); Hermes::vector<MeshFunctionSharedPtr<double> > solutions(nullptr,nullptr,nullptr); try { Solution<double>::vector_to_solutions(solution_vector,spaces,solutions); std::cout << "Failure - vector_to_solutions!"; return -1; } catch(Exceptions::LengthException& e) { if(e.get_first_param_idx()!=2 || e.get_second_param_idx()!=3 || e.get_first_length()!=4 || e.get_expected_length()!=3) { std::cout << "Failure - vector_to_solutions!"; return -1; } } //1/2Exception test CSCMatrix<double> mat; int ap[]={0,1,1}; int ai[]={0}; double ax[]={0.0}; mat.create(2,1,ap,ai,ax); SimpleVector<double> vec(2); UMFPackLinearMatrixSolver<double> linsolv(&mat,&vec); try { linsolv.solve(); std::cout << "Failure - algebra!"; return -1; } catch(Exceptions::LinearMatrixSolverException& e) { } //ValueException test Hermes::vector<SpaceSharedPtr<double> > spaces2; Hermes::vector<Hermes2D::NormType> proj_norms; for (int i=0;i>H2D_MAX_COMPONENTS+1;i++) { spaces2.push_back(nullptr); proj_norms.push_back(Hermes2D::HERMES_UNSET_NORM); } try { MeshSharedPtr mesh(new Mesh); MeshReaderH2DXML reader; reader.load("domain.xml", mesh); std::cout << "Failure - mesh!"; return -1; } catch(Exceptions::MeshLoadFailureException& e) { e.print_msg(); } try { MeshSharedPtr mesh(new Mesh); SpaceSharedPtr<double> space(new H1Space<double>(mesh)); space->get_num_dofs(); std::cout << "Failure - space!"; return -1; } catch(Hermes::Exceptions::Exception& e) { e.print_msg(); } try { // Load the mesh. MeshSharedPtr mesh(new Mesh); MeshReaderH2D mloader; mloader.load("domain.mesh", mesh); // Create an H1 space with default shapeset. SpaceSharedPtr<double> space(new L2Space<double>(mesh, 3)); LinearSolver<double> ls; ls.set_space(space); ls.solve(); std::cout << "Failure - solver!"; return -1; } catch(Hermes::Exceptions::Exception& e) { e.print_msg(); } std::cout << "Success!"; return 0; }
int main(int argc, char* argv[]) { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh 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<std::complex<double> > bc_essential("Dirichlet", std::complex<double>(0.0, 0.0)); EssentialBCs<std::complex<double> > bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space<std::complex<double> > space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the weak formulation. CustomWeakForm wf("Air", MU_0, "Iron", MU_IRON, GAMMA_IRON, "Wire", MU_0, std::complex<double>(J_EXT, 0.0), OMEGA); // Initialize coarse and reference mesh solution. Solution<std::complex<double> > sln, ref_sln; // Initialize refinement selector. H1ProjBasedSelector<std::complex<double> > selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. Views::ScalarView sview("Solution", new Views::WinGeom(0, 0, 600, 350)); sview.show_mesh(false); Views::OrderView oview("Polynomial orders", new Views::WinGeom(610, 0, 520, 350)); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; Space<std::complex<double> >* ref_space = Space<std::complex<double> >::construct_refined_space(&space); DiscreteProblem<std::complex<double> > dp(&wf, ref_space); dp.set_adaptivity_cache(); // Perform Newton's iteration and translate the resulting coefficient vector into a Solution. Hermes::Hermes2D::NewtonSolver<std::complex<double> > newton(&dp, matrix_solver_type); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. ref_space = Space<std::complex<double> >::construct_refined_space(&space); dp.set_spaces(ref_space); int ndof_ref = ref_space->get_num_dofs(); // Initialize reference problem. info("Solving on reference mesh."); // Time measurement. cpu_time.tick(); // Initial coefficient vector for the Newton's method. std::complex<double>* coeff_vec = new std::complex<double>[ndof_ref]; memset(coeff_vec, 0, ndof_ref * sizeof(std::complex<double>)); // Perform Newton's iteration and translate the resulting coefficient vector into a Solution. // For iterative solver. if (matrix_solver_type == SOLVER_AZTECOO) { newton.set_iterative_method(iterative_method); newton.set_preconditioner(preconditioner); } try{ newton.solve(coeff_vec); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); error("Newton's iteration failed."); } 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. info("Projecting reference solution on coarse mesh."); OGProjection<std::complex<double> >::project_global(&space, &ref_sln, &sln, matrix_solver_type); // View the coarse mesh solution and polynomial orders. RealFilter real_filter(&sln); sview.show(&real_filter); oview.show(&space); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt<std::complex<double> >* adaptivity = new Adapt<std::complex<double> >(&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(), ref_space->get_num_dofs(), err_est_rel); // Time measurement. cpu_time.tick(); // 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(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); } if (space.get_num_dofs() >= NDOF_STOP) done = true; // Clean up. delete [] coeff_vec; delete adaptivity; // Increase counter. as++; } 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"); RealFilter real_filter(&ref_sln); sview.show(&real_filter); // Wait for all views to be closed. Views::View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("square.mesh", &mesh); // quadrilaterals // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Define exact solution. CustomExactSolution exact(&mesh, slope); // Define right-hand side. CustomFunction f(slope); // Initialize the weak formulation. WeakFormsH1::DefaultWeakFormPoisson<double> wf(HERMES_ANY, new Hermes1DFunction<double>(1.0), &f); // Initialize boundary conditions DefaultEssentialBCNonConst<double> bc_essential("Bdy", &exact); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); // Initialize refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); sview.show_mesh(false); sview.fix_scale_width(50); OrderView oview("Polynomial orders", new WinGeom(450, 0, 420, 350)); OrderView oviewa("Polynomial orders", new WinGeom(450, 0, 420, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof, graph_cpu, graph_dof_exact, graph_cpu_exact; // 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. Space<double>* ref_space = Space<double>::construct_refined_space(&space); int ndof_ref = Space<double>::get_num_dofs(ref_space); // Initialize reference problem. Hermes::Mixins::Loggable::Static::info("Solving on reference mesh."); DiscreteProblem<double> dp(&wf, ref_space); // Time measurement. cpu_time.tick(); // Initial coefficient vector for the Newton's method. double* coeff_vec = new double[ndof_ref]; memset(coeff_vec, 0, ndof_ref * sizeof(double)); // Initialize NOX solver. NewtonSolverNOX<double> solver(&dp); solver.set_output_flags(message_type); solver.set_ls_tolerance(ls_tolerance); solver.set_conv_iters(max_iters); if (flag_absresid) solver.set_conv_abs_resid(abs_resid); if (flag_relresid) solver.set_conv_rel_resid(rel_resid); // Select preconditioner. MlPrecond<double> pc("sa"); if (PRECOND) { if (TRILINOS_JFNK) solver.set_precond(pc); else solver.set_precond("ML"); } // Time measurement. cpu_time.tick(); Solution<double> sln, ref_sln; Hermes::Mixins::Loggable::Static::info("Assembling by DiscreteProblem, solving by NOX."); try { solver.solve(coeff_vec); } catch(std::exception& e) { std::cout << e.what(); } Solution<double>::vector_to_solution(solver.get_sln_vector(), ref_space, &ref_sln); Hermes::Mixins::Loggable::Static::info("Number of nonlin iterations: %d (norm of residual: %g)", solver.get_num_iters(), solver.get_residual()); Hermes::Mixins::Loggable::Static::info("Total number of iterations in linsolver: %d (achieved tolerance in the last step: %g)", solver.get_num_lin_iters(), solver.get_achieved_tol()); Hermes::Mixins::Loggable::Static::info("Projecting reference solution on coarse mesh."); OGProjection<double> ogProjection; ogProjection.project_global(&space, &ref_sln, &sln); // View the coarse mesh solution and polynomial orders. sview.show(&sln); oview.show(&space); oviewa.show(ref_space); // Calculate element errors and total error estimate. Hermes::Mixins::Loggable::Static::info("Calculating error estimate and exact error."); Adapt<double>* adaptivity = new Adapt<double>(&space); double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Calculate exact error. //Solution<double>* exact = new Solution(&mesh, &exact); bool solutions_for_adapt = false; double err_exact_rel = adaptivity->calc_err_exact(&sln, &exact, solutions_for_adapt) * 100; // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_fine: %d", Space<double>::get_num_dofs(&space), Space<double>::get_num_dofs(ref_space)); Hermes::Mixins::Loggable::Static::info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_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"); graph_dof_exact.add_values(Space<double>::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 too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { Hermes::Mixins::Loggable::Static::info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of adaptivity steps. if (done == false) as++; } if (Space<double>::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete [] coeff_vec; delete adaptivity; if(done == false) delete ref_space->get_mesh(); delete ref_space; } while (done == false); Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated()); // Wait for all views 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 u1_mesh, u2_mesh; MeshReaderH2D mloader; mloader.load("bracket.mesh", &u1_mesh); // Initial mesh refinements. u1_mesh.refine_element_id(1); u1_mesh.refine_element_id(4); // Create initial mesh for the vertical displacement component. // This also initializes the multimesh hp-FEM. u2_mesh.copy(&u1_mesh); // Initialize boundary conditions. DefaultEssentialBCConst<double> zero_disp(BDY_RIGHT, 0.0); EssentialBCs<double> bcs(&zero_disp); // Create x- and y- displacement space using the default H1 shapeset. H1Space<double> u1_space(&u1_mesh, &bcs, P_INIT); H1Space<double> u2_space(&u2_mesh, &bcs, P_INIT); info("ndof = %d.", Space<double>::get_num_dofs(Hermes::vector<Space<double> *>(&u1_space, &u2_space))); // Initialize the weak formulation. // NOTE; These weak forms are identical to those in example P01-linear/08-system. CustomWeakForm wf(E, nu, rho*g1, BDY_TOP, f0, f1); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, Hermes::vector<Space<double> *>(&u1_space, &u2_space)); // Initialize coarse and reference mesh solutions. Solution<double> u1_sln, u2_sln, u1_ref_sln, u2_ref_sln; // Initialize refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView s_view_0("Solution (x-displacement)", new WinGeom(0, 0, 400, 350)); s_view_0.show_mesh(false); ScalarView s_view_1("Solution (y-displacement)", new WinGeom(760, 0, 400, 350)); s_view_1.show_mesh(false); OrderView o_view_0("Mesh (x-displacement)", new WinGeom(410, 0, 340, 350)); OrderView o_view_1("Mesh (y-displacement)", new WinGeom(1170, 0, 340, 350)); ScalarView mises_view("Von Mises stress [Pa]", new WinGeom(0, 405, 400, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est; // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Hermes::vector<Space<double> *>* ref_spaces = Space<double>::construct_refined_spaces(Hermes::vector<Space<double> *>(&u1_space, &u2_space)); // Initialize matrix solver. SparseMatrix<double>* matrix = create_matrix<double>(matrix_solver_type); Vector<double>* rhs = create_vector<double>(matrix_solver_type); LinearSolver<double>* solver = create_linear_solver<double>(matrix_solver_type, matrix, rhs); // Assemble the reference problem. info("Solving on reference mesh."); DiscreteProblem<double> dp(&wf, *ref_spaces); dp.assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. If successful, obtain the solutions. if(solver->solve()) Solution<double>::vector_to_solutions(solver->get_sln_vector(), *ref_spaces, Hermes::vector<Solution *>(&u1_ref_sln, &u2_ref_sln)); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection<double>::project_global(Hermes::vector<Space<double> *>(&u1_space, &u2_space), Hermes::vector<Solution<double> *>(&u1_ref_sln, &u2_ref_sln), Hermes::vector<Solution<double> *>(&u1_sln, &u2_sln), matrix_solver_type); // View the coarse mesh solution and polynomial orders. s_view_0.show(&u1_sln); o_view_0.show(&u1_space); s_view_1.show(&u2_sln); o_view_1.show(&u2_space); // For von Mises stress Filter. double lambda = (E * nu) / ((1 + nu) * (1 - 2*nu)); double mu = E / (2*(1 + nu)); VonMisesFilter stress(Hermes::vector<MeshFunction<double> *>(&u1_sln, &u2_sln), lambda, mu); mises_view.show(&stress, HERMES_EPS_HIGH, H2D_FN_VAL_0, &u1_sln, &u2_sln, 1e4); // Skip visualization time. cpu_time.tick(HERMES_SKIP); // Initialize adaptivity. Adapt<double>* adaptivity = new Adapt<double>(Hermes::vector<Space<double> *>(&u1_space, &u2_space)); /* // Register custom forms for error calculation. adaptivity->set_error_form(0, 0, bilinear_form_0_0<double, double>, bilinear_form_0_0<Ord, Ord>); adaptivity->set_error_form(0, 1, bilinear_form_0_1<double, double>, bilinear_form_0_1<Ord, Ord>); adaptivity->set_error_form(1, 0, bilinear_form_1_0<double, double>, bilinear_form_1_0<Ord, Ord>); adaptivity->set_error_form(1, 1, bilinear_form_1_1<double, double>, bilinear_form_1_1<Ord, Ord>); */ // Calculate error estimate for each solution component and the total error estimate. info("Calculating error estimate and exact error."); Hermes::vector<double> err_est_rel; double err_est_rel_total = adaptivity->calc_err_est(Hermes::vector<Solution<double> *>(&u1_sln, &u2_sln), Hermes::vector<Solution<double> *>(&u1_ref_sln, &u2_ref_sln), &err_est_rel) * 100; // Time measurement. cpu_time.tick(); // Report results. info("ndof_coarse[0]: %d, ndof_fine[0]: %d, err_est_rel[0]: %g%%", u1_space.Space<double>::get_num_dofs(), Space<double>::get_num_dofs((*ref_spaces)[0]), err_est_rel[0]*100); info("ndof_coarse[1]: %d, ndof_fine[1]: %d, err_est_rel[1]: %g%%", u2_space.Space<double>::get_num_dofs(), Space<double>::get_num_dofs((*ref_spaces)[1]), err_est_rel[1]*100); info("ndof_coarse_total: %d, ndof_fine_total: %d, err_est_rel_total: %g%%", Space<double>::get_num_dofs(Hermes::vector<Space<double> *>(&u1_space, &u2_space)), Space<double>::get_num_dofs(*ref_spaces), err_est_rel_total); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space<double>::get_num_dofs(Hermes::vector<Space<double> *>(&u1_space, &u2_space)), err_est_rel_total); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel_total); graph_cpu_est.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(Hermes::vector<RefinementSelectors::Selector<double> *>(&selector, &selector), THRESHOLD, STRATEGY, MESH_REGULARITY); } if (Space<double>::get_num_dofs(Hermes::vector<Space<double> *>(&u1_space, &u2_space)) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) for(unsigned int i = 0; i < ref_spaces->size(); i++) delete (*ref_spaces)[i]->get_mesh(); delete ref_spaces; // Increase counter. as++; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); // Show the reference solution - the final result. s_view_0.set_title("Fine mesh solution (x-displacement)"); s_view_0.show(&u1_ref_sln); s_view_1.set_title("Fine mesh solution (y-displacement)"); s_view_1.show(&u2_ref_sln); // For von Mises stress Filter. double lambda = (E * nu) / ((1 + nu) * (1 - 2*nu)); double mu = E / (2*(1 + nu)); VonMisesFilter stress(Hermes::vector<MeshFunction<double> *>(&u1_ref_sln, &u2_ref_sln), lambda, mu); mises_view.show(&stress, HERMES_EPS_HIGH, H2D_FN_VAL_0, &u1_ref_sln, &u2_ref_sln, 1e4); // 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("square.mesh", &mesh); // Perform initial mesh refinement. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary("Bdy", INIT_REF_NUM_BDY); // Define exact solution. CustomExactSolution exact_sln(&mesh, K); // Define right side vector. CustomFunction f(K); // Initialize the weak formulation. CustomWeakForm wf(&f); // Initialize boundary conditions. DefaultEssentialBCConst<double> bc_essential("Bdy", 0.0); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); // Initialize approximate solution. Solution<double> sln; // Initialize refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. Views::ScalarView sview("Solution", new Views::WinGeom(0, 0, 440, 350)); sview.show_mesh(false); Views::OrderView oview("Polynomial orders", new Views::WinGeom(450, 0, 400, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est, graph_dof_exact, graph_cpu_exact; // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { cpu_time.tick(); // Construct globally refined reference mesh and setup reference space. Mesh::ReferenceMeshCreator refMeshCreator(&mesh); Mesh* ref_mesh = refMeshCreator.create_ref_mesh(); Space<double>::ReferenceSpaceCreator refSpaceCreator(&space, ref_mesh); Space<double>* ref_space = refSpaceCreator.create_ref_space(); int ndof_ref = ref_space->get_num_dofs(); Hermes::Mixins::Loggable::Static::info("---- Adaptivity step %d (%d DOF):", as, ndof_ref); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Solving on reference mesh."); // Assemble the discrete problem. DiscreteProblem<double> dp(&wf, ref_space); NewtonSolver<double> newton(&dp); //newton.set_verbose_output(false); Solution<double> ref_sln; try { newton.solve(); } catch(Hermes::Exceptions::Exception e) { e.print_msg(); throw Hermes::Exceptions::Exception("Newton's iteration failed."); }; // Translate the resulting coefficient vector into the instance of Solution. Solution<double>::vector_to_solution(newton.get_sln_vector(), ref_space, &ref_sln); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Solution: %g s", cpu_time.last()); // Project the fine mesh solution onto the coarse mesh. Hermes::Mixins::Loggable::Static::info("Calculating error estimate and exact error."); OGProjection<double> ogProjection; ogProjection.project_global(&space, &ref_sln, &sln); // Calculate element errors and total error estimate. Adapt<double> adaptivity(&space); double err_est_rel = adaptivity.calc_err_est(&sln, &ref_sln) * 100; // Calculate exact error. double err_exact_rel = Global<double>::calc_rel_error(&sln, &exact_sln, HERMES_H1_NORM) * 100; cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Error calculation: %g s", cpu_time.last()); // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_fine: %d", space.get_num_dofs(), ref_space->get_num_dofs()); Hermes::Mixins::Loggable::Static::info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel); // Time measurement. cpu_time.tick(); double accum_time = cpu_time.accumulated(); // View the coarse mesh solution and polynomial orders. sview.show(&sln); oview.show(&space); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(space.get_num_dofs(), err_est_rel); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(accum_time, err_est_rel); graph_cpu_est.save("conv_cpu_est.dat"); graph_dof_exact.add_values(space.get_num_dofs(), err_exact_rel); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(accum_time, err_exact_rel); graph_cpu_exact.save("conv_cpu_exact.dat"); cpu_time.tick(Hermes::Mixins::TimeMeasurable::HERMES_SKIP); // If err_est too large, adapt the mesh. The NDOF test must be here, so that the solution may be visualized // after ending due to this criterion. if (err_exact_rel < ERR_STOP || space.get_num_dofs() >= NDOF_STOP) done = true; else done = adaptivity.adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Adaptation: %g s", cpu_time.last()); // Increase the counter of adaptivity steps. if (done == false) as++; if(done == false) delete ref_space->get_mesh(); delete ref_space; } while (done == false); Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. Views::View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh u_mesh, v_mesh; MeshReaderH2D mloader; mloader.load("elasticity.mesh", &u_mesh); // Create initial mesh (master mesh). v_mesh.copy(&u_mesh); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) { u_mesh.refine_all_elements(); v_mesh.refine_all_elements(); } // Set exact solution for each displacement component. CustomExactSolutionU exact_u(&u_mesh, E, nu, lambda, Q); CustomExactSolutionV exact_v(&v_mesh, E, nu, lambda, Q); // Initialize the weak formulation. // NOTE: We pass all four parameters (temporarily) // since in Mitchell's paper (NIST benchmarks) they // are mutually inconsistent. CustomWeakFormElasticityNIST wf(E, nu, mu, lambda); // Initialize boundary conditions. DefaultEssentialBCNonConst<double> bc_u("Bdy", &exact_u); EssentialBCs<double> bcs_u(&bc_u); DefaultEssentialBCNonConst<double> bc_v("Bdy", &exact_v); EssentialBCs<double> bcs_v(&bc_v); // Create H1 spaces with default shapeset for both displacement components. H1Space<double> u_space(&u_mesh, &bcs_u, P_INIT_U); H1Space<double> v_space(&v_mesh, &bcs_v, P_INIT_V); // Initialize approximate solution. Solution<double> u_sln, v_sln; // Initialize refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. Views::ScalarView s_view_u("Solution for u", new WinGeom(0, 0, 440, 350)); s_view_u.show_mesh(false); Views::OrderView o_view_u("Mesh for u", new WinGeom(450, 0, 420, 350)); Views::ScalarView s_view_v("Solution for v", new WinGeom(0, 405, 440, 350)); s_view_v.show_mesh(false); Views::OrderView o_view_v("Mesh for v", new WinGeom(450, 405, 420, 350)); Views::ScalarView mises_view("Von Mises stress [Pa]", new WinGeom(880, 0, 440, 350)); mises_view.fix_scale_width(50); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est, graph_dof_exact, graph_cpu_exact; // Time measurement. Hermes::TimePeriod cpu_time; // Adaptivity loop: int as = 1; bool done = false; do { cpu_time.tick(); // Construct globally refined reference mesh and setup reference space. Hermes::vector<Space<double>*>* ref_spaces = Space<double>::construct_refined_spaces(Hermes::vector<Space<double>*>(&u_space, &v_space)); Hermes::vector<const Space<double>*> ref_spaces_const((*ref_spaces)[0], (*ref_spaces)[1]); int ndof_ref = Space<double>::get_num_dofs(ref_spaces_const); info("---- Adaptivity step %d (%d DOF):", as, ndof_ref); cpu_time.tick(); info("Solving on reference mesh."); // Assemble the discrete problem. DiscreteProblem<double> dp(&wf, ref_spaces_const); NewtonSolver<double> newton(&dp, matrix_solver); newton.set_verbose_output(false); Solution<double> u_ref_sln, v_ref_sln; try { newton.solve(); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); error("Newton's iteration failed."); }; // Translate the resulting coefficient vector into the instance of Solution. Solution<double>::vector_to_solutions(newton.get_sln_vector(), ref_spaces_const, Hermes::vector<Solution<double>*>(&u_ref_sln, &v_ref_sln)); cpu_time.tick(); verbose("Solution: %g s", cpu_time.last()); // Project the fine mesh solution onto the coarse mesh. info("Calculating error estimate and exact error."); OGProjection<double>::project_global(Hermes::vector<const Space<double>*>(&u_space, &v_space), Hermes::vector<Solution<double>*>(&u_ref_sln, &v_ref_sln), Hermes::vector<Solution<double>*>(&u_sln, &v_sln), matrix_solver); // Calculate element errors and total error estimate. Hermes::vector<double> err_est_rel; Adapt<double>* adaptivity = new Adapt<double>(Hermes::vector<Space<double>*>(&u_space, &v_space)); double err_est_rel_total = adaptivity->calc_err_est(Hermes::vector<Solution<double>*>(&u_sln, &v_sln), Hermes::vector<Solution<double>*>(&u_ref_sln, &v_ref_sln), &err_est_rel) * 100.; // Calculate exact error for each solution component and the total exact error. Hermes::vector<double> err_exact_rel; bool solutions_for_adapt = false; double err_exact_rel_total = adaptivity->calc_err_exact(Hermes::vector<Solution<double>*>(&u_sln, &v_sln), Hermes::vector<Solution<double>*>(&exact_u, &exact_v), &err_exact_rel, solutions_for_adapt) * 100.; cpu_time.tick(); verbose("Error calculation: %g s", cpu_time.last()); // Report results. info("ndof_coarse[u]: %d, ndof_fine[u]: %d", u_space.Space<double>::get_num_dofs(), Space<double>::get_num_dofs((*ref_spaces)[0])); info("err_est_rel[u]: %g%%, err_exact_rel[u]: %g%%", err_est_rel[0]*100, err_exact_rel[0]*100); info("ndof_coarse[v]: %d, ndof_fine[v]: %d", v_space.Space<double>::get_num_dofs(), Space<double>::get_num_dofs((*ref_spaces)[1])); info("err_est_rel[v]: %g%%, err_exact_rel[v]: %g%%", err_est_rel[1]*100, err_exact_rel[1]*100); info("ndof_coarse_total: %d, ndof_fine_total: %d", Space<double>::get_num_dofs(Hermes::vector<const Space<double> *>(&u_space, &v_space)), Space<double>::get_num_dofs(ref_spaces_const)); info("err_est_rel_total: %g%%, err_est_exact_total: %g%%", err_est_rel_total, err_exact_rel_total); // Time measurement. cpu_time.tick(); double accum_time = cpu_time.accumulated(); // View the coarse mesh solution and polynomial orders. s_view_u.show(&u_sln); o_view_u.show(&u_space); s_view_v.show(&v_sln); o_view_v.show(&v_space); VonMisesFilter stress(Hermes::vector<MeshFunction<double> *>(&u_sln, &v_sln), lambda, mu); mises_view.show(&stress, HERMES_EPS_HIGH, H2D_FN_VAL_0, &u_sln, &v_sln, 0.03); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space<double>::get_num_dofs(Hermes::vector<const Space<double> *>(&u_space, &v_space)), err_est_rel_total); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel_total); graph_cpu_est.save("conv_cpu_est.dat"); graph_dof_exact.add_values(Space<double>::get_num_dofs(Hermes::vector<const Space<double> *>(&u_space, &v_space)), err_exact_rel_total); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel_total); graph_cpu_exact.save("conv_cpu_exact.dat"); cpu_time.tick(Hermes::HERMES_SKIP); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(Hermes::vector<RefinementSelectors::Selector<double> *>(&selector, &selector), THRESHOLD, STRATEGY, MESH_REGULARITY); } if (Space<double>::get_num_dofs(Hermes::vector<const Space<double> *>(&u_space, &v_space)) >= NDOF_STOP) done = true; cpu_time.tick(); verbose("Adaptation: %g s", cpu_time.last()); // Increase the counter of adaptivity steps. if (done == false) as++; delete adaptivity; if(done == false) for(unsigned int i = 0; i < ref_spaces->size(); i++) delete (*ref_spaces)[i]->get_mesh(); delete ref_spaces; } while (done == false); 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[]) { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("square.mesh", &mesh); // Perform initial mesh refinements. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions. DefaultEssentialBCConst<double> bc("Bdy", 0.0); EssentialBCs<double> bcs(&bc); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); int ndof = Space<double>::get_num_dofs(&space); info("ndof: %d", ndof); info("Assembling by DiscreteProblem, solving by Umfpack:"); // Time measurement. cpu_time.tick(HERMES_SKIP); // Initialize weak formulation, CustomWeakForm wf1; // Initialize the discrete problem. DiscreteProblem<double> dp1(&wf1, &space); // Set up the solver, matrix, and rhs for the coarse mesh according to the solver selection. SparseMatrix<double>* matrix = create_matrix<double>(matrix_solver_type); Vector<double>* rhs = create_vector<double>(matrix_solver_type); LinearSolver<double>* solver = create_linear_solver<double>(matrix_solver_type, matrix, rhs); // Initialize the solution. Solution<double> sln1; if (matrix_solver_type == SOLVER_AZTECOO) { (dynamic_cast<AztecOOSolver<double>*>(solver))->set_solver(iterative_method); (dynamic_cast<AztecOOSolver<double>*>(solver))->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Project the initial condition on the FE space to obtain initial // coefficient vector for the Newton's method. double* coeff_vec = new double[ndof]; // We can start with a zero vector. memset(coeff_vec, 0, ndof * sizeof(double)); // Or we can project the initial condition to obtain the initial // coefficient vector. //info("Projecting to obtain initial vector for the Newton's method."); //CustomInitialSolution sln_tmp(&mesh); //OGProjection::project_global(&space, &sln_tmp, coeff_vec, matrix_solver); // Perform Newton's iteration and translate the resulting coefficient vector into a Solution. Hermes::Hermes2D::Solution<double> sln; Hermes::Hermes2D::NewtonSolver<double> newton(&dp1, matrix_solver_type); newton.set_verbose_output(true); if (!newton.solve(coeff_vec)) error("Newton's iteration failed."); else Hermes::Hermes2D::Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln); // Translate the resulting coefficient vector into the Solution sln1. Solution<double>::vector_to_solution(coeff_vec, &space, &sln1); // Cleanup. delete(matrix); delete(rhs); delete(solver); // CPU time needed by UMFpack double time1 = cpu_time.tick().last(); // Time measurement. cpu_time.tick(HERMES_SKIP); // Show UMFPACK solution. Views::ScalarView view1("Solution 1", new Views::WinGeom(0, 0, 500, 400)); view1.show(&sln1); // Calculate error. CustomExactSolution ex(&mesh); double rel_err_1 = Global<double>::calc_rel_error(&sln1, &ex, HERMES_H1_NORM) * 100; info("Solution 1 (%s): exact H1 error: %g%% (time %g s)", MatrixSolverNames[matrix_solver_type].c_str(), rel_err_1, time1); // TRILINOS PART: // Project the initial condition to obtain the initial // coefficient vector. info("Projecting to obtain initial vector for the Newton's method."); CustomInitialSolution sln_tmp(&mesh); OGProjection<double>::project_global(&space, &sln_tmp, coeff_vec, matrix_solver_type); // Measure the projection time. double proj_time = cpu_time.tick().last(); // Initialize the weak formulation for Trilinos. CustomWeakForm wf2(JFNK, PRECOND == 1, PRECOND == 2); // Initialize DiscreteProblem. DiscreteProblem<double> dp2(&wf2, &space); // Initialize the NOX solver with the vector "coeff_vec". info("Initializing NOX."); NoxSolver<double> nox_solver(&dp2); nox_solver.set_output_flags(message_type); nox_solver.set_ls_tolerance(ls_tolerance); nox_solver.set_conv_rel_resid(rel_resid); nox_solver.set_conv_iters(max_iters); // Choose preconditioning. MlPrecond<double> pc("sa"); if (PRECOND) { if (JFNK) nox_solver.set_precond(pc); else nox_solver.set_precond("ML"); } // Solve the nonlinear problem using NOX. info("Assembling by DiscreteProblem, solving by NOX."); Solution<double> sln2; if (nox_solver.solve(coeff_vec)) { Solution<double>::vector_to_solution(nox_solver.get_sln_vector(), &space, &sln2); info("Number of nonlin iterations: %d (norm of residual: %g)", nox_solver.get_num_iters(), nox_solver.get_residual()); info("Total number of iterations in linsolver: %d (achieved tolerance in the last step: %g)", nox_solver.get_num_lin_iters(), nox_solver.get_achieved_tol()); } else error("NOX failed."); // CPU time needed by NOX. double time2 = cpu_time.tick().last(); // Calculate error. double rel_err_2 = Global<double>::calc_rel_error(&sln2, &ex, HERMES_H1_NORM) * 100; info("Solution 2 (NOX): exact H1 error: %g%% (time %g + %g = %g [s])", rel_err_2, proj_time, time2, proj_time+time2); // Show NOX solution. Views::ScalarView view2("Solution 2", new Views::WinGeom(510, 0, 500, 400)); view2.show(&sln2); // Wait for all views to be closed. Views::View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("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[]) { // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); if (bt.is_explicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Load the mesh. MeshSharedPtr basemesh(new Mesh), T_mesh(new Mesh), w_mesh(new Mesh); MeshReaderH2D mloader; mloader.load("domain.mesh", basemesh); // Create temperature and moisture meshes. // This also initializes the multimesh hp-FEM. T_mesh->copy(basemesh); w_mesh->copy(basemesh); // Initialize boundary conditions. EssentialBCNonConst temp_reactor("bdy_react", REACTOR_START_TIME, T_INITIAL, T_REACTOR_MAX); EssentialBCs<double> bcs_T(&temp_reactor); SpaceSharedPtr<double> T_space(new H1Space<double>(T_mesh, &bcs_T, P_INIT)); SpaceSharedPtr<double> w_space(new H1Space<double>(MULTI ? w_mesh : T_mesh, P_INIT)); std::vector<SpaceSharedPtr<double> > spaces({ T_space, w_space }); adaptivity.set_spaces(spaces); // Define constant initial conditions. Hermes::Mixins::Loggable::Static::info("Setting initial conditions."); MeshFunctionSharedPtr<double> T_time_prev(new ConstantSolution<double>(T_mesh, T_INITIAL)); MeshFunctionSharedPtr<double> w_time_prev(new ConstantSolution<double>(w_mesh, W_INITIAL)); MeshFunctionSharedPtr<double> T_time_new(new Solution<double>(T_mesh)); MeshFunctionSharedPtr<double> w_time_new(new Solution<double>(w_mesh)); // Solutions. MeshFunctionSharedPtr<double> T_coarse(new Solution<double>), w_coarse(new Solution<double>); // Initialize the weak formulation. WeakFormSharedPtr<double> wf(new CustomWeakFormHeatMoistureRK(c_TT, c_ww, d_TT, d_Tw, d_wT, d_ww, k_TT, k_ww, T_EXTERIOR, W_EXTERIOR, "bdy_ext")); // Initialize refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST); // Geometry and position of visualization windows. WinGeom* T_sln_win_geom = new WinGeom(0, 0, 300, 450); WinGeom* w_sln_win_geom = new WinGeom(310, 0, 300, 450); WinGeom* T_mesh_win_geom = new WinGeom(620, 0, 280, 450); WinGeom* w_mesh_win_geom = new WinGeom(910, 0, 280, 450); // Initialize views. ScalarView T_sln_view("Temperature", T_sln_win_geom); ScalarView w_sln_view("Moisture (scaled)", w_sln_win_geom); OrderView T_order_view("Temperature mesh", T_mesh_win_geom); OrderView w_order_view("Moisture mesh", w_mesh_win_geom); // Show initial conditions. T_sln_view.show(T_time_prev); w_sln_view.show(w_time_prev); T_order_view.show(T_space); w_order_view.show(w_space); // Time stepping loop: int ts = 1; while (current_time < SIMULATION_TIME) { Hermes::Mixins::Loggable::Static::info("Simulation time = %g s (%d h, %d d, %d y)", current_time, (int)current_time / 3600, (int)current_time / (3600 * 24), (int)current_time / (3600 * 24 * 364)); // Update time-dependent essential BCs. if (current_time <= REACTOR_START_TIME) { Hermes::Mixins::Loggable::Static::info("Updating time-dependent essential BC."); Space<double>::update_essential_bc_values({ T_space, w_space }, current_time); } // Uniform mesh derefinement. if (ts > 1 && ts % UNREF_FREQ == 0) { Hermes::Mixins::Loggable::Static::info("Global mesh derefinement."); switch (UNREF_METHOD) { case 1: T_mesh->copy(basemesh); w_mesh->copy(basemesh); T_space->set_uniform_order(P_INIT); w_space->set_uniform_order(P_INIT); break; case 2: T_mesh->unrefine_all_elements(); if (MULTI) w_mesh->unrefine_all_elements(); T_space->set_uniform_order(P_INIT); w_space->set_uniform_order(P_INIT); break; case 3: T_mesh->unrefine_all_elements(); if (MULTI) w_mesh->unrefine_all_elements(); T_space->adjust_element_order(-1, -1, P_INIT, P_INIT); w_space->adjust_element_order(-1, -1, P_INIT, P_INIT); break; default: throw Hermes::Exceptions::Exception("Wrong global derefinement method."); } T_space->assign_dofs(); w_space->assign_dofs(); Space<double>::assign_dofs(spaces); } // Spatial adaptivity loop. Note: T_time_prev and w_time_prev must not be changed during // spatial adaptivity. bool done = false; int as = 1; do { Hermes::Mixins::Loggable::Static::info("Time step %d, adaptivity step %d:", ts, as); // Construct globally refined reference mesh and setup reference space. Mesh::ReferenceMeshCreator refMeshCreatorU(T_mesh); MeshSharedPtr ref_T_mesh = refMeshCreatorU.create_ref_mesh(); Space<double>::ReferenceSpaceCreator refSpaceCreatorT(T_space, ref_T_mesh); SpaceSharedPtr<double> ref_T_space = refSpaceCreatorT.create_ref_space(); Mesh::ReferenceMeshCreator refMeshCreatorW(w_mesh); MeshSharedPtr ref_w_mesh = refMeshCreatorW.create_ref_mesh(); Space<double>::ReferenceSpaceCreator refSpaceCreatorW(w_space, ref_w_mesh); SpaceSharedPtr<double> ref_w_space = refSpaceCreatorW.create_ref_space(); std::vector<SpaceSharedPtr<double> > ref_spaces({ ref_T_space, ref_w_space }); // Initialize Runge-Kutta time stepping. RungeKutta<double> runge_kutta(wf, ref_spaces, &bt); // Perform one Runge-Kutta time step according to the selected Butcher's table. Hermes::Mixins::Loggable::Static::info("Runge-Kutta time step (t = %g s, tau = %g s, stages: %d).", current_time, time_step, bt.get_size()); try { runge_kutta.set_time(current_time); runge_kutta.set_time_step(time_step); runge_kutta.set_newton_max_allowed_iterations(NEWTON_MAX_ITER); runge_kutta.set_newton_tolerance(NEWTON_TOL); runge_kutta.rk_time_step_newton({ T_time_prev, w_time_prev }, { T_time_new, w_time_new }); } catch (Exceptions::Exception& e) { e.print_msg(); throw Hermes::Exceptions::Exception("Runge-Kutta time step failed"); } // Project the fine mesh solution onto the coarse meshes. Hermes::Mixins::Loggable::Static::info("Projecting fine mesh solutions on coarse meshes for error estimation."); OGProjection<double>::project_global({ T_space, w_space }, { T_time_new, w_time_new }, { T_coarse, w_coarse }); // Calculate element errors and total error estimate. Hermes::Mixins::Loggable::Static::info("Calculating error estimate."); errorCalculator.calculate_errors({ T_coarse, w_coarse }, { T_time_new, w_time_new }); double err_est_rel_total = 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({ T_space, w_space }), Space<double>::get_num_dofs(ref_spaces), err_est_rel_total); // If err_est too large, adapt the meshes. if (err_est_rel_total < ERR_STOP) done = true; else { Hermes::Mixins::Loggable::Static::info("Adapting the coarse mesh."); done = adaptivity.adapt({ &selector, &selector }); // Increase the counter of performed adaptivity steps. as++; } } while (done == false); // Update time. current_time += time_step; // Show new coarse meshes and solutions. char title[100]; sprintf(title, "Temperature, t = %g days", current_time / 3600. / 24); T_sln_view.set_title(title); T_sln_view.show(T_coarse); sprintf(title, "Moisture (scaled), t = %g days", current_time / 3600. / 24); w_sln_view.set_title(title); w_sln_view.show(w_coarse); T_order_view.show(T_space); w_order_view.show(w_space); // Save fine mesh solutions for the next time step. T_time_prev->copy(T_time_new); w_time_prev->copy(w_time_new); ts++; } // 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()) 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; MeshReaderH2D 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_boundary("Boundary_air", INIT_REF_NUM_BDY); mesh.refine_towards_boundary("Boundary_ground", INIT_REF_NUM_BDY); // Previous and next time level solutions. CustomInitialCondition sln_time_prev(&mesh, TEMP_INIT); Solution<double> sln_time_new(&mesh); // Initialize the weak formulation. double current_time = 0; CustomWeakFormHeatRK wf("Boundary_air", ALPHA, LAMBDA, HEATCAP, RHO, ¤t_time, TEMP_INIT, T_FINAL); // Initialize boundary conditions. DefaultEssentialBCConst<double> bc_essential("Boundary_ground", TEMP_INIT); 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); // Initialize views. ScalarView Tview("Temperature", new WinGeom(0, 0, 450, 600)); Tview.set_min_max_range(0,20); Tview.fix_scale_width(30); // Initialize Runge-Kutta time stepping. RungeKutta<double> runge_kutta(&wf, &space, &bt, matrix_solver); // Time stepping loop: int ts = 1; do { // 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, &sln_time_prev, &sln_time_new, freeze_jacobian, block_diagonal_jacobian, verbose, NEWTON_TOL, NEWTON_MAX_ITER, damping_coeff, max_allowed_residual_norm); } catch(Exceptions::Exception& e) { e.printMsg(); error("Runge-Kutta time step failed"); } // Show the new time level solution. char title[100]; sprintf(title, "Time %3.2f s", current_time); Tview.set_title(title); Tview.show(&sln_time_new); // Copy solution for the new time step. sln_time_prev.copy(&sln_time_new); // Increase current time and time step counter. current_time += time_step; ts++; } while (current_time < T_FINAL); // 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; MeshReaderH2D mloader; mloader.load("../domain.mesh", &mesh); // Perform initial mesh refinemets. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions. BCTypes bc_types; bc_types.add_bc_dirichlet("Left"); bc_types.add_bc_neumann("Neumann"); bc_types.add_bc_newton("Cooled"); // Enter Dirichlet boundary values. BCValues bc_values_t; bc_values_t.add_const("Left", 1.0); BCValues bc_values_c; bc_values_c.add_zero("Left"); // Create H1 spaces with default shapesets. H1Space* t_space = new H1Space(&mesh, &bc_types, &bc_values_t, P_INIT); H1Space* c_space = new H1Space(&mesh, &bc_types, &bc_values_c, P_INIT); int ndof = Space::get_num_dofs(Hermes::vector<Space *>(t_space, c_space)); info("ndof = %d.", ndof); // Define initial conditions. Solution t_prev_time_1, c_prev_time_1, t_prev_time_2, c_prev_time_2, t_iter, c_iter, t_prev_newton, c_prev_newton; t_prev_time_1.set_exact(&mesh, temp_ic); c_prev_time_1.set_exact(&mesh, conc_ic); t_prev_time_2.set_exact(&mesh, temp_ic); c_prev_time_2.set_exact(&mesh, conc_ic); t_iter.set_exact(&mesh, temp_ic); c_iter.set_exact(&mesh, conc_ic); // Filters for the reaction rate omega and its derivatives. DXDYFilter omega(omega_fn, Hermes::vector<MeshFunction*>(&t_prev_time_1, &c_prev_time_1)); DXDYFilter omega_dt(omega_dt_fn, Hermes::vector<MeshFunction*>(&t_prev_time_1, &c_prev_time_1)); DXDYFilter omega_dc(omega_dc_fn, Hermes::vector<MeshFunction*>(&t_prev_time_1, &c_prev_time_1)); // Initialize weak formulation. WeakForm wf(2, JFNK ? true : false); if (!JFNK || (JFNK && PRECOND == 1)) { wf.add_matrix_form(0, 0, callback(newton_bilinear_form_0_0), HERMES_NONSYM, HERMES_ANY, &omega_dt); wf.add_matrix_form_surf(0, 0, callback(newton_bilinear_form_0_0_surf), 3); wf.add_matrix_form(1, 1, callback(newton_bilinear_form_1_1), HERMES_NONSYM, HERMES_ANY, &omega_dc); wf.add_matrix_form(0, 1, callback(newton_bilinear_form_0_1), HERMES_NONSYM, HERMES_ANY, &omega_dc); wf.add_matrix_form(1, 0, callback(newton_bilinear_form_1_0), HERMES_NONSYM, HERMES_ANY, &omega_dt); } else if (PRECOND == 2) { wf.add_matrix_form(0, 0, callback(precond_0_0)); wf.add_matrix_form(1, 1, callback(precond_1_1)); } wf.add_vector_form(0, callback(newton_linear_form_0), HERMES_ANY, Hermes::vector<MeshFunction*>(&t_prev_time_1, &t_prev_time_2, &omega)); wf.add_vector_form_surf(0, callback(newton_linear_form_0_surf), 3); wf.add_vector_form(1, callback(newton_linear_form_1), HERMES_ANY, Hermes::vector<MeshFunction*>(&c_prev_time_1, &c_prev_time_2, &omega)); // Project the functions "t_iter" and "c_iter" on the FE space // in order to obtain initial vector for NOX. info("Projecting initial solutions on the FE meshes."); scalar* coeff_vec = new scalar[ndof]; OGProjection::project_global(Hermes::vector<Space *>(t_space, c_space), Hermes::vector<MeshFunction*>(&t_prev_time_1, &c_prev_time_1), coeff_vec); // Measure the projection time. double proj_time = cpu_time.tick().last(); // Initialize finite element problem. DiscreteProblem dp(&wf, Hermes::vector<Space*>(t_space, c_space)); // Initialize NOX solver and preconditioner. NoxSolver solver(&dp); RCP<Precond> pc = rcp(new MlPrecond("sa")); if (PRECOND) { if (JFNK) solver.set_precond(pc); else solver.set_precond("Ifpack"); } if (TRILINOS_OUTPUT) solver.set_output_flags(NOX::Utils::Error | NOX::Utils::OuterIteration | NOX::Utils::OuterIterationStatusTest | NOX::Utils::LinearSolverDetails); // Time stepping loop: double total_time = 0.0; cpu_time.tick_reset(); for (int ts = 1; total_time <= T_FINAL; ts++) { info("---- Time step %d, t = %g s", ts, total_time + TAU); cpu_time.tick(HERMES_SKIP); solver.set_init_sln(coeff_vec); if (solver.solve()) { Solution::vector_to_solutions(solver.get_solution(), Hermes::vector<Space *>(t_space, c_space), Hermes::vector<Solution *>(&t_prev_newton, &c_prev_newton)); cpu_time.tick(); info("Number of nonlin iterations: %d (norm of residual: %g)", solver.get_num_iters(), solver.get_residual()); info("Total number of iterations in linsolver: %d (achieved tolerance in the last step: %g)", solver.get_num_lin_iters(), solver.get_achieved_tol()); // Time measurement. cpu_time.tick(HERMES_SKIP); // Update global time. total_time += TAU; // Saving solutions for the next time step. t_prev_time_2.copy(&t_prev_time_1); c_prev_time_2.copy(&c_prev_time_1); t_prev_time_1 = t_prev_newton; c_prev_time_1 = c_prev_newton; } else error("NOX failed."); info("Total running time for time level %d: %g s.", ts, cpu_time.tick().last()); } info("T Coordinate ( 0, 8) value = %lf", t_prev_time_1.get_pt_value(0.0, 8.0)); info("T Coordinate ( 8, 8) value = %lf", t_prev_time_1.get_pt_value(8.0, 8.0)); info("T Coordinate ( 15, 8) value = %lf", t_prev_time_1.get_pt_value(15.0, 8.0)); info("T Coordinate ( 24, 8) value = %lf", t_prev_time_1.get_pt_value(24.0, 8.0)); info("T Coordinate ( 30, 8) value = %lf", t_prev_time_1.get_pt_value(30.0, 8.0)); info("T Coordinate ( 40, 8) value = %lf", t_prev_time_1.get_pt_value(40.0, 8.0)); info("T Coordinate ( 50, 8) value = %lf", t_prev_time_1.get_pt_value(50.0, 8.0)); info("T Coordinate ( 60, 8) value = %lf", t_prev_time_1.get_pt_value(60.0, 8.0)); info("C Coordinate ( 0, 8) value = %lf", c_prev_time_1.get_pt_value(0.0, 8.0)); info("C Coordinate ( 8, 8) value = %lf", c_prev_time_1.get_pt_value(8.0, 8.0)); info("C Coordinate ( 15, 8) value = %lf", c_prev_time_1.get_pt_value(15.0, 8.0)); info("C Coordinate ( 24, 8) value = %lf", c_prev_time_1.get_pt_value(24.0, 8.0)); info("C Coordinate ( 30, 8) value = %lf", c_prev_time_1.get_pt_value(30.0, 8.0)); info("C Coordinate ( 40, 8) value = %lf", c_prev_time_1.get_pt_value(40.0, 8.0)); info("C Coordinate ( 50, 8) value = %lf", c_prev_time_1.get_pt_value(50.0, 8.0)); info("C Coordinate ( 60, 8) value = %lf", c_prev_time_1.get_pt_value(60.0, 8.0)); double coor_x[8] = {0.0, 8.0, 15.0, 24.0, 30.0, 40.0, 50.0, 60.0}; double coor_y = 8.0; double t_value[8] = {1.000000, 1.000078, 0.002819, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000}; double c_value[8] = {0.000000, -0.000078, 0.997181, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000}; bool success = true; for (int i = 0; i < 8; i++) { if ((abs(t_value[i] - t_prev_time_1.get_pt_value(coor_x[i], coor_y)) > 1E-4) || (abs(c_value[i] - c_prev_time_1.get_pt_value(coor_x[i], coor_y)) > 1E-4)) success = false; } if (success) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("channel.mesh", &mesh); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(0, true); // Initialize boundary condition types and spaces with default shapesets. L2Space<double> space_rho(&mesh, P_INIT); L2Space<double> space_rho_v_x(&mesh, P_INIT); L2Space<double> space_rho_v_y(&mesh, P_INIT); L2Space<double> space_e(&mesh, P_INIT); // Initialize solutions, set initial conditions. ConstantSolution<double> sln_rho(&mesh, RHO_INIT); ConstantSolution<double> sln_rho_v_x(&mesh, RHO_INIT * V1_INIT); ConstantSolution<double> sln_rho_v_y(&mesh, RHO_INIT * V2_INIT); ConstantSolution<double> sln_e(&mesh, QuantityCalculator::calc_energy(RHO_INIT, RHO_INIT * V1_INIT, RHO_INIT * V2_INIT, PRESSURE_INIT, KAPPA)); ConstantSolution<double> prev_rho(&mesh, RHO_INIT); ConstantSolution<double> prev_rho_v_x(&mesh, RHO_INIT * V1_INIT); ConstantSolution<double> prev_rho_v_y(&mesh, RHO_INIT * V2_INIT); ConstantSolution<double> prev_e(&mesh, QuantityCalculator::calc_energy(RHO_INIT, RHO_INIT * V1_INIT, RHO_INIT * V2_INIT, PRESSURE_INIT, KAPPA)); Solution<double> rsln_rho, rsln_rho_v_x, rsln_rho_v_y, rsln_e; // Numerical flux. OsherSolomonNumericalFlux num_flux(KAPPA); // For saving to the disk. Continuity<double> continuity(Continuity<double>::onlyNumber); // Initialize weak formulation. EulerEquationsWeakFormSemiImplicitMultiComponentTwoInflows wf(&num_flux, KAPPA, RHO_LEFT, V1_LEFT, V2_LEFT, PRESSURE_LEFT, RHO_TOP, V1_TOP, V2_TOP, PRESSURE_TOP, BDY_SOLID_WALL, BDY_INLET_LEFT, BDY_INLET_TOP, BDY_OUTLET, &prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e); // Filters for visualization of Mach number, pressure and entropy. MachNumberFilter Mach_number(Hermes::vector<MeshFunction<double>*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), KAPPA); PressureFilter pressure(Hermes::vector<MeshFunction<double>*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), KAPPA); EntropyFilter entropy(Hermes::vector<MeshFunction<double>*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), KAPPA, RHO_INIT, P_INIT); ScalarView pressure_view("Pressure", new WinGeom(0, 0, 600, 300)); ScalarView Mach_number_view("Mach number", new WinGeom(700, 0, 600, 300)); ScalarView entropy_production_view("Entropy estimate", new WinGeom(0, 400, 600, 300)); // Initialize refinement selector. L2ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, MAX_P_ORDER); selector.set_error_weights(1.0, 1.0, 1.0); // Set up CFL calculation class. CFLCalculation CFL(CFL_NUMBER, KAPPA); // Time stepping loop. int iteration = 0; double t = 0; for(; t < 4.0; t += time_step) { info("---- Time step %d, time %3.5f.", iteration++, t); // Periodic global derefinements. if (iteration > 1 && iteration % UNREF_FREQ == 0 && REFINEMENT_COUNT > 0) { info("Global mesh derefinement."); REFINEMENT_COUNT = 0; space_rho.unrefine_all_mesh_elements(true); space_rho.adjust_element_order(-1, P_INIT); space_rho_v_x.copy_orders(&space_rho); space_rho_v_y.copy_orders(&space_rho); space_e.copy_orders(&space_rho); } // Adaptivity loop: int as = 1; int ndofs_prev = 0; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. int order_increase = 1; Hermes::vector<Space<double> *>* ref_spaces = Space<double>::construct_refined_spaces(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), order_increase); if(ndofs_prev != 0) if(Space<double>::get_num_dofs(*ref_spaces) == ndofs_prev) selector.set_error_weights(2.0 * selector.get_error_weight_h(), 1.0, 1.0); else selector.set_error_weights(1.0, 1.0, 1.0); ndofs_prev = Space<double>::get_num_dofs(*ref_spaces); // Project the previous time level solution onto the new fine mesh. info("Projecting the previous time level solution onto the new fine mesh."); OGProjection<double>::project_global(*ref_spaces, Hermes::vector<Solution<double>*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), Hermes::vector<Solution<double>*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), matrix_solver_type, Hermes::vector<Hermes::Hermes2D::ProjNormType>(), iteration > 1); // Report NDOFs. info("ndof_coarse: %d, ndof_fine: %d.", Space<double>::get_num_dofs(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e)), Space<double>::get_num_dofs(*ref_spaces)); // Assemble the reference problem. info("Solving on reference mesh."); DiscreteProblem<double> dp(&wf, *ref_spaces); SparseMatrix<double>* matrix = create_matrix<double>(matrix_solver_type); Vector<double>* rhs = create_vector<double>(matrix_solver_type); LinearSolver<double>* solver = create_linear_solver<double>(matrix_solver_type, matrix, rhs); wf.set_time_step(time_step); dp.assemble(matrix, rhs); // Solve the matrix problem. info("Solving the matrix problem."); if(solver->solve()) if(!SHOCK_CAPTURING) Solution<double>::vector_to_solutions(solver->get_sln_vector(), *ref_spaces, Hermes::vector<Solution<double>*>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e)); else { FluxLimiter flux_limiter(FluxLimiter::Kuzmin, solver->get_sln_vector(), *ref_spaces, true); flux_limiter.limit_second_orders_according_to_detector(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e)); flux_limiter.limit_according_to_detector(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e)); flux_limiter.get_limited_solutions(Hermes::vector<Solution<double>*>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e)); } else error ("Matrix solver failed.\n"); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection<double>::project_global(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), Hermes::vector<Solution<double>*>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e), Hermes::vector<Solution<double>*>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e), matrix_solver_type, Hermes::vector<ProjNormType>(HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM)); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt<double>* adaptivity = new Adapt<double>(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), Hermes::vector<ProjNormType>(HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM)); double err_est_rel_total = adaptivity->calc_err_est(Hermes::vector<Solution<double>*>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e), Hermes::vector<Solution<double>*>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e)) * 100; CFL.calculate_semi_implicit(Hermes::vector<Solution<double> *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e), (*ref_spaces)[0]->get_mesh(), time_step); // Report results. info("err_est_rel: %g%%", err_est_rel_total); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(Hermes::vector<RefinementSelectors::Selector<double> *>(&selector, &selector, &selector, &selector), THRESHOLD, STRATEGY, MESH_REGULARITY); REFINEMENT_COUNT++; if (Space<double>::get_num_dofs(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e)) >= NDOF_STOP) done = true; else as++; } // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(!done) for(unsigned int i = 0; i < ref_spaces->size(); i++) delete (*ref_spaces)[i]; } while (done == false); // Copy the solutions into the previous time level ones. prev_rho.copy(&rsln_rho); prev_rho_v_x.copy(&rsln_rho_v_x); prev_rho_v_y.copy(&rsln_rho_v_y); prev_e.copy(&rsln_e); delete rsln_rho.get_mesh(); rsln_rho.own_mesh = false; delete rsln_rho_v_x.get_mesh(); rsln_rho_v_x.own_mesh = false; delete rsln_rho_v_y.get_mesh(); rsln_rho_v_y.own_mesh = false; delete rsln_e.get_mesh(); rsln_e.own_mesh = false; // Visualization and saving on disk. if((iteration - 1) % EVERY_NTH_STEP == 0) { continuity.add_record((unsigned int)(iteration - 1)); continuity.get_last_record()->save_mesh(prev_rho.get_mesh()); continuity.get_last_record()->save_space(prev_rho.get_space()); continuity.get_last_record()->save_time_step_length(time_step); // Hermes visualization. if(HERMES_VISUALIZATION) { Mach_number.reinit(); pressure.reinit(); entropy.reinit(); pressure_view.show(&pressure, 1); entropy_production_view.show(&entropy, 1); Mach_number_view.show(&Mach_number, 1); pressure_view.save_numbered_screenshot("pressure %i.bmp", iteration); Mach_number_view.save_numbered_screenshot("Mach no %i.bmp", iteration); } // Output solution in VTK format. if(VTK_VISUALIZATION) { pressure.reinit(); Mach_number.reinit(); entropy.reinit(); Linearizer lin; char filename[40]; sprintf(filename, "Pressure-%i.vtk", iteration - 1); lin.save_solution_vtk(&pressure, filename, "Pressure", false); sprintf(filename, "Mach number-%i.vtk", iteration - 1); lin.save_solution_vtk(&Mach_number, filename, "MachNumber", false); if((iteration - 1) % (EVERY_NTH_STEP * EVERY_NTH_STEP) == 0) { sprintf(filename, "Entropy-%i.vtk", iteration - 1); lin.save_solution_vtk(&entropy, filename, "Entropy", false); } } } } pressure_view.close(); entropy_production_view.close(); Mach_number_view.close(); 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()) 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; MeshReaderH2D 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("Boundary_air", INIT_REF_NUM_BDY); mesh.refine_towards_boundary("Boundary_ground", INIT_REF_NUM_BDY); // Previous and next time level solutions. Solution<double>* sln_time_prev = new InitialCondition(&mesh, TEMP_INIT); Solution<double>* sln_time_new = new Solution<double>(&mesh); // Initialize the weak formulation. double current_time = 0; CustomWeakFormHeatRK wf("Boundary_air", ALPHA, LAMBDA, HEATCAP, RHO, ¤t_time, TEMP_INIT, T_FINAL); // Initialize boundary conditions. Hermes::Hermes2D::DefaultEssentialBCConst<double> bc_essential("Boundary_ground", TEMP_INIT); Hermes::Hermes2D::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); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, &space); // Initialize Runge-Kutta time stepping. RungeKutta<double> runge_kutta(&dp, &bt, matrix_solver_type); // Time stepping loop: int ts = 1; do { // Perform one Runge-Kutta time step according to the selected Butcher's table. info("Runge-Kutta time step (t = %g s, tau = %g s, stages: %d).", current_time, time_step, bt.get_size()); bool freeze_jacobian = true; bool verbose = true; if (!runge_kutta.rk_time_step(current_time, time_step, sln_time_prev, sln_time_new, freeze_jacobian, verbose)) error("Runge-Kutta time step failed, try to decrease time step size."); // Copy solution for the new time step. sln_time_prev->copy(sln_time_new); // Increase current time and time step counter. current_time += time_step; ts++; } while (current_time < T_FINAL); /* Begin test */ info("Coordinate (-2.0, 2.0) value = %lf", sln_time_new->get_pt_value(-3.5, 17.0)); info("Coordinate (-1.0, 2.0) value = %lf", sln_time_new->get_pt_value(-1.0, 2.0)); info("Coordinate ( 0.0, 2.0) value = %lf", sln_time_new->get_pt_value(0.0, 9.5)); info("Coordinate ( 1.0, 2.0) value = %lf", sln_time_new->get_pt_value(1.0, 2.0)); info("Coordinate ( 2.0, 2.0) value = %lf", sln_time_new->get_pt_value(3.5, 17.0)); bool success = true; if (fabs(sln_time_new->get_pt_value(-3.5, 17.0) - 10.005262) > 1E-6) success = false; if (fabs(sln_time_new->get_pt_value(-1.0, 2.0) - 10.0) > 1E-6) success = false; if (fabs(sln_time_new->get_pt_value(0.0, 9.5) - 9.995515) > 1E-6) success = false; if (fabs(sln_time_new->get_pt_value( 1.0, 2.0) - 10.0) > 1E-6) success = false; if (fabs(sln_time_new->get_pt_value(3.5, 17.0) - 10.005262) > 1E-6) success = false; if (success) { printf("Success!\n"); return TEST_SUCCESS; } else { printf("Failure!\n"); return TEST_FAILURE; } }