int main(int argc, char* argv[]) { // Time measurement TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("lshape3q.mesh", &mesh); // quadrilaterals //mloader.load("lshape3t.mesh", &mesh); // triangles // Perform initial mesh refinemets. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(Hermes::Tuple<int>(BDY_1, BDY_6)); bc_types.add_bc_newton(Hermes::Tuple<int>(BDY_2, BDY_3, BDY_4, BDY_5)); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_zero(Hermes::Tuple<int>(BDY_1, BDY_6)); // Create an Hcurl space with default shapeset. HcurlSpace space(&mesh, &bc_types, &bc_values, P_INIT); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(bilinear_form), HERMES_SYM); wf.add_matrix_form_surf(callback(bilinear_form_surf)); wf.add_vector_form_surf(linear_form_surf, linear_form_surf_ord); // Initialize coarse and reference mesh solutions. Solution sln, ref_sln; // Initialize exact solution. ExactSolution sln_exact(&mesh, exact); // Initialize refinement selector. HcurlProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est, graph_dof_exact, graph_cpu_exact; // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(&space); // Assemble the reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. If successful, obtain the solution. if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); Adapt* adaptivity = new Adapt(&space); double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Calculate exact error, bool solutions_for_adapt = false; double err_exact_rel = adaptivity->calc_err_exact(&sln, &sln_exact, solutions_for_adapt) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space)); info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu_est.save("conv_cpu_est.dat"); graph_dof_exact.add_values(Space::get_num_dofs(&space), err_exact_rel); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel); graph_cpu_exact.save("conv_cpu_exact.dat"); // If err_est_rel too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) delete ref_space->get_mesh(); delete ref_space; delete dp; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); int ndof = Space::get_num_dofs(&space); printf("ndof allowed = %d\n", 1400); printf("ndof actual = %d\n", ndof); if (ndof < 1400) { // ndofs was 1384 atthe time this test was created printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh, basemesh; H2DReader mloader; mloader.load("square.mesh", &basemesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) basemesh.refine_all_elements(); mesh.copy(&basemesh); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(Hermes::vector<int>(BDY_BOTTOM, BDY_RIGHT, BDY_TOP, BDY_LEFT)); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_zero(Hermes::vector<int>(BDY_BOTTOM, BDY_RIGHT, BDY_TOP, BDY_LEFT)); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); // Initialize coarse and reference mesh solution. Solution sln, ref_sln; // Convert initial condition into a Solution. Solution sln_prev_time; sln_prev_time.set_exact(&mesh, init_cond); // Initialize the weak formulation. WeakForm wf; if(TIME_DISCR == 1) { wf.add_matrix_form(callback(J_euler), HERMES_NONSYM, HERMES_ANY); wf.add_vector_form(callback(F_euler), HERMES_ANY, &sln_prev_time); } else { wf.add_matrix_form(callback(J_cranic), HERMES_NONSYM, HERMES_ANY); wf.add_vector_form(callback(F_cranic), HERMES_ANY, &sln_prev_time); } // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp_coarse(&wf, &space, is_linear); // Set up the solver, matrix, and rhs for the coarse mesh according to the solver selection. SparseMatrix* matrix_coarse = create_matrix(matrix_solver); Vector* rhs_coarse = create_vector(matrix_solver); Solver* solver_coarse = create_linear_solver(matrix_solver, matrix_coarse, rhs_coarse); // Create a selector which will select optimal candidate. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Project the initial condition on the FE space to obtain initial // coefficient vector for the Newton's method. info("Projecting initial condition to obtain initial vector for the Newton's method."); scalar* coeff_vec_coarse = new scalar[ndof]; OGProjection::project_global(&space, &sln_prev_time, coeff_vec_coarse, matrix_solver); Solution init_proj; Solution::vector_to_solution(coeff_vec_coarse, &space, &init_proj); // Newton's loop on the coarse mesh. info("Solving on coarse mesh:"); bool verbose = true; if (!solve_newton(coeff_vec_coarse, &dp_coarse, solver_coarse, matrix_coarse, rhs_coarse, NEWTON_TOL_COARSE, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution::vector_to_solution(coeff_vec_coarse, &space, &sln); // Cleanup after the Newton loop on the coarse mesh. delete matrix_coarse; delete rhs_coarse; delete solver_coarse; delete [] coeff_vec_coarse; // Time stepping loop. int num_time_steps = (int)(T_FINAL/TAU + 0.5); for(int ts = 1; ts <= num_time_steps; ts++) { // Periodic global derefinements. if (ts > 1 && ts % UNREF_FREQ == 0) { info("Global mesh derefinement."); mesh.copy(&basemesh); space.set_uniform_order(P_INIT); // Project on globally derefined mesh. info("Projecting previous fine mesh solution on derefined mesh."); OGProjection::project_global(&space, &sln_prev_time, &sln); } // Adaptivity loop: 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* ref_space = construct_refined_space(&space); scalar* coeff_vec = new scalar[Space::get_num_dofs(ref_space)]; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Calculate initial coefficient vector for Newton on the fine mesh. if (as == 1) { info("Projecting coarse mesh solution to obtain coefficient vector on new fine mesh."); OGProjection::project_global(ref_space, &sln, coeff_vec, matrix_solver); } else { info("Projecting previous fine mesh solution to obtain coefficient vector on new fine mesh."); OGProjection::project_global(ref_space, &ref_sln, coeff_vec, matrix_solver); } // Now we can deallocate the previous fine mesh. if(as > 1) delete ref_sln.get_mesh(); // Newton's loop on the fine mesh. info("Solving on fine mesh:"); if (!solve_newton(coeff_vec, dp, solver, matrix, rhs, NEWTON_TOL_FINE, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Store the result in ref_sln. Solution::vector_to_solution(coeff_vec, ref_space, &ref_sln); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt* adaptivity = new Adapt(&space); double err_est_rel_total = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Report results. info("ndof: %d, ref_ndof: %d, err_est_rel: %g%%", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_est_rel_total); // 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::get_num_dofs(&space) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; delete ref_space; delete dp; delete [] coeff_vec; } while (done == false); // Copy last reference solution into sln_prev_time. sln_prev_time.copy(&ref_sln); } AbsFilter mag2(&sln); int success = 1; double eps = 1e-5; double val = std::abs(mag2.get_pt_value(0.1, 0.1)); info("Coordinate ( 0.1, 0.1) xvel value = %lf", val); if (fabs(val - (0.65773)) > eps) { printf("Coordinate ( 0.1, 0.1) xvel value = %lf\n", val); success = 0; } val = std::abs(mag2.get_pt_value(0.1, -0.1)); info("Coordinate ( 0.1, -0.1) xvel value = %lf", val); if (fabs(val - (0.65773)) > eps) { printf("Coordinate ( 0.1, -0.1) xvel value = %lf\n", val); success = 0; } val = std::abs(mag2.get_pt_value(0.2, 0.1)); info("Coordinate ( 0.2, 0.1) xvel value = %lf", val); if (fabs(val - (0.39062)) > eps) { printf("Coordinate ( 0.2, 0.1) xvel value = %lf\n", val); success = 0; } if (success == 1) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); // Perform initial uniform mesh refinement. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_neumann(Hermes::vector<int>(BDY_NEUMANN)); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, P_INIT); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(bilinear_form_1, bilinear_form_ord, HERMES_SYM, 1); wf.add_matrix_form(bilinear_form_2, bilinear_form_ord, HERMES_SYM, 2); wf.add_matrix_form(bilinear_form_3, bilinear_form_ord, HERMES_SYM, 3); wf.add_matrix_form(bilinear_form_4, bilinear_form_ord, HERMES_SYM, 4); wf.add_matrix_form(bilinear_form_5, bilinear_form_ord, HERMES_SYM, 5); wf.add_vector_form(linear_form_1, linear_form_ord, 1); wf.add_vector_form(linear_form_3, linear_form_ord, 3); // Initialize coarse and reference mesh solution. Solution sln, ref_sln; // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); sview.fix_scale_width(50); sview.show_mesh(false); OrderView oview("Polynomial orders", new WinGeom(450, 0, 400, 350)); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(&space); // Initialize matrix and matrix solver. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Assemble the reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. // If successful, obtain the solution. if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Time measurement. cpu_time.tick(); // View the coarse mesh solution and polynomial orders. sview.show(&sln); oview.show(&space); // Skip visualization time. cpu_time.tick(HERMES_SKIP); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt* adaptivity = new Adapt(&space); double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_est_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) delete ref_space->get_mesh(); delete ref_space; delete dp; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); // Show the reference solution - the final result. sview.set_title("Fine mesh solution"); sview.show_mesh(false); sview.show(&ref_sln); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // 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; H2DReader 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 bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof_coarse = Space::get_num_dofs(&space); info("ndof_coarse = %d.", ndof_coarse); // Initial condition vector is the zero vector. This is why we // use the H_OFFSET. scalar* coeff_vec = new scalar[ndof_coarse]; memset(coeff_vec, 0, ndof_coarse*sizeof(double)); // Convert initial condition into a Solution. Solution h_time_prev, h_time_new; Solution::vector_to_solution(coeff_vec, &space, &h_time_prev); delete [] coeff_vec; // Initialize the weak formulation. CustomWeakFormRichardsRK wf; // Initialize the FE problem. DiscreteProblem dp(&wf, &space); // Create a refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // 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: 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_coarse = Space::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* ref_space = Space::construct_refined_space(&space); int ndof_ref = Space::get_num_dofs(ref_space); // Initialize discrete problem on reference mesh. DiscreteProblem dp(&wf, ref_space); // Initialize Runge-Kutta time stepping. RungeKutta runge_kutta(&dp, &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 jacobian_changed = true; bool verbose = true; double damping_coeff = 1.0; double max_allowed_residual_norm = 1e10; if (!runge_kutta.rk_time_step(current_time, time_step, &h_time_prev, &h_time_new, jacobian_changed, verbose, NEWTON_TOL, NEWTON_MAX_ITER, damping_coeff, max_allowed_residual_norm)) { error("Runge-Kutta time step failed, try to decrease time step size."); } // Project the fine mesh solution onto the coarse mesh. Solution sln_coarse; info("Projecting fine mesh solution on coarse mesh for error estimation."); OGProjection::project_global(&space, &h_time_new, &sln_coarse, matrix_solver); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt* adaptivity = new Adapt(&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::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_est_rel_total); // 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::get_num_dofs(&space) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } // Clean up. delete adaptivity; delete ref_space; if(!done) delete h_time_new.get_mesh(); } while (done == false); // 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); int ndof_allowed = 35; printf("ndof actual = %d\n", Space::get_num_dofs(&space)); printf("ndof allowed = %d\n", ndof_allowed); if (Space::get_num_dofs(&space) <= ndof_allowed) { // ndofs was 33 at the time this test was created 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; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh u_mesh, v_mesh; H2DReader mloader; mloader.load("square.mesh", &u_mesh); if (MULTI == false) u_mesh.refine_towards_boundary("Bdy", INIT_REF_BDY); // Create initial mesh (master mesh). v_mesh.copy(&u_mesh); // Initial mesh refinements in the v_mesh towards the boundary. if (MULTI == true) v_mesh.refine_towards_boundary("Bdy", INIT_REF_BDY); // Set exact solutions. ExactSolutionFitzHughNagumo1 exact_u(&u_mesh); ExactSolutionFitzHughNagumo2 exact_v(&v_mesh, K); // Define right-hand sides. CustomRightHandSide1 g1(K, D_u, SIGMA); CustomRightHandSide2 g2(K, D_v); // Initialize the weak formulation. WeakFormFitzHughNagumo wf(&g1, &g2); // Initialize boundary conditions DefaultEssentialBCConst bc_u("Bdy", 0.0); EssentialBCs bcs_u(&bc_u); DefaultEssentialBCConst bc_v("Bdy", 0.0); EssentialBCs bcs_v(&bc_v); // Create H1 spaces with default shapeset for both displacement components. H1Space u_space(&u_mesh, &bcs_u, P_INIT_U); H1Space v_space(MULTI ? &v_mesh : &u_mesh, &bcs_v, P_INIT_V); // Initialize coarse and reference mesh solutions. Solution u_sln, v_sln, u_ref_sln, v_ref_sln; // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView s_view_0("Solution[0]", new WinGeom(0, 0, 440, 350)); s_view_0.show_mesh(false); OrderView o_view_0("Mesh[0]", new WinGeom(450, 0, 420, 350)); ScalarView s_view_1("Solution[1]", new WinGeom(880, 0, 440, 350)); s_view_1.show_mesh(false); OrderView o_view_1("Mesh[1]", new WinGeom(1330, 0, 420, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est, graph_dof_exact, graph_cpu_exact; // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Hermes::vector<Space *>* ref_spaces = Space::construct_refined_spaces(Hermes::vector<Space *>(&u_space, &v_space)); int ndof_ref = Space::get_num_dofs(*ref_spaces); // Initialize matrix solver. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize reference problem. info("Solving on reference mesh."); DiscreteProblem* dp = new DiscreteProblem(&wf, *ref_spaces); // Time measurement. cpu_time.tick(); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof_ref]; memset(coeff_vec, 0, ndof_ref * sizeof(scalar)); // Perform Newton's iteration. bool jacobian_changed = true; bool verbose = true; if (!hermes2d.solve_newton(coeff_vec, dp, solver, matrix, rhs, jacobian_changed, 1e-8, 100, verbose)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution::vector_to_solutions(coeff_vec, *ref_spaces, Hermes::vector<Solution *>(&u_ref_sln, &v_ref_sln)); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(Hermes::vector<Space *>(&u_space, &v_space), Hermes::vector<Solution *>(&u_ref_sln, &v_ref_sln), Hermes::vector<Solution *>(&u_sln, &v_sln), matrix_solver); cpu_time.tick(); // View the coarse mesh solution and polynomial orders. s_view_0.show(&u_sln); o_view_0.show(&u_space); s_view_1.show(&v_sln); o_view_1.show(&v_space); // Calculate element errors. info("Calculating error estimate and exact error."); Adapt* adaptivity = new Adapt(Hermes::vector<Space *>(&u_space, &v_space)); // Calculate error estimate for each solution component and the total error estimate. Hermes::vector<double> err_est_rel; double err_est_rel_total = adaptivity->calc_err_est(Hermes::vector<Solution *>(&u_sln, &v_sln), Hermes::vector<Solution *>(&u_ref_sln, &v_ref_sln), &err_est_rel) * 100; // Calculate exact error for each solution component and the total exact error. Hermes::vector<double> err_exact_rel; bool solutions_for_adapt = false; double err_exact_rel_total = adaptivity->calc_err_exact(Hermes::vector<Solution *>(&u_sln, &v_sln), Hermes::vector<Solution *>(&exact_u, &exact_v), &err_exact_rel, solutions_for_adapt) * 100; // Time measurement. cpu_time.tick(); // Report results. info("ndof_coarse[0]: %d, ndof_fine[0]: %d", u_space.Space::get_num_dofs(), Space::get_num_dofs((*ref_spaces)[0])); info("err_est_rel[0]: %g%%, err_exact_rel[0]: %g%%", err_est_rel[0]*100, err_exact_rel[0]*100); info("ndof_coarse[1]: %d, ndof_fine[1]: %d", v_space.Space::get_num_dofs(), Space::get_num_dofs((*ref_spaces)[1])); info("err_est_rel[1]: %g%%, err_exact_rel[1]: %g%%", err_est_rel[1]*100, err_exact_rel[1]*100); info("ndof_coarse_total: %d, ndof_fine_total: %d", Space::get_num_dofs(Hermes::vector<Space *>(&u_space, &v_space)), Space::get_num_dofs(*ref_spaces)); info("err_est_rel_total: %g%%, err_est_exact_total: %g%%", err_est_rel_total, err_exact_rel_total); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space::get_num_dofs(Hermes::vector<Space *>(&u_space, &v_space)), err_est_rel_total); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel_total); graph_cpu_est.save("conv_cpu_est.dat"); graph_dof_exact.add_values(Space::get_num_dofs(Hermes::vector<Space *>(&u_space, &v_space)), err_exact_rel_total); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel_total); graph_cpu_exact.save("conv_cpu_exact.dat"); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(Hermes::vector<RefinementSelectors::Selector *>(&selector, &selector), THRESHOLD, STRATEGY, MESH_REGULARITY); } if (Space::get_num_dofs(Hermes::vector<Space *>(&u_space, &v_space)) >= NDOF_STOP) done = true; // Clean up. delete [] coeff_vec; delete solver; delete matrix; delete rhs; delete adaptivity; for(unsigned int i = 0; i < ref_spaces->size(); i++) delete (*ref_spaces)[i]->get_mesh(); delete ref_spaces; delete dp; // Increase counter. as++; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("square.mesh", &mesh); // Perform initial mesh refinements. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(1, INIT_REF_NUM_BDY); // Create an H1 space with default shapeset. H1Space space(&mesh, bc_types, essential_bc_values, P_INIT); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(bilinear_form), HERMES_SYM); wf.add_vector_form(callback(linear_form)); // Initialize coarse and reference mesh solution. Solution sln, ref_sln; // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(&space); // Assemble the reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. // If successful, obtain the solution. if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt* adaptivity = new Adapt(&space, HERMES_H1_NORM); bool solutions_for_adapt = true; double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_est_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) delete ref_space->get_mesh(); delete ref_space; delete dp; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); int ndof = Space::get_num_dofs(&space); #define ERROR_SUCCESS 0 #define ERROR_FAILURE -1 int n_dof_allowed = 750; printf("n_dof_actual = %d\n", ndof); printf("n_dof_allowed = %d\n", n_dof_allowed);// ndofs was 729 at the time this test was created if (ndof <= n_dof_allowed) { printf("Success!\n"); return ERROR_SUCCESS; } else { printf("Failure!\n"); return ERROR_FAILURE; } }
int main(int argc, char* argv[]) { // Load the mesh. Mesh u_mesh, v_mesh; MeshReaderH2D mloader; mloader.load("elasticity.mesh", &u_mesh); // Create initial mesh (master mesh). v_mesh.copy(&u_mesh); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) { u_mesh.refine_all_elements(); v_mesh.refine_all_elements(); } // Set exact solution for each displacement component. CustomExactSolutionU exact_u(&u_mesh, E, nu, lambda, Q); CustomExactSolutionV exact_v(&v_mesh, E, nu, lambda, Q); // Initialize the weak formulation. // NOTE: We pass all four parameters (temporarily) // since in Mitchell's paper (NIST benchmarks) they // are mutually inconsistent. CustomWeakFormElasticityNIST wf(E, nu, mu, lambda); // Initialize boundary conditions. DefaultEssentialBCNonConst<double> bc_u("Bdy", &exact_u); EssentialBCs<double> bcs_u(&bc_u); DefaultEssentialBCNonConst<double> bc_v("Bdy", &exact_v); EssentialBCs<double> bcs_v(&bc_v); // Create H1 spaces with default shapeset for both displacement components. H1Space<double> u_space(&u_mesh, &bcs_u, P_INIT_U); H1Space<double> v_space(&v_mesh, &bcs_v, P_INIT_V); // Initialize approximate solution. Solution<double> u_sln, v_sln; // Initialize refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. Views::ScalarView s_view_u("Solution for u", new WinGeom(0, 0, 440, 350)); s_view_u.show_mesh(false); Views::OrderView o_view_u("Mesh for u", new WinGeom(450, 0, 420, 350)); Views::ScalarView s_view_v("Solution for v", new WinGeom(0, 405, 440, 350)); s_view_v.show_mesh(false); Views::OrderView o_view_v("Mesh for v", new WinGeom(450, 405, 420, 350)); Views::ScalarView mises_view("Von Mises stress [Pa]", new WinGeom(880, 0, 440, 350)); mises_view.fix_scale_width(50); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est, graph_dof_exact, graph_cpu_exact; // Time measurement. Hermes::TimePeriod cpu_time; // Adaptivity loop: int as = 1; bool done = false; do { cpu_time.tick(); // Construct globally refined reference mesh and setup reference space. Hermes::vector<Space<double>*>* ref_spaces = Space<double>::construct_refined_spaces(Hermes::vector<Space<double>*>(&u_space, &v_space)); Hermes::vector<const Space<double>*> ref_spaces_const((*ref_spaces)[0], (*ref_spaces)[1]); int ndof_ref = Space<double>::get_num_dofs(ref_spaces_const); info("---- Adaptivity step %d (%d DOF):", as, ndof_ref); cpu_time.tick(); info("Solving on reference mesh."); // Assemble the discrete problem. DiscreteProblem<double> dp(&wf, ref_spaces_const); NewtonSolver<double> newton(&dp, matrix_solver); newton.set_verbose_output(false); Solution<double> u_ref_sln, v_ref_sln; try { newton.solve(); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); error("Newton's iteration failed."); }; // Translate the resulting coefficient vector into the instance of Solution. Solution<double>::vector_to_solutions(newton.get_sln_vector(), ref_spaces_const, Hermes::vector<Solution<double>*>(&u_ref_sln, &v_ref_sln)); cpu_time.tick(); verbose("Solution: %g s", cpu_time.last()); // Project the fine mesh solution onto the coarse mesh. info("Calculating error estimate and exact error."); OGProjection<double>::project_global(Hermes::vector<const Space<double>*>(&u_space, &v_space), Hermes::vector<Solution<double>*>(&u_ref_sln, &v_ref_sln), Hermes::vector<Solution<double>*>(&u_sln, &v_sln), matrix_solver); // Calculate element errors and total error estimate. Hermes::vector<double> err_est_rel; Adapt<double>* adaptivity = new Adapt<double>(Hermes::vector<Space<double>*>(&u_space, &v_space)); double err_est_rel_total = adaptivity->calc_err_est(Hermes::vector<Solution<double>*>(&u_sln, &v_sln), Hermes::vector<Solution<double>*>(&u_ref_sln, &v_ref_sln), &err_est_rel) * 100.; // Calculate exact error for each solution component and the total exact error. Hermes::vector<double> err_exact_rel; bool solutions_for_adapt = false; double err_exact_rel_total = adaptivity->calc_err_exact(Hermes::vector<Solution<double>*>(&u_sln, &v_sln), Hermes::vector<Solution<double>*>(&exact_u, &exact_v), &err_exact_rel, solutions_for_adapt) * 100.; cpu_time.tick(); verbose("Error calculation: %g s", cpu_time.last()); // Report results. info("ndof_coarse[u]: %d, ndof_fine[u]: %d", u_space.Space<double>::get_num_dofs(), Space<double>::get_num_dofs((*ref_spaces)[0])); info("err_est_rel[u]: %g%%, err_exact_rel[u]: %g%%", err_est_rel[0]*100, err_exact_rel[0]*100); info("ndof_coarse[v]: %d, ndof_fine[v]: %d", v_space.Space<double>::get_num_dofs(), Space<double>::get_num_dofs((*ref_spaces)[1])); info("err_est_rel[v]: %g%%, err_exact_rel[v]: %g%%", err_est_rel[1]*100, err_exact_rel[1]*100); info("ndof_coarse_total: %d, ndof_fine_total: %d", Space<double>::get_num_dofs(Hermes::vector<const Space<double> *>(&u_space, &v_space)), Space<double>::get_num_dofs(ref_spaces_const)); info("err_est_rel_total: %g%%, err_est_exact_total: %g%%", err_est_rel_total, err_exact_rel_total); // Time measurement. cpu_time.tick(); double accum_time = cpu_time.accumulated(); // View the coarse mesh solution and polynomial orders. s_view_u.show(&u_sln); o_view_u.show(&u_space); s_view_v.show(&v_sln); o_view_v.show(&v_space); VonMisesFilter stress(Hermes::vector<MeshFunction<double> *>(&u_sln, &v_sln), lambda, mu); mises_view.show(&stress, HERMES_EPS_HIGH, H2D_FN_VAL_0, &u_sln, &v_sln, 0.03); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space<double>::get_num_dofs(Hermes::vector<const Space<double> *>(&u_space, &v_space)), err_est_rel_total); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel_total); graph_cpu_est.save("conv_cpu_est.dat"); graph_dof_exact.add_values(Space<double>::get_num_dofs(Hermes::vector<const Space<double> *>(&u_space, &v_space)), err_exact_rel_total); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel_total); graph_cpu_exact.save("conv_cpu_exact.dat"); cpu_time.tick(Hermes::HERMES_SKIP); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(Hermes::vector<RefinementSelectors::Selector<double> *>(&selector, &selector), THRESHOLD, STRATEGY, MESH_REGULARITY); } if (Space<double>::get_num_dofs(Hermes::vector<const Space<double> *>(&u_space, &v_space)) >= NDOF_STOP) done = true; cpu_time.tick(); verbose("Adaptation: %g s", cpu_time.last()); // Increase the counter of adaptivity steps. if (done == false) as++; delete adaptivity; if(done == false) for(unsigned int i = 0; i < ref_spaces->size(); i++) delete (*ref_spaces)[i]->get_mesh(); delete ref_spaces; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. Views::View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("../square_quad.mesh", &mesh); // quadrilaterals // mloader.load("../square_tri.mesh", &mesh); // triangles // Perform initial mesh refinement. for (int i=0; i<INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(BDY_LAYER, INIT_REF_NUM_BDY); // Initialize the weak formulation. WeakFormLinearAdvectionDiffusion wf(STABILIZATION_ON, SHOCK_CAPTURING_ON, B1, B2, EPSILON); // Initialize boundary conditions DefaultEssentialBCConst bc_rest(BDY_REST, 1.0); EssentialBCNonConst bc_layer(BDY_LAYER); EssentialBCs bcs(Hermes::vector<EssentialBoundaryCondition *>(&bc_rest, &bc_layer)); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); // Initialize coarse and reference mesh solution. Solution sln, ref_sln; // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = Space::construct_refined_space(&space); // Assemble the reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. // If successful, obtain the solution. if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt* adaptivity = new Adapt(&space); double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_est_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) delete ref_space->get_mesh(); delete ref_space; delete dp; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); int ndof = Space::get_num_dofs(&space); int n_dof_allowed = 570; printf("n_dof_actual = %d\n", ndof); printf("n_dof_allowed = %d\n", n_dof_allowed);// ndofs was 558 at the time this test was created if (ndof <= n_dof_allowed) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main (int argc, char* argv[]) { // Load the mesh. Mesh basemesh; ExodusIIReader mesh_loader; if (!mesh_loader.load("coarse_mesh_full.e", &basemesh)) error("Loading mesh file '%s' failed.\n", "coarse_mesh_full.e"); Mesh C_mesh, phi_mesh; C_mesh.copy(basemesh); phi_mesh.copy(basemesh); H1Space C_space(&C_mesh, bc_types_C, essential_bc_values_C, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); H1Space phi_space(MULTIMESH ? &phi_mesh : &C_mesh, bc_types_phi, essential_bc_values_phi, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); Solution C_prev_time(&C_mesh); C_prev_time.set_const(C0); Solution phi_prev_time(MULTIMESH ? &phi_mesh : &C_mesh); phi_prev_time.set_const(0.0); WeakForm wf(2); // Add the bilinear and linear forms. if (TIME_DISCR == 1) { // Implicit Euler. wf.add_matrix_form(0, 0, callback(J_euler_DFcDYc), HERMES_NONSYM); wf.add_matrix_form(0, 1, callback(J_euler_DFcDYphi), HERMES_NONSYM); wf.add_matrix_form(1, 0, callback(J_euler_DFphiDYc), HERMES_NONSYM); wf.add_matrix_form(1, 1, callback(J_euler_DFphiDYphi), HERMES_NONSYM); wf.add_vector_form(0, callback(Fc_euler), HERMES_ANY_INT, Hermes::vector<MeshFunction*>(&C_prev_time, &phi_prev_time)); wf.add_vector_form(1, callback(Fphi_euler), HERMES_ANY, Hermes::vector<MeshFunction*>(&C_prev_time, &phi_prev_time)); } else { wf.add_matrix_form(0, 0, callback(J_cranic_DFcDYc), HERMES_NONSYM); wf.add_matrix_form(0, 1, callback(J_cranic_DFcDYphi), HERMES_NONSYM); wf.add_matrix_form(1, 0, callback(J_cranic_DFphiDYc), HERMES_NONSYM); wf.add_matrix_form(1, 1, callback(J_cranic_DFphiDYphi), HERMES_NONSYM); wf.add_vector_form(0, callback(Fc_cranic), HERMES_ANY, Hermes::vector<MeshFunction*>(&C_prev_time, &phi_prev_time)); wf.add_vector_form(1, callback(Fphi_cranic), HERMES_ANY); } int ndof = Space::get_num_dofs(Hermes::vector<Space*>(&C_space, &phi_space)); Solution C_sln(C_space.get_mesh()); Solution phi_sln(phi_space.get_mesh()); info("Projecting initial condition to obtain initial vector for the Newton's method."); scalar* coeff_vec_coarse = new scalar[ndof]; OGProjection::project_global(Hermes::vector<Space *>(&C_space, &phi_space), Hermes::vector<MeshFunction *>(&C_prev_time, &phi_prev_time), coeff_vec_coarse, matrix_solver); bool is_linear = false; DiscreteProblem dp_coarse(&wf, Hermes::vector<Space *>(&C_space, &phi_space), is_linear); //Solution::vector_to_solutions(coeff_vec_coarse, dp_coarse.get_spaces(), Hermes::vector<Solution *>(&C_sln, &phi_sln), NULL); // Set up the solver, matrix, and rhs for the coarse mesh according to the solver selection. SparseMatrix* matrix_coarse = create_matrix(matrix_solver); Vector* rhs_coarse = create_vector(matrix_solver); Solver* solver_coarse = create_linear_solver(matrix_solver, matrix_coarse, rhs_coarse); info("Solving on coarse mesh:"); bool verbose = true; if (!solve_newton(coeff_vec_coarse, &dp_coarse, solver_coarse, matrix_coarse, rhs_coarse, NEWTON_TOL_COARSE, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); info("Solved!"); // Translate the resulting coefficient vector into the Solution sln. Solution::vector_to_solutions(coeff_vec_coarse, Hermes::vector<Space *>(&C_space, &phi_space), Hermes::vector<Solution *>(&C_sln, &phi_sln)); out_fn_vtk(&C_sln,"C_init_sln"); out_fn_vtk(&phi_sln,"phi_init_sln"); //out_fn_vtk(&sln, "sln", ts); Solution *C_ref_sln, *phi_ref_sln; PidTimestepController pid(T_FINAL, false, INIT_TAU); TAU = pid.timestep; info("Starting time iteration with the step %g", *TAU); do { pid.begin_step(); if (pid.get_timestep_number() > 1 && pid.get_timestep_number() % UNREF_FREQ == 0) { info("Global mesh derefinement."); C_mesh.copy(basemesh); if (MULTIMESH) { phi_mesh.copy(basemesh); } C_space.set_uniform_order(Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); phi_space.set_uniform_order(Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); } bool done = false; int as = 1; double err_est; do { info("Time step %d, adaptivity step %d:", pid.get_timestep_number(), as); // Construct globally refined reference mesh // and setup reference space. int order_increase = 1; Hermes::vector<Space *>* ref_spaces = construct_refined_spaces(Hermes::vector<Space *>(&C_space, &phi_space), order_increase); scalar* coeff_vec = new scalar[Space::get_num_dofs(*ref_spaces)]; DiscreteProblem* dp = new DiscreteProblem(&wf, *ref_spaces, is_linear); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); if (as == 1 && pid.get_timestep_number() == 1) { info("Projecting coarse mesh solution to obtain coefficient vector on new fine mesh."); OGProjection::project_global(*ref_spaces, Hermes::vector<MeshFunction *>(&C_sln, &phi_sln), coeff_vec, matrix_solver); } else { info("Projecting previous fine mesh solution to obtain coefficient vector on new fine mesh."); OGProjection::project_global(*ref_spaces, Hermes::vector<MeshFunction *>(C_ref_sln, phi_ref_sln), coeff_vec, matrix_solver); } if (as > 1) { // Now deallocate the previous mesh info("Deallocating the previous mesh"); //delete C_ref_sln->get_mesh(); //delete phi_ref_sln->get_mesh(); //delete C_ref_sln; //delete phi_ref_sln; } /*TODO TEMP */ if (pid.get_timestep_number() > 1) { delete C_ref_sln; delete phi_ref_sln; } info("Solving on fine mesh:"); if (!solve_newton(coeff_vec, dp, solver, matrix, rhs, NEWTON_TOL_FINE, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Store the result in ref_sln. C_ref_sln = new Solution(ref_spaces->at(0)->get_mesh()); phi_ref_sln = new Solution(ref_spaces->at(1)->get_mesh()); Solution::vector_to_solutions(coeff_vec, *ref_spaces, Hermes::vector<Solution *>(C_ref_sln, phi_ref_sln)); // Projecting reference solution onto the coarse mesh info("Projecting fine mesh solution on coarse mesh."); OGProjection::project_global(Hermes::vector<Space *>(&C_space, &phi_space), Hermes::vector<Solution *>(C_ref_sln, phi_ref_sln), Hermes::vector<Solution *>(&C_sln, &phi_sln), matrix_solver); info("Calculating error estimate."); Adapt* adaptivity = new Adapt(Hermes::vector<Space *>(&C_space, &phi_space), Hermes::vector<ProjNormType> (HERMES_H1_NORM, HERMES_H1_NORM)); Hermes::vector<double> err_est_rel; bool solutions_for_adapt = true; double err_est_rel_total = adaptivity->calc_err_est(Hermes::vector<Solution *>(&C_sln, &phi_sln), Hermes::vector<Solution *>(C_ref_sln, phi_ref_sln), solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_ABS, &err_est_rel) * 100; // Report results. info("ndof_coarse[0]: %d, ndof_fine[0]: %d", C_space.get_num_dofs(), (*ref_spaces)[0]->get_num_dofs()); info("err_est_rel[0]: %g%%", err_est_rel[0]*100); info("ndof_coarse[1]: %d, ndof_fine[1]: %d", phi_space.get_num_dofs(), (*ref_spaces)[1]->get_num_dofs()); info("err_est_rel[1]: %g%%", err_est_rel[1]*100); // Report results. info("ndof_coarse_total: %d, ndof_fine_total: %d, err_est_rel: %g%%", Space::get_num_dofs(Hermes::vector<Space *>(&C_space, &phi_space)), Space::get_num_dofs(*ref_spaces), err_est_rel_total); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting the coarse mesh."); adaptivity->adapt(THRESHOLD); info("Adapted..."); if (Space::get_num_dofs(Hermes::vector<Space *>(&C_space, &phi_space)) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } //as++; delete solver; delete matrix; delete rhs; delete ref_spaces; delete dp; delete[] coeff_vec; done = true; } while (!done); out_fn_vtk(C_ref_sln,"C_sln", pid.get_timestep_number()); out_fn_vtk(phi_ref_sln,"phi_sln", pid.get_timestep_number()); pid.end_step(Hermes::vector<Solution*> (C_ref_sln, phi_ref_sln), Hermes::vector<Solution*> (&C_prev_time, &phi_prev_time)); // Copy last reference solution into sln_prev_time. C_prev_time.copy(C_ref_sln); phi_prev_time.copy(phi_ref_sln); } while (pid.has_next()); //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; switch (PARAM) { case 0: mloader.load("../geom0.mesh", &mesh); break; case 1: mloader.load("../geom1.mesh", &mesh); break; case 2: mloader.load("../geom2.mesh", &mesh); break; case 3: mloader.load("../geom3.mesh", &mesh); break; default: error("Admissible values of PARAM are 0, 1, 2, 3."); } // Perform initial mesh refinements. for (int i=0; i<INIT_REF_NUM; i++) mesh.refine_all_elements(); // Set exact solution. CustomExactSolution exact(&mesh, PARAM); // Initialize the weak formulation. DefaultWeakFormLaplace wf; // Initialize boundary conditions DefaultEssentialBCNonConst bc_essential(BDY_DIRICHLET, &exact); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // DOF and CPU convergence graphs. SimpleGraph graph_dof, graph_cpu, graph_dof_exact, graph_cpu_exact; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = Space::construct_refined_space(&space); // 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); // Assemble the reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. If successful, obtain the solution. Solution ref_sln; if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Project the fine mesh solution onto the coarse mesh. Solution sln; info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); Adapt* adaptivity = new Adapt(&space); double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Calculate exact error. double err_exact_rel = hermes2d.calc_rel_error(&sln, &exact, HERMES_H1_NORM) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space)); info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); graph_dof_exact.add_values(Space::get_num_dofs(&space), err_exact_rel); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel); graph_cpu_exact.save("conv_cpu_exact.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) delete ref_space->get_mesh(); delete ref_space; delete dp; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); int ndof = Space::get_num_dofs(&space); int n_dof_allowed = 650; printf("n_dof_actual = %d\n", ndof); printf("n_dof_allowed = %d\n", n_dof_allowed); if (ndof <= n_dof_allowed) { 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("square_quad.mesh", &mesh); // Avoid zero ndof situation. if (P_INIT == 1) { if (is_hp(CAND_LIST)) P_INIT++; else mesh.refine_element_id(0, 0); } // Define exact solution. CustomExactSolution exact_sln(&mesh); // Initialize the weak formulation. HermesFunction lambda(1.0); CustomFunction f; WeakFormsH1::DefaultWeakFormPoisson wf(HERMES_ANY, &lambda, &f); // 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); // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); sview.show_mesh(false); OrderView oview("Polynomial orders", new WinGeom(450, 0, 400, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof, graph_cpu, graph_dof_exact, graph_cpu_exact; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = Space::construct_refined_space(&space); int ndof_ref = Space::get_num_dofs(ref_space); // 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 reference problem. info("Solving on reference mesh."); DiscreteProblem dp(&wf, ref_space); // Time measurement. cpu_time.tick(); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof_ref]; memset(coeff_vec, 0, ndof_ref * sizeof(scalar)); // Perform Newton's iteration. 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 ref_sln; Solution::vector_to_solution(coeff_vec, ref_space, &ref_sln); // Project the fine mesh solution onto the coarse mesh. Solution sln; info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // View the coarse mesh solution and polynomial orders. sview.show(&sln); oview.show(&space); // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); Adapt* adaptivity = new Adapt(&space); double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Calculate exact error. double err_exact_rel = hermes2d.calc_rel_error(&sln, &exact_sln, HERMES_H1_NORM) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space)); info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); graph_dof_exact.add_values(Space::get_num_dofs(&space), err_exact_rel); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel); graph_cpu_exact.save("conv_cpu_exact.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete [] coeff_vec; delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) delete ref_space->get_mesh(); delete ref_space; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. View::wait(); }
int main(int argc, char* argv[]) { Hermes2D hermes2d; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); //MeshView mv("Initial mesh", new WinGeom(0, 0, 400, 400)); //mv.show(&mesh); //View::wait(HERMES_WAIT_KEYPRESS); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions. DefaultEssentialBCConst bc_essential("Source", P_SOURCE); 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. CustomWeakFormAcoustics wf(BDY_NEWTON, RHO, SOUND_SPEED, OMEGA); // Initialize coarse and reference mesh solution. Solution sln, ref_sln; // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 600, 350)); sview.show_mesh(false); sview.fix_scale_width(50); OrderView oview("Polynomial orders", new WinGeom(610, 0, 600, 350)); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; 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). } // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = Space::construct_refined_space(&space); int ndof_ref = Space::get_num_dofs(ref_space); // Assemble the reference problem. info("Solving on reference mesh."); DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space); // Time measurement. cpu_time.tick(); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof_ref]; memset(coeff_vec, 0, ndof_ref * sizeof(scalar)); // Perform Newton's iteration. if (!hermes2d.solve_newton(coeff_vec, dp, solver, matrix, rhs)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution::vector_to_solution(coeff_vec, ref_space, &ref_sln); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Time measurement. cpu_time.tick(); // View the coarse mesh solution and polynomial orders. sview.show(&sln); oview.show(&space); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt* adaptivity = new Adapt(&space); double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_est_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; delete adaptivity; if (done == false) delete ref_space->get_mesh(); delete ref_space; delete dp; // Increase counter. as++; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); // Clean up. delete solver; delete matrix; delete rhs; // Show the reference solution - the final result. sview.set_title("Fine mesh solution"); sview.show(&ref_sln); // 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("domain.mesh", &mesh); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions. Hermes::Hermes2D::DefaultEssentialBCConst<std::complex<double> > bc_essential("Dirichlet", std::complex<double>(0.0, 0.0)); EssentialBCs<std::complex<double> > bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space<std::complex<double> > space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the weak formulation. CustomWeakForm wf("Air", MU_0, "Iron", MU_IRON, GAMMA_IRON, "Wire", MU_0, std::complex<double>(J_EXT, 0.0), OMEGA); // Initialize coarse and reference mesh solution. Solution<std::complex<double> > sln, ref_sln; // Initialize refinement selector. H1ProjBasedSelector<std::complex<double> > selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. Views::ScalarView sview("Solution", new Views::WinGeom(0, 0, 600, 350)); sview.show_mesh(false); Views::OrderView oview("Polynomial orders", new Views::WinGeom(610, 0, 520, 350)); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; Space<std::complex<double> >* ref_space = Space<std::complex<double> >::construct_refined_space(&space); DiscreteProblem<std::complex<double> > dp(&wf, ref_space); dp.set_adaptivity_cache(); // Perform Newton's iteration and translate the resulting coefficient vector into a Solution. Hermes::Hermes2D::NewtonSolver<std::complex<double> > newton(&dp, matrix_solver_type); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. ref_space = Space<std::complex<double> >::construct_refined_space(&space); dp.set_spaces(ref_space); int ndof_ref = ref_space->get_num_dofs(); // Initialize reference problem. info("Solving on reference mesh."); // Time measurement. cpu_time.tick(); // Initial coefficient vector for the Newton's method. std::complex<double>* coeff_vec = new std::complex<double>[ndof_ref]; memset(coeff_vec, 0, ndof_ref * sizeof(std::complex<double>)); // Perform Newton's iteration and translate the resulting coefficient vector into a Solution. // For iterative solver. if (matrix_solver_type == SOLVER_AZTECOO) { newton.set_iterative_method(iterative_method); newton.set_preconditioner(preconditioner); } try{ newton.solve(coeff_vec); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); error("Newton's iteration failed."); } Hermes::Hermes2D::Solution<std::complex<double> >::vector_to_solution(newton.get_sln_vector(), ref_space, &ref_sln); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection<std::complex<double> >::project_global(&space, &ref_sln, &sln, matrix_solver_type); // View the coarse mesh solution and polynomial orders. RealFilter real_filter(&sln); sview.show(&real_filter); oview.show(&space); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt<std::complex<double> >* adaptivity = new Adapt<std::complex<double> >(&space); double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", space.get_num_dofs(), ref_space->get_num_dofs(), err_est_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(space.get_num_dofs(), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); } if (space.get_num_dofs() >= NDOF_STOP) done = true; // Clean up. delete [] coeff_vec; delete adaptivity; // Increase counter. as++; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); // Show the reference solution - the final result. sview.set_title("Fine mesh solution"); RealFilter real_filter(&ref_sln); sview.show(&real_filter); // Wait for all views to be closed. Views::View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; if (ALIGN_MESH) mloader.load("oven_load_circle.mesh", &mesh); else mloader.load("oven_load_square.mesh", &mesh); // Perform initial mesh refinemets. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(BDY_DIRICHLET); bc_types.add_bc_neumann(BDY_NEUMANN); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_zero(BDY_DIRICHLET); // Create an Hcurl space. HcurlSpace space(&mesh, &bc_types, &bc_values, P_INIT); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(bilinear_form)); wf.add_vector_form_surf(callback(linear_form_surf)); // Initialize coarse and reference mesh solution. Solution sln, ref_sln; // Initialize refinements selector. HcurlProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. VectorView eview("Electric field", new WinGeom(0, 0, 580, 400)); OrderView oview("Polynomial orders", new WinGeom(590, 0, 550, 400)); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(&space); // Assemble the reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. // If successful, obtain the solution. if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver, HERMES_HCURL_NORM); // Time measurement. cpu_time.tick(); // Show real part of the solution. AbsFilter abs(&sln); eview.set_min_max_range(0, 4e3); eview.show(&abs); oview.show(&space); // Skip visualization time. cpu_time.tick(HERMES_SKIP); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt* adaptivity = new Adapt(&space, HERMES_HCURL_NORM); bool solutions_for_adapt = true; double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_est_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) delete ref_space->get_mesh(); delete ref_space; delete dp; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); // Show the reference solution - the final result. eview.set_title("Fine mesh solution"); eview.show(&ref_sln); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char **args) { // Load the mesh. Mesh mesh; H3DReader mesh_loader; mesh_loader.load("fichera-corner.mesh3d", &mesh); // Perform initial mesh refinement. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(H3D_H3D_H3D_REFT_HEX_XYZ); // Create an H1 space with default shapeset. H1Space space(&mesh, bc_types, essential_bc_values, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); // Initialize weak formulation. WeakForm wf; wf.add_matrix_form(bilinear_form<double, double>, bilinear_form<Ord, Ord>, HERMES_SYM, HERMES_ANY); wf.add_vector_form(linear_form<double, double>, linear_form<Ord, Ord>, HERMES_ANY); // Set exact solution. ExactSolution exact(&mesh, fndd); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est, graph_dof_exact, graph_cpu_exact; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Initialize the solver in the case of SOLVER_PETSC or SOLVER_MUMPS. initialize_solution_environment(matrix_solver, argc, args); // Adaptivity loop. int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(&space,1 , H3D_H3D_H3D_REFT_HEX_XYZ); // Initialize discrete problem. bool is_linear = true; DiscreteProblem dp(&wf, ref_space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the preconditioner in the case of SOLVER_AZTECOO. if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Assemble the reference problem. info("Assembling on reference mesh (ndof: %d).", Space::get_num_dofs(ref_space)); dp.assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system on reference mesh. If successful, obtain the solution. info("Solving on reference mesh."); Solution ref_sln(ref_space->get_mesh()); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Project the reference solution on the coarse mesh. Solution sln(space.get_mesh()); info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Time measurement. cpu_time.tick(); // Output solution and mesh with polynomial orders. if (solution_output) { out_fn_vtk(&sln, "sln", as); out_orders_vtk(&space, "order", as); } // Skip the visualization time. cpu_time.tick(HERMES_SKIP); // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); Adapt *adaptivity = new Adapt(&space, HERMES_H1_NORM); bool solutions_for_adapt = true; double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt) * 100; // Calculate exact error. solutions_for_adapt = false; double err_exact_rel = adaptivity->calc_err_exact(&sln, &exact, solutions_for_adapt) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d.", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space)); info("err_est_rel: %g%%, err_exact_rel: %g%%.", err_est_rel, err_exact_rel); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu_est.save("conv_cpu_est.dat"); graph_dof_exact.add_values(Space::get_num_dofs(&space), err_exact_rel); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel); graph_cpu_exact.save("conv_cpu_exact.dat"); // If err_est_rel is too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); adaptivity->adapt(THRESHOLD); } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete ref_space->get_mesh(); delete ref_space; delete matrix; delete rhs; delete solver; delete adaptivity; // Increase the counter of performed adaptivity steps. as++; } while (!done); // Properly terminate the solver in the case of SOLVER_PETSC or SOLVER_MUMPS. finalize_solution_environment(matrix_solver); return 1; }
int main(int argc, char* argv[]) { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain2.mesh", &mesh); // Perform initial mesh refinements. for (int i=0; i<INIT_REF_NUM; i++) mesh.refine_all_elements(); // Create an H1 space with default shapeset. H1Space space(&mesh, bc_types, essential_bc_values, P_INIT); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(bilinear_form_iron), HERMES_SYM, 3); wf.add_matrix_form(callback(bilinear_form_wire), HERMES_SYM, 2); wf.add_matrix_form(callback(bilinear_form_air), HERMES_SYM, 1); wf.add_vector_form(callback(linear_form_wire), 2); // Initialize coarse and reference mesh solution. Solution sln, ref_sln; // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 600, 350)); sview.show_mesh(false); OrderView oview("Polynomial orders", new WinGeom(610, 0, 520, 350)); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; initialize_solution_environment(matrix_solver, argc, argv); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(&space); // Assemble the reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); 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). } dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. If successful, obtain the solution. if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // View the coarse mesh solution and polynomial orders. sview.show(&sln); oview.show(&space); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt* adaptivity = new Adapt(&space, HERMES_H1_NORM); bool solutions_for_adapt = true; double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_est_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if (done == false) delete ref_space->get_mesh(); delete ref_space; delete dp; // Increase counter. as++; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); finalize_solution_environment(matrix_solver); // Show the reference solution - the final result. sview.set_title("Fine mesh solution"); sview.show(&ref_sln); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("square.mesh", &mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(1, INIT_BDY_REF_NUM); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(BDY_DIRICHLET); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_function(BDY_DIRICHLET, essential_bc_values); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(jac), HERMES_UNSYM, HERMES_ANY); wf.add_vector_form(callback(res), HERMES_ANY); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp_coarse(&wf, &space, is_linear); // Set up the solver, matrix, and rhs for the coarse mesh according to the solver selection. SparseMatrix* matrix_coarse = create_matrix(matrix_solver); Vector* rhs_coarse = create_vector(matrix_solver); Solver* solver_coarse = create_linear_solver(matrix_solver, matrix_coarse, rhs_coarse); // Create a selector which will select optimal candidate. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize coarse and reference mesh solution. Solution sln, ref_sln; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est; // Project the initial condition on the FE space to obtain initial // coefficient vector for the Newton's method. info("Projecting initial condition to obtain initial vector on the coarse mesh."); scalar* coeff_vec_coarse = new scalar[Space::get_num_dofs(&space)] ; Solution* init_sln = new Solution(&mesh, init_cond); OGProjection::project_global(&space, init_sln, coeff_vec_coarse, matrix_solver); delete init_sln; // Newton's loop on the coarse mesh. This is needed to obtain a good // starting point for the Newton's method on the reference mesh. info("Solving on coarse mesh:"); bool verbose = true; if (!solve_newton(coeff_vec_coarse, &dp_coarse, solver_coarse, matrix_coarse, rhs_coarse, NEWTON_TOL_COARSE, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution::vector_to_solution(coeff_vec_coarse, &space, &sln); // Cleanup after the Newton loop on the coarse mesh. delete matrix_coarse; delete rhs_coarse; delete solver_coarse; delete [] coeff_vec_coarse; // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(&space); // Initialize discrete problem on the reference mesh. DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); // Initialize matrix solver. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Calculate initial coefficient vector on the reference mesh. scalar* coeff_vec = new scalar[Space::get_num_dofs(ref_space)]; if (as == 1) { // In the first step, project the coarse mesh solution. info("Projecting coarse mesh solution to obtain initial vector on new fine mesh."); OGProjection::project_global(ref_space, &sln, coeff_vec, matrix_solver); } else { // In all other steps, project the previous fine mesh solution. info("Projecting previous fine mesh solution to obtain initial vector on new fine mesh."); OGProjection::project_global(ref_space, &ref_sln, coeff_vec, matrix_solver); } // Now we can deallocate the previous fine mesh. if(as > 1) delete ref_sln.get_mesh(); // Newton's loop on the fine mesh. info("Solving on fine mesh:"); if (!solve_newton(coeff_vec, dp, solver, matrix, rhs, NEWTON_TOL_FINE, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution ref_sln. Solution::vector_to_solution(coeff_vec, ref_space, &ref_sln); // Project the fine mesh solution on the coarse mesh. if (as > 1) { info("Projecting reference solution on new coarse mesh for error calculation."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); } // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt* adaptivity = new Adapt(&space, HERMES_H1_NORM); bool solutions_for_adapt = true; double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_est_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu_est.save("conv_cpu_est.dat"); // If err_est_rel too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting the coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); if (Space::get_num_dofs(&space) >= NDOF_STOP) { done = true; break; } // Project last fine mesh solution on the new coarse mesh // to obtain new coars emesh solution. info("Projecting reference solution on new coarse mesh for error calculation."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); } // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; delete ref_space; delete dp; delete [] coeff_vec; as++; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); int ndof = Space::get_num_dofs(&space); printf("ndof allowed = %d\n", 400); printf("ndof actual = %d\n", ndof); if (ndof < 400) { // ndofs was 389 at the time this test was created. printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh u_mesh, v_mesh; H2DReader mloader; mloader.load("bracket.mesh", &u_mesh); // Initial mesh refinements. u_mesh.refine_element_id(1); u_mesh.refine_element_id(4); // Create initial mesh for the vertical displacement component. // This also initializes the multimesh hp-FEM. v_mesh.copy(&u_mesh); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(BDY_LEFT); bc_types.add_bc_neumann(Hermes::vector<int>(BDY_TOP, BDY_REST)); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_zero(BDY_LEFT); // Create H1 spaces with default shapesets. H1Space u_space(&u_mesh, &bc_types, &bc_values, P_INIT); H1Space v_space(MULTI ? &v_mesh : &u_mesh, &bc_types, &bc_values, P_INIT); // Initialize the weak formulation. WeakForm wf(2); wf.add_matrix_form(0, 0, callback(bilinear_form_0_0), HERMES_SYM); // note that only one symmetric part is wf.add_matrix_form(0, 1, callback(bilinear_form_0_1), HERMES_SYM); // added in the case of symmetric bilinear wf.add_matrix_form(1, 1, callback(bilinear_form_1_1), HERMES_SYM); // forms wf.add_vector_form_surf(1, linear_form_surf_1, linear_form_surf_1_ord, BDY_TOP); // Initialize coarse and reference mesh solutions. Solution u_sln, v_sln, u_ref_sln, v_ref_sln; // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est; // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Hermes::vector<Space *>* ref_spaces = construct_refined_spaces(Hermes::vector<Space *>(&u_space, &v_space)); // Assemble the reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, *ref_spaces, is_linear); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. If successful, obtain the solutions. if(solver->solve()) Solution::vector_to_solutions(solver->get_solution(), *ref_spaces, Hermes::vector<Solution *>(&u_ref_sln, &v_ref_sln)); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(Hermes::vector<Space *>(&u_space, &v_space), Hermes::vector<Solution *>(&u_ref_sln, &v_ref_sln), Hermes::vector<Solution *>(&u_sln, &v_sln), matrix_solver); // Calculate element errors. info("Calculating error estimate and exact error."); Adapt* adaptivity = new Adapt(Hermes::vector<Space *>(&u_space, &v_space)); adaptivity->set_error_form(0, 0, bilinear_form_0_0<scalar, scalar>, bilinear_form_0_0<Ord, Ord>); adaptivity->set_error_form(0, 1, bilinear_form_0_1<scalar, scalar>, bilinear_form_0_1<Ord, Ord>); adaptivity->set_error_form(1, 0, bilinear_form_1_0<scalar, scalar>, bilinear_form_1_0<Ord, Ord>); adaptivity->set_error_form(1, 1, bilinear_form_1_1<scalar, scalar>, bilinear_form_1_1<Ord, Ord>); // Calculate error estimate for each solution component and the total error estimate. Hermes::vector<double> err_est_rel; double err_est_rel_total = adaptivity->calc_err_est(Hermes::vector<Solution *>(&u_sln, &v_sln), Hermes::vector<Solution *>(&u_ref_sln, &v_ref_sln), &err_est_rel) * 100; // Time measurement. cpu_time.tick(); // Report results. info("ndof_coarse[0]: %d, ndof_fine[0]: %d, err_est_rel[0]: %g%%", u_space.Space::get_num_dofs(), (*ref_spaces)[0]->Space::get_num_dofs(), err_est_rel[0]*100); info("ndof_coarse[1]: %d, ndof_fine[1]: %d, err_est_rel[1]: %g%%", v_space.Space::get_num_dofs(), (*ref_spaces)[1]->Space::get_num_dofs(), err_est_rel[1]*100); info("ndof_coarse_total: %d, ndof_fine_total: %d, err_est_rel_total: %g%%", Space::get_num_dofs(Hermes::vector<Space *>(&u_space, &v_space)), Space::get_num_dofs(*ref_spaces), err_est_rel_total); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space::get_num_dofs(Hermes::vector<Space *>(&u_space, &v_space)), err_est_rel_total); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel_total); graph_cpu_est.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(Hermes::vector<RefinementSelectors::Selector *>(&selector, &selector), THRESHOLD, STRATEGY, MESH_REGULARITY); } if (Space::get_num_dofs(Hermes::vector<Space *>(&u_space, &v_space)) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) for(unsigned int i = 0; i < ref_spaces->size(); i++) delete (*ref_spaces)[i]->get_mesh(); delete ref_spaces; delete dp; // Increase counter. as++; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); int ndof = Space::get_num_dofs(Hermes::vector<Space *>(&u_space, &v_space)); int ndof_allowed = 1450; printf("ndof actual = %d\n", ndof); printf("ndof allowed = %d\n", ndof_allowed); if (ndof <= ndof_allowed) { // ndofs was 1414 at the time this test was created printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { if (NUMBER_OF_EIGENVALUES > 6) error("Maximum number of eigenvalues is 6."); info("Desired number of eigenvalues: %d.", NUMBER_OF_EIGENVALUES); // 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 boundary conditions. DefaultEssentialBCConst bc_essential(Hermes::vector<std::string>(BDY_BOTTOM, BDY_RIGHT, BDY_TOP, BDY_LEFT), 0.0); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); // Initialize the weak formulation. WeakFormEigenLeft wf_left; WeakFormEigenRight wf_right; // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView sview_1("", new WinGeom(0, 0, 400, 360)); sview_1.show_mesh(false); sview_1.fix_scale_width(60); ScalarView sview_2("", new WinGeom(405, 0, 400, 360)); sview_2.show_mesh(false); sview_2.fix_scale_width(60); ScalarView sview_3("", new WinGeom(810, 0, 400, 360)); sview_3.show_mesh(false); sview_3.fix_scale_width(60); ScalarView sview_4("", new WinGeom(0, 410, 400, 360)); sview_4.show_mesh(false); sview_4.fix_scale_width(60); ScalarView sview_5("", new WinGeom(405, 410, 400, 360)); sview_5.show_mesh(false); sview_5.fix_scale_width(60); ScalarView sview_6("", new WinGeom(810, 410, 400, 360)); sview_6.show_mesh(false); sview_6.fix_scale_width(60); OrderView oview("Polynomial orders", new WinGeom(1215, 0, 400, 360)); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); Solution sln[NUMBER_OF_EIGENVALUES], ref_sln[NUMBER_OF_EIGENVALUES]; // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); info("Solving on reference mesh."); // Construct globally refined reference mesh and setup reference space. Space* ref_space = Space::construct_refined_space(&space); int ref_ndof = Space::get_num_dofs(ref_space); info("ref_ndof: %d.", ref_ndof); // Initialize matrices and matrix solver on referenc emesh. RCP<SparseMatrix> matrix_left = rcp(new CSCMatrix()); RCP<SparseMatrix> matrix_right = rcp(new CSCMatrix()); Solver* solver = create_linear_solver(matrix_solver, matrix_left.get()); // Assemble the matrices on reference mesh. DiscreteProblem* dp_left = new DiscreteProblem(&wf_left, ref_space); dp_left->assemble(matrix_left.get()); DiscreteProblem* dp_right = new DiscreteProblem(&wf_right, ref_space); dp_right->assemble(matrix_right.get()); // Time measurement. cpu_time.tick(); // Time measurement. cpu_time.tick(HERMES_SKIP); EigenSolver es(matrix_left, matrix_right); info("Calling Pysparse..."); es.solve(NUMBER_OF_EIGENVALUES, TARGET_VALUE, TOL, MAX_ITER); info("Pysparse finished."); es.print_eigenvalues(); // Initializing solution vector, solution and ScalarView. double* ref_coeff_vec; //Solution sln[NUMBER_OF_EIGENVALUES], ref_sln[NUMBER_OF_EIGENVALUES]; //ScalarView view("Solution", new WinGeom(0, 0, 440, 350)); // Reading solution vectors from file and visualizing. double eigenval[NUMBER_OF_EIGENVALUES]; int neig = es.get_n_eigs(); if (neig != NUMBER_OF_EIGENVALUES) error("Mismatched number of eigenvectors in the eigensolver output file."); for (int ieig = 0; ieig < NUMBER_OF_EIGENVALUES; ieig++) { eigenval[ieig] = es.get_eigenvalue(ieig); int n; es.get_eigenvector(ieig, &ref_coeff_vec, &n); // Convert coefficient vector into a Solution. Solution::vector_to_solution(ref_coeff_vec, ref_space, &(ref_sln[ieig])); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution %d on coarse mesh.", ieig); OGProjection::project_global(&space, &(ref_sln[ieig]), &(sln[ieig]), matrix_solver); } // FIXME: Below, the adaptivity is done for the last eigenvector only, // this needs to be changed to take into account all eigenvectors. // View the coarse mesh solution and polynomial orders. //char title[100]; //if (NUMBER_OF_EIGENVALUES > 0) { // sprintf(title, "Solution 0, val = %g", eigenval[0]); // sview_1.set_title(title); // sview_1.show(&(sln[0])); //} //if (NUMBER_OF_EIGENVALUES > 1) { // sprintf(title, "Solution 1, val = %g", eigenval[1]); // sview_2.set_title(title); // sview_2.show(&(sln[1])); //} //if (NUMBER_OF_EIGENVALUES > 2) { // sprintf(title, "Solution 2, val = %g", eigenval[2]); // sview_3.set_title(title); // sview_3.show(&(sln[2])); //} //if (NUMBER_OF_EIGENVALUES > 3) { // sprintf(title, "Solution 3, val = %g", eigenval[3]); // sview_4.set_title(title); // sview_4.show(&(sln[3])); //} //if (NUMBER_OF_EIGENVALUES > 4) { // sprintf(title, "Solution 4, val = %g", eigenval[4]); // sview_5.set_title(title); // sview_5.show(&(sln[4])); //} //if (NUMBER_OF_EIGENVALUES > 5) { // sprintf(title, "Solution 5, val = %g", eigenval[5]); // sview_6.set_title(title); // sview_6.show(&(sln[5])); //} //oview.show(&space); // Calculate element errors and total error estimate. info("Calculating error estimate."); Hermes::vector<Space *> spaces; for(int i = 0; i < NUMBER_OF_EIGENVALUES; i++) spaces.push_back(&space); Adapt* adaptivity = new Adapt(spaces); Hermes::vector<Solution *> slns; if (NUMBER_OF_EIGENVALUES > 0) slns.push_back(&sln[0]); if (NUMBER_OF_EIGENVALUES > 1) slns.push_back(&sln[1]); if (NUMBER_OF_EIGENVALUES > 2) slns.push_back(&sln[2]); if (NUMBER_OF_EIGENVALUES > 3) slns.push_back(&sln[3]); if (NUMBER_OF_EIGENVALUES > 4) slns.push_back(&sln[4]); if (NUMBER_OF_EIGENVALUES > 5) slns.push_back(&sln[5]); Hermes::vector<Solution *> ref_slns; if (NUMBER_OF_EIGENVALUES > 0) ref_slns.push_back(&ref_sln[0]); if (NUMBER_OF_EIGENVALUES > 1) ref_slns.push_back(&ref_sln[1]); if (NUMBER_OF_EIGENVALUES > 2) ref_slns.push_back(&ref_sln[2]); if (NUMBER_OF_EIGENVALUES > 3) ref_slns.push_back(&ref_sln[3]); if (NUMBER_OF_EIGENVALUES > 4) ref_slns.push_back(&ref_sln[4]); if (NUMBER_OF_EIGENVALUES > 5) ref_slns.push_back(&ref_sln[5]); Hermes::vector<double> component_errors; double err_est_rel = adaptivity->calc_err_est(slns, ref_slns, &component_errors) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d.", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space)); if (NUMBER_OF_EIGENVALUES > 0) info("err_est_rel[0]: %g%%", component_errors[0] * 100); if (NUMBER_OF_EIGENVALUES > 1) info("err_est_rel[1]: %g%%", component_errors[1] * 100); if (NUMBER_OF_EIGENVALUES > 2) info("err_est_rel[2]: %g%%", component_errors[2] * 100); if (NUMBER_OF_EIGENVALUES > 3) info("err_est_rel[3]: %g%%", component_errors[3] * 100); if (NUMBER_OF_EIGENVALUES > 4) info("err_est_rel[4]: %g%%", component_errors[4] * 100); if (NUMBER_OF_EIGENVALUES > 5) info("err_est_rel[5]: %g%%", component_errors[5] * 100); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu_est.save("conv_cpu_est.dat"); // Wait for keypress. //View::wait(HERMES_WAIT_KEYPRESS); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); Hermes::vector<RefinementSelectors::Selector *> selectors; for(int i = 0; i < NUMBER_OF_EIGENVALUES; i++) selectors.push_back(&selector); done = adaptivity->adapt(selectors, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete solver; delete adaptivity; if(done == false) delete ref_space->get_mesh(); delete ref_space; delete dp_left; delete dp_right; } while (done == false); int ndof = Space::get_num_dofs(&space); if (ndof < 450) { // Was 401 when this test was created. 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; // Define nonlinear thermal conductivity lambda(u) via a cubic spline. // Step 1: Fill the x values and use lambda(u) = 1 + u^4 for the y values. #define lambda(x) (1 + pow(x, 4)) Hermes::vector<double> lambda_pts(-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0); Hermes::vector<double> lambda_val; for (unsigned int i = 0; i < lambda_pts.size(); i++) lambda_val.push_back(lambda(lambda_pts[i])); // Step 2: 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 = true; bool extrapolate_der_right = true; CubicSpline spline_coeff(lambda_pts, lambda_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."); double interval_extension = 3.0; // The interval of definition of the spline will be // extended by "interval_extension" on both sides. spline_coeff.plot("spline.dat", interval_extension); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("../square.mesh", &mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary("Bdy", INIT_BDY_REF_NUM); // Initialize boundary conditions. CustomEssentialBCNonConst bc_essential("Bdy"); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); // Initialize the weak formulation DefaultFunction heat_src(HEAT_SRC); double const_coeff = 1.0; DefaultWeakFormPoisson wf(&heat_src, HERMES_ANY, const_coeff, &spline_coeff); // Initialize the FE problem. DiscreteProblem dp_coarse(&wf, &space); // Set up the solver, matrix, and rhs for the coarse mesh according to the solver selection. SparseMatrix* matrix_coarse = create_matrix(matrix_solver); Vector* rhs_coarse = create_vector(matrix_solver); Solver* solver_coarse = create_linear_solver(matrix_solver, matrix_coarse, rhs_coarse); // Create a selector which will select optimal candidate. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize coarse and reference mesh solution. Solution sln, ref_sln; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est; // Project the initial condition on the FE space to obtain initial // coefficient vector for the Newton's method. info("Projecting initial condition to obtain initial vector on the coarse mesh."); scalar* coeff_vec_coarse = new scalar[Space::get_num_dofs(&space)] ; InitialSolutionHeatTransfer init_sln(&mesh); OGProjection::project_global(&space, &init_sln, coeff_vec_coarse, matrix_solver); // Newton's loop on the coarse mesh. This is needed to obtain a good // starting point for the Newton's method on the reference mesh. info("Solving on coarse mesh:"); bool verbose = true; bool jacobian_changed = true; if (!hermes2d.solve_newton(coeff_vec_coarse, &dp_coarse, solver_coarse, matrix_coarse, rhs_coarse, jacobian_changed, NEWTON_TOL_COARSE, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution::vector_to_solution(coeff_vec_coarse, &space, &sln); // Cleanup after the Newton loop on the coarse mesh. delete matrix_coarse; delete rhs_coarse; delete solver_coarse; delete [] coeff_vec_coarse; // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = Space::construct_refined_space(&space); // Initialize discrete problem on the reference mesh. DiscreteProblem dp(&wf, ref_space); // Initialize matrix solver. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Calculate initial coefficient vector on the reference mesh. scalar* coeff_vec = new scalar[Space::get_num_dofs(ref_space)]; if (as == 1) { // In the first step, project the coarse mesh solution. info("Projecting coarse mesh solution to obtain initial vector on new fine mesh."); OGProjection::project_global(ref_space, &sln, coeff_vec, matrix_solver); } else { // In all other steps, project the previous fine mesh solution. info("Projecting previous fine mesh solution to obtain initial vector on new fine mesh."); OGProjection::project_global(ref_space, &ref_sln, coeff_vec, matrix_solver); } // Now we can deallocate the previous fine mesh. if(as > 1) delete ref_sln.get_mesh(); // Newton's loop on the fine mesh. info("Solving on fine mesh:"); if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs, jacobian_changed, NEWTON_TOL_FINE, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution ref_sln. Solution::vector_to_solution(coeff_vec, ref_space, &ref_sln); // Project the fine mesh solution on the coarse mesh. if (as > 1) { info("Projecting reference solution on new coarse mesh for error calculation."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); } // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt* adaptivity = new Adapt(&space); double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_est_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu_est.save("conv_cpu_est.dat"); // If err_est_rel too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting the coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); if (Space::get_num_dofs(&space) >= NDOF_STOP) { done = true; break; } } // Clean up. delete [] coeff_vec; delete solver; delete matrix; delete rhs; delete adaptivity; delete ref_space; as++; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); int ndof = Space::get_num_dofs(&space); printf("ndof allowed = %d\n", 400); printf("ndof actual = %d\n", ndof); if (ndof < 400) { // ndofs was 389 at the time this test was created. printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Load the mesh. MeshSharedPtr mesh(new Mesh); MeshReaderH2D mloader; mloader.load("domain.mesh", mesh); // Define exact solution. MeshFunctionSharedPtr<double> exact_sln(new CustomExactSolution(mesh)); // Initialize the weak formulation. CustomWeakForm wf("Right"); // Initialize boundary conditions. DefaultEssentialBCConst<double> bc_essential("Left", 0.0); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT)); // Set the space to adaptivity. adaptivity.set_space(space); // Initialize approximate solution. MeshFunctionSharedPtr<double> sln(new Solution<double>()); // Initialize refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST); // Initialize views. Views::ScalarView sview("Solution", new Views::WinGeom(0, 0, 440, 350)); sview.show_mesh(false); sview.fix_scale_width(50); Views::OrderView oview("Polynomial orders", new Views::WinGeom(450, 0, 420, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est, graph_dof_exact, graph_cpu_exact; // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { cpu_time.tick(); // Construct globally refined reference mesh and setup reference space. Mesh::ReferenceMeshCreator refMeshCreator(mesh); MeshSharedPtr ref_mesh = refMeshCreator.create_ref_mesh(); Space<double>::ReferenceSpaceCreator refSpaceCreator(space, ref_mesh); SpaceSharedPtr<double> ref_space = refSpaceCreator.create_ref_space(); int ndof_ref = ref_space->get_num_dofs(); Hermes::Mixins::Loggable::Static::info("---- Adaptivity step %d (%d DOF):", as, ndof_ref); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Solving on reference mesh."); // Assemble the discrete problem. DiscreteProblem<double> dp(&wf, ref_space); NewtonSolver<double> newton(&dp); //newton.set_verbose_output(false); MeshFunctionSharedPtr<double> ref_sln(new Solution<double>()); try { newton.solve(); } catch(Hermes::Exceptions::Exception e) { e.print_msg(); throw Hermes::Exceptions::Exception("Newton's iteration failed."); }; // Translate the resulting coefficient vector into the instance of Solution. Solution<double>::vector_to_solution(newton.get_sln_vector(), ref_space, ref_sln); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Solution: %g s", cpu_time.last()); // Project the fine mesh solution onto the coarse mesh. Hermes::Mixins::Loggable::Static::info("Calculating error estimate and exact error."); OGProjection<double> ogProjection; ogProjection.project_global(space, ref_sln, sln); // Calculate element errors and total error estimate. errorCalculator.calculate_errors(sln, exact_sln, false); double err_exact_rel = errorCalculator.get_total_error_squared() * 100; errorCalculator.calculate_errors(sln, ref_sln, true); double err_est_rel = errorCalculator.get_total_error_squared() * 100; cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Error calculation: %g s", cpu_time.last()); // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_fine: %d", space->get_num_dofs(), ref_space->get_num_dofs()); Hermes::Mixins::Loggable::Static::info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel); // Time measurement. cpu_time.tick(); double accum_time = cpu_time.accumulated(); // View the coarse mesh solution and polynomial orders. sview.show(sln); oview.show(space); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(space->get_num_dofs(), err_est_rel); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(accum_time, err_est_rel); graph_cpu_est.save("conv_cpu_est.dat"); graph_dof_exact.add_values(space->get_num_dofs(), err_exact_rel); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(accum_time, err_exact_rel); graph_cpu_exact.save("conv_cpu_exact.dat"); cpu_time.tick(Hermes::Mixins::TimeMeasurable::HERMES_SKIP); // If err_est too large, adapt the mesh. The NDOF test must be here, so that the solution may be visualized // after ending due to this criterion. if (err_exact_rel < ERR_STOP) done = true; else done = adaptivity.adapt(&selector); cpu_time.tick(); Hermes::Mixins::Loggable::Static::info("Adaptation: %g s", cpu_time.last()); // Increase the counter of adaptivity steps. if (done == false) as++; } while (done == false); Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. Views::View::wait(); }
int main(int argc, char **args) { // Test variable. int success_test = 1; // Check the number of command-line parameters. if (argc < 2) { info("Use x, y, z, xy, xz, yz, or xyz as a command-line parameter."); error("Not enough command-line parameters."); } // Determine anisotropy type from the command-line parameter. ANISO_TYPE = parse_aniso_type(args[1]); // Load the mesh. Mesh mesh; H3DReader mesh_loader; mesh_loader.load("hex-0-1.mesh3d", &mesh); // Assign the lowest possible directional polynomial degrees so that the problem's NDOF >= 1. assign_poly_degrees(); // Create an H1 space with default shapeset. info("Setting directional polynomial degrees %d, %d, %d.", P_INIT_X, P_INIT_Y, P_INIT_Z); H1Space space(&mesh, bc_types, essential_bc_values, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); // Initialize weak formulation. WeakForm wf; wf.add_matrix_form(bilinear_form<double, scalar>, bilinear_form<Ord, Ord>, HERMES_SYM, HERMES_ANY); wf.add_vector_form(linear_form<double, scalar>, linear_form<Ord, Ord>, HERMES_ANY); // Set exact solution. ExactSolution exact(&mesh, fndd); // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Adaptivity loop. int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(&space, 1); // Initialize discrete problem. bool is_linear = true; DiscreteProblem dp(&wf, ref_space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the preconditioner in the case of SOLVER_AZTECOO. if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Assemble the reference problem. info("Assembling on reference mesh (ndof: %d).", Space::get_num_dofs(ref_space)); dp.assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system on reference mesh. If successful, obtain the solution. info("Solving on reference mesh."); Solution ref_sln(ref_space->get_mesh()); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else { error ("Matrix solver failed.\n"); success_test = 0; } // Time measurement. cpu_time.tick(); // Project the reference solution on the coarse mesh. Solution sln(space.get_mesh()); info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Time measurement. cpu_time.tick(); // Output solution and mesh with polynomial orders. if (solution_output) { out_fn_vtk(&sln, "sln", as); out_orders_vtk(&space, "order", as); } // Skip the visualization time. cpu_time.tick(HERMES_SKIP); // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); Adapt *adaptivity = new Adapt(&space, HERMES_H1_NORM); bool solutions_for_adapt = true; double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt) * 100; // Calculate exact error. solutions_for_adapt = false; double err_exact_rel = adaptivity->calc_err_exact(&sln, &exact, solutions_for_adapt) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d.", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space)); info("err_est_rel: %g%%, err_exact_rel: %g%%.", err_est_rel, err_exact_rel); // If err_est_rel is too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); adaptivity->adapt(THRESHOLD); } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete ref_space->get_mesh(); delete ref_space; delete matrix; delete rhs; delete solver; delete adaptivity; // Increase the counter of performed adaptivity steps. as++; } while (!done); // This is the actual test. #define ERROR_SUCCESS 0 #define ERROR_FAILURE -1 int ndof_allowed; switch (ANISO_TYPE) { case ANISO_X: ndof_allowed = 28; break; case ANISO_Y: ndof_allowed = 28; break; case ANISO_Z: ndof_allowed = 28; break; case ANISO_X | ANISO_Y: ndof_allowed = 98; break; case ANISO_X | ANISO_Z: ndof_allowed = 98; break; case ANISO_Y | ANISO_Z: ndof_allowed = 98; break; case ANISO_X | ANISO_Y | ANISO_Z: ndof_allowed = 343; break; default: error("Admissible command-line options are x, y, x, xy, xz, yz, xyz."); } int ndof = Space::get_num_dofs(&space); info("ndof_actual = %d", ndof); info("ndof_allowed = %d", ndof_allowed); if (ndof > ndof_allowed) success_test = 0; if (success_test) { info("Success!"); return ERR_SUCCESS; } else { info("Failure!"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(BDY_BOTTOM); bc_types.add_bc_neumann(Hermes::Tuple<int>(BDY_RIGHT, BDY_TOP, BDY_LEFT)); // Enter Dirichlet boudnary values. BCValues bc_values; bc_values.add_zero(BDY_BOTTOM); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(bilinear_form), HERMES_SYM); wf.add_vector_form(callback(linear_form)); wf.add_vector_form_surf(callback(linear_form_surf), BDY_TOP); // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Set exact solution. ExactSolution exact(&mesh, fndd); // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); sview.show_mesh(false); OrderView oview("Polynomial orders", new WinGeom(450, 0, 400, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof, graph_cpu, graph_dof_exact, graph_cpu_exact; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(&space); // Assemble the reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. If successful, obtain the solution. Solution ref_sln; if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Project the fine mesh solution onto the coarse mesh. Solution sln; info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // View the coarse mesh solution and polynomial orders. sview.show(&sln); oview.show(&space); // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); Adapt* adaptivity = new Adapt(&space, HERMES_H1_NORM); bool solutions_for_adapt = true; double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100; // Calculate exact error. solutions_for_adapt = false; double err_exact_rel = adaptivity->calc_err_exact(&sln, &exact, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space)); info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); graph_dof_exact.add_values(Space::get_num_dofs(&space), err_exact_rel); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel); graph_cpu_exact.save("conv_cpu_exact.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) delete ref_space->get_mesh(); delete ref_space; delete dp; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. View::wait(); }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("motor.mesh", &mesh); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(Hermes::Tuple<int>(OUTER_BDY, STATOR_BDY)); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_const(STATOR_BDY, VOLTAGE); bc_values.add_const(OUTER_BDY, 0.0); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(biform1), HERMES_SYM, MATERIAL_1); wf.add_matrix_form(callback(biform2), HERMES_SYM, MATERIAL_2); // Initialize coarse and reference mesh solution. Solution sln, ref_sln; // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 410, 600)); sview.fix_scale_width(50); sview.show_mesh(false); OrderView oview("Polynomial orders", new WinGeom(420, 0, 400, 600)); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(&space); // Initialize matrix solver. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Assemble reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. // If successful, obtain the solution. if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Time measurement. cpu_time.tick(); // View the coarse mesh solution and polynomial orders. sview.show(&sln); oview.show(&space); // Skip visualization time. cpu_time.tick(HERMES_SKIP); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt* adaptivity = new Adapt(&space); bool solutions_for_adapt = true; // In the following function, the Boolean parameter "solutions_for_adapt" determines whether // the calculated errors are intended for use with adaptivity (this may not be the case, for example, // when error wrt. an exact solution is calculated). The default value is solutions_for_adapt = true, // The last parameter "error_flags" determine whether the total and element errors are treated as // absolute or relative. Its default value is error_flags = HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL. // In subsequent examples and benchmarks, these two parameters will be often used with // their default values, and thus they will not be present in the code explicitly. double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_est_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) delete ref_space->get_mesh(); delete ref_space; delete dp; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); // Show the reference solution - the final result. sview.set_title("Fine mesh solution"); sview.show_mesh(false); sview.show(&ref_sln); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load("channel.mesh", &mesh); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(0, true); // Initialize boundary condition types and spaces with default shapesets. L2Space<double> space_rho(&mesh, P_INIT); L2Space<double> space_rho_v_x(&mesh, P_INIT); L2Space<double> space_rho_v_y(&mesh, P_INIT); L2Space<double> space_e(&mesh, P_INIT); // Initialize solutions, set initial conditions. ConstantSolution<double> sln_rho(&mesh, RHO_INIT); ConstantSolution<double> sln_rho_v_x(&mesh, RHO_INIT * V1_INIT); ConstantSolution<double> sln_rho_v_y(&mesh, RHO_INIT * V2_INIT); ConstantSolution<double> sln_e(&mesh, QuantityCalculator::calc_energy(RHO_INIT, RHO_INIT * V1_INIT, RHO_INIT * V2_INIT, PRESSURE_INIT, KAPPA)); ConstantSolution<double> prev_rho(&mesh, RHO_INIT); ConstantSolution<double> prev_rho_v_x(&mesh, RHO_INIT * V1_INIT); ConstantSolution<double> prev_rho_v_y(&mesh, RHO_INIT * V2_INIT); ConstantSolution<double> prev_e(&mesh, QuantityCalculator::calc_energy(RHO_INIT, RHO_INIT * V1_INIT, RHO_INIT * V2_INIT, PRESSURE_INIT, KAPPA)); Solution<double> rsln_rho, rsln_rho_v_x, rsln_rho_v_y, rsln_e; // Numerical flux. OsherSolomonNumericalFlux num_flux(KAPPA); // For saving to the disk. Continuity<double> continuity(Continuity<double>::onlyNumber); // Initialize weak formulation. EulerEquationsWeakFormSemiImplicitMultiComponentTwoInflows wf(&num_flux, KAPPA, RHO_LEFT, V1_LEFT, V2_LEFT, PRESSURE_LEFT, RHO_TOP, V1_TOP, V2_TOP, PRESSURE_TOP, BDY_SOLID_WALL, BDY_INLET_LEFT, BDY_INLET_TOP, BDY_OUTLET, &prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e); // Filters for visualization of Mach number, pressure and entropy. MachNumberFilter Mach_number(Hermes::vector<MeshFunction<double>*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), KAPPA); PressureFilter pressure(Hermes::vector<MeshFunction<double>*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), KAPPA); EntropyFilter entropy(Hermes::vector<MeshFunction<double>*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), KAPPA, RHO_INIT, P_INIT); ScalarView pressure_view("Pressure", new WinGeom(0, 0, 600, 300)); ScalarView Mach_number_view("Mach number", new WinGeom(700, 0, 600, 300)); ScalarView entropy_production_view("Entropy estimate", new WinGeom(0, 400, 600, 300)); // Initialize refinement selector. L2ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, MAX_P_ORDER); selector.set_error_weights(1.0, 1.0, 1.0); // Set up CFL calculation class. CFLCalculation CFL(CFL_NUMBER, KAPPA); // Time stepping loop. int iteration = 0; double t = 0; for(; t < 4.0; t += time_step) { info("---- Time step %d, time %3.5f.", iteration++, t); // Periodic global derefinements. if (iteration > 1 && iteration % UNREF_FREQ == 0 && REFINEMENT_COUNT > 0) { info("Global mesh derefinement."); REFINEMENT_COUNT = 0; space_rho.unrefine_all_mesh_elements(true); space_rho.adjust_element_order(-1, P_INIT); space_rho_v_x.copy_orders(&space_rho); space_rho_v_y.copy_orders(&space_rho); space_e.copy_orders(&space_rho); } // Adaptivity loop: int as = 1; int ndofs_prev = 0; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. int order_increase = 1; Hermes::vector<Space<double> *>* ref_spaces = Space<double>::construct_refined_spaces(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), order_increase); if(ndofs_prev != 0) if(Space<double>::get_num_dofs(*ref_spaces) == ndofs_prev) selector.set_error_weights(2.0 * selector.get_error_weight_h(), 1.0, 1.0); else selector.set_error_weights(1.0, 1.0, 1.0); ndofs_prev = Space<double>::get_num_dofs(*ref_spaces); // Project the previous time level solution onto the new fine mesh. info("Projecting the previous time level solution onto the new fine mesh."); OGProjection<double>::project_global(*ref_spaces, Hermes::vector<Solution<double>*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), Hermes::vector<Solution<double>*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), matrix_solver_type, Hermes::vector<Hermes::Hermes2D::ProjNormType>(), iteration > 1); // Report NDOFs. info("ndof_coarse: %d, ndof_fine: %d.", Space<double>::get_num_dofs(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e)), Space<double>::get_num_dofs(*ref_spaces)); // Assemble the reference problem. info("Solving on reference mesh."); DiscreteProblem<double> dp(&wf, *ref_spaces); SparseMatrix<double>* matrix = create_matrix<double>(matrix_solver_type); Vector<double>* rhs = create_vector<double>(matrix_solver_type); LinearSolver<double>* solver = create_linear_solver<double>(matrix_solver_type, matrix, rhs); wf.set_time_step(time_step); dp.assemble(matrix, rhs); // Solve the matrix problem. info("Solving the matrix problem."); if(solver->solve()) if(!SHOCK_CAPTURING) Solution<double>::vector_to_solutions(solver->get_sln_vector(), *ref_spaces, Hermes::vector<Solution<double>*>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e)); else { FluxLimiter flux_limiter(FluxLimiter::Kuzmin, solver->get_sln_vector(), *ref_spaces, true); flux_limiter.limit_second_orders_according_to_detector(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e)); flux_limiter.limit_according_to_detector(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e)); flux_limiter.get_limited_solutions(Hermes::vector<Solution<double>*>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e)); } else error ("Matrix solver failed.\n"); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection<double>::project_global(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), Hermes::vector<Solution<double>*>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e), Hermes::vector<Solution<double>*>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e), matrix_solver_type, Hermes::vector<ProjNormType>(HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM)); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt<double>* adaptivity = new Adapt<double>(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), Hermes::vector<ProjNormType>(HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM)); double err_est_rel_total = adaptivity->calc_err_est(Hermes::vector<Solution<double>*>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e), Hermes::vector<Solution<double>*>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e)) * 100; CFL.calculate_semi_implicit(Hermes::vector<Solution<double> *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e), (*ref_spaces)[0]->get_mesh(), time_step); // Report results. info("err_est_rel: %g%%", err_est_rel_total); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(Hermes::vector<RefinementSelectors::Selector<double> *>(&selector, &selector, &selector, &selector), THRESHOLD, STRATEGY, MESH_REGULARITY); REFINEMENT_COUNT++; if (Space<double>::get_num_dofs(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e)) >= NDOF_STOP) done = true; else as++; } // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(!done) for(unsigned int i = 0; i < ref_spaces->size(); i++) delete (*ref_spaces)[i]; } while (done == false); // Copy the solutions into the previous time level ones. prev_rho.copy(&rsln_rho); prev_rho_v_x.copy(&rsln_rho_v_x); prev_rho_v_y.copy(&rsln_rho_v_y); prev_e.copy(&rsln_e); delete rsln_rho.get_mesh(); rsln_rho.own_mesh = false; delete rsln_rho_v_x.get_mesh(); rsln_rho_v_x.own_mesh = false; delete rsln_rho_v_y.get_mesh(); rsln_rho_v_y.own_mesh = false; delete rsln_e.get_mesh(); rsln_e.own_mesh = false; // Visualization and saving on disk. if((iteration - 1) % EVERY_NTH_STEP == 0) { continuity.add_record((unsigned int)(iteration - 1)); continuity.get_last_record()->save_mesh(prev_rho.get_mesh()); continuity.get_last_record()->save_space(prev_rho.get_space()); continuity.get_last_record()->save_time_step_length(time_step); // Hermes visualization. if(HERMES_VISUALIZATION) { Mach_number.reinit(); pressure.reinit(); entropy.reinit(); pressure_view.show(&pressure, 1); entropy_production_view.show(&entropy, 1); Mach_number_view.show(&Mach_number, 1); pressure_view.save_numbered_screenshot("pressure %i.bmp", iteration); Mach_number_view.save_numbered_screenshot("Mach no %i.bmp", iteration); } // Output solution in VTK format. if(VTK_VISUALIZATION) { pressure.reinit(); Mach_number.reinit(); entropy.reinit(); Linearizer lin; char filename[40]; sprintf(filename, "Pressure-%i.vtk", iteration - 1); lin.save_solution_vtk(&pressure, filename, "Pressure", false); sprintf(filename, "Mach number-%i.vtk", iteration - 1); lin.save_solution_vtk(&Mach_number, filename, "MachNumber", false); if((iteration - 1) % (EVERY_NTH_STEP * EVERY_NTH_STEP) == 0) { sprintf(filename, "Entropy-%i.vtk", iteration - 1); lin.save_solution_vtk(&entropy, filename, "Entropy", false); } } } } pressure_view.close(); entropy_production_view.close(); Mach_number_view.close(); return 0; }
int main(int argc, char* argv[]) { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh u1_mesh, u2_mesh; MeshReaderH2D mloader; mloader.load("bracket.mesh", &u1_mesh); // Initial mesh refinements. u1_mesh.refine_element_id(1); u1_mesh.refine_element_id(4); // Create initial mesh for the vertical displacement component. // This also initializes the multimesh hp-FEM. u2_mesh.copy(&u1_mesh); // Initialize boundary conditions. DefaultEssentialBCConst<double> zero_disp(BDY_RIGHT, 0.0); EssentialBCs<double> bcs(&zero_disp); // Create x- and y- displacement space using the default H1 shapeset. H1Space<double> u1_space(&u1_mesh, &bcs, P_INIT); H1Space<double> u2_space(&u2_mesh, &bcs, P_INIT); info("ndof = %d.", Space<double>::get_num_dofs(Hermes::vector<Space<double> *>(&u1_space, &u2_space))); // Initialize the weak formulation. // NOTE; These weak forms are identical to those in example P01-linear/08-system. CustomWeakForm wf(E, nu, rho*g1, BDY_TOP, f0, f1); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, Hermes::vector<Space<double> *>(&u1_space, &u2_space)); // Initialize coarse and reference mesh solutions. Solution<double> u1_sln, u2_sln, u1_ref_sln, u2_ref_sln; // Initialize refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView s_view_0("Solution (x-displacement)", new WinGeom(0, 0, 400, 350)); s_view_0.show_mesh(false); ScalarView s_view_1("Solution (y-displacement)", new WinGeom(760, 0, 400, 350)); s_view_1.show_mesh(false); OrderView o_view_0("Mesh (x-displacement)", new WinGeom(410, 0, 340, 350)); OrderView o_view_1("Mesh (y-displacement)", new WinGeom(1170, 0, 340, 350)); ScalarView mises_view("Von Mises stress [Pa]", new WinGeom(0, 405, 400, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est; // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Hermes::vector<Space<double> *>* ref_spaces = Space<double>::construct_refined_spaces(Hermes::vector<Space<double> *>(&u1_space, &u2_space)); // Initialize matrix solver. SparseMatrix<double>* matrix = create_matrix<double>(matrix_solver_type); Vector<double>* rhs = create_vector<double>(matrix_solver_type); LinearSolver<double>* solver = create_linear_solver<double>(matrix_solver_type, matrix, rhs); // Assemble the reference problem. info("Solving on reference mesh."); DiscreteProblem<double> dp(&wf, *ref_spaces); dp.assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. If successful, obtain the solutions. if(solver->solve()) Solution<double>::vector_to_solutions(solver->get_sln_vector(), *ref_spaces, Hermes::vector<Solution *>(&u1_ref_sln, &u2_ref_sln)); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection<double>::project_global(Hermes::vector<Space<double> *>(&u1_space, &u2_space), Hermes::vector<Solution<double> *>(&u1_ref_sln, &u2_ref_sln), Hermes::vector<Solution<double> *>(&u1_sln, &u2_sln), matrix_solver_type); // View the coarse mesh solution and polynomial orders. s_view_0.show(&u1_sln); o_view_0.show(&u1_space); s_view_1.show(&u2_sln); o_view_1.show(&u2_space); // For von Mises stress Filter. double lambda = (E * nu) / ((1 + nu) * (1 - 2*nu)); double mu = E / (2*(1 + nu)); VonMisesFilter stress(Hermes::vector<MeshFunction<double> *>(&u1_sln, &u2_sln), lambda, mu); mises_view.show(&stress, HERMES_EPS_HIGH, H2D_FN_VAL_0, &u1_sln, &u2_sln, 1e4); // Skip visualization time. cpu_time.tick(HERMES_SKIP); // Initialize adaptivity. Adapt<double>* adaptivity = new Adapt<double>(Hermes::vector<Space<double> *>(&u1_space, &u2_space)); /* // Register custom forms for error calculation. adaptivity->set_error_form(0, 0, bilinear_form_0_0<double, double>, bilinear_form_0_0<Ord, Ord>); adaptivity->set_error_form(0, 1, bilinear_form_0_1<double, double>, bilinear_form_0_1<Ord, Ord>); adaptivity->set_error_form(1, 0, bilinear_form_1_0<double, double>, bilinear_form_1_0<Ord, Ord>); adaptivity->set_error_form(1, 1, bilinear_form_1_1<double, double>, bilinear_form_1_1<Ord, Ord>); */ // Calculate error estimate for each solution component and the total error estimate. info("Calculating error estimate and exact error."); Hermes::vector<double> err_est_rel; double err_est_rel_total = adaptivity->calc_err_est(Hermes::vector<Solution<double> *>(&u1_sln, &u2_sln), Hermes::vector<Solution<double> *>(&u1_ref_sln, &u2_ref_sln), &err_est_rel) * 100; // Time measurement. cpu_time.tick(); // Report results. info("ndof_coarse[0]: %d, ndof_fine[0]: %d, err_est_rel[0]: %g%%", u1_space.Space<double>::get_num_dofs(), Space<double>::get_num_dofs((*ref_spaces)[0]), err_est_rel[0]*100); info("ndof_coarse[1]: %d, ndof_fine[1]: %d, err_est_rel[1]: %g%%", u2_space.Space<double>::get_num_dofs(), Space<double>::get_num_dofs((*ref_spaces)[1]), err_est_rel[1]*100); info("ndof_coarse_total: %d, ndof_fine_total: %d, err_est_rel_total: %g%%", Space<double>::get_num_dofs(Hermes::vector<Space<double> *>(&u1_space, &u2_space)), Space<double>::get_num_dofs(*ref_spaces), err_est_rel_total); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space<double>::get_num_dofs(Hermes::vector<Space<double> *>(&u1_space, &u2_space)), err_est_rel_total); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel_total); graph_cpu_est.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(Hermes::vector<RefinementSelectors::Selector<double> *>(&selector, &selector), THRESHOLD, STRATEGY, MESH_REGULARITY); } if (Space<double>::get_num_dofs(Hermes::vector<Space<double> *>(&u1_space, &u2_space)) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) for(unsigned int i = 0; i < ref_spaces->size(); i++) delete (*ref_spaces)[i]->get_mesh(); delete ref_spaces; // Increase counter. as++; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); // Show the reference solution - the final result. s_view_0.set_title("Fine mesh solution (x-displacement)"); s_view_0.show(&u1_ref_sln); s_view_1.set_title("Fine mesh solution (y-displacement)"); s_view_1.show(&u2_ref_sln); // For von Mises stress Filter. double lambda = (E * nu) / ((1 + nu) * (1 - 2*nu)); double mu = E / (2*(1 + nu)); VonMisesFilter stress(Hermes::vector<MeshFunction<double> *>(&u1_ref_sln, &u2_ref_sln), lambda, mu); mises_view.show(&stress, HERMES_EPS_HIGH, H2D_FN_VAL_0, &u1_ref_sln, &u2_ref_sln, 1e4); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("square_quad.mesh", &mesh); // Perform initial mesh refinement. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Set exact solution. CustomExactSolution exact(&mesh, EPSILON); // Define right-hand side. CustomRightHandSide rhs(EPSILON); // Initialize the weak formulation. CustomWeakForm wf(&rhs); // Initialize boundary conditions DefaultEssentialBCNonConst bc_essential(BDY_DIRICHLET, &exact); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 460, 350)); sview.show_mesh(false); sview.fix_scale_width(70); OrderView oview("Polynomial orders", new WinGeom(470, 0, 410, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof, graph_cpu, graph_dof_exact, graph_cpu_exact; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = Space::construct_refined_space(&space); // 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); // Assemble the reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. If successful, obtain the solution. Solution ref_sln; if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Project the fine mesh solution onto the coarse mesh. Solution sln; info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // View the coarse mesh solution and polynomial orders. sview.show(&sln); oview.show(&space); // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); Adapt* adaptivity = new Adapt(&space); double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Calculate exact error for each solution component. double err_exact_rel = hermes2d.calc_rel_error(&sln, &exact, HERMES_H1_NORM) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space)); info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); graph_dof_exact.add_values(Space::get_num_dofs(&space), err_exact_rel); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel); graph_cpu_exact.save("conv_cpu_exact.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) delete ref_space->get_mesh(); delete ref_space; delete dp; } while (done == false); 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[]) { info("Desired number of eigenvalues: %d.", NUMBER_OF_EIGENVALUES); // 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(); // Enter boundary markers. // Note: "essential" means that solution value is prescribed. BCTypes bc_types; bc_types.add_bc_dirichlet(Hermes::vector<int>(BDY_BOTTOM, BDY_RIGHT, BDY_TOP, BDY_LEFT)); // Enter Dirichlet boudnary values. BCValues bc_values; bc_values.add_zero(Hermes::vector<int>(BDY_BOTTOM, BDY_RIGHT, BDY_TOP, BDY_LEFT)); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); // Initialize the weak formulation for the left hand side i.e. H WeakForm wf_left, wf_right; wf_left.add_matrix_form(callback(bilinear_form_left)); wf_right.add_matrix_form(callback(bilinear_form_right)); // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); Solution sln[NUMBER_OF_EIGENVALUES], ref_sln[NUMBER_OF_EIGENVALUES]; // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); info("Solving on reference mesh."); // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(&space); int ref_ndof = Space::get_num_dofs(ref_space); info("ref_ndof: %d.", ref_ndof); // Initialize matrices and matrix solver on referenc emesh. SparseMatrix* matrix_left = create_matrix(matrix_solver); SparseMatrix* matrix_right = create_matrix(matrix_solver); Vector* eivec = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix_left, eivec); // Assemble the matrices on reference mesh. bool is_linear = true; DiscreteProblem* dp_left = new DiscreteProblem(&wf_left, ref_space, is_linear); dp_left->assemble(matrix_left, eivec); DiscreteProblem* dp_right = new DiscreteProblem(&wf_right, ref_space, is_linear); dp_right->assemble(matrix_right, eivec); // Time measurement. cpu_time.tick(); // Write matrix_left in MatrixMarket format. write_matrix_mm("mat_left.mtx", matrix_left); // Write matrix_left in MatrixMarket format. write_matrix_mm("mat_right.mtx", matrix_right); // Time measurement. cpu_time.tick(HERMES_SKIP); // Calling Python eigensolver. Solution will be written to "eivecs.dat". char call_cmd[255]; sprintf(call_cmd, "python solveGenEigenFromMtx.py mat_left.mtx mat_right.mtx %g %d %g %d", TARGET_VALUE, NUMBER_OF_EIGENVALUES, TOL, MAX_ITER); system(call_cmd); // Initializing solution vector, solution and ScalarView. double* ref_coeff_vec = new double[ref_ndof]; // Reading solution vectors from file and visualizing. FILE *file = fopen("eivecs.dat", "r"); char line [64]; // Maximum line size. fgets(line, sizeof line, file); // ref_ndof int n = atoi(line); if (n != ref_ndof) error("Mismatched ndof in the eigensolver output file."); fgets(line, sizeof line, file); // Number of eigenvectors in the file. int neig = atoi(line); if (neig != NUMBER_OF_EIGENVALUES) error("Mismatched number of eigenvectors in the eigensolver output file."); for (int ieig = 0; ieig < NUMBER_OF_EIGENVALUES; ieig++) { // Get next eigenvector from the file. for (int i = 0; i < ref_ndof; i++) { fgets(line, sizeof line, file); ref_coeff_vec[i] = atof(line); } // Convert coefficient vector into a Solution. Solution::vector_to_solution(ref_coeff_vec, ref_space, &(ref_sln[ieig])); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &(ref_sln[ieig]), &(sln[ieig]), matrix_solver); } fclose(file); delete [] ref_coeff_vec; // FIXME: Below, the adaptivity is done for the last eigenvector only, // this needs to be changed to take into account all eigenvectors. // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); Adapt* adaptivity = new Adapt(&space); bool solutions_for_adapt = true; double err_est_rel = adaptivity->calc_err_est(&(sln[NUMBER_OF_EIGENVALUES-1]), &(ref_sln[NUMBER_OF_EIGENVALUES-1])) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_est_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu_est.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix_left; delete matrix_right; delete eivec; delete adaptivity; if(done == false) delete ref_space->get_mesh(); delete ref_space; delete dp_left; delete dp_right; } while (done == false); info("Coordinate ( 0.5, 0.5) value = %lf", sln[5].get_pt_value(0.5, 0.5)); info("Coordinate ( 1.0, 0.5) value = %lf", sln[5].get_pt_value(1.0, 0.5)); info("Coordinate ( 1.5, 0.5) value = %lf", sln[5].get_pt_value(1.5, 0.5)); info("Coordinate ( 2.0, 0.5) value = %lf", sln[5].get_pt_value(2.0, 0.5)); double coor_x[4] = {0.5, 1.0, 1.5, 2.0}; double coor_y = 0.5; double t_value[4] = {0.154053, -0.178300, -0.530477, -0.313066}; bool success = true; for (int i = 0; i < 4; i++) { if (abs(t_value[i] - sln[5].get_pt_value(coor_x[i], coor_y)) > 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[]) { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh basemesh, mesh_T, mesh_phi; H2DReader mloader; mloader.load("domain.mesh", &basemesh); // Perform initial mesh refinements. for (int i=0; i < INIT_GLOB_REF_NUM; i++) basemesh.refine_all_elements(); basemesh.refine_towards_boundary(1, INIT_BDY_REF_NUM); // Create a special mesh for each physical field. mesh_T.copy(&basemesh); mesh_phi.copy(&basemesh); // Create H1 spaces with default shapesets. H1Space space_T(&mesh_T, bc_types_T, essential_bc_values_T, P_INIT); H1Space space_phi(&mesh_phi, bc_types_phi, essential_bc_values_phi, P_INIT); Tuple<Space*> spaces(&space_T, &space_phi); int ndof = Space::get_num_dofs(spaces); // Solutions in the previous time step (converging within the time stepping loop). Solution T_prev_time, phi_prev_time; Tuple<Solution*> prev_time_solutions(&T_prev_time, &phi_prev_time); // Solutions on the coarse and refined meshes in current time step (converging within the Newton's loop). Solution T_coarse, phi_coarse, T_fine, phi_fine; Tuple<Solution*> coarse_mesh_solutions(&T_coarse, &phi_coarse); Tuple<Solution*> fine_mesh_solutions(&T_fine, &phi_fine); // Initialize the weak formulation. WeakForm wf(2); wf.add_matrix_form(0, 0, jac_TT, jac_TT_ord); wf.add_matrix_form(0, 1, jac_Tphi, jac_Tphi_ord); wf.add_vector_form(0, res_T, res_T_ord, HERMES_ANY, &T_prev_time); wf.add_matrix_form(1, 0, jac_phiT, jac_phiT_ord); wf.add_matrix_form(1, 1, jac_phiphi, jac_phiphi_ord); wf.add_vector_form(1, res_phi, res_phi_ord, HERMES_ANY, &phi_prev_time); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est_T, graph_dof_exact_T, graph_cpu_est_T, graph_cpu_exact_T; SimpleGraph graph_dof_est_phi, graph_dof_exact_phi, graph_cpu_est_phi, graph_cpu_exact_phi; // Exact solutions for error evaluation. ExactSolution T_exact_solution(&mesh_T, T_exact); ExactSolution phi_exact_solution(&mesh_phi, phi_exact); // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize the nonlinear system. DiscreteProblem dp(&wf, spaces); Tuple<ProjNormType> proj_norms(HERMES_H1_NORM, HERMES_H1_NORM); // Set initial conditions. T_prev_time.set_exact(&mesh_T, T_exact); phi_prev_time.set_exact(&mesh_phi, phi_exact); // Newton's loop on the initial coarse meshes. info("Solving on coarse meshes."); scalar* coeff_vec_coarse = new scalar[Space::get_num_dofs(spaces)]; OGProjection::project_global(spaces, Tuple<MeshFunction*>((MeshFunction*)&T_prev_time, (MeshFunction*)&phi_prev_time), coeff_vec_coarse, matrix_solver, proj_norms); bool verbose = true; // Default is false. // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp_coarse(&wf, spaces, is_linear); // Set up the solver_coarse, matrix_coarse, and rhs_coarse according to the solver_coarse selection. SparseMatrix* matrix_coarse = create_matrix(matrix_solver); Vector* rhs_coarse = create_vector(matrix_solver); Solver* solver_coarse = create_linear_solver(matrix_solver, matrix_coarse, rhs_coarse); // Perform Newton's iteration. int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(spaces); // Assemble the Jacobian matrix_coarse and residual vector. dp_coarse.assemble(coeff_vec_coarse, matrix_coarse, rhs_coarse, false); // Multiply the residual vector with -1 since the matrix_coarse // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). for (int i = 0; i < ndof; i++) rhs_coarse->set(i, -rhs_coarse->get(i)); // Calculate the l2-norm of residual vector. double res_l2_norm = get_l2_norm(rhs_coarse); // Info for user. info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(spaces), res_l2_norm); // If l2 norm of the residual vector is within tolerance, or the maximum number // of iteration has been reached, then quit. if (res_l2_norm < NEWTON_TOL_COARSE || it > NEWTON_MAX_ITER) break; // Solve the linear system. if(!solver_coarse->solve()) error ("matrix_coarse solver_coarse failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof; i++) coeff_vec_coarse[i] += solver_coarse->get_solution()[i]; if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); it++; } // Translate the resulting coefficient vector into the actual solutions. Solution::vector_to_solutions(coeff_vec_coarse, spaces, coarse_mesh_solutions); delete [] coeff_vec_coarse; delete rhs_coarse; delete matrix_coarse; delete solver_coarse; // Time stepping loop: int nstep = (int)(T_FINAL/TAU + 0.5); for(int ts = 1; ts <= nstep; ts++) { // Update global time. TIME = ts*TAU; // Update time-dependent exact solutions. T_exact_solution.update(&mesh_T, T_exact); phi_exact_solution.update(&mesh_phi, phi_exact); // Periodic global derefinement. if (ts > 1) { if (ts % UNREF_FREQ == 0) { info("---- Time step %d - prior to adaptivity:", ts); info("Global mesh derefinement."); mesh_T.copy(&basemesh); mesh_phi.copy(&basemesh); space_T.set_uniform_order(P_INIT); space_phi.set_uniform_order(P_INIT); if (SOLVE_ON_COARSE_MESH) { // Newton's loop on the globally derefined meshes. scalar* coeff_vec_coarse = new scalar[Space::get_num_dofs(spaces)]; info("Solving on globally derefined meshes, starting from the latest fine mesh solutions."); OGProjection::project_global(spaces, Tuple<MeshFunction*>((MeshFunction*)&T_fine, (MeshFunction*)&phi_fine), coeff_vec_coarse, matrix_solver, proj_norms); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp_coarse(&wf, spaces, is_linear); // Set up the solver_coarse, matrix_coarse, and rhs_coarse according to the solver_coarse selection. SparseMatrix* matrix_coarse = create_matrix(matrix_solver); Vector* rhs_coarse = create_vector(matrix_solver); Solver* solver_coarse = create_linear_solver(matrix_solver, matrix_coarse, rhs_coarse); // Perform Newton's iteration. int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(spaces); // Assemble the Jacobian matrix_coarse and residual vector. dp_coarse.assemble(coeff_vec_coarse, matrix_coarse, rhs_coarse, false); // Multiply the residual vector with -1 since the matrix_coarse // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). for (int i = 0; i < ndof; i++) rhs_coarse->set(i, -rhs_coarse->get(i)); // Calculate the l2-norm of residual vector. double res_l2_norm = get_l2_norm(rhs_coarse); // Info for user. info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(spaces), res_l2_norm); // If l2 norm of the residual vector is within tolerance, or the maximum number // of iteration has been reached, then quit. if (res_l2_norm < NEWTON_TOL_COARSE || it > NEWTON_MAX_ITER) break; // Solve the linear system. if(!solver_coarse->solve()) error ("matrix_coarse solver_coarse failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof; i++) coeff_vec_coarse[i] += solver_coarse->get_solution()[i]; if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); it++; } // Translate the resulting coefficient vector into the actual solutions. Solution::vector_to_solutions(coeff_vec_coarse, spaces, coarse_mesh_solutions); delete [] coeff_vec_coarse; delete rhs_coarse; delete matrix_coarse; delete solver_coarse; } else { // Projection onto the globally derefined meshes. info("Projecting the latest fine mesh solution onto globally derefined meshes."); OGProjection::project_global(spaces, fine_mesh_solutions, coarse_mesh_solutions, matrix_solver, proj_norms); } } } // Adaptivity loop: bool done = false; int as = 0; do { as++; info("---- Time step %d, adaptivity step %d:", ts, as); // Construct globally refined reference mesh // and setup reference space. Tuple<Space *>* ref_spaces = construct_refined_spaces(spaces); // Newton's loop on the refined meshes. scalar* coeff_vec = new scalar[Space::get_num_dofs(*ref_spaces)]; if (as == 1) { info("Solving on fine meshes, starting from previous coarse mesh solutions."); OGProjection::project_global(*ref_spaces, Tuple<MeshFunction*>((MeshFunction*)&T_coarse, (MeshFunction*)&phi_coarse), coeff_vec, matrix_solver, proj_norms); } else { info("Solving on fine meshes, starting from previous fine mesh solutions."); OGProjection::project_global(*ref_spaces, Tuple<MeshFunction*>((MeshFunction*)&T_fine, (MeshFunction*)&phi_fine), coeff_vec, matrix_solver, proj_norms); } // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp(&wf, *ref_spaces, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Perform Newton's iteration. int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(*ref_spaces); // Assemble the Jacobian matrix and residual vector. dp.assemble(coeff_vec, matrix, rhs, false); // Multiply the residual vector with -1 since the matrix // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). for (int i = 0; i < ndof; i++) rhs->set(i, -rhs->get(i)); // Calculate the l2-norm of residual vector. double res_l2_norm = get_l2_norm(rhs); // Info for user. info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(*ref_spaces), res_l2_norm); // If l2 norm of the residual vector is within tolerance, or the maximum number // of iteration has been reached, then quit. if (res_l2_norm < NEWTON_TOL_FINE || it > NEWTON_MAX_ITER) break; // Solve the linear system. if(!solver->solve()) error ("Matrix solver failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof; i++) coeff_vec[i] += solver->get_solution()[i]; if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); it++; } // Translate the resulting coefficient vector into the actual solutions. Solution::vector_to_solutions(coeff_vec, *ref_spaces, fine_mesh_solutions); delete [] coeff_vec; delete rhs; delete matrix; delete solver; // Calculate element errors. info("Calculating error estimate and exact error."); Adapt* adaptivity = new Adapt(spaces, proj_norms); // Calculate error estimate for each solution component and the total error estimate. bool solutions_for_adapt = true; Tuple<double> err_est_rel; double err_est_rel_total = adaptivity->calc_err_est(coarse_mesh_solutions, fine_mesh_solutions, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_ABS, &err_est_rel) * 100; // Calculate exact error for each solution component and the total exact error. solutions_for_adapt = false; Tuple<double> err_exact_rel; double err_exact_rel_total = adaptivity->calc_err_exact(coarse_mesh_solutions, Tuple<Solution *>(&T_exact_solution, &phi_exact_solution), solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_ABS, &err_exact_rel) * 100; info("T: ndof_coarse: %d, ndof_fine: %d, err_est: %g %%, err_exact: %g %%", space_T.get_num_dofs(), (*ref_spaces)[0]->get_num_dofs(), err_est_rel[0]*100, err_exact_rel[0]*100); info("phi: ndof_coarse: %d, ndof_fine: %d, err_est: %g %%, err_exact: %g %%", space_phi.get_num_dofs(), (*ref_spaces)[1]->get_num_dofs(), err_est_rel[1]*100, err_exact_rel[1]*100); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting the coarse meshes."); done = adaptivity->adapt(Tuple<RefinementSelectors::Selector*> (&selector, &selector), THRESHOLD, STRATEGY, MESH_REGULARITY); if (Space::get_num_dofs(spaces) >= NDOF_STOP) done = true; if (!done) { if (SOLVE_ON_COARSE_MESH) { // Newton's loop on the new coarse meshes. scalar* coeff_vec_coarse = new scalar[Space::get_num_dofs(spaces)]; info("Solving on coarse meshes, starting from the latest fine mesh solutions."); OGProjection::project_global(spaces, Tuple<MeshFunction*>((MeshFunction*)&T_fine, (MeshFunction*)&phi_fine), coeff_vec_coarse, matrix_solver, proj_norms); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp_coarse(&wf, spaces, is_linear); // Set up the solver_coarse, matrix_coarse, and rhs_coarse according to the solver_coarse selection. SparseMatrix* matrix_coarse = create_matrix(matrix_solver); Vector* rhs_coarse = create_vector(matrix_solver); Solver* solver_coarse = create_linear_solver(matrix_solver, matrix_coarse, rhs_coarse); // Perform Newton's iteration. int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(spaces); // Assemble the Jacobian matrix_coarse and residual vector. dp.assemble(coeff_vec_coarse, matrix_coarse, rhs_coarse, false); // Multiply the residual vector with -1 since the matrix_coarse // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). for (int i = 0; i < ndof; i++) rhs_coarse->set(i, -rhs_coarse->get(i)); // Calculate the l2-norm of residual vector. double res_l2_norm = get_l2_norm(rhs_coarse); // Info for user. info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(spaces), res_l2_norm); // If l2 norm of the residual vector is within tolerance, or the maximum number // of iteration has been reached, then quit. if (res_l2_norm < NEWTON_TOL_COARSE || it > NEWTON_MAX_ITER) break; // Solve the linear system. if(!solver_coarse->solve()) error ("matrix_coarse solver_coarse failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof; i++) coeff_vec_coarse[i] += solver_coarse->get_solution()[i]; if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); it++; } // Translate the resulting coefficient vector into the actual solutions. Solution::vector_to_solutions(coeff_vec_coarse, spaces, coarse_mesh_solutions); delete [] coeff_vec_coarse; delete rhs_coarse; delete matrix_coarse; delete solver_coarse; } else { // Projection onto the new coarse meshes. info("Projecting the latest fine mesh solution onto new coarse meshes."); OGProjection::project_global(spaces, fine_mesh_solutions, coarse_mesh_solutions, matrix_solver, proj_norms); } } } delete adaptivity; for(int i = 0; i < ref_spaces->size(); i++) delete (*ref_spaces)[i]->get_mesh(); delete ref_spaces; } while (!done); // Make the fine mesh solution at current time level the previous time level solution in the following time step. T_prev_time.copy(&T_fine); phi_prev_time.copy(&phi_fine); } info("Coordinate ( 25.0, 25.0) T value = %lf", T_prev_time.get_pt_value(25.0, 25.0)); info("Coordinate ( 25.0, 75.0) T value = %lf", T_prev_time.get_pt_value(25.0, 75.0)); info("Coordinate ( 75.0, 25.0) T value = %lf", T_prev_time.get_pt_value(75.0, 25.0)); info("Coordinate ( 75.0, 75.0) T value = %lf", T_prev_time.get_pt_value(75.0, 75.0)); info("Coordinate ( 50.0, 50.0) T value = %lf", T_prev_time.get_pt_value(50.0, 50.0)); info("Coordinate ( 25.0, 25.0) phi value = %lf", phi_prev_time.get_pt_value(25.0, 25.0)); info("Coordinate ( 25.0, 75.0) phi value = %lf", phi_prev_time.get_pt_value(25.0, 75.0)); info("Coordinate ( 75.0, 25.0) phi value = %lf", phi_prev_time.get_pt_value(75.0, 25.0)); info("Coordinate ( 75.0, 75.0) phi value = %lf", phi_prev_time.get_pt_value(75.0, 75.0)); info("Coordinate ( 50.0, 50.0) phi value = %lf", phi_prev_time.get_pt_value(50.0, 50.0)); #define ERROR_SUCCESS 0 #define ERROR_FAILURE -1 int ndof_allowed_T = 130; int ndof_allowed_phi = 300; int ndof_T = Space::get_num_dofs(&space_T); int ndof_phi = Space::get_num_dofs(&space_phi); printf("ndof_actual_T = %d\n", ndof_T); printf("ndof_actual_phi = %d\n", ndof_phi); printf("ndof_allowed_T = %d\n", ndof_allowed_T); printf("ndof_allowed_phi = %d\n", ndof_allowed_phi); if ((ndof_T <= ndof_allowed_T) && (ndof_phi <= ndof_allowed_phi)) { // ndofs_T was 121 and ndof_phi was 267 at the time this test was created printf("Success!\n"); return ERROR_SUCCESS; } else { printf("Failure!\n"); return ERROR_FAILURE; } }
int main(int argc, char* argv[]) { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh xmesh, ymesh, tmesh; H2DReader mloader; mloader.load("domain.mesh", &xmesh); // Master mesh. // Initialize multimesh hp-FEM. ymesh.copy(&xmesh); // Ydisp will share master mesh with xdisp. tmesh.copy(&xmesh); // Temp will share master mesh with xdisp. // Create H1 spaces with default shapesets. H1Space xdisp(&xmesh, bc_types_x, NULL, P_INIT_DISP); H1Space ydisp(MULTI ? &ymesh : &xmesh, bc_types_y, NULL, P_INIT_DISP); H1Space temp(MULTI ? &tmesh : &xmesh, bc_types_t, essential_bc_values_temp, P_INIT_TEMP); // Initialize the weak formulation. WeakForm wf(3); wf.add_matrix_form(0, 0, callback(bilinear_form_0_0)); wf.add_matrix_form(0, 1, callback(bilinear_form_0_1), HERMES_SYM); wf.add_matrix_form(0, 2, callback(bilinear_form_0_2)); wf.add_matrix_form(1, 1, callback(bilinear_form_1_1)); wf.add_matrix_form(1, 2, callback(bilinear_form_1_2)); wf.add_matrix_form(2, 2, callback(bilinear_form_2_2)); wf.add_vector_form(1, callback(linear_form_1)); wf.add_vector_form(2, callback(linear_form_2)); wf.add_vector_form_surf(2, callback(linear_form_surf_2)); // Initialize coarse and reference mesh solutions. Solution xdisp_sln, ydisp_sln, temp_sln, ref_xdisp_sln, ref_ydisp_sln, ref_temp_sln; // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView s_view_0("Solution[xdisp]", new WinGeom(0, 0, 450, 350)); s_view_0.show_mesh(false); ScalarView s_view_1("Solution[ydisp]", new WinGeom(460, 0, 450, 350)); s_view_1.show_mesh(false); ScalarView s_view_2("Solution[temp]", new WinGeom(920, 0, 450, 350)); s_view_1.show_mesh(false); OrderView o_view_0("Mesh[xdisp]", new WinGeom(0, 360, 450, 350)); OrderView o_view_1("Mesh[ydisp]", new WinGeom(460, 360, 450, 350)); OrderView o_view_2("Mesh[temp]", new WinGeom(920, 360, 450, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est; // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Tuple<Space *>* ref_spaces = construct_refined_spaces(Tuple<Space *>(&xdisp, &ydisp, &temp)); // Assemble the reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, *ref_spaces, is_linear); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. If successful, obtain the solutions. if(solver->solve()) Solution::vector_to_solutions(solver->get_solution(), *ref_spaces, Tuple<Solution *>(&ref_xdisp_sln, &ref_ydisp_sln, &ref_temp_sln)); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(Tuple<Space *>(&xdisp, &ydisp, &temp), Tuple<Solution *>(&ref_xdisp_sln, &ref_ydisp_sln, &ref_temp_sln), Tuple<Solution *>(&xdisp_sln, &ydisp_sln, &temp_sln), matrix_solver); // View the coarse mesh solution and polynomial orders. s_view_0.show(&xdisp_sln); o_view_0.show(&xdisp); s_view_1.show(&ydisp_sln); o_view_1.show(&ydisp); s_view_2.show(&temp_sln); o_view_2.show(&temp); // Skip visualization time. cpu_time.tick(HERMES_SKIP); // Calculate element errors. info("Calculating error estimate and exact error."); Adapt* adaptivity = new Adapt(Tuple<Space *>(&xdisp, &ydisp, &temp), Tuple<ProjNormType>(HERMES_H1_NORM, HERMES_H1_NORM, HERMES_H1_NORM)); adaptivity->set_error_form(0, 0, bilinear_form_0_0<scalar, scalar>, bilinear_form_0_0<Ord, Ord>); adaptivity->set_error_form(0, 1, bilinear_form_0_1<scalar, scalar>, bilinear_form_0_1<Ord, Ord>); adaptivity->set_error_form(0, 2, bilinear_form_0_2<scalar, scalar>, bilinear_form_0_2<Ord, Ord>); adaptivity->set_error_form(1, 0, bilinear_form_1_0<scalar, scalar>, bilinear_form_1_0<Ord, Ord>); adaptivity->set_error_form(1, 1, bilinear_form_1_1<scalar, scalar>, bilinear_form_1_1<Ord, Ord>); adaptivity->set_error_form(1, 2, bilinear_form_1_2<scalar, scalar>, bilinear_form_1_2<Ord, Ord>); adaptivity->set_error_form(2, 2, bilinear_form_2_2<scalar, scalar>, bilinear_form_2_2<Ord, Ord>); // Calculate error estimate for each solution component and the total error estimate. Tuple<double> err_est_rel; bool solutions_for_adapt = true; double err_est_rel_total = adaptivity->calc_err_est(Tuple<Solution *>(&xdisp_sln, &ydisp_sln, &temp_sln), Tuple<Solution *>(&ref_xdisp_sln, &ref_ydisp_sln, &ref_temp_sln), solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_ABS, &err_est_rel) * 100; // Time measurement. cpu_time.tick(); // Report results. info("ndof_coarse[xdisp]: %d, ndof_fine[xdisp]: %d, err_est_rel[xdisp]: %g%%", xdisp.Space::get_num_dofs(), Space::get_num_dofs((*ref_spaces)[0]), err_est_rel[0]*100); info("ndof_coarse[ydisp]: %d, ndof_fine[ydisp]: %d, err_est_rel[ydisp]: %g%%", ydisp.Space::get_num_dofs(), Space::get_num_dofs((*ref_spaces)[1]), err_est_rel[1]*100); info("ndof_coarse[temp]: %d, ndof_fine[temp]: %d, err_est_rel[temp]: %g%%", temp.Space::get_num_dofs(), Space::get_num_dofs((*ref_spaces)[2]), err_est_rel[2]*100); info("ndof_coarse_total: %d, ndof_fine_total: %d, err_est_rel_total: %g%%", Space::get_num_dofs(Tuple<Space *>(&xdisp, &ydisp, &temp)), Space::get_num_dofs(*ref_spaces), err_est_rel_total); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space::get_num_dofs(Tuple<Space *>(&xdisp, &ydisp, &temp)), err_est_rel_total); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel_total); graph_cpu_est.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(Tuple<RefinementSelectors::Selector *>(&selector, &selector, &selector), THRESHOLD, STRATEGY, MESH_REGULARITY); } if (Space::get_num_dofs(Tuple<Space *>(&xdisp, &ydisp, &temp)) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) for(int i = 0; i < ref_spaces->size(); i++) delete (*ref_spaces)[i]->get_mesh(); delete ref_spaces; delete dp; // Increase counter. as++; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); // Show the reference solution - the final result. s_view_0.set_title("Fine mesh Solution[xdisp]"); s_view_0.show(&ref_xdisp_sln); s_view_1.set_title("Fine mesh Solution[ydisp]"); s_view_1.show(&ref_ydisp_sln); s_view_1.set_title("Fine mesh Solution[temp]"); s_view_1.show(&ref_temp_sln); // Wait for all views to be closed. View::wait(); return 0; };