int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("square.mesh", &mesh); // Initial mesh refinements. for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(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); int ndof = Space::get_num_dofs(&space); info("ndof = %d.", ndof); // Previous time level solution (initialized by the initial condition). Solution u_prev_time(&mesh, init_cond); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(jac), HERMES_NONSYM, HERMES_ANY); wf.add_vector_form(callback(res), HERMES_ANY, &u_prev_time); // 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 = new scalar[ndof]; OGProjection::project_global(&space, &u_prev_time, coeff_vec, matrix_solver); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 500, 400)); OrderView oview("Mesh", new WinGeom(510, 0, 460, 400)); oview.show(&space); // Time stepping loop: double current_time = 0.0; int ts = 1; do { info("---- Time step %d, t = %g s.", ts, current_time); ts++; // Perform Newton's iteration. info("Solving on coarse mesh:"); bool verbose = true; if (!solve_newton(coeff_vec, &dp, solver, matrix, rhs, NEWTON_TOL, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Update previous time level solution. Solution::vector_to_solution(coeff_vec, &space, &u_prev_time); // Update time. current_time += TAU; // Show the new time level solution. char title[100]; sprintf(title, "Solution, t = %g", current_time); sview.set_title(title); sview.show(&u_prev_time); oview.show(&space); } while (current_time < T_FINAL); // Cleanup. delete [] coeff_vec; delete matrix; delete rhs; delete solver; // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Time measurement TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh 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[]) { // This is a hack I used to run the code a dozen of times when plotting convergence graphs. if (argc > 1) { if (argv[1][0] == 'e') method = IE; else if (argv[1][0] == 's') method = SDIRK; else error("what are you doing?"); } if (argc > 2) { TAU = std::atof(argv[2]); } // This is important to make sure we compare solution at exact same point in time when studying convergence. int N_STEP = std::ceil(T_FINAL / TAU); if (fabs(T_FINAL - N_STEP * TAU) > 1e-10) { error("bad choice of TAU"); } info("t_final = %g, tau = %g, n = %i", T_FINAL, TAU, N_STEP); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("square.mesh", &mesh); // Initial mesh refinements. for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(BDY_DIRICHLET, INIT_BDY_REF_NUM); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(BDY_DIRICHLET); // Enter Dirichlet boudnary values. BCValues bc_values; bc_values.add_zero(BDY_DIRICHLET); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d.", ndof); // Previous time level solution (initialized by the initial condition). Solution u_prev_time(&mesh, exact_solution); // 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 = new scalar[ndof]; OGProjection::project_global(&space, &u_prev_time, coeff_vec, matrix_solver); // 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 views. ScalarView sview("Solution", new WinGeom(0, 0, 500, 400)); OrderView oview("Mesh", new WinGeom(520, 0, 450, 400)); oview.show(&space); if (method == IE) { info("IMPLICIT EULER METHOD"); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(jac), HERMES_NONSYM, HERMES_ANY); wf.add_vector_form(callback(res), HERMES_ANY, &u_prev_time); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp(&wf, &space, is_linear); // Time stepping loop: int ts = 0; do { info("---- Time step %d, t = %g s.", ++ts, TIME); info("We are computing solution at next time step TIME+TAU = %g s.", TIME+TAU); // Perform Newton's iteration. info("Solving nonlinear problem:"); bool verbose = true; if (!solve_newton(coeff_vec, &dp, solver, matrix, rhs, NEWTON_TOL, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Update previous time level solution. Solution::vector_to_solution(coeff_vec, &space, &u_prev_time); // Update time. TIME = TIME + TAU; // Compute exact error. Solution exact_sln(&mesh, exact_solution); double exact_l2_error = calc_abs_error(&u_prev_time, &exact_sln, HERMES_L2_NORM); info("TIME: %g s.", TIME); info("Exact error in l2-norm: %g.", exact_l2_error); // Show the new time level solution. char title[100]; sprintf(title, "Solution, t = %g", TIME); sview.set_title(title); sview.show(&u_prev_time); oview.show(&space); } while (ts < N_STEP); // Cleanup. delete [] coeff_vec; delete matrix; delete rhs; delete solver; // Hack to extract error at final time for convergence graph. Solution citrouille(&mesh, exact_solution); info("IE: tau %g, abs_error %g.", TAU, calc_abs_error(&u_prev_time, &citrouille, HERMES_L2_NORM)); } else if (method == SDIRK) { info("SDIRK22"); Solution Y1(&mesh, init_cond); Solution Y2(&mesh, init_cond); scalar* coeff_vec1 = new scalar[ndof]; OGProjection::project_global(&space, &u_prev_time, coeff_vec1, matrix_solver); scalar* coeff_vec2 = new scalar[ndof]; OGProjection::project_global(&space, &u_prev_time, coeff_vec2, matrix_solver); WeakForm wf1; wf1.add_matrix_form(callback(jac_Y), HERMES_NONSYM, HERMES_ANY); wf1.add_vector_form(callback(res_Y1), HERMES_ANY, Hermes::vector<MeshFunction*>(&u_prev_time)); WeakForm wf2; wf2.add_matrix_form(callback(jac_Y), HERMES_NONSYM, HERMES_ANY); wf2.add_vector_form(callback(res_Y2), HERMES_ANY, Hermes::vector<MeshFunction*>(&u_prev_time, &Y1)); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp1(&wf1, &space, is_linear); DiscreteProblem dp2(&wf2, &space, is_linear); double current_time = 0.0; int ts = 0; do { info("---- Time step %d, t = %g s.", ++ts, current_time); // Compute Y1. info("Compute Y1 at t = %g s.", TIME+GAMMA*TAU); // Perform Newton's iteration for Y1. int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(&space); // Assemble the Jacobian matrix and residual vector. dp1.assemble(coeff_vec1, matrix, rhs, false); // Multiply the residual vector with -1 since the matrix // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). rhs->change_sign(); // 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(&space), 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 || 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_vec1[i] += solver->get_solution()[i]; if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); it++; } // Store Y1. Solution::vector_to_solution(coeff_vec1, &space, &Y1); // Compute Y2. info("Compute Y2 at t = %g s.", TIME+TAU); // Perform Newton's iteration. while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(&space); // Assemble the Jacobian matrix and residual vector. dp2.assemble(coeff_vec2, matrix, rhs, false); // Multiply the residual vector with -1 since the matrix // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). rhs->change_sign(); // 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(&space), 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 || 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_vec2[i] += solver->get_solution()[i]; if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); it++; } // Store Y2. Solution::vector_to_solution(coeff_vec2, &space, &Y2); // Update previous time level solution. u_prev_time = Y2; // Update time. TIME = TIME + TAU; // Compute exact error. Solution exact_sln(&mesh, exact_solution); double exact_l2_error = calc_abs_error(&u_prev_time, &exact_sln, HERMES_L2_NORM); info("TIME: %g s.", TIME); info("Exact error in l2-norm: %g.", exact_l2_error); // Show the new time level solution. char title[100]; sprintf(title, "Solution, t = %g", TIME); sview.set_title(title); sview.show(&u_prev_time); } while (ts < N_STEP); // Hack to extract error at final time for convergence graph. Solution citrouille(&mesh, exact_solution); info("SDIRK: tau %g, abs_error %g.", TAU, calc_abs_error(&u_prev_time, &citrouille, HERMES_L2_NORM)); } // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Choose a Butcher's table or define your own. ButcherTable* bt = new ButcherTable(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); // 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(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); int ndof = Space::get_num_dofs(&space); // Convert initial condition into a Solution. Solution* sln_prev_time = new Solution(&mesh, init_cond); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(stac_jacobian), HERMES_NONSYM, HERMES_ANY, sln_prev_time); wf.add_vector_form(callback(stac_residual), HERMES_ANY, sln_prev_time); // Initialize the discrete problem. bool is_linear = false; DiscreteProblem dp_coarse(&wf, &space, is_linear); // Create a refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Graph for time step history. SimpleGraph time_step_graph; if (ADAPTIVE_TIME_STEP_ON) info("Time step history will be saved to file time_step_history.dat."); // Time stepping loop. double current_time = time_step; int ts = 1; do { info("Begin time step %d.", ts); // Periodic global derefinement. if (ts > 1 && ts % UNREF_FREQ == 0) { info("Global mesh derefinement."); if (UNREF_LEVEL == 1) mesh.unrefine_all_elements(); else mesh.copy(&basemesh); space.set_uniform_order(P_INIT); ndof = Space::get_num_dofs(&space); } // Spatial adaptivity loop. Note: sln_prev_time must not be // changed during spatial adaptivity. Solution ref_sln; Solution* time_error_fn; if (bt->is_embedded() == true) time_error_fn = new Solution(&mesh); else time_error_fn = NULL; bool done = false; int as = 1; double err_est; do { // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(&space); // Initialize discrete problem on reference mesh. DiscreteProblem* ref_dp = new DiscreteProblem(&wf, ref_space); // Runge-Kutta step on the fine mesh. info("Runge-Kutta time step on fine mesh (t = %g s, tau = %g s, stages: %d).", current_time, time_step, bt->get_size()); bool verbose = true; bool is_linear = false; if (!rk_time_step(current_time, time_step, bt, sln_prev_time, &ref_sln, time_error_fn, ref_dp, matrix_solver, verbose, is_linear, NEWTON_TOL_FINE, NEWTON_MAX_ITER)) { error("Runge-Kutta time step failed, try to decrease time step size."); } /* If ADAPTIVE_TIME_STEP_ON == true, estimate temporal error. If too large or too small, then adjust it and restart the time step. */ double rel_err_time; if (bt->is_embedded() == true) { info("Calculating temporal error estimate."); rel_err_time = calc_norm(time_error_fn, HERMES_H1_NORM) / calc_norm(&ref_sln, HERMES_H1_NORM) * 100; if (ADAPTIVE_TIME_STEP_ON == false) info("rel_err_time: %g%%", rel_err_time); } if (ADAPTIVE_TIME_STEP_ON) { if (rel_err_time > TIME_ERR_TOL_UPPER) { info("rel_err_time %g%% is above upper limit %g%%", rel_err_time, TIME_ERR_TOL_UPPER); info("Decreasing tau from %g to %g s and restarting time step.", time_step, time_step * TIME_STEP_DEC_RATIO); time_step *= TIME_STEP_DEC_RATIO; delete ref_space; delete ref_dp; continue; } else if (rel_err_time < TIME_ERR_TOL_LOWER) { info("rel_err_time = %g%% is below lower limit %g%%", rel_err_time, TIME_ERR_TOL_UPPER); info("Increasing tau from %g to %g s and restarting time step.", time_step, time_step * TIME_STEP_INC_RATIO); time_step *= TIME_STEP_INC_RATIO; delete ref_space; delete ref_dp; continue; } else { info("rel_err_time = %g%% is in acceptable interval (%g%%, %g%%)", rel_err_time, TIME_ERR_TOL_LOWER, TIME_ERR_TOL_UPPER); } // Add entry to time step history graph. time_step_graph.add_values(current_time, time_step); time_step_graph.save("time_step_history.dat"); } /* Estimate spatial errors and perform mesh refinement */ info("Spatial adaptivity step %d.", as); // Project the fine mesh solution onto the coarse mesh. Solution sln; info("Projecting fine mesh solution on coarse mesh for error estimation."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Calculate element errors and spatial error estimate. info("Calculating spatial error estimate."); Adapt* adaptivity = new Adapt(&space); double err_rel_space = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Report results. info("ndof: %d, ref_ndof: %d, err_rel_space: %g%%", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_rel_space); // If err_est too large, adapt the mesh. if (err_rel_space < SPACE_ERR_TOL) done = true; else { info("Adapting the coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } // Clean up. delete adaptivity; delete ref_space; delete ref_dp; } while (done == false); // Clean up. if (time_error_fn != NULL) delete time_error_fn; // Copy last reference solution into sln_prev_time. sln_prev_time->copy(&ref_sln); // Increase current time and counter of time steps. current_time += time_step; ts++; } while (current_time < T_FINAL); // Clean up. delete sln_prev_time; delete bt; ndof = Space::get_num_dofs(&space); printf("ndof allowed = %d\n", 130); printf("ndof actual = %d\n", ndof); if (ndof < 130) { // ndofs was 121 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) { int res = ERR_SUCCESS; #ifdef WITH_PETSC PetscInitialize(&argc, &argv, (char *) PETSC_NULL, PETSC_NULL); #endif set_verbose(false); if (argc < 3) error("Not enough parameters"); HcurlShapesetLobattoHex shapeset; printf("* Loading mesh '%s'\n", argv[1]); Mesh mesh; Mesh3DReader mesh_loader; if (!mesh_loader.load(argv[1], &mesh)) error("Loading mesh file '%s'\n", argv[1]); printf("* Setting the space up\n"); HcurlSpace space(&mesh, &shapeset); space.set_bc_types(bc_types); int order; sscanf(argv[2], "%d", &order); int dir_x = order, dir_y = order, dir_z = order; order3_t o(dir_x, dir_y, dir_z); printf(" - Setting uniform order to (%d, %d, %d)\n", o.x, o.y ,o.z); space.set_uniform_order(o); int ndofs = space.assign_dofs(); printf(" - Number of DOFs: %d\n", ndofs); printf("* Calculating a solution\n"); #if defined WITH_UMFPACK UMFPackMatrix mat; UMFPackVector rhs; UMFPackLinearSolver solver(&mat, &rhs); #elif defined WITH_PARDISO PardisoMatrix mat; PardisoVector rhs; PardisoSolver solver(&mat, &rhs); #elif defined WITH_PETSC PetscMatrix mat; PetscVector rhs; PetscLinearSolver solver(&mat, &rhs); #elif defined WITH_MUMPS MumpsMatrix mat; MumpsVector rhs; MumpsSolver solver(&mat, &rhs); #endif WeakForm wf; wf.add_matrix_form(bilinear_form<double, scalar>, bilinear_form<ord_t, ord_t>, SYM); wf.add_matrix_form_surf(bilinear_form_surf<double, scalar>, bilinear_form_surf<ord_t, ord_t>); wf.add_vector_form(linear_form<double, scalar>, linear_form<ord_t, ord_t>); wf.add_vector_form_surf(linear_form_surf<double, scalar>, linear_form_surf<ord_t, ord_t>); LinearProblem lp(&wf, &space); // assemble stiffness matrix Timer assemble_timer("Assembling stiffness matrix"); assemble_timer.start(); lp.assemble(&mat, &rhs); assemble_timer.stop(); // solve the stiffness matrix Timer solve_timer("Solving stiffness matrix"); solve_timer.start(); bool solved = solver.solve(); solve_timer.stop(); //#ifdef OUTPUT_DIR mat.dump(stdout, "a"); rhs.dump(stdout, "b"); //#endif if (solved) { scalar *s = solver.get_solution(); Solution sln(&mesh); sln.set_coeff_vector(&space, s); printf("* Solution:\n"); for (int i = 1; i <= ndofs; i++) { printf(" x[% 3d] = " SCALAR_FMT "\n", i, SCALAR(s[i])); } // output the measured values printf("%s: %s (%lf secs)\n", assemble_timer.get_name(), assemble_timer.get_human_time(), assemble_timer.get_seconds()); printf("%s: %s (%lf secs)\n", solve_timer.get_name(), solve_timer.get_human_time(), solve_timer.get_seconds()); // norm ExactSolution ex_sln(&mesh, exact_solution); double hcurl_sln_norm = hcurl_norm(&sln); double hcurl_err_norm = hcurl_error(&sln, &ex_sln); printf(" - Hcurl solution norm: % le\n", hcurl_sln_norm); printf(" - Hcurl error norm: % le\n", hcurl_err_norm); double l2_sln_norm = l2_norm_hcurl(&sln); double l2_err_norm = l2_error_hcurl(&sln, &ex_sln); printf(" - L2 solution norm: % le\n", l2_sln_norm); printf(" - L2 error norm: % le\n", l2_err_norm); if (hcurl_err_norm > EPS || l2_err_norm > EPS) { // calculated solution is not enough precise res = ERR_FAILURE; } #if 0 //def OUTPUT_DIR // output printf("starting output\n"); const char *of_name = OUTPUT_DIR "/solution.vtk"; FILE *ofile = fopen(of_name, "w"); if (ofile != NULL) { ExactSolution ex_sln(&mesh, exact_solution_0, exact_solution_1, exact_solution_2); RealPartFilter real_sln(&mesh, &sln, FN_VAL); ImagPartFilter imag_sln(&mesh, &sln, FN_VAL); DiffFilter eh(&mesh, &sln, &ex_sln); DiffFilter eh_dx(&mesh, &sln, &ex_sln, FN_DX, FN_DX); // DiffFilter eh_dy(&mesh, &sln, &ex_sln, FN_DY, FN_DY); // DiffFilter eh_dz(&mesh, &sln, &ex_sln, FN_DZ, FN_DZ); // GmshOutputEngine output(ofile); VtkOutputEngine output(ofile); output.out(&real_sln, "real_Uh", FN_VAL); output.out(&imag_sln, "imag_Uh", FN_VAL); output.out(&real_sln, "real_Uh_0", FN_VAL_0); output.out(&real_sln, "real_Uh_1", FN_VAL_1); output.out(&real_sln, "real_Uh_2", FN_VAL_2); output.out(&imag_sln, "imag_Uh_0", FN_VAL_0); output.out(&imag_sln, "imag_Uh_1", FN_VAL_1); output.out(&imag_sln, "imag_Uh_2", FN_VAL_2); fclose(ofile); } else { warning("Can not open '%s' for writing.", of_name); } #endif } #ifdef WITH_PETSC mat.free(); rhs.free(); PetscFinalize(); #endif return res; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; ExodusIIReader mloader; if (!mloader.load("iron-water.e", &mesh)) error("ExodusII mesh load failed."); // 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_dirichlet(Hermes::vector<int>(WATER_2, IRON)); bc_types.add_bc_neumann(WATER_1); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_zero(Hermes::vector<int>(WATER_2, IRON)); // 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(bilinear_form_water, bilinear_form_ord, HERMES_SYM, WATER_1); wf.add_matrix_form(bilinear_form_water, bilinear_form_ord, HERMES_SYM, WATER_2); wf.add_matrix_form(bilinear_form_iron, bilinear_form_ord, HERMES_SYM, IRON); wf.add_vector_form(linear_form_source, linear_form_ord, WATER_1); // 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); 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); #define ERROR_SUCCESS 0 #define ERROR_FAILURE -1 int n_dof_allowed = 170; printf("n_dof_actual = %d\n", ndof); printf("n_dof_allowed = %d\n", n_dof_allowed);// ndofs was 158 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 **args) { // Test variable. int success_test = 1; // Load the initial mesh. Mesh mesh; H3DReader mesh_loader; mesh_loader.load("../hexahedron.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 H1 space with default shapeset. H1Space space(&mesh, bc_types, essential_bc_values, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); // Construct initial solution and set it to zero. Solution sln_prev(&mesh); sln_prev.set_zero(); // Initialize weak formulation. WeakForm wf; wf.add_matrix_form(bilinear_form<double, scalar>, bilinear_form<Ord, Ord>, HERMES_SYM); wf.add_vector_form(linear_form<double, scalar>, linear_form<Ord, Ord>, HERMES_ANY_INT, &sln_prev); // Initialize discrete problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the 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). } // Exact error for testing purposes. double err_exact; // Time stepping. int nsteps = (int) (FINAL_TIME/TAU + 0.5); for (int ts = 0; ts < nsteps; ts++) { info("---- Time step %d, time %3.5f.", ts, TIME); // Assemble the linear problem. info("Assembling the linear problem (ndof: %d).", Space::get_num_dofs(&space)); if (ts == 0) dp.assemble(matrix, rhs); else dp.assemble(NULL, rhs); // Solve the linear system. If successful, obtain the solution. info("Solving the linear problem."); Solution sln(space.get_mesh()); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); // Output solution. if (solution_output) out_fn_vtk(&sln, "sln", ts); // Calculate exact error. ExactSolution esln(&mesh, fndd); info("Calculating exact error."); Adapt *adaptivity = new Adapt(&space, HERMES_H1_NORM); bool solutions_for_adapt = false; err_exact = adaptivity->calc_err_exact(&sln, &esln, solutions_for_adapt, HERMES_TOTAL_ERROR_ABS) * 100; info("Err. exact: %g%%.", err_exact); // Next time step. sln_prev = sln; TIME += TAU; // Cleanup. delete adaptivity; } if(err_exact > 3.00) success_test = 0; // Clean up. delete matrix; delete rhs; delete solver; if (success_test) { info("Success!"); return ERR_SUCCESS; } else { info("Failure!"); return ERR_FAILURE; } }
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 mloader; mloader.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(); // 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 the FE 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 { printf("Matrix solver failed.\n"); success_test = 0; } // Time measurement. cpu_time.tick(); // Project the reference solution on the coarse mesh. Solution sln(space.get_mesh()); info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Time measurement. cpu_time.tick(); // 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); // Properly terminate the solver in the case of SOLVER_PETSC or SOLVER_MUMPS. finalize_solution_environment(matrix_solver); // 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("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 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(); return 0; }
int main(int argc, char **args) { // Test variable. int success_test = 1; if (argc < 3) error("Not enough parameters."); // Load the mesh. Mesh mesh; H3DReader mloader; if (!mloader.load(args[1], &mesh)) error("Loading mesh file '%s'.", args[1]); // Initialize the space according to the // command-line parameters passed. int o; sscanf(args[2], "%d", &o); Ord3 order(o, o, o); HcurlSpace space(&mesh, bc_types, NULL, order); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(bilinear_form), HERMES_SYM); wf.add_vector_form(callback(linear_form)); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the 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 linear problem. info("Assembling (ndof: %d).", Space::get_num_dofs(&space)); dp.assemble(matrix, rhs); // Solve the linear system. If successful, obtain the solution. info("Solving."); Solution sln(&mesh); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); ExactSolution ex_sln(&mesh, exact_solution); // Calculate exact error. info("Calculating exact error."); Adapt *adaptivity = new Adapt(&space, HERMES_HCURL_NORM); bool solutions_for_adapt = false; double err_exact = adaptivity->calc_err_exact(&sln, &ex_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_ABS); if (err_exact > EPS) // Calculated solution is not precise enough. success_test = 0; // Clean up. delete matrix; delete rhs; delete solver; delete adaptivity; if (success_test) { info("Success!"); return ERR_SUCCESS; } else { info("Failure!"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Choose a Butcher's table or define your own. ButcherTable* bt = new ButcherTable(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("wall.mesh", &basemesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) basemesh.refine_all_elements(); basemesh.refine_towards_boundary(BDY_BOTTOM, INIT_REF_NUM_BDY); mesh.copy(&basemesh); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_neumann(Hermes::vector<int>(BDY_RIGHT, BDY_LEFT)); bc_types.add_bc_newton(Hermes::vector<int>(BDY_BOTTOM, BDY_TOP)); // Initialize an H1 space with default shapeset. H1Space space(&mesh, &bc_types, NULL, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d.", ndof); // Convert initial condition into a Solution. Solution* sln_prev_time = new Solution(&mesh, TEMP_INIT); // Initialize weak formulation. WeakForm wf; wf.add_matrix_form(stac_jacobian_vol, stac_jacobian_vol_ord, HERMES_NONSYM, HERMES_ANY, sln_prev_time); wf.add_vector_form(stac_residual_vol, stac_residual_vol_ord, HERMES_ANY, sln_prev_time); wf.add_matrix_form_surf(stac_jacobian_bottom, stac_jacobian_bottom_ord, BDY_BOTTOM, sln_prev_time); wf.add_vector_form_surf(stac_residual_bottom, stac_residual_bottom_ord, BDY_BOTTOM, sln_prev_time); wf.add_matrix_form_surf(stac_jacobian_top, stac_jacobian_top_ord, BDY_TOP, sln_prev_time); wf.add_vector_form_surf(stac_residual_top, stac_residual_top_ord, BDY_TOP, sln_prev_time); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Create a refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Visualize initial condition. char title[100]; ScalarView sln_view("Initial condition", new WinGeom(0, 0, 1500, 360)); OrderView ordview("Initial mesh", new WinGeom(0, 410, 1500, 360)); ScalarView time_error_view("Temporal error", new WinGeom(0, 800, 1500, 360)); time_error_view.fix_scale_width(40); ScalarView space_error_view("Spatial error", new WinGeom(0, 1220, 1500, 360)); space_error_view.fix_scale_width(40); sln_view.show(sln_prev_time, HERMES_EPS_VERYHIGH); ordview.show(&space); // Graph for time step history. SimpleGraph time_step_graph; if (ADAPTIVE_TIME_STEP_ON) info("Time step history will be saved to file time_step_history.dat."); // Time stepping loop: double current_time = 0; int ts = 1; do { info("Begin time step %d.", ts); // Periodic global derefinement. if (ts > 1 && ts % UNREF_FREQ == 0) { info("Global mesh derefinement."); if (UNREF_LEVEL == 1) mesh.unrefine_all_elements(); else mesh.copy(&basemesh); space.set_uniform_order(P_INIT); ndof = Space::get_num_dofs(&space); } // Spatial adaptivity loop. Note: sln_prev_time must not be // changed during spatial adaptivity. Solution ref_sln; Solution* time_error_fn; if (bt->is_embedded() == true) time_error_fn = new Solution(&mesh); else time_error_fn = NULL; bool done = false; int as = 1; double err_est; do { // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(&space); // Initialize discrete problem on reference mesh. DiscreteProblem* ref_dp = new DiscreteProblem(&wf, ref_space); // Runge-Kutta step on the fine mesh. info("Runge-Kutta time step on fine mesh (t = %g s, tau = %g s, stages: %d).", current_time, time_step, bt->get_size()); bool verbose = true; bool is_linear = false; if (!rk_time_step(current_time, time_step, bt, sln_prev_time, &ref_sln, time_error_fn, ref_dp, matrix_solver, verbose, is_linear, NEWTON_TOL_FINE, NEWTON_MAX_ITER)) { error("Runge-Kutta time step failed, try to decrease time step size."); } /* If ADAPTIVE_TIME_STEP_ON == true, estimate temporal error. If too large or too small, then adjust it and restart the time step. */ double rel_err_time; if (bt->is_embedded() == true) { info("Calculating temporal error estimate."); // Show temporal error. char title[100]; sprintf(title, "Temporal error est, spatial adaptivity step %d", as); time_error_view.set_title(title); time_error_view.show_mesh(false); time_error_view.show(time_error_fn, HERMES_EPS_VERYHIGH); rel_err_time = calc_norm(time_error_fn, HERMES_H1_NORM) / calc_norm(&ref_sln, HERMES_H1_NORM) * 100; if (ADAPTIVE_TIME_STEP_ON == false) info("rel_err_time: %g%%", rel_err_time); } if (ADAPTIVE_TIME_STEP_ON) { if (rel_err_time > TIME_ERR_TOL_UPPER) { info("rel_err_time %g%% is above upper limit %g%%", rel_err_time, TIME_ERR_TOL_UPPER); info("Decreasing tau from %g to %g s and restarting time step.", time_step, time_step * TIME_STEP_DEC_RATIO); time_step *= TIME_STEP_DEC_RATIO; delete ref_space; delete ref_dp; continue; } else if (rel_err_time < TIME_ERR_TOL_LOWER) { info("rel_err_time = %g%% is below lower limit %g%%", rel_err_time, TIME_ERR_TOL_UPPER); info("Increasing tau from %g to %g s.", time_step, time_step * TIME_STEP_INC_RATIO); time_step *= TIME_STEP_INC_RATIO; } else { info("rel_err_time = %g%% is in acceptable interval (%g%%, %g%%)", rel_err_time, TIME_ERR_TOL_LOWER, TIME_ERR_TOL_UPPER); } // Add entry to time step history graph. time_step_graph.add_values(current_time, time_step); time_step_graph.save("time_step_history.dat"); } /* Estimate spatial errors and perform mesh refinement */ info("Spatial adaptivity step %d.", as); // Project the fine mesh solution onto the coarse mesh. Solution sln; info("Projecting fine mesh solution on coarse mesh for error estimation."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Show spatial error. sprintf(title, "Spatial error est, spatial adaptivity step %d", as); DiffFilter* space_error_fn = new DiffFilter(Hermes::vector<MeshFunction*>(&ref_sln, &sln)); space_error_view.set_title(title); space_error_view.show_mesh(false); AbsFilter abs_sef(space_error_fn); space_error_view.show(&abs_sef, HERMES_EPS_VERYHIGH); // Calculate element errors and spatial error estimate. info("Calculating spatial error estimate."); Adapt* adaptivity = new Adapt(&space); double err_rel_space = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Report results. info("ndof: %d, ref_ndof: %d, err_rel_space: %g%%", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_rel_space); // If err_est too large, adapt the mesh. if (err_rel_space < SPACE_ERR_TOL) done = true; else { info("Adapting the coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } // Clean up. delete adaptivity; delete ref_space; delete ref_dp; delete space_error_fn; } while (done == false); // Clean up. if (time_error_fn != NULL) delete time_error_fn; // Visualize the solution and mesh. char title[100]; sprintf(title, "Solution, time %g s", current_time); sln_view.set_title(title); sln_view.show_mesh(false); sln_view.show(&ref_sln, HERMES_EPS_VERYHIGH); sprintf(title, "Mesh, time %g s", current_time); ordview.set_title(title); ordview.show(&space); // Copy last reference solution into sln_prev_time. sln_prev_time->copy(&ref_sln); // Increase current time and counter of time steps. current_time += time_step; ts++; } while (current_time < T_FINAL); // Clean up. delete sln_prev_time; delete bt; // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); if (bt.is_explicit()) info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("cathedral.mesh", &mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(BDY_AIR, INIT_REF_NUM_BDY); mesh.refine_towards_boundary(BDY_GROUND, INIT_REF_NUM_BDY); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(Hermes::vector<std::string>(BDY_GROUND)); bc_types.add_bc_newton(BDY_AIR); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_const(BDY_GROUND, TEMP_INIT); // Initialize an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d.", ndof); // Previous time level solution (initialized by the external temperature). Solution u_prev_time(&mesh, TEMP_INIT); // Initialize weak formulation. WeakForm wf; wf.add_matrix_form(callback(stac_jacobian_vol)); wf.add_vector_form(callback(stac_residual_vol)); wf.add_matrix_form_surf(callback(stac_jacobian_surf), BDY_AIR); wf.add_vector_form_surf(callback(stac_residual_surf), BDY_AIR); // Project the initial condition on the FE space to obtain initial solution coefficient vector. info("Projecting initial condition to translate initial condition into a vector."); scalar* coeff_vec = new scalar[ndof]; OGProjection::project_global(&space, &u_prev_time, coeff_vec, matrix_solver); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp(&wf, &space, is_linear); // Initialize views. ScalarView Tview("Temperature", new WinGeom(0, 0, 450, 600)); Tview.set_min_max_range(0,20); Tview.fix_scale_width(30); // Time stepping loop: double current_time = 0.0; int ts = 1; do { // Perform one Runge-Kutta time step according to the selected Butcher's table. info("Runge-Kutta time step (t = %g, tau = %g, stages: %d).", current_time, time_step, bt.get_size()); bool verbose = true; bool is_linear = true; if (!rk_time_step(current_time, time_step, &bt, coeff_vec, &dp, matrix_solver, verbose, is_linear)) { error("Runge-Kutta time step failed, try to decrease time step size."); } // Convert coeff_vec into a new time level solution. Solution::vector_to_solution(coeff_vec, &space, &u_prev_time); // Update time. current_time += time_step; // Show the new time level solution. char title[100]; sprintf(title, "Time %3.2f, exterior temperature %3.5f", current_time, temp_ext(current_time)); Tview.set_title(title); Tview.show(&u_prev_time); // Increase counter of time steps. ts++; } while (current_time < T_FINAL); // Cleanup. delete [] coeff_vec; // Wait for the view to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh, basemesh; H2DReader mloader; mloader.load("square.mesh", &basemesh); // Perform initial mesh refinements. mesh.copy(&basemesh); for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(BDY_TOP, INIT_REF_NUM_BDY); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(Hermes::Tuple<int>(BDY_TOP, BDY_REST)); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_function(Hermes::Tuple<int>(BDY_TOP, BDY_REST), essential_bc_values); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); // Create an H1 space for the initial coarse mesh solution. H1Space init_space(&basemesh, &bc_types, &bc_values, P_INIT); // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Solutions for the time stepping and adaptivity. Solution u_prev_time, sln, ref_sln; // Initialize views. char title_init[200]; sprintf(title_init, "Projection of initial condition"); ScalarView* view_init = new ScalarView(title_init, new WinGeom(0, 0, 410, 300)); sprintf(title_init, "Initial mesh"); OrderView* ordview_init = new OrderView(title_init, new WinGeom(420, 0, 350, 300)); view_init->fix_scale_width(80); // Initialize u_prev_time. // Note: only if adaptivity to initial condition is not done. u_prev_time.set_exact(&basemesh, init_cond); // Initialize the weak formulation. WeakForm wf; if (TIME_INTEGRATION == 1) { wf.add_matrix_form(jac_euler, jac_ord, HERMES_UNSYM, HERMES_ANY, &u_prev_time); wf.add_vector_form(res_euler, res_ord, HERMES_ANY, &u_prev_time); } else { wf.add_matrix_form(jac_cranic, jac_ord, HERMES_UNSYM, HERMES_ANY, &u_prev_time); wf.add_vector_form(res_cranic, res_ord, HERMES_ANY, &u_prev_time); } // Error estimate and discrete problem size as a function of physical time. SimpleGraph graph_time_err_est, graph_time_err_exact, graph_time_dof, graph_time_cpu; // Project the initial condition on the FE space // to obtain initial coefficient vector for the Newton's method. info("Projecting initial condition to obtain coefficient vector for Newton on coarse mesh."); scalar* coeff_vec_coarse = new scalar[Space::get_num_dofs(&space)]; OGProjection::project_global(&space, init_cond, coeff_vec_coarse, matrix_solver); ScalarView view("Projection of initial condition", new WinGeom(0, 0, 410, 300)); OrderView ordview("Initial mesh", new WinGeom(420, 0, 350, 300)); view.fix_scale_width(80); // Newton's loop on the coarse mesh. info("Solving on coarse mesh."); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp_coarse(&wf, &space, 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. 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 actual solution. Solution::vector_to_solution(coeff_vec_coarse, &space, &sln); // Clean up. delete [] coeff_vec_coarse; delete rhs_coarse; delete matrix_coarse; delete solver_coarse; // Time stepping loop. int num_time_steps = (int)(T_FINAL/TAU + 0.5); for(int ts = 1; ts <= num_time_steps; ts++) { // Time measurement. cpu_time.tick(); // Updating current time. TIME = ts*TAU; // Periodic global derefinements. if (ts > 1 && ts % UNREF_FREQ == 0) { info("Global mesh derefinement."); mesh.copy(&basemesh); space.set_uniform_order(P_INIT); } // Adaptivity loop (in space): bool done = false; int as = 1; 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)]; // Calculate initial coefficient vector for Newton on the fine mesh. if (as == 1 && ts == 1) { info("Projecting coarse mesh solution to obtain initial vector on new fine mesh."); OGProjection::project_global(ref_space, &sln, coeff_vec, matrix_solver); } else { 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); delete ref_sln.get_mesh(); } // Initialize the FE problem. bool is_linear = false; 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); // Perform Newton's iteration. 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 actual solutions. Solution::vector_to_solutions(coeff_vec, ref_space, &ref_sln); // Project the fine mesh solution on the coarse mesh. info("Projecting fine mesh solution on coarse mesh for error calculation."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Calculate element errors. info("Calculating error estimate and exact error."); Adapt* adaptivity = new Adapt(&space, HERMES_H1_NORM); bool solutions_for_adapt = true; // Calculate error estimate wrt. fine mesh solution. double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_ABS) * 100; // Calculate error wrt. exact solution. ExactSolution exact(&mesh, exact_sol); 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("space_err_est_rel: %g%%, space_err_exact_rel: %g%%", err_est_rel, err_exact_rel); // Add entries to convergence graphs. graph_time_err_est.add_values(ts*TAU, err_est_rel); graph_time_err_est.save("time_error_est.dat"); graph_time_err_exact.add_values(ts*TAU, err_exact_rel); graph_time_err_exact.save("time_error_exact.dat"); graph_time_dof.add_values(ts*TAU, Space::get_num_dofs(&space)); graph_time_dof.save("time_dof.dat"); graph_time_cpu.add_values(ts*TAU, cpu_time.accumulated()); graph_time_cpu.save("time_cpu.dat"); // If space_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; break; } as++; } // Clean up. delete [] coeff_vec; delete solver; delete matrix; delete rhs; delete adaptivity; delete ref_space; } while (!done); // Visualize the solution and mesh. char title[100]; sprintf(title, "Solution, time level %d", ts); view.set_title(title); view.show(&sln); sprintf(title, "Mesh, time level %d", ts); ordview.set_title(title); ordview.show(&space); // Copy new time level solution into u_prev_time. u_prev_time.copy(&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("cathedral.mesh", &mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(BDY_AIR, INIT_REF_NUM_BDY); mesh.refine_towards_boundary(BDY_GROUND, INIT_REF_NUM_BDY); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(Hermes::vector<std::string>(BDY_GROUND)); bc_types.add_bc_newton(BDY_AIR); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_const(BDY_GROUND, TEMP_INIT); // Initialize an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d.", ndof); // Previous time level solution (initialized by the external temperature). Solution tsln(&mesh, TEMP_INIT); // Initialize weak formulation. WeakForm wf; wf.add_matrix_form(callback(bilinear_form)); wf.add_matrix_form_surf(callback(bilinear_form_surf), BDY_AIR); wf.add_vector_form(callback(linear_form), HERMES_ANY, &tsln); wf.add_vector_form_surf(callback(linear_form_surf), BDY_AIR); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); solver->set_factorization_scheme(HERMES_REUSE_FACTORIZATION_COMPLETELY); // Initialize views. ScalarView Tview("Temperature", new WinGeom(0, 0, 450, 600)); Tview.set_min_max_range(0,20); Tview.fix_scale_width(30); // Time stepping: int ts = 1; bool rhs_only = false; do { info("---- Time step %d, time %3.5f s, ext_temp %g C", ts, current_time, temp_ext(current_time)); // First time assemble both the stiffness matrix and right-hand side vector, // then just the right-hand side vector. if (rhs_only == false) info("Assembling the stiffness matrix and right-hand side vector."); else info("Assembling the right-hand side vector (only)."); dp.assemble(matrix, rhs, rhs_only); rhs_only = true; // Solve the linear system and if successful, obtain the solution. info("Solving the matrix problem."); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &tsln); else error ("Matrix solver failed.\n"); // Visualize the solution. char title[100]; sprintf(title, "Time %3.2f s, exterior temperature %3.5f C", current_time, temp_ext(current_time)); Tview.set_title(title); Tview.show(&tsln); // Increase current time and time step counter. current_time += time_step; ts++; } while (current_time < T_FINAL); // Wait for the view to be closed. View::wait(); return 0; }
// Main function. int main(int argc, char* argv[]) { // Either use exact constitutive relations (slow) (method 0) or precalculate // their linear approximations (faster) (method 1) or // precalculate their quintic polynomial approximations (method 2) -- managed by following loop "Initializing polynomial approximation". if (CONSTITUTIVE_TABLE_METHOD == 1) CONSTITUTIVE_TABLES_READY = get_constitutive_tables(ITERATIVE_METHOD); // Points to be used for polynomial approximation of K(h). double* points = new double[NUM_OF_INSIDE_PTS]; // The van Genuchten + Mualem K(h) function is approximated by polynomials close to zero in case of CONSTITUTIVE_TABLE_METHOD=1. // In case of CONSTITUTIVE_TABLE_METHOD=2, all constitutive functions are approximated by polynomials. info("Initializing polynomial approximations."); for (int i=0; i < MATERIAL_COUNT; i++) { info("Processing layer %d", i); init_polynomials(6 + NUM_OF_INSIDE_PTS, LOW_LIMIT, points, NUM_OF_INSIDE_PTS, i); } POLYNOMIALS_READY = true; if (CONSTITUTIVE_TABLE_METHOD == 2) { CONSTITUTIVE_TABLES_READY = true ; //Assign table limit to global definition. TABLE_LIMIT = INTERVALS_4_APPROX[NUM_OF_INTERVALS-1]; } // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh, basemesh; H2DReader mloader; mloader.load(mesh_file, &basemesh); // Initial refinements. //basemesh.refine_towards_boundary(1, 1); //basemesh.refine_towards_boundary(3, 1); //basemesh.refine_towards_boundary(4, 1); // Perform initial mesh refinements. mesh.copy(&basemesh); 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_1); bc_types.add_bc_neumann(Hermes::Tuple<int>(BDY_2, BDY_3, BDY_4)); // Enter Dirichlet boundary values. BCValues bc_values(&TIME); bc_values.add_timedep_function(BDY_1, essential_bc_values); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d.", ndof); // Create a selector which will select optimal candidate. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Solutions for the time stepping and the Newton's method. Solution sln, ref_sln, sln_prev_time, sln_prev_iter; // Assign the function f() to the fine mesh. sln_prev_time.set_exact(&mesh, init_cond); sln_prev_iter.set_exact(&mesh, init_cond); // Initialize the weak formulation. WeakForm wf; if (ITERATIVE_METHOD == 1) { if (TIME_INTEGRATION == 1) { info("Registering forms for the Newton's method (implicit Euler in time)."); wf.add_matrix_form(jac_form_vol_euler, jac_form_vol_ord, HERMES_NONSYM, HERMES_ANY, &sln_prev_time); wf.add_vector_form(res_form_vol_euler, res_form_vol_ord, HERMES_ANY, &sln_prev_time); } else { info("Registering forms for the Newton's method (Crank-Nicolson in time)."); wf.add_matrix_form(jac_form_vol_cranic, jac_form_vol_ord, HERMES_NONSYM, HERMES_ANY, &sln_prev_time); wf.add_vector_form(res_form_vol_cranic, res_form_vol_ord, HERMES_ANY, &sln_prev_time); } } else { if (TIME_INTEGRATION == 1) { info("Registering forms for the Picard's method (implicit Euler in time)."); wf.add_matrix_form(bilinear_form_picard_euler, bilinear_form_picard_euler_ord, HERMES_NONSYM, HERMES_ANY, &sln_prev_iter); wf.add_vector_form(linear_form_picard_euler, linear_form_picard_euler_ord, HERMES_ANY, Hermes::Tuple<MeshFunction*>(&sln_prev_iter, &sln_prev_time)); } else { info("Registering forms for the Picard's method (Crank-Nicolson in time)."); error("Not implemented yet."); wf.add_matrix_form(bilinear_form_picard_euler, bilinear_form_picard_euler_ord, HERMES_NONSYM, HERMES_ANY, &sln_prev_iter); wf.add_vector_form(linear_form_picard_euler, linear_form_picard_euler_ord, HERMES_ANY, Hermes::Tuple<MeshFunction*>(&sln_prev_iter, &sln_prev_time)); } } // Error estimate and discrete problem size as a function of physical time. SimpleGraph graph_time_err_est, graph_time_err_exact, graph_time_dof, graph_time_cpu, graph_time_step; // Visualize the projection and mesh. ScalarView view("Initial condition", new WinGeom(0, 0, 630, 350)); view.fix_scale_width(50); OrderView ordview("Initial mesh", new WinGeom(640, 0, 600, 350)); view.show(&sln_prev_time, HERMES_EPS_HIGH); ordview.show(&space); //MeshView mview("Mesh", new WinGeom(840, 0, 600, 350)); //mview.show(&mesh); //View::wait(); // Time stepping loop. int num_time_steps = (int)(T_FINAL/TAU + 0.5); for(int ts = 1; ts <= num_time_steps; ts++) { info("---- Time step %d:", ts); // Time measurement. cpu_time.tick(); // Periodic global derefinements. if (ts > 1 && ts % UNREF_FREQ == 0) { info("Global mesh derefinement."); //mesh.copy(&basemesh); // Brings the mesh back to the basemesh. mesh.unrefine_all_elements(); // Shaves off one layer of refinement for all elements. space.set_uniform_order(P_INIT); // Resets poly degree to the initial one. } // Spatial adaptivity loop. Note: sln_prev_time must not be touched during adaptivity. bool done = false; int as = 1; double err_est_rel; do { info("---- Time step %d, time step lenght %g, time %g (days), adaptivity step %d:", ts, TAU, TIME, as); // Construct globally refined reference mesh // and setup reference space. Space* ref_space = construct_refined_space(&space); ndof = Space::get_num_dofs(ref_space); // debug //BaseView bview("FE basis", new WinGeom(0, 360, 600, 350)); //H1Space *temp = (H1Space*)space.dup(&mesh); //temp->copy_orders((Space*)&space, 0); //bview.show(temp); // Next we need to calculate the reference solution. // Newton's method: if(ITERATIVE_METHOD == 1) { scalar* coeff_vec = new scalar[Space::get_num_dofs(ref_space)]; // Calculate initial coefficient vector for Newton on the fine mesh. if (as == 1 && ts == 1) { info("Projecting coarse mesh solution to obtain initial vector on new fine mesh."); OGProjection::project_global(ref_space, &sln_prev_time, coeff_vec, matrix_solver); } else { 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); delete ref_sln.get_mesh(); } // Initialize the FE problem. bool is_linear = false; 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); // Perform Newton's iteration on the reference mesh. If necessary, // reduce time step to make it converge, but then restore time step // size to its original value. info("Performing Newton's iteration (tau = %g days):", TAU); bool success, verbose = true; double* save_coeff_vec = new double[ndof]; // Save coefficient vector. for (int i=0; i < ndof; i++) save_coeff_vec[i] = coeff_vec[i]; double damping_coeff = 1.0; while (!solve_newton(coeff_vec, &dp, solver, matrix, rhs, NEWTON_TOL, NEWTON_MAX_ITER, verbose, damping_coeff)) { // Restore solution from the beginning of time step. for (int i=0; i < ndof; i++) coeff_vec[i] = save_coeff_vec[i]; // Reducing time step to 50%. info("Reducing time step size from %g to %g days for the rest of this time step.", TAU, TAU * TIMESTEP_DEC); TAU *= TIMESTEP_DEC; // If TAU less than the prescribed minimum, stop. if (TAU < TAU_MIN) error("Time step dropped below prescribed minimum value."); } // Delete the saved coefficient vector. delete [] save_coeff_vec; // Translate the resulting coefficient vector // into the desired reference solution. Solution::vector_to_solution(coeff_vec, ref_space, &ref_sln); // Cleanup. delete [] coeff_vec; delete solver; delete matrix; delete rhs; } else { // Calculate initial condition for Picard on the fine mesh. if (as == 1 && ts == 1) { info("Projecting coarse mesh solution to obtain initial vector on new fine mesh."); OGProjection::project_global(ref_space, &sln_prev_time, &sln_prev_iter, matrix_solver); } else { info("Projecting previous fine mesh solution to obtain initial vector on new fine mesh."); OGProjection::project_global(ref_space, &ref_sln, &sln_prev_iter, matrix_solver); } // Perform Picard iteration on the reference mesh. If necessary, // reduce time step to make it converge, but then restore time step // size to its original value. info("Performing Picard's iteration (tau = %g days):", TAU); bool success, verbose = true; while(!solve_picard(&wf, ref_space, &sln_prev_iter, matrix_solver, PICARD_TOL, PICARD_MAX_ITER, verbose)) { // Restore solution from the beginning of time step. sln_prev_iter.copy(&sln_prev_time); // Reducing time step to 50%. info("Reducing time step size from %g to %g days for the rest of this time step", TAU, TAU * TIMESTEP_DEC); TAU *= TIMESTEP_DEC; // If TAU less than the prescribed minimum, stop. if (TAU < TAU_MIN) error("Time step dropped below prescribed minimum value."); } ref_sln.copy(&sln_prev_iter); } /*** ADAPTIVITY ***/ // Project the fine mesh solution on the coarse mesh. info("Projecting fine mesh solution on coarse mesh for error calculation."); if(space.get_mesh() == NULL) error("it is NULL"); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Calculate element errors. info("Calculating error estimate."); Adapt* adaptivity = new Adapt(&space); // Calculate error estimate wrt. fine mesh solution. err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d, space_err_est_rel: %g%%", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_est_rel); // If space_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; break; } as++; } delete adaptivity; delete ref_space; } while (!done); // Add entries to graphs. graph_time_err_est.add_values(TIME, err_est_rel); graph_time_err_est.save("time_error_est.dat"); graph_time_dof.add_values(TIME, Space::get_num_dofs(&space)); graph_time_dof.save("time_dof.dat"); graph_time_cpu.add_values(TIME, cpu_time.accumulated()); graph_time_cpu.save("time_cpu.dat"); graph_time_step.add_values(TIME, TAU); graph_time_step.save("time_step_history.dat"); // Visualize the solution and mesh. char title[100]; sprintf(title, "Solution, time %g days", TIME); view.set_title(title); view.show(&sln, HERMES_EPS_HIGH); sprintf(title, "Mesh, time %g days", TIME); ordview.set_title(title); ordview.show(&space); // Save complete Solution. char* filename = new char[100]; sprintf(filename, "outputs/tsln_%f.dat", TIME); bool compress = false; // Gzip compression not used as it only works on Linux. sln.save(filename, compress); info("Solution at time %g saved to file %s.", TIME, filename); // Copy new reference level solution into sln_prev_time. // This starts new time step. sln_prev_time.copy(&ref_sln); // Updating time step. Note that TAU might have been reduced during adaptivity. TIME += TAU; // Increase time step. if (TAU < TAU_MAX) { info("Increasing time step from %g to %g days.", TAU, TAU * TIMESTEP_INC); TAU *= TIMESTEP_INC; } } // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char **args) { // Load the mesh. Mesh mesh; H3DReader mloader; mloader.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(); // 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); return 0; }
int main() { // Create space, set Dirichlet BC, enumerate basis functions. Space* space = new Space(A, B, NELEM, DIR_BC_LEFT, DIR_BC_RIGHT, P_INIT, NEQ); int ndof = Space::get_num_dofs(space); info("ndof: %d", ndof); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(jacobian_vol); wf.add_vector_form(residual_vol); wf.add_vector_form_surf(0, residual_surf_right, BOUNDARY_RIGHT); // Initialize the FE problem. bool is_linear = false; DiscreteProblem *dp = new DiscreteProblem(&wf, space, is_linear); // Newton's loop. // Fill vector coeff_vec using dof and coeffs arrays in elements. double *coeff_vec = new double[Space::get_num_dofs(space)]; get_coeff_vector(space, coeff_vec); // 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); int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(space); // Assemble the Jacobian matrix and residual vector. dp->assemble(coeff_vec, matrix, rhs); // 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(space), res_l2_norm); // If l2 norm of the residual vector is within tolerance, then quit. // NOTE: at least one full iteration forced // here because sometimes the initial // residual on fine mesh is too small. if(res_l2_norm < NEWTON_TOL && it > 1) break; // 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)); // 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 the maximum number of iteration has been reached, then quit. if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); // Copy coefficients from vector y to elements. set_coeff_vector(coeff_vec, space); it++; } // Plot the solution. Linearizer l(space); l.plot_solution("solution.gp"); // Plot the resulting space. space->plot("space.gp"); // Cleaning delete dp; delete rhs; delete solver; delete[] coeff_vec; delete space; delete bc; delete matrix; info("Done."); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("cathedral.mesh", &mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(bdy_air, INIT_REF_NUM_BDY); // Initialize an H1 space with default shepeset. H1Space space(&mesh, bc_types, essential_bc_values, P_INIT); int ndof = get_num_dofs(&space); info("ndof = %d.", ndof); // Set initial condition. Solution tsln; tsln.set_const(&mesh, T_INIT); // Initialize weak formulation. WeakForm wf; wf.add_matrix_form(bilinear_form<double, double>, bilinear_form<Ord, Ord>); wf.add_matrix_form_surf(bilinear_form_surf<double, double>, bilinear_form_surf<Ord, Ord>, bdy_air); wf.add_vector_form(linear_form<double, double>, linear_form<Ord, Ord>, H2D_ANY, &tsln); wf.add_vector_form_surf(linear_form_surf<double, double>, linear_form_surf<Ord, Ord>, bdy_air); // Initialize the linear problem. LinearProblem lp(&wf, &space); // Initialize matrix solver. Matrix* mat; Vector* rhs; CommonSolver* solver; init_matrix_solver(matrix_solver, ndof, mat, rhs, solver); // Initialize views. ScalarView Tview("Temperature", new WinGeom(0, 0, 450, 600)); char title[100]; sprintf(title, "Time %3.5f, exterior temperature %3.5f", TIME, temp_ext(TIME)); Tview.set_min_max_range(0,20); Tview.set_title(title); Tview.fix_scale_width(3); // Time stepping: int nsteps = (int)(FINAL_TIME/TAU + 0.5); bool rhsonly = false; for(int ts = 1; ts <= nsteps; ts++) { info("---- Time step %d, time %3.5f, ext_temp %g", ts, TIME, temp_ext(TIME)); // Assemble stiffness matrix and rhs. lp.assemble(mat, rhs, rhsonly); rhsonly = true; // Solve the matrix problem. if (!solver->solve(mat, rhs)) error ("Matrix solver failed.\n"); // Update tsln. tsln.set_fe_solution(&space, rhs); // Update the time variable. TIME += TAU; // Visualize the solution. sprintf(title, "Time %3.2f, exterior temperature %3.5f", TIME, temp_ext(TIME)); Tview.set_title(title); Tview.show(&tsln); } // Wait for the view to be closed. View::wait(); return 0; }
// Main function. int main(int argc, char* argv[]) { // Either use exact constitutive relations (slow) (method 0) or precalculate // their linear approximations (faster) (method 1) or // precalculate their quintic polynomial approximations (method 2) -- managed by // the following loop "Initializing polynomial approximation". if (CONSTITUTIVE_TABLE_METHOD == 1) CONSTITUTIVE_TABLES_READY = get_constitutive_tables(1); // 1 stands for the Newton's method. // Points to be used for polynomial approximation of K(h). double* points = new double[NUM_OF_INSIDE_PTS]; // The van Genuchten + Mualem K(h) function is approximated by polynomials close // to zero in case of CONSTITUTIVE_TABLE_METHOD==1. // In case of CONSTITUTIVE_TABLE_METHOD==2, all constitutive functions are approximated by polynomials. info("Initializing polynomial approximations."); for (int i=0; i < MATERIAL_COUNT; i++) { init_polynomials(6 + NUM_OF_INSIDE_PTS, LOW_LIMIT, points, NUM_OF_INSIDE_PTS, i); } POLYNOMIALS_READY = true; if (CONSTITUTIVE_TABLE_METHOD == 2) { CONSTITUTIVE_TABLES_READY = true ; //Assign table limit to global definition. TABLE_LIMIT = INTERVALS_4_APPROX[NUM_OF_INTERVALS-1]; } // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); if (bt.is_explicit()) info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Load the mesh. Mesh mesh, basemesh; H2DReader mloader; mloader.load(mesh_file, &basemesh); // Perform initial mesh refinements. mesh.copy(&basemesh); for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(BDY_TOP, INIT_REF_NUM_BDY_TOP); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(BDY_TOP); bc_types.add_bc_neumann(Hermes::vector<int>(BDY_RIGHT, BDY_BOTTOM, BDY_LEFT)); // Enter Dirichlet boundary values. BCValues bc_values(¤t_time); bc_values.add_timedep_function(BDY_TOP, essential_bc_values); // Create an H1 space with default shapeset. H1Space* space = new H1Space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(space); info("ndof = %d.", ndof); // Solution (initialized by the initial condition) and error function. Solution* sln_time_prev = new Solution(&mesh, init_cond); Solution* sln_time_new = new Solution(&mesh); Solution* time_error_fn = new Solution(&mesh, 0.0); // Initialize the weak formulation. WeakForm wf; info("Registering forms for the Newton's method."); wf.add_matrix_form(jac_form_vol, jac_form_vol_ord, HERMES_NONSYM, HERMES_ANY, sln_time_prev); wf.add_vector_form(res_form_vol, res_form_vol_ord, HERMES_ANY, sln_time_prev); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp(&wf, space, is_linear); // Visualize the projection and mesh. ScalarView sview("Initial condition", new WinGeom(0, 0, 400, 350)); sview.fix_scale_width(50); sview.show(sln_time_prev, HERMES_EPS_VERYHIGH); ScalarView eview("Temporal error", new WinGeom(405, 0, 400, 350)); eview.fix_scale_width(50); eview.show(time_error_fn, HERMES_EPS_VERYHIGH); OrderView oview("Initial mesh", new WinGeom(810, 0, 350, 350)); oview.show(space); // Graph for time step history. SimpleGraph time_step_graph; info("Time step history will be saved to file time_step_history.dat."); // Time stepping loop: int ts = 1; do { // Perform one Runge-Kutta time step according to the selected Butcher's table. info("Runge-Kutta time step (t = %g, tau = %g, stages: %d).", current_time, time_step, bt.get_size()); bool verbose = true; bool is_linear = false; if (!rk_time_step(current_time, time_step, &bt, sln_time_prev, sln_time_new, time_error_fn, &dp, matrix_solver, verbose, is_linear, NEWTON_TOL, NEWTON_MAX_ITER)) { info("Runge-Kutta time step failed, decreasing time step size from %g to %g days.", time_step, time_step * time_step_dec); time_step *= time_step_dec; if (time_step < time_step_min) error("Time step became too small."); continue; } // Show error function. char title[100]; sprintf(title, "Temporal error, t = %g", current_time); eview.set_title(title); eview.show(time_error_fn, HERMES_EPS_VERYHIGH); // Calculate relative time stepping error and decide whether the // time step can be accepted. If not, then the time step size is // reduced and the entire time step repeated. If yes, then another // check is run, and if the relative error is very low, time step // is increased. double rel_err_time = calc_norm(time_error_fn, HERMES_H1_NORM) / calc_norm(sln_time_new, HERMES_H1_NORM) * 100; info("rel_err_time = %g%%", rel_err_time); if (rel_err_time > time_tol_upper) { info("rel_err_time above upper limit %g%% -> decreasing time step from %g to %g days and repeating time step.", time_tol_upper, time_step, time_step * time_step_dec); time_step *= time_step_dec; continue; } if (rel_err_time < time_tol_lower) { info("rel_err_time = below lower limit %g%% -> increasing time step from %g to %g days", time_tol_lower, time_step, time_step * time_step_inc); time_step *= time_step_inc; } // Add entry to the timestep graph. time_step_graph.add_values(current_time, time_step); time_step_graph.save("time_step_history.dat"); // Update time. current_time += time_step; // Show the new time level solution. sprintf(title, "Solution, t = %g", current_time); sview.set_title(title); sview.show(sln_time_new, HERMES_EPS_VERYHIGH); oview.show(space); // Save complete Solution. char filename[100]; sprintf(filename, "outputs/tsln_%f.dat", current_time); bool compress = false; // Gzip compression not used as it only works on Linux. sln_time_new->save(filename, compress); info("Solution at time %g saved to file %s.", current_time, filename); // Save solution for the next time step. sln_time_prev->copy(sln_time_new); // Increase counter of time steps. ts++; } while (current_time < T_FINAL); // Cleanup. delete space; delete sln_time_prev; delete sln_time_new; delete time_error_fn; // 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); // Initial mesh refinements. 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_DIRICHLET_1, BDY_DIRICHLET_2, BDY_DIRICHLET_3, BDY_DIRICHLET_4)); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_zero(Hermes::Tuple<int>(BDY_DIRICHLET_1, BDY_DIRICHLET_2, BDY_DIRICHLET_3, BDY_DIRICHLET_4)); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d.", ndof); // Previous time level solution. Solution psi_prev_time(&mesh, init_cond); // Initialize the weak formulation. WeakForm wf; if(TIME_DISCR == 1) { wf.add_matrix_form(callback(J_euler), HERMES_UNSYM, HERMES_ANY); wf.add_vector_form(callback(F_euler), HERMES_ANY, &psi_prev_time); } else { wf.add_matrix_form(callback(J_cranic), HERMES_UNSYM, HERMES_ANY); wf.add_vector_form(callback(F_cranic), HERMES_ANY, &psi_prev_time); } // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // 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 = new scalar[ndof]; OGProjection::project_global(&space, &psi_prev_time, coeff_vec, matrix_solver); // Time stepping loop: int nstep = (int)(T_FINAL/TAU + 0.5); for(int ts = 1; ts <= nstep; ts++) { info("Time step %d:", ts); // Perform Newton's iteration. info("Solving nonlinear problem:"); bool verbose = true; if (!solve_newton(coeff_vec, &dp, solver, matrix, rhs, NEWTON_TOL, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Update previous time level solution. Solution::vector_to_solution(coeff_vec, &space, &psi_prev_time); } delete coeff_vec; delete matrix; delete rhs; delete solver; AbsFilter mag2(&psi_prev_time); 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) psi value = %lf", val); if (fabs(val - (0.804900)) > eps) { printf("Coordinate ( 0.1, 0.1) psi value = %lf\n", val); success = 0; } val = std::abs(mag2.get_pt_value(0.1, -0.1)); info("Coordinate ( 0.1, -0.1) psi value = %lf", val); if (fabs(val - (0.804900)) > eps) { printf("Coordinate ( 0.1, -0.1) psi value = %lf\n", val); success = 0; } val = std::abs(mag2.get_pt_value(0.2, 0.1)); info("Coordinate ( 0.2, 0.1) psi value = %lf", val); if (fabs(val - (0.602930)) > eps) { printf("Coordinate ( 0.2, 0.1) psi 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[]) { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); // Perform initial mesh refinements. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Create an H1 space with default shapeset. H1Space space(&mesh, bc_types, essential_bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d", ndof); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(bilinear_form, bilinear_form_ord, HERMES_SYM); wf.add_vector_form(linear_form, linear_form_ord); wf.add_vector_form_surf(linear_form_surf, linear_form_surf_ord, BDY_VERTICAL); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); initialize_solution_environment(matrix_solver, argc, argv); 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). } // Initialize the solution. Solution sln; // Assemble the stiffness matrix and right-hand side vector. info("Assembling the stiffness matrix and right-hand side vector."); dp.assemble(matrix, rhs); // Solve the linear system and if successful, obtain the solution. info("Solving the matrix problem."); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Clean up. delete solver; delete matrix; delete rhs; finalize_solution_environment(matrix_solver); // View the solution and mesh. ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); sview.show(&sln); OrderView oview("Polynomial orders", new WinGeom(450, 0, 400, 350)); oview.show(&space); // Skip visualization time. cpu_time.tick(HERMES_SKIP); // Print timing information. verbose("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char **argv) { int res = ERR_SUCCESS; #ifdef WITH_PETSC PetscInitialize(&argc, &argv, (char *) PETSC_NULL, PETSC_NULL); #endif set_verbose(false); if (argc < 3) error("Not enough parameters"); printf("* Loading mesh '%s'\n", argv[1]); Mesh mesh; H3DReader mesh_loader; if (!mesh_loader.load(argv[1], &mesh)) error("Loading mesh file '%s'\n", argv[1]); int o; sscanf(argv[2], "%d", &o); printf(" - Setting uniform order to %d\n", o); printf("* Setting the space up\n"); H1Space space(&mesh, bc_types, NULL, o); int ndofs = space.assign_dofs(); printf(" - Number of DOFs: %d\n", ndofs); printf("* Calculating a solution\n"); #if defined WITH_UMFPACK UMFPackMatrix mat; UMFPackVector rhs; UMFPackLinearSolver solver(&mat, &rhs); #elif defined WITH_PARDISO PardisoMatrix mat; PardisoVector rhs; PardisoLinearSolver solver(&mat, &rhs); #elif defined WITH_PETSC PetscMatrix mat; PetscVector rhs; PetscLinearSolver solver(&mat, &rhs); #elif defined WITH_MUMPS MumpsMatrix mat; MumpsVector rhs; MumpsSolver solver(&mat, &rhs); #endif WeakForm wf; wf.add_matrix_form(FORM_CB(bilinear_form), SYM); wf.add_vector_form(FORM_CB(linear_form)); DiscreteProblem dp(&wf, &space, true); // assemble stiffness matrix Timer assemble_timer("Assembling stiffness matrix"); assemble_timer.start(); dp.assemble(&mat, &rhs); assemble_timer.stop(); // solve the stiffness matrix Timer solve_timer("Solving stiffness matrix"); solve_timer.start(); bool solved = solver.solve(); solve_timer.stop(); // output the measured values printf("%s: %s (%lf secs)\n", assemble_timer.get_name(), assemble_timer.get_human_time(), assemble_timer.get_seconds()); printf("%s: %s (%lf secs)\n", solve_timer.get_name(), solve_timer.get_human_time(), solve_timer.get_seconds()); // mat.dump(stdout, "a"); // rhs.dump(stdout, "b"); if (solved) { Solution sln(&mesh); sln.set_coeff_vector(&space, solver.get_solution() ); ExactSolution ex_sln(&mesh, exact_solution); // norm // double h1_sln_norm = h1_norm(&sln); double h1_err_norm = h1_error(&sln, &ex_sln); // printf(" - H1 solution norm: % le\n", h1_sln_norm); printf(" - H1 error norm: % le\n", h1_err_norm); // double l2_sln_norm = l2_norm(&sln); // double l2_err_norm = l2_error(&sln, &ex_sln); // printf(" - L2 solution norm: % le\n", l2_sln_norm); // printf(" - L2 error norm: % le\n", l2_err_norm); // if (h1_err_norm > EPS || l2_err_norm > EPS) { // calculated solution is not enough precise // res = ERR_FAILURE; // } #ifdef AOUTPUT_DIR // output const char *of_name = OUTPUT_DIR "/solution.pos"; FILE *ofile = fopen(of_name, "w"); if (ofile != NULL) { DiffFilter eh(&sln, &ex_sln); // DiffFilter eh_dx(&sln, &ex_sln, FN_DX, FN_DX); // DiffFilter eh_dy(&sln, &ex_sln, FN_DY, FN_DY); // DiffFilter eh_dz(&sln, &ex_sln, FN_DZ, FN_DZ); GmshOutputEngine output(ofile); output.out(&sln, "Uh"); // output.out(&sln, "Uh dx", FN_DX_0); // output.out(&sln, "Uh dy", FN_DY_0); // output.out(&sln, "Uh dz", FN_DZ_0); output.out(&eh, "Eh"); // output.out(&eh_dx, "Eh dx"); // output.out(&eh_dy, "Eh dy"); // output.out(&eh_dz, "Eh dz"); output.out(&ex_sln, "U"); // output.out(&ex_sln, "U dx", FN_DX_0); // output.out(&ex_sln, "U dy", FN_DY_0); // output.out(&ex_sln, "U dz", FN_DZ_0); fclose(ofile); } else { warning("Can not open '%s' for writing.", of_name); } #endif } #ifdef WITH_PETSC mat.free(); rhs.free(); PetscFinalize(); #endif return res; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); // Perform initial mesh refinements. for(int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_vertex(3, CORNER_REF_LEVEL); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(BDY_LEFT); bc_types.add_bc_neumann(Hermes::vector<int>(BDY_OUTER, BDY_INNER)); bc_types.add_bc_newton(BDY_BOTTOM); // Enter Dirichlet boudnary values. BCValues bc_values; bc_values.add_const(BDY_LEFT, T1); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d", ndof); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(bilinear_form)); wf.add_matrix_form_surf(callback(bilinear_form_surf), BDY_BOTTOM); wf.add_vector_form_surf(callback(linear_form_surf), BDY_BOTTOM); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the solution. Solution sln; // Assemble the stiffness matrix and right-hand side vector. info("Assembling the stiffness matrix and right-hand side vector."); dp.assemble(matrix, rhs); // Solve the linear system and if successful, obtain the solution. info("Solving the matrix problem."); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); // Visualize the solution. ScalarView view("Solution", new WinGeom(0, 0, 440, 350)); view.show(&sln); // Compute and show gradient magnitude. // (Note that the gradient at the re-entrant // corner needs to be truncated for visualization purposes.) ScalarView gradview("Gradient", new WinGeom(450, 0, 400, 350)); MagFilter grad(Hermes::vector<MeshFunction *>(&sln, &sln), Hermes::vector<int>(H2D_FN_DX, H2D_FN_DY)); gradview.show(&grad); // Wait for all views to be closed. View::wait(); // Clean up. delete solver; delete matrix; delete rhs; return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh, basemesh; H2DReader mloader; mloader.load("domain.mesh", &basemesh); // Perform initial mesh refinements. mesh.copy(&basemesh); for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(3, INIT_REF_NUM_BDY); // Create an H1 space with default shapeset. H1Space space(&mesh, bc_types, essential_bc_values, P_INIT); int ndof = get_num_dofs(&space); info("ndof = %d.", ndof); // Create a selector which will select optimal candidate. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Solutions for the time stepping and the Newton's method. Solution sln, ref_sln, u_prev_time; // Adapt mesh to represent initial condition with given accuracy. int proj_norm = 1; // H1 norm. bool verbose = false; double err_stop_init_cond = 0.1 * ERR_STOP; adapt_to_exact_function(&space, proj_norm, init_cond, &selector, THRESHOLD, STRATEGY, MESH_REGULARITY, ERR_STOP, NDOF_STOP, verbose, &u_prev_time); // Assign initial condition to mesh. u_prev_time.set_exact(&mesh, init_cond); Vector *coeff_vec = new AVector(ndof); // Calculating initial vector for Newton. info("Projecting initial condition to obtain coefficient vector for Newton on coarse mesh."); project_global(&space, H2D_H1_NORM, &u_prev_time, &u_prev_time, coeff_vec); // Initialize the weak formulation. WeakForm wf; if (TIME_INTEGRATION == 1) { wf.add_matrix_form(jac_form_vol_euler, jac_form_vol_ord, H2D_UNSYM, H2D_ANY, Tuple<MeshFunction*>(&u_prev_time)); wf.add_matrix_form_surf(jac_form_surf_1_euler, jac_form_surf_1_ord, BDY_1); wf.add_matrix_form_surf(jac_form_surf_4_euler, jac_form_surf_4_ord, BDY_4); wf.add_matrix_form_surf(jac_form_surf_6_euler, jac_form_surf_6_ord, BDY_6); wf.add_vector_form(res_form_vol_euler, res_form_vol_ord, H2D_ANY, Tuple<MeshFunction*>(&u_prev_time)); wf.add_vector_form_surf(res_form_surf_1_euler, res_form_surf_1_ord, BDY_1); wf.add_vector_form_surf(res_form_surf_4_euler, res_form_surf_4_ord, BDY_4); wf.add_vector_form_surf(res_form_surf_6_euler, res_form_surf_6_ord, BDY_6); } else { wf.add_matrix_form(jac_form_vol_cranic, jac_form_vol_ord, H2D_UNSYM, H2D_ANY, Tuple<MeshFunction*>(&u_prev_time)); wf.add_matrix_form_surf(jac_form_surf_1_cranic, jac_form_surf_1_ord, BDY_1); wf.add_matrix_form_surf(jac_form_surf_4_cranic, jac_form_surf_4_ord, BDY_4); wf.add_matrix_form_surf(jac_form_surf_6_cranic, jac_form_surf_6_ord, BDY_6); wf.add_vector_form(res_form_vol_cranic, res_form_vol_ord, H2D_ANY, Tuple<MeshFunction*>(&u_prev_time)); wf.add_vector_form_surf(res_form_surf_1_cranic, res_form_surf_1_ord, BDY_1, Tuple<MeshFunction*>( &u_prev_time)); wf.add_vector_form_surf(res_form_surf_4_cranic, res_form_surf_4_ord, BDY_4, Tuple<MeshFunction*>(&u_prev_time)); wf.add_vector_form_surf(res_form_surf_6_cranic, res_form_surf_6_ord, BDY_6, Tuple<MeshFunction*>(&u_prev_time)); } // Initialize adaptivity parameters. AdaptivityParamType apt(ERR_STOP, NDOF_STOP, THRESHOLD, STRATEGY, MESH_REGULARITY); // Time stepping loop. int num_time_steps = (int)(T_FINAL/TAU + 0.5); for(int ts = 1; ts <= num_time_steps; ts++) { info("---- Time step %d:", ts); // Periodic global derefinements. if (ts > 1 && ts % UNREF_FREQ == 0) { info("Global mesh derefinement."); mesh.copy(&basemesh); space.set_uniform_order(P_INIT); } // Update the coefficient vector and u_prev_time. info("Projecting to obtain coefficient vector on coarse mesh."); project_global(&space, H2D_H1_NORM, &u_prev_time, &u_prev_time, coeff_vec); bool verbose = false; // Print info during adaptivity. info("Projecting coarse mesh solution to obtain initial vector on new fine mesh."); // The NULL pointers mean that we are not interested in visualization during the Newton's loop. solve_newton_adapt(&space, &wf, coeff_vec, matrix_solver, H2D_H1_NORM, &sln, &ref_sln, Tuple<WinGeom *>(), Tuple<WinGeom *>(), &selector, &apt, NEWTON_TOL_COARSE, NEWTON_TOL_FINE, NEWTON_MAX_ITER, verbose); // Copy new time level reference solution into u_prev_time. u_prev_time.set_coeff_vector(&space, coeff_vec); } // Waiting for test. }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("motor.mesh", &mesh); // 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(biform1), HERMES_SYM, OMEGA_1); wf.add_matrix_form(callback(biform2), HERMES_SYM, OMEGA_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, 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()); // 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, basemesh; H2DReader mloader; mloader.load("square.mesh", &basemesh); // Initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) basemesh.refine_all_elements(); mesh.copy(&basemesh); // Create an H1 space with default shapeset. H1Space space(&mesh, bc_types, essential_bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d.", ndof); // Initialize coarse and reference mesh solution. Solution sln, ref_sln; Solution sln_prev_time(&mesh, init_cond); // Initialize the weak formulation. WeakForm wf; if(TIME_DISCR == 1) { wf.add_matrix_form(callback(J_euler), HERMES_UNSYM, HERMES_ANY); wf.add_vector_form(callback(F_euler), HERMES_ANY, &sln_prev_time); } else { wf.add_matrix_form(callback(J_cranic), HERMES_UNSYM, 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); // Show the projection of the initial condition. char title[100]; ScalarView magview("Projection of initial condition", new WinGeom(0, 0, 440, 350)); magview.fix_scale_width(60); Solution init_proj; // init_proj->set_coeff_vector(space, coeff_vec_coarse); Solution::vector_to_solution(coeff_vec_coarse, &space, &init_proj); AbsFilter mag(&init_proj); magview.show(&mag); // delete init_proj; OrderView ordview("Initial mesh", new WinGeom(450, 0, 400, 350)); ordview.show(&space); // Newton's loop on the coarse mesh. info("Solving on coarse mesh:"); int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(&space); // Assemble the Jacobian matrix and residual vector. dp_coarse.assemble(coeff_vec_coarse, matrix_coarse, rhs_coarse, 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_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(&space), res_l2_norm); // If l2 norm of the residual vector is in tolerance, or the maximum number // of iteration has been hit, then quit. if (res_l2_norm < NEWTON_TOL_COARSE || it > NEWTON_MAX_ITER) break; // Solve the linear system and if successful, obtain the solution. if(!solver_coarse->solve()) error ("Matrix solver 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 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, &ref_sln, &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); } else { info("Projecting previous fine mesh solution to obtain coefficient vector on new fine mesh."); OGProjection::project_global(ref_space, &ref_sln, coeff_vec); } // Newton's loop on the fine mesh. info("Solving on fine mesh:"); int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(ref_space); // 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_space), 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++; } // 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, HERMES_H1_NORM); bool solutions_for_adapt = true; double err_est_rel_total = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 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++; } info("Projecting fine mesh solution on new coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln); // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; delete ref_space->get_mesh(); delete ref_space; delete dp; // Visualize the solution and mesh. char title[100]; sprintf(title, "Solution, time level %d", ts); magview.set_title(title); magview.show(&sln); sprintf(title, "Mesh, time level %d", ts); ordview.set_title(title); ordview.show(&space); } while (done == false); // Copy last reference solution into sln_prev_time. sln_prev_time.copy(&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(BDY_DIRICHLET, 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); int ndof = Space::get_num_dofs(&space); // Initialize the weak formulation WeakForm wf; wf.add_matrix_form(callback(jac), HERMES_NONSYM, HERMES_ANY); wf.add_vector_form(callback(res), HERMES_ANY); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the solution. Solution sln; // Project the initial condition on the FE space to obtain initial // coefficient vector for the Newton's method. info("Projecting to obtain initial vector for the Newton's method."); scalar* coeff_vec = new scalar[Space::get_num_dofs(&space)] ; Solution* init_sln = new Solution(&mesh, init_cond); OGProjection::project_global(&space, init_sln, coeff_vec, matrix_solver); delete init_sln; // Perform Newton's iteration. bool verbose = true; if (!solve_newton(coeff_vec, &dp, solver, matrix, rhs, NEWTON_TOL, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution::vector_to_solution(coeff_vec, &space, &sln); // Cleanup. delete []coeff_vec; delete matrix; delete rhs; delete solver; info("ndof = %d", ndof); info("Coordinate (1, 0) value = %lf", sln.get_pt_value(1.0, 0.0)); info("Coordinate (3, 0) value = %lf", sln.get_pt_value(3.0, 0.0)); info("Coordinate (5, 0) value = %lf", sln.get_pt_value(5.0, 0.0)); info("Coordinate (7, 0) value = %lf", sln.get_pt_value(7.0, 0.0)); double coor_x[4] = {1.0, 3.0, 5.0, 7.0}; double coor_y = 0.0; double t_value[4] = {2.867436, 2.873677, 2.832594, 2.709390}; bool success = true; for (int i = 0; i < 4; i++) { if (abs(t_value[i] - sln.get_pt_value(coor_x[i], coor_y)) > 1E-6) success = false; } if (success) { // should pass with NEWTON_MAX_ITER = 9 and fail with NEWTON_MAX_ITER = 8 printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main() { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Create coarse mesh, set Dirichlet BC, enumerate basis functions. Space* space = new Space(A, B, NELEM, DIR_BC_LEFT, DIR_BC_RIGHT, P_INIT, NEQ); // Enumerate basis functions, info for user. int ndof = Space::get_num_dofs(space); info("ndof: %d", ndof); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(jacobian); wf.add_vector_form(residual); // Initialize the FE problem. bool is_linear = false; DiscreteProblem *dp_coarse = new DiscreteProblem(&wf, space, is_linear); // Newton's loop on coarse mesh. // Fill vector coeff_vec using dof and coeffs arrays in elements. double *coeff_vec_coarse = new double[Space::get_num_dofs(space)]; get_coeff_vector(space, coeff_vec_coarse); // Set up the solver, matrix, and rhs 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); int it = 1; bool success = false; while (1) { // Obtain the number of degrees of freedom. int ndof_coarse = Space::get_num_dofs(space); // Assemble the Jacobian matrix and residual vector. dp_coarse->assemble(coeff_vec_coarse, matrix_coarse, rhs_coarse); // 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(space), res_l2_norm); // If l2 norm of the residual vector is within tolerance, then quit. // NOTE: at least one full iteration forced // here because sometimes the initial // residual on fine mesh is too small. if(res_l2_norm < NEWTON_TOL_COARSE && it > 1) break; // 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_coarse; i++) rhs_coarse->set(i, -rhs_coarse->get(i)); // Solve the linear system. if(!solver_coarse->solve()) error ("Matrix solver failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof_coarse; i++) coeff_vec_coarse[i] += solver_coarse->get_solution()[i]; // If the maximum number of iteration has been reached, then quit. if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); // Copy coefficients from vector y to elements. set_coeff_vector(coeff_vec_coarse, space); it++; } // Cleanup. delete matrix_coarse; delete rhs_coarse; delete solver_coarse; delete [] coeff_vec_coarse; delete dp_coarse; // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est; SimpleGraph 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); // Initialize the FE problem. bool is_linear = false; DiscreteProblem* dp = new DiscreteProblem(&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); // Newton's loop on the fine mesh. info("Solving on fine mesh:"); // Fill vector coeff_vec using dof and coeffs arrays in elements. double *coeff_vec = new double[Space::get_num_dofs(ref_space)]; get_coeff_vector(ref_space, coeff_vec); int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(ref_space); // Assemble the Jacobian matrix and residual vector. dp->assemble(coeff_vec, matrix, rhs); // 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_space), res_l2_norm); // If l2 norm of the residual vector is within tolerance, then quit. // NOTE: at least one full iteration forced // here because sometimes the initial // residual on fine mesh is too small. if(res_l2_norm < NEWTON_TOL_REF && it > 1) break; // 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)); // Solve the linear system. if(!(success = 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 the maximum number of iteration has been reached, then quit. if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); // Copy coefficients from vector y to elements. set_coeff_vector(coeff_vec, ref_space); it++; } // Starting with second adaptivity step, obtain new coarse // mesh solution via projecting the fine mesh solution. if(as > 1) { info("Projecting the fine mesh solution onto the coarse mesh."); // Project the fine mesh solution (defined on space_ref) onto the coarse mesh (defined on space). OGProjection::project_global(space, ref_space, matrix_solver); } // Calculate element errors and total error estimate. info("Calculating error estimate."); double err_est_array[MAX_ELEM_NUM]; double err_est_rel = calc_err_est(NORM, space, ref_space, err_est_array) * 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(); // If exact solution available, also calculate exact error. if (EXACT_SOL_PROVIDED) { // Calculate element errors wrt. exact solution. double err_exact_rel = calc_err_exact(NORM, space, exact_sol, NEQ, A, B) * 100; // Info for user. info("Relative error (exact) = %g %%", err_exact_rel); // Add entry to DOF and CPU convergence graphs. graph_dof_exact.add_values(Space::get_num_dofs(space), err_exact_rel); graph_cpu_exact.add_values(cpu_time.accumulated(), 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_cpu_est.add_values(cpu_time.accumulated(), err_est_rel); // If err_est_rel too large, adapt the mesh. if (err_est_rel < NEWTON_TOL_REF) done = true; else { info("Adapting the coarse mesh."); adapt(NORM, ADAPT_TYPE, THRESHOLD, err_est_array, space, ref_space); } as++; // Plot meshes, results, and errors. adapt_plotting(space, ref_space, NORM, EXACT_SOL_PROVIDED, exact_sol); // Cleanup. delete solver; delete matrix; delete rhs; delete ref_space; delete dp; delete [] coeff_vec; } while (done == false); info("Total running time: %g s", cpu_time.accumulated()); // Save convergence graphs. graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.save("conv_cpu_est.dat"); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.save("conv_cpu_exact.dat"); // Test variable. info("ndof = %d.", Space::get_num_dofs(space)); if (Space::get_num_dofs(space) > 60) success = false; if (success) { info("Success!"); return ERROR_SUCCESS; } else { info("Failure!"); return ERROR_FAILURE; } }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); // Perform initial mesh refinements. mesh.refine_element(0); // Create an H1 space. H1Space space(&mesh, bc_types, essential_bc_values, P_INIT); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(bilinear_form)); wf.add_vector_form(callback(linear_form)); // Testing n_dof and correctness of solution vector // for p_init = 1, 2, ..., 10 int success = 1; for (int p_init = 1; p_init <= 10; p_init++) { printf("********* p_init = %d *********\n", p_init); space.set_uniform_order(p_init); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the solution. Solution sln; // Assemble the stiffness matrix and right-hand side vector. info("Assembling the stiffness matrix and right-hand side vector."); bool rhsonly = false; dp.assemble(matrix, rhs, rhsonly); // Solve the linear system and if successful, obtain the solution. info("Solving the matrix problem."); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); int ndof = Space::get_num_dofs(&space); printf("ndof = %d\n", ndof); double sum = 0; for (int i=0; i < ndof; i++) sum += solver->get_solution()[i]; printf("coefficient sum = %g\n", sum); // Actual test. The values of 'sum' depend on the // current shapeset. If you change the shapeset, // you need to correct these numbers. if (p_init == 1 && fabs(sum - 0.1875) > 1e-3) success = 0; if (p_init == 2 && fabs(sum + 0.927932) > 1e-3) success = 0; if (p_init == 3 && fabs(sum + 0.65191) > 1e-3) success = 0; if (p_init == 4 && fabs(sum + 0.939909) > 1e-3) success = 0; if (p_init == 5 && fabs(sum + 0.63356) > 1e-3) success = 0; if (p_init == 6 && fabs(sum + 0.905309) > 1e-3) success = 0; if (p_init == 7 && fabs(sum + 0.61996) > 1e-3) success = 0; if (p_init == 8 && fabs(sum + 0.909494) > 1e-3) success = 0; if (p_init == 9 && fabs(sum + 0.610543) > 1e-3) success = 0; if (p_init == 10 && fabs(sum + 0.902731) > 1e-3) 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("square.mesh", &mesh); // 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); // Create an H1 space with default shapeset. H1Space space(&mesh, bc_types, essential_bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d.", ndof); // Previous time level solution (initialized by the initial condition). Solution u_prev_time(&mesh, init_cond); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(jac), HERMES_UNSYM, HERMES_ANY); wf.add_vector_form(callback(res), HERMES_ANY, &u_prev_time); // 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 = new scalar[ndof]; OGProjection::project_global(&space, &u_prev_time, coeff_vec, matrix_solver); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Time stepping loop: double current_time = 0.0; int ts = 1; do { info("---- Time step %d, t = %g s.", ts, current_time); ts++; // Perform Newton's iteration. int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(&space); // 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(&space), 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 || 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++; } // Update previous time level solution. Solution::vector_to_solution(coeff_vec, &space, &u_prev_time); // Update time. current_time += TAU; } while (current_time < T_FINAL); // Cleanup. delete [] coeff_vec; delete matrix; delete rhs; delete solver; ndof = Space::get_num_dofs(&space); info("Coordinate (-10, -10) value = %lf", u_prev_time.get_pt_value(-10.0, -10.0)); info("Coordinate ( -6, -6) value = %lf", u_prev_time.get_pt_value(-6.0, -6.0)); info("Coordinate ( -2, -2) value = %lf", u_prev_time.get_pt_value(-2.0, -2.0)); info("Coordinate ( 2, 2) value = %lf", u_prev_time.get_pt_value(2.0, 2.0)); info("Coordinate ( 6, 6) value = %lf", u_prev_time.get_pt_value(6.0, 6.0)); info("Coordinate ( 10, 10) value = %lf", u_prev_time.get_pt_value(10.0, 10.0)); #define ERROR_SUCCESS 0 #define ERROR_FAILURE -1 double coor_x_y[6] = {-10.0, -6.0, -2.0, 2.0, 6.0, 10.0}; double value[6] = {0.000000, 2.311376, 2.748304, 2.919943, 3.146120, 4.000000}; for (int i = 0; i < 6; i++) { if ((value[i] - u_prev_time.get_pt_value(coor_x_y[i], coor_x_y[i])) < 1E-6) { printf("Success!\n"); } else { printf("Failure!\n"); return ERROR_FAILURE; } } return ERROR_SUCCESS; }