int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load(mesh_file, &mesh); // Perform initial mesh refinements (optional). for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions. DefaultEssentialBCConst bc_essential(BDY_MARKER, 0.0); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d", ndof); // Initialize the weak formulation. WeakFormPoisson wf(CONST_F); // Initialize the FE problem. DiscreteProblem dp(&wf, &space); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the solution. Solution sln; // Assemble the stiffness matrix and right-hand side vector. info("Assembling the stiffness matrix and right-hand side vector."); dp.assemble(matrix, rhs); // Solve the linear system and if successful, obtain the solution. info("Solving the matrix problem."); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); // Visualize the solution. ScalarView view("Solution", new WinGeom(0, 0, 800, 350)); view.show(&sln); // Wait for the view to be closed. View::wait(); // Clean up. delete solver; delete matrix; delete rhs; return 0; }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load(mesh_file, &mesh); // Perform initial mesh refinements (optional). for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions. DefaultEssentialBCConst bc_essential("Bdy", 0.0); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d", ndof); // Initialize the weak formulation. WeakFormPoisson wf(CONST_F); // Initialize the FE problem. DiscreteProblem dp(&wf, &space); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof]; memset(coeff_vec, 0, ndof*sizeof(scalar)); // Perform Newton's iteration. if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution sln; Solution::vector_to_solution(coeff_vec, &space, &sln); // Visualize the solution. ScalarView view("Solution", new WinGeom(0, 0, 800, 350)); view.show(&sln); // Wait for the view to be closed. View::wait(); // Clean up. delete solver; delete matrix; delete rhs; return 0; }
int main(int argc, char* argv[]) { try { // Sanity check for omega. double K_squared = Hermes::sqr(OMEGA / M_PI) * (OMEGA - 2) / (1 - OMEGA); if (K_squared <= 0) throw Hermes::Exceptions::Exception("Wrong choice of omega, K_squared < 0!"); double K_norm_coeff = std::sqrt(K_squared) / std::sqrt(Hermes::sqr(K_x) + Hermes::sqr(K_y)); Hermes::Mixins::Loggable::Static::info("Wave number K = %g", std::sqrt(K_squared)); K_x *= K_norm_coeff; K_y *= K_norm_coeff; // Wave number. double K = std::sqrt(Hermes::sqr(K_x) + Hermes::sqr(K_y)); // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table); 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 E_mesh(new Mesh), H_mesh(new Mesh), P_mesh(new Mesh); MeshReaderH2D mloader; mloader.load("domain.mesh", E_mesh); mloader.load("domain.mesh", H_mesh); mloader.load("domain.mesh", P_mesh); // Perform initial mesh refinemets. for (int i = 0; i < INIT_REF_NUM; i++) { E_mesh->refine_all_elements(); H_mesh->refine_all_elements(); P_mesh->refine_all_elements(); } // Initialize solutions. double current_time = 0; MeshFunctionSharedPtr<double> E_time_prev(new CustomInitialConditionE(E_mesh, current_time, OMEGA, K_x, K_y)); MeshFunctionSharedPtr<double> H_time_prev(new CustomInitialConditionH(H_mesh, current_time, OMEGA, K_x, K_y)); MeshFunctionSharedPtr<double> P_time_prev(new CustomInitialConditionP(P_mesh, current_time, OMEGA, K_x, K_y)); std::vector<MeshFunctionSharedPtr<double> > slns_time_prev({ E_time_prev, H_time_prev, P_time_prev }); MeshFunctionSharedPtr<double> E_time_new(new Solution<double>(E_mesh)), H_time_new(new Solution<double>(H_mesh)), P_time_new(new Solution<double>(P_mesh)); MeshFunctionSharedPtr<double> E_time_new_coarse(new Solution<double>(E_mesh)), H_time_new_coarse(new Solution<double>(H_mesh)), P_time_new_coarse(new Solution<double>(P_mesh)); std::vector<MeshFunctionSharedPtr<double> > slns_time_new({ E_time_new, H_time_new, P_time_new }); // Initialize the weak formulation. WeakFormSharedPtr<double> wf(new CustomWeakFormMD(OMEGA, K_x, K_y, MU_0, EPS_0, EPS_INF, EPS_Q, TAU)); // Initialize boundary conditions DefaultEssentialBCConst<double> bc_essential("Bdy", 0.0); EssentialBCs<double> bcs(&bc_essential); SpaceSharedPtr<double> E_space(new HcurlSpace<double>(E_mesh, &bcs, P_INIT)); SpaceSharedPtr<double> H_space(new H1Space<double>(H_mesh, NULL, P_INIT)); //L2Space<double> H_space(mesh, P_INIT)); SpaceSharedPtr<double> P_space(new HcurlSpace<double>(P_mesh, &bcs, P_INIT)); std::vector<SpaceSharedPtr<double> > spaces = std::vector<SpaceSharedPtr<double> >({ E_space, H_space, P_space }); // Initialize views. ScalarView E1_view("Solution E1", new WinGeom(0, 0, 400, 350)); E1_view.fix_scale_width(50); ScalarView E2_view("Solution E2", new WinGeom(410, 0, 400, 350)); E2_view.fix_scale_width(50); ScalarView H_view("Solution H", new WinGeom(0, 410, 400, 350)); H_view.fix_scale_width(50); ScalarView P1_view("Solution P1", new WinGeom(410, 410, 400, 350)); P1_view.fix_scale_width(50); ScalarView P2_view("Solution P2", new WinGeom(820, 410, 400, 350)); P2_view.fix_scale_width(50); // Visualize initial conditions. char title[100]; sprintf(title, "E1 - Initial Condition"); E1_view.set_title(title); E1_view.show(E_time_prev, H2D_FN_VAL_0); sprintf(title, "E2 - Initial Condition"); E2_view.set_title(title); E2_view.show(E_time_prev, H2D_FN_VAL_1); sprintf(title, "H - Initial Condition"); H_view.set_title(title); H_view.show(H_time_prev); sprintf(title, "P1 - Initial Condition"); P1_view.set_title(title); P1_view.show(P_time_prev, H2D_FN_VAL_0); sprintf(title, "P2 - Initial Condition"); P2_view.set_title(title); P2_view.show(P_time_prev, H2D_FN_VAL_1); // Initialize Runge-Kutta time stepping. RungeKutta<double> runge_kutta(wf, spaces, &bt); runge_kutta.set_newton_max_allowed_iterations(NEWTON_MAX_ITER); runge_kutta.set_newton_tolerance(NEWTON_TOL); runge_kutta.set_verbose_output(true); // Initialize refinement selector. H1ProjBasedSelector<double> H1selector(CAND_LIST); HcurlProjBasedSelector<double> HcurlSelector(CAND_LIST); // Time stepping loop. int ts = 1; do { // Perform one Runge-Kutta time step according to the selected Butcher's table. Hermes::Mixins::Loggable::Static::info("\nRunge-Kutta time step (t = %g s, time_step = %g s, stages: %d).", current_time, time_step, bt.get_size()); // Periodic global derefinements. if (ts > 1 && ts % UNREF_FREQ == 0 && REFINEMENT_COUNT > 0) { Hermes::Mixins::Loggable::Static::info("Global mesh derefinement."); REFINEMENT_COUNT = 0; E_space->unrefine_all_mesh_elements(true); H_space->unrefine_all_mesh_elements(true); P_space->unrefine_all_mesh_elements(true); E_space->adjust_element_order(-1, P_INIT); H_space->adjust_element_order(-1, P_INIT); P_space->adjust_element_order(-1, P_INIT); E_space->assign_dofs(); H_space->assign_dofs(); P_space->assign_dofs(); } // 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. int order_increase = 1; Mesh::ReferenceMeshCreator refMeshCreatorE(E_mesh); Mesh::ReferenceMeshCreator refMeshCreatorH(H_mesh); Mesh::ReferenceMeshCreator refMeshCreatorP(P_mesh); MeshSharedPtr ref_mesh_E = refMeshCreatorE.create_ref_mesh(); MeshSharedPtr ref_mesh_H = refMeshCreatorH.create_ref_mesh(); MeshSharedPtr ref_mesh_P = refMeshCreatorP.create_ref_mesh(); Space<double>::ReferenceSpaceCreator refSpaceCreatorE(E_space, ref_mesh_E, order_increase); SpaceSharedPtr<double> ref_space_E = refSpaceCreatorE.create_ref_space(); Space<double>::ReferenceSpaceCreator refSpaceCreatorH(H_space, ref_mesh_H, order_increase); SpaceSharedPtr<double> ref_space_H = refSpaceCreatorH.create_ref_space(); Space<double>::ReferenceSpaceCreator refSpaceCreatorP(P_space, ref_mesh_P, order_increase); SpaceSharedPtr<double> ref_space_P = refSpaceCreatorP.create_ref_space(); std::vector<SpaceSharedPtr<double> > ref_spaces({ ref_space_E, ref_space_H, ref_space_P }); int ndof = Space<double>::get_num_dofs(ref_spaces); Hermes::Mixins::Loggable::Static::info("ndof = %d.", ndof); try { runge_kutta.set_spaces(ref_spaces); runge_kutta.set_time(current_time); runge_kutta.set_time_step(time_step); runge_kutta.rk_time_step_newton(slns_time_prev, slns_time_new); } catch (Exceptions::Exception& e) { e.print_msg(); throw Hermes::Exceptions::Exception("Runge-Kutta time step failed"); } // Visualize the solutions. char title[100]; sprintf(title, "E1, t = %g", current_time + time_step); E1_view.set_title(title); E1_view.show(E_time_new, H2D_FN_VAL_0); sprintf(title, "E2, t = %g", current_time + time_step); E2_view.set_title(title); E2_view.show(E_time_new, H2D_FN_VAL_1); sprintf(title, "H, t = %g", current_time + time_step); H_view.set_title(title); H_view.show(H_time_new); sprintf(title, "P1, t = %g", current_time + time_step); P1_view.set_title(title); P1_view.show(P_time_new, H2D_FN_VAL_0); sprintf(title, "P2, t = %g", current_time + time_step); P2_view.set_title(title); P2_view.show(P_time_new, H2D_FN_VAL_1); // Project the fine mesh solution onto the coarse mesh. Hermes::Mixins::Loggable::Static::info("Projecting reference solution on coarse mesh."); OGProjection<double>::project_global({ E_space, H_space, P_space }, { E_time_new, H_time_new, P_time_new }, { E_time_new_coarse, H_time_new_coarse, P_time_new_coarse }); // Calculate element errors and total error estimate. Hermes::Mixins::Loggable::Static::info("Calculating error estimate."); adaptivity.set_spaces({ E_space, H_space, P_space }); errorCalculator.calculate_errors({ E_time_new_coarse, H_time_new_coarse, P_time_new_coarse }, { E_time_new, H_time_new, P_time_new }); double err_est_rel_total = errorCalculator.get_total_error_squared() * 100.; // Report results. Hermes::Mixins::Loggable::Static::info("Error estimate: %g%%", err_est_rel_total); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) { Hermes::Mixins::Loggable::Static::info("Error estimate under the specified threshold -> moving to next time step."); done = true; } else { Hermes::Mixins::Loggable::Static::info("Adapting coarse mesh."); REFINEMENT_COUNT++; done = adaptivity.adapt({ &HcurlSelector, &H1selector, &HcurlSelector }); if (!done) as++; } } while (!done); //View::wait(); E_time_prev->copy(E_time_new); H_time_prev->copy(H_time_new); P_time_prev->copy(P_time_new); // Update time. current_time += time_step; ts++; } while (current_time < T_FINAL); // Wait for the view to be closed. View::wait(); } catch (std::exception& e) { std::cout << e.what(); } return 0; }
int main(int argc, char* argv[]) { // 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 solutions. CustomInitialConditionWave E_sln(&mesh); ZeroSolutionVector F_sln(&mesh); Hermes::vector<Solution<double>*> slns(&E_sln, &F_sln); // Initialize the weak formulation. CustomWeakFormWave wf(time_step, C_SQUARED, &E_sln, &F_sln); // Initialize boundary conditions DefaultEssentialBCConst<double> bc_essential("Perfect conductor", 0.0); EssentialBCs<double> bcs(&bc_essential); // Create x- and y- displacement space using the default H1 shapeset. HcurlSpace<double> E_space(&mesh, &bcs, P_INIT); HcurlSpace<double> F_space(&mesh, &bcs, P_INIT); Hermes::vector<Space<double> *> spaces = Hermes::vector<Space<double> *>(&E_space, &F_space); info("ndof = %d.", Space<double>::get_num_dofs(spaces)); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, spaces); // 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); solver->set_factorization_scheme(HERMES_REUSE_FACTORIZATION_COMPLETELY); // Initialize views. ScalarView E1_view("Solution E1", new WinGeom(0, 0, 400, 350)); E1_view.fix_scale_width(50); ScalarView E2_view("Solution E2", new WinGeom(410, 0, 400, 350)); E2_view.fix_scale_width(50); // Time stepping loop. double current_time = 0; int ts = 1; do { // Perform one implicit Euler time step. info("Implicit Euler time step (t = %g s, time_step = %g s).", current_time, time_step); // First time assemble both the stiffness matrix and right-hand side vector, // then just the right-hand side vector. if (ts == 1) { info("Assembling the stiffness matrix and right-hand side vector."); dp.assemble(matrix, rhs); static char file_name[1024]; sprintf(file_name, "matrix.m"); FILE *f = fopen(file_name, "w"); matrix->dump(f, "A"); fclose(f); } else { info("Assembling the right-hand side vector (only)."); dp.assemble(rhs); } // Solve the linear system and if successful, obtain the solution. info("Solving the matrix problem."); if(solver->solve()) Solution<double>::vector_to_solutions(solver->get_sln_vector(), spaces, slns); else error ("Matrix solver failed.\n"); // Visualize the solutions. char title[100]; sprintf(title, "E1, t = %g", current_time); E1_view.set_title(title); E1_view.show(&E_sln, HERMES_EPS_NORMAL, H2D_FN_VAL_0); sprintf(title, "E2, t = %g", current_time); E2_view.set_title(title); E2_view.show(&E_sln, HERMES_EPS_NORMAL, H2D_FN_VAL_1); // Update time. current_time += time_step; } while (current_time < T_FINAL); // Wait for the view to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); if (bt.is_explicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Load the mesh. MeshSharedPtr mesh(new Mesh), basemesh(new Mesh); MeshReaderH2D mloader; mloader.load("square.mesh", basemesh); mesh->copy(basemesh); // Initial mesh refinements. for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh->refine_all_elements(); mesh->refine_towards_boundary("Top", INIT_REF_NUM_BDY); // Initialize boundary conditions. CustomEssentialBCNonConst bc_essential(Hermes::vector<std::string>("Bottom", "Right", "Top", "Left")); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT)); int ndof_coarse = Space<double>::get_num_dofs(space); adaptivity.set_space(space); Hermes::Mixins::Loggable::Static::info("ndof_coarse = %d.", ndof_coarse); // Zero initial solution. This is why we use H_OFFSET. MeshFunctionSharedPtr<double> h_time_prev(new ZeroSolution<double>(mesh)), h_time_new(new ZeroSolution<double>(mesh)); // Initialize the constitutive relations. ConstitutiveRelations* constitutive_relations; if(constitutive_relations_type == CONSTITUTIVE_GENUCHTEN) constitutive_relations = new ConstitutiveRelationsGenuchten(ALPHA, M, N, THETA_S, THETA_R, K_S, STORATIVITY); else constitutive_relations = new ConstitutiveRelationsGardner(ALPHA, THETA_S, THETA_R, K_S); // Initialize the weak formulation. CustomWeakFormRichardsRK wf(constitutive_relations); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, space); // Create a refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST); // Visualize initial condition. char title[100]; ScalarView view("Initial condition", new WinGeom(0, 0, 440, 350)); OrderView ordview("Initial mesh", new WinGeom(445, 0, 440, 350)); view.show(h_time_prev); ordview.show(space); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; cpu_time.tick(); // Time stepping loop. double current_time = 0; int ts = 1; do { // Periodic global derefinement. if (ts > 1 && ts % UNREF_FREQ == 0) { Hermes::Mixins::Loggable::Static::info("Global mesh derefinement."); switch (UNREF_METHOD) { case 1: mesh->copy(basemesh); space->set_uniform_order(P_INIT); break; case 2: mesh->unrefine_all_elements(); space->set_uniform_order(P_INIT); break; case 3: space->unrefine_all_mesh_elements(); space->adjust_element_order(-1, -1, P_INIT, P_INIT); break; default: throw Hermes::Exceptions::Exception("Wrong global derefinement method."); } space->assign_dofs(); ndof_coarse = Space<double>::get_num_dofs(space); } // Spatial adaptivity loop. Note: h_time_prev must not be changed // during spatial adaptivity. bool done = false; int as = 1; double err_est; do { Hermes::Mixins::Loggable::Static::info("Time step %d, adaptivity step %d:", ts, as); // Construct globally refined reference mesh and setup reference space. Mesh::ReferenceMeshCreator refMeshCreator(mesh); MeshSharedPtr ref_mesh = refMeshCreator.create_ref_mesh(); Space<double>::ReferenceSpaceCreator refSpaceCreator(space, ref_mesh); SpaceSharedPtr<double> ref_space = refSpaceCreator.create_ref_space(); int ndof_ref = Space<double>::get_num_dofs(ref_space); // Time measurement. cpu_time.tick(); // Initialize Runge-Kutta time stepping. RungeKutta<double> runge_kutta(&wf, ref_space, &bt); // Perform one Runge-Kutta time step according to the selected Butcher's table. Hermes::Mixins::Loggable::Static::info("Runge-Kutta time step (t = %g s, tau = %g s, stages: %d).", current_time, time_step, bt.get_size()); try { runge_kutta.set_time(current_time); runge_kutta.set_time_step(time_step); runge_kutta.set_max_allowed_iterations(NEWTON_MAX_ITER); runge_kutta.set_tolerance(NEWTON_TOL); runge_kutta.rk_time_step_newton(h_time_prev, h_time_new); } catch(Exceptions::Exception& e) { e.print_msg(); throw Hermes::Exceptions::Exception("Runge-Kutta time step failed"); } // Project the fine mesh solution onto the coarse mesh. MeshFunctionSharedPtr<double> sln_coarse(new Solution<double>); Hermes::Mixins::Loggable::Static::info("Projecting fine mesh solution on coarse mesh for error estimation."); OGProjection<double> ogProjection; ogProjection.project_global(space, h_time_new, sln_coarse); // Calculate element errors and total error estimate. Hermes::Mixins::Loggable::Static::info("Calculating error estimate."); errorCalculator.calculate_errors(sln_coarse, h_time_new, true); double err_est_rel_total = errorCalculator.get_total_error_squared() * 100; // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_ref: %d, err_est_rel: %g%%", Space<double>::get_num_dofs(space), Space<double>::get_num_dofs(ref_space), err_est_rel_total); // Time measurement. cpu_time.tick(); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { Hermes::Mixins::Loggable::Static::info("Adapting the coarse mesh."); done = adaptivity.adapt(&selector); // Increase the counter of performed adaptivity steps. as++; } } while (done == false); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(current_time, Space<double>::get_num_dofs(space)); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(current_time, cpu_time.accumulated()); graph_cpu.save("conv_cpu_est.dat"); // Visualize the solution and mesh-> char title[100]; sprintf(title, "Solution, time %g", current_time); view.set_title(title); view.show_mesh(false); view.show(h_time_new); sprintf(title, "Mesh, time %g", current_time); ordview.set_title(title); ordview.show(space); // Copy last reference solution into h_time_prev. h_time_prev->copy(h_time_new); // Increase current time and counter of time steps. current_time += time_step; ts++; } while (current_time < T_FINAL); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Initialize refinement selector. MySelector selector(hORpSelectionBasedOnDOFs); HermesCommonApi.set_integral_param_value(Hermes::showInternalWarnings, false); // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; cpu_time.tick(); // Load the mesh. MeshSharedPtr mesh(new Mesh); MeshReaderH2D mloader; mloader.load("domain.mesh", mesh); // Error calculation & adaptivity. DefaultErrorCalculator<complex, HERMES_H1_NORM> errorCalculator(RelativeErrorToGlobalNorm, 1); // Stopping criterion for an adaptivity step. AdaptStoppingCriterionSingleElement<complex> stoppingCriterion(THRESHOLD); // Adaptivity processor class. Adapt<complex> adaptivity(&errorCalculator, &stoppingCriterion); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); // Initialize boundary conditions. DefaultEssentialBCConst<complex> bc_essential("Source", P_SOURCE); EssentialBCs<complex> bcs(&bc_essential); // Create an H1 space with default shapeset. SpaceSharedPtr<complex> space(new H1Space<complex> (mesh, &bcs, P_INIT)); int ndof = Space<complex>::get_num_dofs(space); //Hermes::Mixins::Loggable::Static::info("ndof = %d", ndof); // Initialize the weak formulation. CustomWeakFormAcoustics wf("Wall", RHO, SOUND_SPEED, OMEGA); // Initialize coarse and reference mesh solution. MeshFunctionSharedPtr<complex> sln(new Solution<complex>), ref_sln(new Solution<complex>); // Initialize views. ScalarView sview("Acoustic pressure", new WinGeom(600, 0, 600, 350)); sview.show_contours(.2); ScalarView eview("Error", new WinGeom(600, 377, 600, 350)); sview.show_mesh(false); sview.fix_scale_width(50); OrderView oview("Polynomial orders", new WinGeom(1208, 0, 600, 350)); ScalarView ref_view("Refined elements", new WinGeom(1208, 377, 600, 350)); ref_view.show_scale(false); ref_view.set_min_max_range(0, 2); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; //Hermes::Mixins::Loggable::Static::info("Solving on reference mesh."); // Time measurement. cpu_time.tick(); // Perform Newton's iteration. Hermes::Hermes2D::NewtonSolver<complex> newton(&wf, space); newton.set_verbose_output(false); // Adaptivity loop: int as = 1; adaptivity.set_space(space); bool done = false; do { //Hermes::Mixins::Loggable::Static::info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Mesh::ReferenceMeshCreator refMeshCreator(mesh); MeshSharedPtr ref_mesh = refMeshCreator.create_ref_mesh(); Space<complex>::ReferenceSpaceCreator refSpaceCreator(space, ref_mesh); SpaceSharedPtr<complex> ref_space = refSpaceCreator.create_ref_space(); int ndof_ref = Space<complex>::get_num_dofs(ref_space); wf.set_verbose_output(false); newton.set_space(ref_space); // Assemble the reference problem. try { newton.solve(); } catch(Hermes::Exceptions::Exception e) { e.print_msg(); throw Hermes::Exceptions::Exception("Newton's iteration failed."); }; // Translate the resulting coefficient vector into the Solution<complex> sln-> Hermes::Hermes2D::Solution<complex>::vector_to_solution(newton.get_sln_vector(), ref_space, ref_sln); // Project the fine mesh solution onto the coarse mesh. //Hermes::Mixins::Loggable::Static::info("Projecting reference solution on coarse mesh."); OGProjection<complex> ogProjection; ogProjection.project_global(space, ref_sln, sln); // Time measurement. cpu_time.tick(); // View the coarse mesh solution and polynomial orders. MeshFunctionSharedPtr<double> acoustic_pressure(new RealFilter(sln)); sview.show(acoustic_pressure); oview.show(space); // Calculate element errors and total error estimate. //Hermes::Mixins::Loggable::Static::info("Calculating error estimate."); errorCalculator.calculate_errors(sln, ref_sln); double err_est_rel = errorCalculator.get_total_error_squared() * 100; eview.show(errorCalculator.get_errorMeshFunction()); // Report results. //Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space<complex>::get_num_dofs(space), Space<complex>::get_num_dofs(ref_space), err_est_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(Space<complex>::get_num_dofs(space), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { //Hermes::Mixins::Loggable::Static::info("Adapting coarse mesh."); done = adaptivity.adapt(&selector); ref_view.show(adaptivity.get_refinementInfoMeshFunction()); cpu_time.tick(); std::cout << "Adaptivity step: " << as << ", running CPU time: " << cpu_time.accumulated_str() << std::endl; } // Increase counter. as++; } while (done == false); //Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated()); // Show the reference solution - the final result. sview.set_title("Fine mesh solution magnitude"); MeshFunctionSharedPtr<double> ref_mag(new RealFilter(ref_sln)); sview.show(ref_mag); // Output solution in VTK format. Linearizer lin(FileExport); bool mode_3D = true; lin.save_solution_vtk(ref_mag, "sln.vtk", "Acoustic pressure", mode_3D); //Hermes::Mixins::Loggable::Static::info("Solution in VTK format saved to file %s.", "sln.vtk"); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("cathedral.mesh", &mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary("Boundary air", INIT_REF_NUM_BDY); mesh.refine_towards_boundary("Boundary ground", INIT_REF_NUM_BDY); // Previous time level solution (initialized by the external temperature). Solution tsln(&mesh, TEMP_INIT); // Initialize the weak formulation. double current_time = 0; CustomWeakFormHeatRK1 wf("Boundary air", ALPHA, LAMBDA, HEATCAP, RHO, time_step, ¤t_time, TEMP_INIT, T_FINAL, &tsln); // Initialize boundary conditions. DefaultEssentialBCConst bc_essential("Boundary ground", TEMP_INIT); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the FE problem. DiscreteProblem dp(&wf, &space); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); solver->set_factorization_scheme(HERMES_REUSE_FACTORIZATION_COMPLETELY); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof]; memset(coeff_vec, 0, ndof*sizeof(scalar)); // Initialize views. ScalarView Tview("Temperature", new WinGeom(0, 0, 450, 600)); Tview.set_min_max_range(0,20); Tview.fix_scale_width(30); // Time stepping: int ts = 1; bool jacobian_changed = true; do { info("---- Time step %d, time %3.5f s", ts, current_time); // Perform Newton's iteration. if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs, jacobian_changed)) error("Newton's iteration failed."); jacobian_changed = false; // Translate the resulting coefficient vector into the Solution sln. Solution::vector_to_solution(coeff_vec, &space, &tsln); // Visualize the solution. char title[100]; sprintf(title, "Time %3.2f s", current_time); Tview.set_title(title); Tview.show(&tsln); // 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[]) { // 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. Hermes::Hermes2D::Mesh mesh; Hermes::Hermes2D::MeshReaderH2DXML mloader; mloader.load("domain.xml", &mesh); // Perform initial mesh refinements (optional). for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // This is here basically to show off that we can save a mesh with refinements and load it back again. mloader.save("domain2.xml", &mesh); mloader.load("domain2.xml", &mesh); // Initialize the weak formulation. CustomWeakFormPoisson wf(new Hermes::Hermes1DFunction<double>(LAMBDA_AL), "Aluminum", new Hermes::Hermes1DFunction<double>(LAMBDA_CU), "Copper", new Hermes::Hermes2DFunction<double>(-VOLUME_HEAT_SRC)); // Initialize essential boundary conditions. Hermes::Hermes2D::DefaultEssentialBCConst<double> bc_essential(Hermes::vector<std::string>("Bottom", "Inner", "Outer", "Left"), FIXED_BDY_TEMP); Hermes::Hermes2D::EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. Hermes::Hermes2D::H1Space<double> space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the FE problem. Hermes::Hermes2D::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)); // Perform Newton's iteration and translate the resulting coefficient vector into a Solution. Hermes::Hermes2D::Solution<double> sln; Hermes::Hermes2D::NewtonSolver<double> newton(&dp, matrix_solver_type); try { newton.solve_keep_jacobian(coeff_vec, 1e-3, 10); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); Hermes::Hermes2D::Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln); // VTK output. if (VTK_VISUALIZATION) { // Output solution in VTK format. Hermes::Hermes2D::Views::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. Hermes::Hermes2D::Views::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) { Hermes::Hermes2D::Views::ScalarView view("Solution", new Hermes::Hermes2D::Views::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::Hermes2D::Views::HERMES_EPS_HIGH); Hermes::Hermes2D::Views::View::wait(); } // Clean up. delete [] coeff_vec; } Hermes::Hermes2D::Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln); // VTK output. if (VTK_VISUALIZATION) { // Output solution in VTK format. Hermes::Hermes2D::Views::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. Hermes::Hermes2D::Views::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) { Hermes::Hermes2D::Views::ScalarView view("Solution", new Hermes::Hermes2D::Views::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::Hermes2D::Views::HERMES_EPS_HIGH); Hermes::Hermes2D::Views::View::wait(); } // Clean up. delete [] coeff_vec; return 0; }
int main(int argc, char* argv[]) { // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; if (USE_XML_FORMAT == true) { MeshReaderH2DXML mloader; Hermes::Mixins::Loggable::Static::info("Reading mesh in XML format."); mloader.load("domain.xml", &mesh); } else { MeshReaderH2D mloader; Hermes::Mixins::Loggable::Static::info("Reading mesh in original format."); mloader.load("domain.mesh", &mesh); } // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions CustomEssentialBCNonConst bc_essential("Horizontal"); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); Hermes::Mixins::Loggable::Static::info("ndof = %d", ndof); // Initialize the weak formulation. CustomWeakFormGeneral wf("Horizontal"); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, &space); // Initialize Newton solver. NewtonSolver<double> newton(&dp); // Perform Newton's iteration. try { newton.solve(); } catch(std::exception& e) { std::cout << e.what(); } // Translate the resulting coefficient vector into a Solution. Solution<double> sln; Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln); // Time measurement. cpu_time.tick(); // View the solution and mesh. ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); sview.show(&sln); OrderView oview("Polynomial orders", new WinGeom(450, 0, 405, 350)); oview.show(&space); // Print timing information. Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // 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; H2DReader mloader; mloader.load("../domain.mesh", &mesh); // Convert to quadrilaterals. mesh.convert_triangles_to_quads(); // Refine towards boundary. mesh.refine_towards_boundary("Bdy", 1, true); // Refine once towards vertex #4. mesh.refine_towards_vertex(4, 1); // Initialize solutions. CustomInitialConditionWave u_sln(&mesh); Solution v_sln(&mesh, 0.0); Hermes::vector<Solution*> slns(&u_sln, &v_sln); // Initialize the weak formulation. CustomWeakFormWave wf(time_step, C_SQUARED, &u_sln, &v_sln); // Initialize boundary conditions DefaultEssentialBCConst bc_essential("Bdy", 0.0); EssentialBCs bcs(&bc_essential); // Create x- and y- displacement space using the default H1 shapeset. H1Space u_space(&mesh, &bcs, P_INIT); H1Space v_space(&mesh, &bcs, P_INIT); info("ndof = %d.", Space::get_num_dofs(Hermes::vector<Space *>(&u_space, &v_space))); // Initialize the FE problem. DiscreteProblem dp(&wf, Hermes::vector<Space *>(&u_space, &v_space)); // Initialize Runge-Kutta time stepping. RungeKutta runge_kutta(&dp, &bt, matrix_solver); // Time stepping loop. double current_time = 0; 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 jacobian_changed = false; bool verbose = true; if (!runge_kutta.rk_time_step(current_time, time_step, slns, slns, jacobian_changed, verbose)) error("Runge-Kutta time step failed, try to decrease time step size."); // Update time. current_time += time_step; } while (current_time < T_FINAL); double coord_x[4] = {1, 3, 5, 7}; double coord_y[4] = {1, 3, 5, 7}; info("Coordinate (1.0, 0.0) value = %lf", u_sln.get_pt_value(coord_x[0], coord_y[0])); info("Coordinate (3.0, 3.0) value = %lf", u_sln.get_pt_value(coord_x[1], coord_y[1])); info("Coordinate (5.0, 5.0) value = %lf", u_sln.get_pt_value(coord_x[2], coord_y[2])); info("Coordinate (7.0, 7.0) value = %lf", u_sln.get_pt_value(coord_x[3], coord_y[3])); info("Coordinate (1.0, 0.0) value = %lf", v_sln.get_pt_value(coord_x[0], coord_y[0])); info("Coordinate (3.0, 3.0) value = %lf", v_sln.get_pt_value(coord_x[1], coord_y[1])); info("Coordinate (5.0, 5.0) value = %lf", v_sln.get_pt_value(coord_x[2], coord_y[2])); info("Coordinate (7.0, 7.0) value = %lf", v_sln.get_pt_value(coord_x[3], coord_y[3])); double t_value[8] = {0.212655, 0.000163, 0.000000, 0.000000, -0.793316, 0.007255, 0.000001, 0.000000}; bool success = true; for (int i = 0; i < 4; i++) { if (fabs(t_value[i] - u_sln.get_pt_value(coord_x[i], coord_y[i])) > 1E-6) success = false; } for (int i = 4; i < 8; i++) { if (fabs(t_value[i] - v_sln.get_pt_value(coord_x[i-4], coord_y[i-4])) > 1E-6) success = false; } if (success) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } // Wait for the view to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Define nonlinear magnetic permeability via a cubic spline. Hermes::vector<double> mu_inv_pts(0.0, 0.5, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.6, 1.7, 1.8, 1.9, 3.0, 5.0, 10.0); Hermes::vector<double> mu_inv_val(1/1500.0, 1/1480.0, 1/1440.0, 1/1400.0, 1/1300.0, 1/1150.0, 1/950.0, 1/750.0, 1/250.0, 1/180.0, 1/175.0, 1/150.0, 1/20.0, 1/10.0, 1/5.0); /* // This is for debugging (iron is assumed linear with mu_r = 300.0 Hermes::vector<double> mu_inv_pts(0.0, 10.0); Hermes::vector<double> mu_inv_val(1/300.0, 1/300.0); */ // Create the cubic spline (and plot it for visual control). double bc_left = 0.0; double bc_right = 0.0; bool first_der_left = false; bool first_der_right = false; bool extrapolate_der_left = false; bool extrapolate_der_right = false; CubicSpline mu_inv_iron(mu_inv_pts, mu_inv_val, bc_left, bc_right, first_der_left, first_der_right, extrapolate_der_left, extrapolate_der_right); info("Saving cubic spline into a Pylab file spline.dat."); // The interval of definition of the spline will be // extended by "interval_extension" on both sides. double interval_extension = 1.0; bool plot_derivative = false; mu_inv_iron.plot("spline.dat", interval_extension, plot_derivative); plot_derivative = true; mu_inv_iron.plot("spline_der.dat", interval_extension, plot_derivative); // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("actuator.mesh", &mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); //MeshView mv("Mesh", new WinGeom(0, 0, 400, 400)); //mv.show(&mesh); // Initialize boundary conditions. DefaultEssentialBCConst<double> bc_essential(BDY_DIRICHLET, 0.0); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); info("ndof: %d", Space<double>::get_num_dofs(&space)); // Initialize the weak formulation // This determines the increase of integration order // for the axisymmetric term containing 1/r. Default is 3. int order_inc = 3; CustomWeakFormMagnetostatics wf(MAT_IRON_1, MAT_IRON_2, &mu_inv_iron, MAT_AIR, MAT_COPPER, MU_VACUUM, CURRENT_DENSITY, order_inc); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, &space); // Initialize the solution. ConstantSolution<double> sln(&mesh, INIT_COND); // Project the initial condition on the FE space to obtain initial // coefficient vector for the Newton's method. info("Projecting to obtain initial vector for the Newton's method."); double* coeff_vec = new double[Space<double>::get_num_dofs(&space)] ; OGProjection<double>::project_global(&space, &sln, coeff_vec, matrix_solver_type); // Perform Newton's iteration. Hermes::Hermes2D::NewtonSolver<double> newton(&dp, matrix_solver_type); bool verbose = true; newton.set_verbose_output(verbose); try { newton.solve(coeff_vec, NEWTON_TOL, NEWTON_MAX_ITER); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); error("Newton's iteration failed."); }; // Translate the resulting coefficient vector into the Solution sln. Solution<double>::vector_to_solution(coeff_vec, &space, &sln); // Cleanup. delete [] coeff_vec; // Visualise the solution and mesh. ScalarView s_view1("Vector potencial", new WinGeom(0, 0, 350, 450)); FilterVectorPotencial vector_potencial(Hermes::vector<MeshFunction<double> *>(&sln, &sln), Hermes::vector<int>(H2D_FN_VAL, H2D_FN_VAL)); s_view1.show_mesh(false); s_view1.show(&vector_potencial); ScalarView s_view2("Flux density", new WinGeom(360, 0, 350, 450)); FilterFluxDensity flux_density(Hermes::vector<MeshFunction<double> *>(&sln, &sln)); s_view2.show_mesh(false); s_view2.show(&flux_density); OrderView o_view("Mesh", new WinGeom(720, 0, 350, 450)); o_view.show(&space); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); // Perform initial mesh refinements. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions CustomEssentialBCNonConst bc_essential("Boundary horizontal"); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the weak formulation. CustomWeakFormGeneral wf("Boundary horizontal"); // Initialize the FE problem. DiscreteProblem dp(&wf, &space); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof]; memset(coeff_vec, 0, ndof*sizeof(scalar)); // Perform Newton's iteration. if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution sln; Solution::vector_to_solution(coeff_vec, &space, &sln); // Time measurement. cpu_time.tick(); // Clean up. delete solver; delete matrix; delete rhs; delete [] coeff_vec; // View the solution and mesh. ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); sview.show(&sln); OrderView oview("Polynomial orders", new WinGeom(450, 0, 400, 350)); oview.show(&space); // Skip visualization time. cpu_time.tick(HERMES_SKIP); // Print timing information. verbose("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); if (bt.is_explicit()) info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Load the mesh. Mesh mesh, basemesh; MeshReaderH2D mloader; mloader.load("square.mesh", &basemesh); mesh.copy(&basemesh); // Initial mesh refinements. for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary("Top", INIT_REF_NUM_BDY); // Initialize boundary conditions. CustomEssentialBCNonConst bc_essential(Hermes::vector<std::string>("Bottom", "Right", "Top", "Left")); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); int ndof_coarse = Space<double>::get_num_dofs(&space); info("ndof_coarse = %d.", ndof_coarse); // Zero initial solution. This is why we use H_OFFSET. ZeroSolution h_time_prev(&mesh), h_time_new(&mesh); // Initialize the constitutive relations. ConstitutiveRelations* constitutive_relations; if(constitutive_relations_type == CONSTITUTIVE_GENUCHTEN) constitutive_relations = new ConstitutiveRelationsGenuchten(ALPHA, M, N, THETA_S, THETA_R, K_S, STORATIVITY); else constitutive_relations = new ConstitutiveRelationsGardner(ALPHA, THETA_S, THETA_R, K_S); // Initialize the weak formulation. CustomWeakFormRichardsRK wf(constitutive_relations); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, &space); // Create a refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Visualize initial condition. char title[100]; ScalarView view("Initial condition", new WinGeom(0, 0, 440, 350)); OrderView ordview("Initial mesh", new WinGeom(445, 0, 440, 350)); view.show(&h_time_prev); ordview.show(&space); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Time stepping loop. double current_time = 0; int ts = 1; do { // Periodic global derefinement. if (ts > 1 && ts % UNREF_FREQ == 0) { info("Global mesh derefinement."); switch (UNREF_METHOD) { case 1: mesh.copy(&basemesh); space.set_uniform_order(P_INIT); break; case 2: mesh.unrefine_all_elements(); space.set_uniform_order(P_INIT); break; case 3: space.unrefine_all_mesh_elements(); space.adjust_element_order(-1, -1, P_INIT, P_INIT); break; default: error("Wrong global derefinement method."); } ndof_coarse = Space<double>::get_num_dofs(&space); } // Spatial adaptivity loop. Note: h_time_prev must not be changed // during spatial adaptivity. bool done = false; int as = 1; double err_est; do { info("Time step %d, adaptivity step %d:", ts, as); // Construct globally refined reference mesh and setup reference space. Space<double>* ref_space = Space<double>::construct_refined_space(&space); int ndof_ref = Space<double>::get_num_dofs(ref_space); // Time measurement. cpu_time.tick(); // Initialize Runge-Kutta time stepping. RungeKutta<double> runge_kutta(&wf, ref_space, &bt, matrix_solver); // 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 = false; bool block_diagonal_jacobian = false; bool verbose = true; double damping_coeff = 1.0; double max_allowed_residual_norm = 1e10; try { runge_kutta.rk_time_step_newton(current_time, time_step, &h_time_prev, &h_time_new, 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"); } // Project the fine mesh solution onto the coarse mesh. Solution<double> sln_coarse; info("Projecting fine mesh solution on coarse mesh for error estimation."); OGProjection<double>::project_global(&space, &h_time_new, &sln_coarse, matrix_solver); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt<double>* adaptivity = new Adapt<double>(&space); double err_est_rel_total = adaptivity->calc_err_est(&sln_coarse, &h_time_new) * 100; // Report results. info("ndof_coarse: %d, ndof_ref: %d, err_est_rel: %g%%", Space<double>::get_num_dofs(&space), Space<double>::get_num_dofs(ref_space), err_est_rel_total); // Time measurement. cpu_time.tick(); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting the coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); if (Space<double>::get_num_dofs(&space) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } // Clean up. delete adaptivity; if(!done) { delete h_time_new.get_space(); delete h_time_new.get_mesh(); } } while (done == false); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(current_time, Space<double>::get_num_dofs(&space)); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(current_time, cpu_time.accumulated()); graph_cpu.save("conv_cpu_est.dat"); // Visualize the solution and mesh. char title[100]; sprintf(title, "Solution, time %g", current_time); view.set_title(title); view.show_mesh(false); view.show(&h_time_new); sprintf(title, "Mesh, time %g", current_time); ordview.set_title(title); ordview.show(&space); // Copy last reference solution into h_time_prev. h_time_prev.copy(&h_time_new); delete h_time_new.get_mesh(); // Increase current time and counter of time steps. current_time += time_step; ts++; } while (current_time < T_FINAL); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char **argv) { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("square.mesh", &mesh); // Perform initial mesh refinemets. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Set exact solution. CustomExactSolution exact(&mesh); // Initialize boundary conditions DefaultEssentialBCNonConst<double> bc_essential("Bdy", &exact); EssentialBCs<double> bcs(&bc_essential); // Initialize the weak formulation. CustomWeakFormPoisson wf1; // 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 %s:", MatrixSolverNames[matrix_solver].c_str()); // Initialize the linear discrete problem. DiscreteProblem<double> dp1(&wf1, &space); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix<double>* matrix = create_matrix<double>(matrix_solver); Vector<double>* rhs = create_vector<double>(matrix_solver); LinearSolver<double>* solver = create_linear_solver<double>(matrix_solver, matrix, rhs); #ifdef HAVE_AZTECOO if (matrix_solver == 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). } #endif // Begin time measurement of assembly. cpu_time.tick(HERMES_SKIP); // Initial coefficient vector for the Newton's method. double* coeff_vec = new double[ndof]; memset(coeff_vec, 0, ndof*sizeof(double)); // Initialize the Newton solver. Hermes::Hermes2D::NewtonSolver<double> newton(&dp1, matrix_solver); // Perform Newton's iteration and translate the resulting coefficient vector into a Solution. Hermes::Hermes2D::Solution<double> sln1; try { newton.solve(coeff_vec); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); error("Newton's iteration failed."); } Hermes::Hermes2D::Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln1); // CPU time measurement. double time = cpu_time.tick().last(); // Calculate errors. double rel_err_1 = Global<double>::calc_rel_error(&sln1, &exact, HERMES_H1_NORM) * 100; info("CPU time: %g s.", time); info("Exact H1 error: %g%%.", rel_err_1); delete(matrix); delete(rhs); delete(solver); // View the solution and mesh. ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); sview.show(&sln1); //OrderView oview("Polynomial orders", new WinGeom(450, 0, 400, 350)); //oview.show(&space); // TRILINOS PART: info("---- Assembling by DiscreteProblem, solving by NOX:"); // Initialize the weak formulation for Trilinos. CustomWeakFormPoisson wf2(TRILINOS_JFNK); // Initialize DiscreteProblem. DiscreteProblem<double> dp2(&wf2, &space); // Time measurement. cpu_time.tick(HERMES_SKIP); // Set initial vector for NOX. // NOTE: Using zero vector was causing convergence problems. info("Projecting to obtain initial vector for the Newton's method."); ZeroSolution init_sln(&mesh); // Initialize the NOX solver with the vector "coeff_vec". info("Initializing NOX."); NewtonSolverNOX<double> nox_solver(&dp2); nox_solver.set_output_flags(message_type); nox_solver.set_ls_type(iterative_method); nox_solver.set_ls_tolerance(ls_tolerance); nox_solver.set_conv_iters(max_iters); if (flag_absresid) nox_solver.set_conv_abs_resid(abs_resid); if (flag_relresid) nox_solver.set_conv_rel_resid(rel_resid); // Choose preconditioning. MlPrecond<double> pc("sa"); if (PRECOND) { if (TRILINOS_JFNK) nox_solver.set_precond(pc); else nox_solver.set_precond(preconditioner); } // Assemble and solve using NOX. Solution<double> sln2; OGProjection<double>::project_global(&space, &init_sln, coeff_vec); try { nox_solver.solve(coeff_vec); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); error("NOX failed."); } 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()); // CPU time needed by NOX. time = cpu_time.tick().last(); // Show the NOX solution. ScalarView view2("Solution<double> 2", new WinGeom(450, 0, 460, 350)); view2.show(&sln2); //view2.show(&exact); // Calculate errors. double rel_err_2 = Global<double>::calc_rel_error(&sln2, &exact, HERMES_H1_NORM) * 100; info("CPU time: %g s.", time); info("Exact H1 error: %g%%.", rel_err_2); // 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; H2DReader mloader; mloader.load("../domain.mesh", &mesh); // Perform initial mesh refinemets. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize solutions. CustomInitialConditionWave E_sln(&mesh); Solution F_sln(&mesh, 0.0, 0.0); Hermes::vector<Solution*> slns(&E_sln, &F_sln); // Initialize the weak formulation. CustomWeakFormWave wf(C_SQUARED); // Initialize boundary conditions DefaultEssentialBCConst bc_essential(BDY, 0.0); EssentialBCs bcs(&bc_essential); // Create x- and y- displacement space using the default H1 shapeset. HcurlSpace E_space(&mesh, &bcs, P_INIT); HcurlSpace F_space(&mesh, &bcs, P_INIT); Hermes::vector<Space *> spaces = Hermes::vector<Space *>(&E_space, &F_space); info("ndof = %d.", Space::get_num_dofs(spaces)); // Initialize the FE problem. DiscreteProblem dp(&wf, spaces); // Initialize Runge-Kutta time stepping. RungeKutta runge_kutta(&dp, &bt, matrix_solver); // Time stepping loop. double current_time = 0; 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 verbose = true; bool jacobian_changed = true; if (!runge_kutta.rk_time_step(current_time, time_step, slns, slns, jacobian_changed, verbose)) error("Runge-Kutta time step failed, try to decrease time step size."); // Update time. current_time += time_step; } while (current_time < T_FINAL); double coord_x[4] = {0.3, 0.6, 0.9, 1.4}; double coord_y[4] = {0, 0.3, 0.5, 0.7}; info("Coordinate (0.3, 0.0) value = %lf", F_sln.get_pt_value(coord_x[0], coord_y[0])); info("Coordinate (0.6, 0.3) value = %lf", F_sln.get_pt_value(coord_x[1], coord_y[1])); info("Coordinate (0.9, 0.5) value = %lf", F_sln.get_pt_value(coord_x[2], coord_y[2])); info("Coordinate (1.4, 0.7) value = %lf", F_sln.get_pt_value(coord_x[3], coord_y[3])); double t_value[4] = {-0.144673, -0.264077, -0.336536, -0.368983}; bool success = true; for (int i = 0; i < 4; i++) { if (fabs(t_value[i] - F_sln.get_pt_value(coord_x[i], coord_y[i])) > 1E-6) success = false; } if (success) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. // 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()); // Turn off adaptive time stepping if R-K method is not embedded. if (bt.is_embedded() == false && ADAPTIVE_TIME_STEP_ON == true) { warn("R-K method not embedded, turning off adaptive time stepping."); ADAPTIVE_TIME_STEP_ON = false; } // Load the mesh. Mesh mesh, basemesh; MeshReaderH2D mloader; mloader.load("square.mesh", &basemesh); mesh.copy(&basemesh); // Initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Convert initial condition into a Solution<std::complex<double> >. CustomInitialCondition psi_time_prev(&mesh); // Initialize the weak formulation. double current_time = 0; CustomWeakFormGPRK wf(h, m, g, omega); // Initialize boundary conditions. DefaultEssentialBCConst<std::complex<double> > bc_essential("Bdy", 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 FE problem. DiscreteProblem<std::complex<double> > dp(&wf, &space); // Create a refinement selector. H1ProjBasedSelector<std::complex<double> > selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Visualize initial condition. char title[100]; ScalarView sview_real("Initial condition - real part", new WinGeom(0, 0, 600, 500)); ScalarView sview_imag("Initial condition - imaginary part", new WinGeom(610, 0, 600, 500)); sview_real.show_mesh(false); sview_imag.show_mesh(false); sview_real.fix_scale_width(50); sview_imag.fix_scale_width(50); OrderView ord_view("Initial mesh", new WinGeom(445, 0, 440, 350)); ord_view.fix_scale_width(50); ScalarView time_error_view("Temporal error", new WinGeom(0, 400, 440, 350)); time_error_view.fix_scale_width(50); time_error_view.fix_scale_width(60); ScalarView space_error_view("Spatial error", new WinGeom(445, 400, 440, 350)); space_error_view.fix_scale_width(50); RealFilter real(&psi_time_prev); ImagFilter imag(&psi_time_prev); sview_real.show(&real); sview_imag.show(&imag); ord_view.show(&space); // Graph for time step history. SimpleGraph time_step_graph; if (ADAPTIVE_TIME_STEP_ON) info("Time step history will be saved to file time_step_history.dat."); // Time stepping: int num_time_steps = (int)(T_FINAL/time_step + 0.5); for(int ts = 1; ts <= num_time_steps; ts++) // Time stepping loop. double current_time = 0.0; int ts = 1; do { info("Begin time step %d.", ts); // Periodic global derefinement. if (ts > 1 && ts % UNREF_FREQ == 0) { info("Global mesh derefinement."); switch (UNREF_METHOD) { case 1: mesh.copy(&basemesh); space.set_uniform_order(P_INIT); break; case 2: mesh.unrefine_all_elements(); space.set_uniform_order(P_INIT); break; case 3: mesh.unrefine_all_elements(); //space.adjust_element_order(-1, P_INIT); space.adjust_element_order(-1, -1, P_INIT, P_INIT); break; default: error("Wrong global derefinement method."); } ndof = Space<std::complex<double> >::get_num_dofs(&space); } info("ndof: %d", ndof); // Spatial adaptivity loop. Note: psi_time_prev must not be // changed during spatial adaptivity. Solution<std::complex<double> > ref_sln; Solution<std::complex<double> >* time_error_fn; if (bt.is_embedded() == true) time_error_fn = new Solution<std::complex<double> >(&mesh); else time_error_fn = NULL; bool done = false; int as = 1; double err_est; do { // Construct globally refined reference mesh and setup reference space. Space<std::complex<double> >* ref_space = Space<std::complex<double> >::construct_refined_space(&space); // Initialize discrete problem on reference mesh. DiscreteProblem<std::complex<double> >* ref_dp = new DiscreteProblem<std::complex<double> >(&wf, ref_space); RungeKutta<std::complex<double> > runge_kutta(ref_dp, &bt, matrix_solver_type); // Runge-Kutta step on the fine mesh. info("Runge-Kutta time step on fine mesh (t = %g s, time step = %g s, stages: %d).", current_time, time_step, bt.get_size()); bool verbose = true; try { runge_kutta.rk_time_step_newton(current_time, time_step, &psi_time_prev, &ref_sln, time_error_fn, false, false, verbose, NEWTON_TOL_FINE, NEWTON_MAX_ITER); } catch(Exceptions::Exception& e) { e.printMsg(); error("Runge-Kutta time step failed"); } /* If ADAPTIVE_TIME_STEP_ON == true, estimate temporal error. If too large or too small, then adjust it and restart the time step. */ double rel_err_time = 0; if (bt.is_embedded() == true) { info("Calculating temporal error estimate."); // Show temporal error. char title[100]; sprintf(title, "Temporal error est, spatial adaptivity step %d", as); time_error_view.set_title(title); time_error_view.show_mesh(false); RealFilter abs_time(time_error_fn); AbsFilter abs_tef(&abs_time); time_error_view.show(&abs_tef, HERMES_EPS_HIGH); rel_err_time = Global<std::complex<double> >::calc_norm(time_error_fn, HERMES_H1_NORM) / Global<std::complex<double> >::calc_norm(&ref_sln, HERMES_H1_NORM) * 100; if (ADAPTIVE_TIME_STEP_ON == false) info("rel_err_time: %g%%", rel_err_time); } if (ADAPTIVE_TIME_STEP_ON) { if (rel_err_time > TIME_ERR_TOL_UPPER) { info("rel_err_time %g%% is above upper limit %g%%", rel_err_time, TIME_ERR_TOL_UPPER); info("Decreasing time step from %g to %g s and restarting time step.", time_step, time_step * TIME_STEP_DEC_RATIO); time_step *= TIME_STEP_DEC_RATIO; delete ref_space; delete ref_dp; continue; } else if (rel_err_time < TIME_ERR_TOL_LOWER) { info("rel_err_time = %g%% is below lower limit %g%%", rel_err_time, TIME_ERR_TOL_LOWER); info("Increasing time step from %g to %g s.", time_step, time_step * TIME_STEP_INC_RATIO); time_step *= TIME_STEP_INC_RATIO; delete ref_space; delete ref_dp; continue; } else { info("rel_err_time = %g%% is in acceptable interval (%g%%, %g%%)", rel_err_time, TIME_ERR_TOL_LOWER, TIME_ERR_TOL_UPPER); } // Add entry to time step history graph. time_step_graph.add_values(current_time, time_step); time_step_graph.save("time_step_history.dat"); } /* Estimate spatial errors and perform mesh refinement */ info("Spatial adaptivity step %d.", as); // Project the fine mesh solution onto the coarse mesh. Solution<std::complex<double> > sln; info("Projecting fine mesh solution on coarse mesh for error estimation."); OGProjection<std::complex<double> >::project_global(&space, &ref_sln, &sln, matrix_solver_type); // Show spatial error. sprintf(title, "Spatial error est, spatial adaptivity step %d", as); DiffFilter<std::complex<double> >* space_error_fn = new DiffFilter<std::complex<double> >(Hermes::vector<MeshFunction<std::complex<double> >*>(&ref_sln, &sln)); space_error_view.set_title(title); space_error_view.show_mesh(false); RealFilter abs_space(space_error_fn); AbsFilter abs_sef(&abs_space); space_error_view.show(&abs_sef); // Calculate element errors and spatial error estimate. info("Calculating spatial error estimate."); Adapt<std::complex<double> >* adaptivity = new Adapt<std::complex<double> >(&space); double err_rel_space = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Report results. info("ndof: %d, ref_ndof: %d, err_rel_space: %g%%", Space<std::complex<double> >::get_num_dofs(&space), Space<std::complex<double> >::get_num_dofs(ref_space), err_rel_space); // If err_est too large, adapt the mesh. if (err_rel_space < SPACE_ERR_TOL) done = true; else { info("Adapting the coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); if (Space<std::complex<double> >::get_num_dofs(&space) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } // Clean up. delete adaptivity; delete ref_space; delete ref_dp; delete space_error_fn; } while (done == false); // Clean up. if (time_error_fn != NULL) delete time_error_fn; // Visualize the solution and mesh. char title[100]; sprintf(title, "Solution - real part, Time %3.2f s", current_time); sview_real.set_title(title); sprintf(title, "Solution - imaginary part, Time %3.2f s", current_time); sview_imag.set_title(title); RealFilter real(&ref_sln); ImagFilter imag(&ref_sln); sview_real.show(&real); sview_imag.show(&imag); sprintf(title, "Mesh, time %g s", current_time); ord_view.set_title(title); ord_view.show(&space); // Copy last reference solution into psi_time_prev. psi_time_prev.copy(&ref_sln); // Increase current time and counter of time steps. current_time += time_step; ts++; } while (current_time < T_FINAL); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. MeshSharedPtr mesh(new Mesh); MeshReaderH2D mloader; mloader.load("square.mesh", mesh); // Initial mesh refinements. for (int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh->refine_all_elements(); mesh->refine_towards_boundary("Top", INIT_REF_NUM_BDY); // Initialize boundary conditions. CustomEssentialBCNonConst bc_essential({ "Bottom", "Right", "Top", "Left" }); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT)); int ndof = space->get_num_dofs(); Hermes::Mixins::Loggable::Static::info("ndof = %d.", ndof); // Zero initial solutions. This is why we use H_OFFSET. MeshFunctionSharedPtr<double> h_time_prev(new ZeroSolution<double>(mesh)); // Initialize views. ScalarView view("Initial condition", new WinGeom(0, 0, 600, 500)); view.fix_scale_width(80); // Visualize the initial condition. view.show(h_time_prev); // Initialize the constitutive relations. ConstitutiveRelations* constitutive_relations; if (constitutive_relations_type == CONSTITUTIVE_GENUCHTEN) constitutive_relations = new ConstitutiveRelationsGenuchten(ALPHA, M, N, THETA_S, THETA_R, K_S, STORATIVITY); else constitutive_relations = new ConstitutiveRelationsGardner(ALPHA, THETA_S, THETA_R, K_S); // Initialize the weak formulation. double current_time = 0; WeakFormSharedPtr<double> wf(new CustomWeakFormRichardsIE(time_step, h_time_prev, constitutive_relations)); // Initialize the FE problem. DiscreteProblem<double> dp(wf, space); // Initialize Newton solver. NewtonSolver<double> newton(&dp); newton.set_verbose_output(true); // Time stepping: int ts = 1; do { Hermes::Mixins::Loggable::Static::info("---- Time step %d, time %3.5f s", ts, current_time); // Perform Newton's iteration. try { newton.set_max_allowed_iterations(NEWTON_MAX_ITER); newton.solve(); } catch (Hermes::Exceptions::Exception e) { e.print_msg(); throw Hermes::Exceptions::Exception("Newton's iteration failed."); }; // Translate the resulting coefficient vector into the Solution<double> sln-> Solution<double>::vector_to_solution(newton.get_sln_vector(), space, h_time_prev); // Visualize the solution. char title[100]; sprintf(title, "Time %g s", current_time); view.set_title(title); view.show(h_time_prev); // 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[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("../domain.mesh", &mesh); // Perform initial mesh refinements. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions EssentialBCNonConst bc_essential(BDY_HORIZONTAL); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the weak formulation. CustomWeakFormGeneral wf; // Testing n_dof and correctness of solution vector // for p_init = 1, 2, ..., 10 int success = 1; Solution sln; for (int p_init = 1; p_init <= 10; p_init++) { printf("********* p_init = %d *********\n", p_init); space.set_uniform_order(p_init); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the solution. Solution sln; // Assemble the stiffness matrix and right-hand side vector. info("Assembling the stiffness matrix and right-hand side vector."); bool rhsonly = false; dp.assemble(matrix, rhs, rhsonly); // Solve the linear system and if successful, obtain the solution. info("Solving the matrix problem."); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); int ndof = Space::get_num_dofs(&space); printf("ndof = %d\n", ndof); double sum = 0; for (int i=0; i < ndof; i++) sum += solver->get_solution()[i]; printf("coefficient sum = %g\n", sum); // Actual test. The values of 'sum' depend on the // current shapeset. If you change the shapeset, // you need to correct these numbers. if (p_init == 1 && fabs(sum - 1.72173) > 1e-2) success = 0; if (p_init == 2 && fabs(sum - 0.639908) > 1e-2) success = 0; if (p_init == 3 && fabs(sum - 0.826367) > 1e-2) success = 0; if (p_init == 4 && fabs(sum - 0.629395) > 1e-2) success = 0; if (p_init == 5 && fabs(sum - 0.574235) > 1e-2) success = 0; if (p_init == 6 && fabs(sum - 0.62792) > 1e-2) success = 0; if (p_init == 7 && fabs(sum - 0.701982) > 1e-2) success = 0; if (p_init == 8 && fabs(sum - 0.7982) > 1e-2) success = 0; if (p_init == 9 && fabs(sum - 0.895069) > 1e-2) success = 0; if (p_init == 10 && fabs(sum - 1.03031) > 1e-2) success = 0; } if (success == 1) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("../domain.mesh", &mesh); // Perform initial mesh refinements (optional). for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize the weak formulation. Not providing the order determination form // (or callback) turns on adaptive numerical quadrature. The quadrature begins // with using a first-order rule in the entire element. Then the element is split // uniformly in space and the quadrature order is increased by "adapt_order_increase". // Then the form is calculated again by employing the new quadrature in subelements. // This provides a more accurate result. If relative error is less than // "adapt_rel_error_tol", the computation stops, otherwise the same procedure is // applied recursively to all four subelements. int adapt_order_increase = 1; double adapt_rel_error_tol = 1e1; CustomWeakFormPoisson wf("Aluminum", new HermesFunction(LAMBDA_AL), "Copper", new HermesFunction(LAMBDA_CU), new HermesFunction(-VOLUME_HEAT_SRC), ADAPTIVE_QUADRATURE, adapt_order_increase, adapt_rel_error_tol); if (ADAPTIVE_QUADRATURE) info("Adaptive quadrature ON."); else info("Adaptive quadrature OFF."); // Initialize essential boundary conditions. DefaultEssentialBCConst bc_essential(Hermes::vector<std::string>("Bottom", "Inner", "Outer", "Left"), FIXED_BDY_TEMP); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the FE problem. DiscreteProblem dp(&wf, &space); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof]; memset(coeff_vec, 0, ndof*sizeof(scalar)); // Perform Newton's iteration. if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into a Solution. Solution sln; Solution::vector_to_solution(coeff_vec, &space, &sln); // Actual test. The values of 'sum' depend on the // current shapeset. If you change the shapeset, // you need to correct these numbers. double sum = 0; for (int i = 0; i < ndof; i++) sum += coeff_vec[i]; printf("coefficient sum = %g\n", sum); bool success = true; if (std::abs(sum + 3.57318) > 1e-4) success = false; if (success == true) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Load the mesh. Hermes::Hermes2D::Mesh mesh; Hermes::Hermes2D::MeshReaderH2DXML mloader; mloader.load("../domain.xml", &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 Hermes::Hermes1DFunction<double>(LAMBDA_AL), "Copper", new Hermes::Hermes1DFunction<double>(LAMBDA_CU), new Hermes::Hermes2DFunction<double>(-VOLUME_HEAT_SRC)); // Initialize essential boundary conditions. Hermes::Hermes2D::DefaultEssentialBCConst<double> bc_essential(Hermes::vector<std::string>("Bottom", "Inner", "Outer", "Left"), FIXED_BDY_TEMP); Hermes::Hermes2D::EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. Hermes::Hermes2D::H1Space<double> space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the FE problem. Hermes::Hermes2D::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)); // Perform Newton's iteration and translate the resulting coefficient vector into a Solution. Hermes::Hermes2D::Solution<double> sln; Hermes::Hermes2D::NewtonSolver<double> newton(&dp, matrix_solver_type); try{ newton.solve(coeff_vec); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); error("Newton's iteration failed."); } Hermes::Hermes2D::Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln); // Actual test. The values of 'sum' depend on the // current shapeset. If you change the shapeset, // you need to correct these numbers. double sum = 0; for (int i = 0; i < ndof; i++) sum += newton.get_sln_vector()[i]; printf("coefficient sum = %g\n", sum); // Clean up. delete [] coeff_vec; bool success = true; if (std::abs(sum + 0.357318) > 1e-4) success = false; if (success == true) { printf("Success!\n"); return TEST_SUCCESS; } else { printf("Failure!\n"); return TEST_FAILURE; } }
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[]) { #ifdef WITH_PARALUTION HermesCommonApi.set_integral_param_value(matrixSolverType, SOLVER_PARALUTION_AMG); // Load the mesh. MeshSharedPtr mesh(new Mesh); MeshReaderH2D mloader; mloader.load("domain.mesh", mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); mesh->refine_towards_boundary("Boundary air", INIT_REF_NUM_BDY); mesh->refine_towards_boundary("Boundary ground", INIT_REF_NUM_BDY); // Previous time level solution (initialized by the external temperature). MeshFunctionSharedPtr<double> tsln(new ConstantSolution<double> (mesh, TEMP_INIT)); // Initialize the weak formulation. double current_time = 0; CustomWeakFormHeatRK1 wf("Boundary air", ALPHA, LAMBDA, HEATCAP, RHO, time_step, ¤t_time, TEMP_INIT, T_FINAL, tsln); // Initialize boundary conditions. DefaultEssentialBCConst<double> bc_essential("Boundary ground", TEMP_INIT); 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 Newton solver. NewtonSolver<double> newton(&wf, space); #ifdef SHOW_OUTPUT newton.set_verbose_output(true); #else newton.set_verbose_output(false); #endif newton.set_jacobian_constant(); newton.get_linear_matrix_solver()->as_AMGSolver()->set_smoother(Solvers::GMRES, Preconditioners::ILU); newton.get_linear_matrix_solver()->as_LoopSolver()->set_tolerance(1e-1, RelativeTolerance); #ifdef SHOW_OUTPUT // Initialize views. ScalarView Tview("Temperature", new WinGeom(0, 0, 450, 600)); Tview.set_min_max_range(0,20); Tview.fix_scale_width(30); #endif // Time stepping: int ts = 1; do { Hermes::Mixins::Loggable::Static::info("---- Time step %d, time %3.5f s", ts, current_time); newton.solve(); // Translate the resulting coefficient vector into the Solution sln. Solution<double>::vector_to_solution(newton.get_sln_vector(), space, tsln); #ifdef SHOW_OUTPUT // Visualize the solution. char title[100]; sprintf(title, "Time %3.2f s", current_time); Tview.set_title(title); Tview.show(tsln); #endif // Increase current time and time step counter. current_time += time_step; ts++; } while (current_time < T_FINAL); // Wait for the view to be closed. #ifdef SHOW_OUTPUT View::wait(); #endif return 0; #endif return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Hermes::Hermes2D::Mesh mesh; Hermes::Hermes2D::H2DReader mloader; mloader.load("domain.mesh", &mesh); // Perform initial mesh refinements (optional). int refinement_type = 2; // Split elements vertically. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(refinement_type); // Show the mesh. Hermes::Hermes2D::Views::MeshView mview("Mesh", new Hermes::Hermes2D::Views::WinGeom(0, 0, 900, 250)); if (HERMES_VISUALIZATION) { mview.show(&mesh); //mview.wait(); } // Initialize the weak formulation. CustomWeakFormPoisson wf("Al", new Hermes::Hermes1DFunction<double>(LAMBDA_AL), "Cu", new Hermes::Hermes1DFunction<double>(LAMBDA_CU), new Hermes::Hermes2DFunction<double>(-VOLUME_HEAT_SRC)); // Initialize essential boundary conditions. Hermes::Hermes2D::DefaultEssentialBCConst<double> bc_essential(Hermes::vector<std::string>("Left", "Right"), FIXED_BDY_TEMP); Hermes::Hermes2D::EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. Hermes::Hermes2D::H1Space<double> space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the FE problem. Hermes::Hermes2D::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)); // Perform Newton's iteration and translate the resulting coefficient vector into a Solution. Hermes::Hermes2D::Solution<double> sln; Hermes::Hermes2D::NewtonSolver<double> newton(&dp, matrix_solver_type); if (!newton.solve(coeff_vec)) error("Newton's iteration failed."); else Hermes::Hermes2D::Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln); // Get info about time spent during assembling in its respective parts. dp.get_all_profiling_output(std::cout); // VTK output. if (VTK_VISUALIZATION) { // Output solution in VTK format. Hermes::Hermes2D::Views::Linearizer<double> 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. Hermes::Hermes2D::Views::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) { Hermes::Hermes2D::Views::ScalarView<double> view("Solution", new Hermes::Hermes2D::Views::WinGeom(0, 300, 900, 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::Hermes2D::Views::HERMES_EPS_HIGH); Hermes::Hermes2D::Views::View::wait(); } // Clean up. delete [] coeff_vec; 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; H2DReader mloader; mloader.load("../domain.mesh", &mesh); // Perform initial mesh refinemets. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize solutions. CustomInitialConditionWave E_sln(&mesh); Solution B_sln(&mesh, 0.0); Hermes::vector<Solution*> slns(&E_sln, &B_sln); // Initialize the weak formulation. CustomWeakFormWave wf(C_SQUARED); // Initialize boundary conditions DefaultEssentialBCConst bc_essential(BDY, 0.0); EssentialBCs bcs_E(&bc_essential); EssentialBCs bcs_B; // Create x- and y- displacement space using the default H1 shapeset. HcurlSpace E_space(&mesh, &bcs_E, P_INIT); H1Space B_space(&mesh, &bcs_B, P_INIT); //L2Space B_space(&mesh, P_INIT); Hermes::vector<Space *> spaces = Hermes::vector<Space *>(&E_space, &B_space); info("ndof = %d.", Space::get_num_dofs(spaces)); // Initialize the FE problem. DiscreteProblem dp(&wf, spaces); // Initialize views. // ScalarView E1_view("Solution E1", new WinGeom(0, 0, 400, 350)); // E1_view.fix_scale_width(50); // ScalarView E2_view("Solution E2", new WinGeom(410, 0, 400, 350)); // E2_view.fix_scale_width(50); // ScalarView B_view("Solution B", new WinGeom(0, 405, 400, 350)); // B_view.fix_scale_width(50); // Initialize Runge-Kutta time stepping. RungeKutta runge_kutta(&dp, &bt, matrix_solver); // Time stepping loop. double current_time = time_step; 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 jacobian_changed = false; bool verbose = true; if (!runge_kutta.rk_time_step(current_time, time_step, slns, slns, jacobian_changed, verbose)) error("Runge-Kutta time step failed, try to decrease time step size."); /* // Visualize the solutions. char title[100]; sprintf(title, "E1, t = %g", current_time); E1_view.set_title(title); E1_view.show(&E_sln, HERMES_EPS_NORMAL, H2D_FN_VAL_0); sprintf(title, "E2, t = %g", current_time); E2_view.set_title(title); E2_view.show(&E_sln, HERMES_EPS_NORMAL, H2D_FN_VAL_1); sprintf(title, "B, t = %g", current_time); B_view.set_title(title); B_view.show(&B_sln, HERMES_EPS_NORMAL, H2D_FN_VAL_0); */ // Update time. current_time += time_step; } while (current_time < T_FINAL); double coord_x[4] = {0.3, 0.6, 0.9, 1.4}; double coord_y[4] = {0, 0.3, 0.5, 0.7}; info("Coordinate (0.3, 0.0) value = %lf", B_sln.get_pt_value(coord_x[0], coord_y[0])); info("Coordinate (0.6, 0.3) value = %lf", B_sln.get_pt_value(coord_x[1], coord_y[1])); info("Coordinate (0.9, 0.5) value = %lf", B_sln.get_pt_value(coord_x[2], coord_y[2])); info("Coordinate (1.4, 0.7) value = %lf", B_sln.get_pt_value(coord_x[3], coord_y[3])); double t_value[4] = {0.0, -0.065100, -0.146515, -0.247677}; bool success = true; for (int i = 0; i < 4; i++) { if (fabs(t_value[i] - B_sln.get_pt_value(coord_x[i], coord_y[i])) > 1E-6) success = false; } if (success) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
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 refinemets. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize solutions. CustomInitialConditionWave E_sln(&mesh); ZeroSolution B_sln(&mesh); Hermes::vector<Solution<double>*> slns(&E_sln, &B_sln); // Initialize the weak formulation. CustomWeakFormWave wf(C_SQUARED); // Initialize boundary conditions DefaultEssentialBCConst<double> bc_essential("Perfect conductor", 0.0); EssentialBCs<double> bcs_E(&bc_essential); EssentialBCs<double> bcs_B; // Create x- and y- displacement space using the default H1 shapeset. HcurlSpace<double> E_space(&mesh, &bcs_E, P_INIT); H1Space<double> B_space(&mesh, &bcs_B, P_INIT); //L2Space<double> B_space(&mesh, P_INIT); Hermes::vector<Space<double> *> spaces = Hermes::vector<Space<double> *>(&E_space, &B_space); info("ndof = %d.", Space<double>::get_num_dofs(spaces)); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, spaces); // Initialize views. ScalarView E1_view("Solution E1", new WinGeom(0, 0, 400, 350)); E1_view.fix_scale_width(50); ScalarView E2_view("Solution E2", new WinGeom(410, 0, 400, 350)); E2_view.fix_scale_width(50); ScalarView B_view("Solution B", new WinGeom(0, 405, 400, 350)); B_view.fix_scale_width(50); // Initialize Runge-Kutta time stepping. RungeKutta<double> runge_kutta(&dp, &bt, matrix_solver_type); // Time stepping loop. double current_time = time_step; 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 jacobian_changed = false; bool verbose = true; try { runge_kutta.rk_time_step_newton(current_time, time_step, slns, slns, jacobian_changed, verbose); } catch(Exceptions::Exception& e) { e.printMsg(); error("Runge-Kutta time step failed"); } // Visualize the solutions. char title[100]; sprintf(title, "E1, t = %g", current_time); E1_view.set_title(title); E1_view.show(&E_sln, HERMES_EPS_NORMAL, H2D_FN_VAL_0); sprintf(title, "E2, t = %g", current_time); E2_view.set_title(title); E2_view.show(&E_sln, HERMES_EPS_NORMAL, H2D_FN_VAL_1); sprintf(title, "B, t = %g", current_time); B_view.set_title(title); B_view.show(&B_sln, HERMES_EPS_NORMAL, H2D_FN_VAL_0); // Update time. current_time += time_step; } while (current_time < T_FINAL); // Wait for the view to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. 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[]) { // Load the mesh. MeshSharedPtr mesh(new Mesh); MeshReaderH2D mloader; mloader.load("domain.mesh", mesh); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements(); // Initialize boundary conditions. Hermes::Hermes2D::DefaultEssentialBCConst<complex> bc_essential("Dirichlet", complex(0.0, 0.0)); EssentialBCs<complex> bcs(&bc_essential); // Create an H1 space with default shapeset. SpaceSharedPtr<complex> space(new H1Space<complex>(mesh, &bcs, P_INIT)); // Initialize the weak formulation. CustomWeakForm wf("Air", MU_0, "Iron", MU_IRON, GAMMA_IRON, "Wire", MU_0, complex(J_EXT, 0.0), OMEGA); // Initialize coarse and reference mesh solution. MeshFunctionSharedPtr<complex> sln(new Hermes::Hermes2D::Solution<complex>()); MeshFunctionSharedPtr<complex> ref_sln(new Hermes::Hermes2D::Solution<complex>()); // Initialize refinement selector. H1ProjBasedSelector<complex> selector(CAND_LIST); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; DiscreteProblem<complex> dp(&wf, space); // Perform Newton's iteration and translate the resulting coefficient vector into a Solution. Hermes::Hermes2D::NewtonSolver<complex> newton(&dp); // Adaptivity loop: int as = 1; bool done = false; adaptivity.set_space(space); do { // Construct globally refined reference mesh and setup reference space-> Mesh::ReferenceMeshCreator ref_mesh_creator(mesh); MeshSharedPtr ref_mesh = ref_mesh_creator.create_ref_mesh(); Space<complex>::ReferenceSpaceCreator ref_space_creator(space, ref_mesh); SpaceSharedPtr<complex> ref_space = ref_space_creator.create_ref_space(); newton.set_space(ref_space); int ndof_ref = ref_space->get_num_dofs(); // Initialize reference problem. // Initial coefficient vector for the Newton's method. complex* coeff_vec = new complex[ndof_ref]; memset(coeff_vec, 0, ndof_ref * sizeof(complex)); // Perform Newton's iteration and translate the resulting coefficient vector into a Solution. try { newton.solve(coeff_vec); } catch(Hermes::Exceptions::Exception& e) { e.print_msg(); } Hermes::Hermes2D::Solution<complex>::vector_to_solution(newton.get_sln_vector(), ref_space, ref_sln); // Project the fine mesh solution onto the coarse mesh. OGProjection<complex> ogProjection; ogProjection.project_global(space, ref_sln, sln); // Calculate element errors and total error estimate. errorCalculator.calculate_errors(sln, ref_sln); // If err_est too large, adapt the mesh-> if(errorCalculator.get_total_error_squared() * 100. < ERR_STOP) done = true; else { adaptivity.adapt(&selector); } // Clean up. delete [] coeff_vec; // Increase counter. as++; } while (done == false); complex sum = 0; for (int i = 0; i < space->get_num_dofs(); i++) sum += newton.get_sln_vector()[i]; printf("coefficient sum = %f\n", sum); complex expected_sum; expected_sum.real(1.4685364e-005); expected_sum.imag(-5.45632171e-007); bool success = true; if(std::abs(sum - expected_sum) > 1e-6) success = false; int ndof = space->get_num_dofs(); if(ndof != 82) // Tested value as of May 2013. success = false; if(success) { printf("Success!\n"); return 0; } else { printf("Failure!\n"); return -1; } }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("../domain.mesh", &mesh); // Perform initial mesh refinements. for(int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions DefaultEssentialBCConst bc_essential("Bottom", T1); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); // Initialize the weak formulation. CustomWeakFormPoissonNewton wf(LAMBDA, ALPHA, T0, "Heat flux"); // Testing n_dof and correctness of solution vector // for p_init = 1, 2, ..., 10 int success = 1; for (int p_init = 1; p_init <= 10; p_init++) { printf("********* p_init = %d *********\n", p_init); space.set_uniform_order(p_init); int ndof = Space::get_num_dofs(&space); info("ndof = %d", ndof); // Initialize the FE problem. DiscreteProblem dp(&wf, &space); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof]; memset(coeff_vec, 0, ndof*sizeof(scalar)); // Perform Newton's iteration. if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution sln; Solution::vector_to_solution(coeff_vec, &space, &sln); double sum = 0; for (int i=0; i < ndof; i++) sum += coeff_vec[i]; printf("coefficient sum = %g\n", sum); // Actual test. The values of 'sum' depend on the // current shapeset. If you change the shapeset, // you need to correct these numbers. if (p_init == 1 && fabs(sum - 597.764) > 1e-1) success = 0; if (p_init == 2 && fabs(sum - 597.808) > 1e-1) success = 0; if (p_init == 3 && fabs(sum - 597.8) > 1e-1) success = 0; if (p_init == 4 && fabs(sum - 597.807) > 1e-1) success = 0; if (p_init == 5 && fabs(sum - 597.8) > 1e-1) success = 0; if (p_init == 6 && fabs(sum - 597.806) > 1e-1) success = 0; if (p_init == 7 && fabs(sum - 597.8) > 1e-1) success = 0; if (p_init == 8 && fabs(sum - 597.806) > 1e-1) success = 0; if (p_init == 9 && fabs(sum - 597.8) > 1e-1) success = 0; if (p_init == 10 && fabs(sum - 597.806) > 1e-1) success = 0; delete [] coeff_vec; } if (success == 1) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("../domain.mesh", &mesh); // Perform initial mesh refinements (optional). for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize the weak formulation. CustomWeakFormPoisson wf("Aluminum", new HermesFunction(LAMBDA_AL), "Copper", new HermesFunction(LAMBDA_CU), new HermesFunction(-VOLUME_HEAT_SRC)); // Initialize boundary conditions. DefaultEssentialBCConst bc_essential(Hermes::vector<std::string>("Bottom", "Inner", "Outer", "Left"), FIXED_BDY_TEMP); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the FE problem. DiscreteProblem dp(&wf, &space); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof]; memset(coeff_vec, 0, ndof*sizeof(scalar)); // Perform Newton's iteration. if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution sln; Solution::vector_to_solution(coeff_vec, &space, &sln); // Actual test. The values of 'sum' depend on the // current shapeset. If you change the shapeset, // you need to correct these numbers. double sum = 0; for (int i=0; i < ndof; i++) sum += coeff_vec[i]; printf("coefficient sum = %g\n", sum); bool success = true; if (std::abs(sum + 0.357318) > 1e-4) success = false; if (success == true) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }