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(); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(BDY_DIRICHLET); // Enter Dirichlet boudnary 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(bilinear_form), HERMES_SYM); wf.add_vector_form(callback(linear_form)); // Initialize approximate solution. Solution sln; // Set exact solution. ExactSolution exact(&mesh, fndd); // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); sview.show_mesh(false); sview.fix_scale_width(50); OrderView oview("Polynomial orders", new WinGeom(450, 0, 640, 480)); // DOF and CPU convergence graphs. SimpleGraph graph_dof, graph_cpu, graph_dof_exact, graph_cpu_exact; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Initialize the matrix solver. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Assemble the discrete problem. info("Solving."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, &space, is_linear); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system. If successful, obtain the solution. if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); // View the approximate solution and polynomial orders. sview.show(&sln); oview.show(&space); // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); BasicKellyAdapt* adaptivity = new BasicKellyAdapt(&space); // Use energy norm for error estimate normalization and measuring of exact error. adaptivity->set_error_form(callback(bilinear_form)); if (USE_RESIDUAL_ESTIMATOR) adaptivity->add_error_estimator_vol(callback(residual_estimator)); double err_est_rel = adaptivity->calc_err_est(&sln) * 100; double err_exact_rel = adaptivity->calc_err_exact(&sln, &exact) * 100; // Time measurement. cpu_time.tick(); // Report results. info("ndof_coarse: %d", Space::get_num_dofs(&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.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"); // Time measurement. cpu_time.tick(HERMES_SKIP); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting the mesh."); done = adaptivity->adapt(THRESHOLD, STRATEGY, MESH_REGULARITY); } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Increase the counter of performed adaptivity steps. if (done == false) as++; // Clean up. delete adaptivity; delete dp; } while (done == false); // Clean up. delete solver; delete matrix; delete rhs; verbose("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. View::wait(); return 0; }