int main (int argc, char* argv[]) { // load the mesh file Mesh Cmesh, phimesh, basemesh; H2DReader mloader; mloader.load("small.mesh", &basemesh); basemesh.refine_towards_boundary(TOP_MARKER, REF_INIT); basemesh.refine_towards_boundary(BOT_MARKER, REF_INIT - 1); Cmesh.copy(&basemesh); phimesh.copy(&basemesh); // Spaces for concentration and the voltage. H1Space C(&Cmesh, C_bc_types, NULL, P_INIT); H1Space phi(MULTIMESH ? &phimesh : &Cmesh, phi_bc_types, essential_bc_values, P_INIT); // set polynomial degrees. C.set_uniform_order(P_INIT); phi.set_uniform_order(P_INIT); info("ndof: %d", C.get_num_dofs() + phi.get_num_dofs()); // The weak form for 2 equations. WeakForm wf(2); Solution C_prev_time, // prveious time step solution, for the time integration C_prev_newton, // solution convergin during the Newton's iteration phi_prev_time, phi_prev_newton; // Add the bilinear and linear forms // generally, the equation system is described: // a11(u1, v1) + a12(u2, v1) + a1n(un, v1) = l1(v1) // a21(u1, v2) + a22(u2, v2) + a2n(un, v2) = l2(v2) // an1(u1, vn) + an2(u2, vn) + ann(un, vn) = ln(vn) wf.add_matrix_form(0, 0, callback(J_euler_DFcDYc), H2D_UNSYM, H2D_ANY, &phi_prev_newton); wf.add_matrix_form(0, 1, callback(J_euler_DFcDYphi), H2D_UNSYM, H2D_ANY, &C_prev_newton); wf.add_matrix_form(1, 0, callback(J_euler_DFphiDYc), H2D_UNSYM); wf.add_matrix_form(1, 1, callback(J_euler_DFphiDYphi), H2D_UNSYM); wf.add_vector_form(0, callback(Fc_euler), H2D_ANY, Tuple<MeshFunction*>(&C_prev_time, &C_prev_newton, &phi_prev_newton)); wf.add_vector_form(1, callback(Fphi_euler), H2D_ANY, Tuple<MeshFunction*>(&C_prev_newton, &phi_prev_newton)); // Neumann voltage boundary. wf.add_vector_form_surf(1, callback(linear_form_surf_top), TOP_MARKER); // Nonlinear solver. NonlinSystem nls(&wf, Tuple<Space*>(&C, &phi)); info("UmfpackSolver initialized"); // View initial guess for Newton's method // initial BC C_prev_time.set_const(&Cmesh, C0); phi_prev_time.set_const(MULTIMESH ? &phimesh : &Cmesh, 0); // phi_prev_time.set_exact(MULTIMESH ? &phimesh : &Cmesh, voltage_ic); // C_prev_time.set_exact(&Cmesh, concentration_ic); C_prev_newton.copy(&C_prev_time); phi_prev_newton.copy(&phi_prev_time); nls.project_global(Tuple<MeshFunction*>(&C_prev_newton, &phi_prev_newton), Tuple<Solution*>(&C_prev_newton, &phi_prev_newton)); bool success = solveAdaptive(Cmesh, phimesh, basemesh, nls, C, phi, C_prev_time, C_prev_newton, phi_prev_time, phi_prev_newton); // bool success = solveNonadaptive(Cmesh, nls, C_prev_time, C_prev_newton, // phi_prev_time, phi_prev_newton); if (success) { printf("SUCCESSFUL\n"); } else { printf("FAIL\n"); } #define ERROR_SUCCESS 0 #define ERROR_FAILURE -1 return success ? ERROR_SUCCESS : ERROR_FAILURE; }
// 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); // 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; } // 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; // 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; return ERR_FAILURE; }
int main(int argc, char **argv) { // Instantiate a class with global functions. Hermes2D hermes2d; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("square.mesh", &mesh); // Perform initial mesh refinemets. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Set exact solution. CustomExactSolution exact(&mesh); // Initialize boundary conditions DefaultEssentialBCNonConst bc_essential("Bdy", &exact); EssentialBCs bcs(&bc_essential); // Initialize the weak formulation. CustomWeakFormPoisson wf1; // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof: %d", ndof); info("---- Assembling by DiscreteProblem, solving by %s:", MatrixSolverNames[matrix_solver].c_str()); // Initialize the linear discrete problem. DiscreteProblem dp1(&wf1, &space); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Begin time measurement of assembly. cpu_time.tick(HERMES_SKIP); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof]; memset(coeff_vec, 0, ndof*sizeof(scalar)); // Perform Newton's iteration. if (!hermes2d.solve_newton(coeff_vec, &dp1, solver, matrix, rhs)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution sln1; Solution::vector_to_solution(coeff_vec, &space, &sln1); // CPU time measurement. double time = cpu_time.tick().last(); // Calculate errors. double rel_err_1 = hermes2d.calc_rel_error(&sln1, &exact, HERMES_H1_NORM) * 100; info("CPU time: %g s.", time); info("Exact H1 error: %g%%.", rel_err_1); delete(matrix); delete(rhs); delete(solver); // View the solution and mesh. ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); sview.show(&sln1); //OrderView oview("Polynomial orders", new WinGeom(450, 0, 400, 350)); //oview.show(&space); // TRILINOS PART: info("---- Assembling by DiscreteProblem, solving by NOX:"); // Initialize the weak formulation for Trilinos. CustomWeakFormPoisson wf2(TRILINOS_JFNK); // Initialize DiscreteProblem. DiscreteProblem dp2(&wf2, &space); // Time measurement. cpu_time.tick(HERMES_SKIP); // Set initial vector for NOX. // NOTE: Using zero vector was causing convergence problems. info("Projecting to obtain initial vector for the Newton's method."); Solution init_sln(&mesh, 0.0); OGProjection::project_global(&space, &init_sln, coeff_vec); // Initialize the NOX solver with the vector "coeff_vec". info("Initializing NOX."); // "" stands for preconditioning that is set later. NoxSolver nox_solver(&dp2, message_type, iterative_method, "Newton", ls_tolerance, "", flag_absresid, abs_resid, flag_relresid, rel_resid, max_iters); nox_solver.set_init_sln(coeff_vec); delete coeff_vec; // Choose preconditioning. RCP<Precond> pc = rcp(new MlPrecond("sa")); if (PRECOND) { if (TRILINOS_JFNK) nox_solver.set_precond(pc); else nox_solver.set_precond(preconditioner); } // Assemble and solve using NOX. Solution sln2; if (nox_solver.solve()) { Solution::vector_to_solution(nox_solver.get_solution(), &space, &sln2); info("Number of nonlin iterations: %d (norm of residual: %g)", nox_solver.get_num_iters(), nox_solver.get_residual()); info("Total number of iterations in linsolver: %d (achieved tolerance in the last step: %g)", nox_solver.get_num_lin_iters(), nox_solver.get_achieved_tol()); } else error("NOX failed"); // CPU time needed by NOX. time = cpu_time.tick().last(); // Show the NOX solution. ScalarView view2("Solution 2", new WinGeom(450, 0, 460, 350)); view2.show(&sln2); //view2.show(&exact); // Calculate errors. double rel_err_2 = hermes2d.calc_rel_error(&sln2, &exact, HERMES_H1_NORM) * 100; info("CPU time: %g s.", time); info("Exact H1 error: %g%%.", rel_err_2); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); // Perform initial mesh refinements. for(int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions DefaultEssentialBCConst bc_essential("Bottom", T1); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d", ndof); // Initialize the weak formulation. CustomWeakFormPoissonNewton wf(LAMBDA, ALPHA, T0, "Heat_flux"); // Initialize the FE problem. DiscreteProblem dp(&wf, &space); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof]; memset(coeff_vec, 0, ndof*sizeof(scalar)); // Perform Newton's iteration. if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution sln; Solution::vector_to_solution(coeff_vec, &space, &sln); // Visualize the solution. ScalarView view("Solution", new WinGeom(0, 0, 300, 400)); view.show(&sln, HERMES_EPS_VERYHIGH); ScalarView gradview("Gradient", new WinGeom(310, 0, 300, 400)); MagFilter grad(Hermes::vector<MeshFunction *>(&sln, &sln), Hermes::vector<int>(H2D_FN_DX, H2D_FN_DY)); gradview.show(&grad, HERMES_EPS_VERYHIGH); // Wait for all views to be closed. View::wait(); // Clean up. delete solver; delete matrix; delete rhs; delete [] coeff_vec; return 0; }
int main(int argc, char* argv[]) { /* So far the DG assembling is very slow for higher order polynomials, so only constant functions are used here. if(argc < 3) error("Too few arguments in example-euler-gamm-explicit"); Ord2 P_INIT= Ord2(atoi(argv[1]), atoi(argv[2])); */ Ord2 P_INIT= Ord2(0, 0); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("GAMM-channel.mesh", &mesh); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(1, 1); mesh.refine_element_id(1053); mesh.refine_element_id(1054); mesh.refine_element_id(1087); mesh.refine_element_id(1088); mesh.refine_element_id(1117); mesh.refine_element_id(1118); mesh.refine_element_id(1151); mesh.refine_element_id(1152); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_neumann(Hermes::vector<int>(BDY_SOLID_WALL, BDY_INLET_OUTLET)); // Create L2 spaces with default shapesets. L2Space space_rho(&mesh, &bc_types, P_INIT); L2Space space_rho_v_x(&mesh, &bc_types, P_INIT); L2Space space_rho_v_y(&mesh, &bc_types, P_INIT); L2Space space_e(&mesh, &bc_types, P_INIT); // Initialize solutions, set initial conditions. Solution sln_rho, sln_rho_v_x, sln_rho_v_y, sln_e, prev_rho, prev_rho_v_x, prev_rho_v_y, prev_e; sln_rho.set_exact(&mesh, ic_density); sln_rho_v_x.set_exact(&mesh, ic_density_vel_x); sln_rho_v_y.set_exact(&mesh, ic_density_vel_y); sln_e.set_exact(&mesh, ic_energy); prev_rho.set_exact(&mesh, ic_density); prev_rho_v_x.set_exact(&mesh, ic_density_vel_x); prev_rho_v_y.set_exact(&mesh, ic_density_vel_y); prev_e.set_exact(&mesh, ic_energy); // Initialize weak formulation. WeakForm wf(4); // Bilinear forms coming from time discretization by explicit Euler's method. wf.add_matrix_form(0, 0, callback(bilinear_form_0_0_time)); wf.add_matrix_form(1, 1, callback(bilinear_form_1_1_time)); wf.add_matrix_form(2, 2, callback(bilinear_form_2_2_time)); wf.add_matrix_form(3, 3, callback(bilinear_form_3_3_time)); // Volumetric linear forms. // Linear forms coming from the linearization by taking the Eulerian fluxes' Jacobian matrices // from the previous time step. // Unnecessary for FVM. if(P_INIT.order_h > 0 || P_INIT.order_v > 0) { // First flux. wf.add_vector_form(0, callback(linear_form_0_1), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho_v_x)); wf.add_vector_form(1, callback(linear_form_1_0_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(1, callback(linear_form_1_1_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(1, callback(linear_form_1_2_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(1, callback(linear_form_1_3_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(2, callback(linear_form_2_0_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(2, callback(linear_form_2_1_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(2, callback(linear_form_2_2_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(2, callback(linear_form_2_3_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(3, callback(linear_form_3_0_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(3, callback(linear_form_3_1_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(3, callback(linear_form_3_2_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(3, callback(linear_form_3_3_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); // Second flux. wf.add_vector_form(0, callback(linear_form_0_2), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho_v_y)); wf.add_vector_form(1, callback(linear_form_1_0_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(1, callback(linear_form_1_1_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(1, callback(linear_form_1_2_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(1, callback(linear_form_1_3_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(2, callback(linear_form_2_0_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(2, callback(linear_form_2_1_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(2, callback(linear_form_2_2_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(2, callback(linear_form_2_3_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(3, callback(linear_form_3_0_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(3, callback(linear_form_3_1_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(3, callback(linear_form_3_2_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(3, callback(linear_form_3_3_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); } // Volumetric linear forms coming from the time discretization. wf.add_vector_form(0, linear_form, linear_form_order, HERMES_ANY, &prev_rho); wf.add_vector_form(1, linear_form, linear_form_order, HERMES_ANY, &prev_rho_v_x); wf.add_vector_form(2, linear_form, linear_form_order, HERMES_ANY, &prev_rho_v_y); wf.add_vector_form(3, linear_form, linear_form_order, HERMES_ANY, &prev_e); // Surface linear forms - inner edges coming from the DG formulation. wf.add_vector_form_surf(0, linear_form_interface_0, linear_form_order, H2D_DG_INNER_EDGE, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(1, linear_form_interface_1, linear_form_order, H2D_DG_INNER_EDGE, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(2, linear_form_interface_2, linear_form_order, H2D_DG_INNER_EDGE, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(3, linear_form_interface_3, linear_form_order, H2D_DG_INNER_EDGE, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); // Surface linear forms - inlet / outlet edges. wf.add_vector_form_surf(0, bdy_flux_inlet_outlet_comp_0, linear_form_order, BDY_INLET_OUTLET, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(1, bdy_flux_inlet_outlet_comp_1, linear_form_order, BDY_INLET_OUTLET, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(2, bdy_flux_inlet_outlet_comp_2, linear_form_order, BDY_INLET_OUTLET, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(3, bdy_flux_inlet_outlet_comp_3, linear_form_order, BDY_INLET_OUTLET, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); // Surface linear forms - Solid wall edges. wf.add_vector_form_surf(0, bdy_flux_solid_wall_comp_0, linear_form_order, BDY_SOLID_WALL, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(1, bdy_flux_solid_wall_comp_1, linear_form_order, BDY_SOLID_WALL, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(2, bdy_flux_solid_wall_comp_2, linear_form_order, BDY_SOLID_WALL, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(3, bdy_flux_solid_wall_comp_3, linear_form_order, BDY_SOLID_WALL, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, Hermes::vector<Space*>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), is_linear); // If the FE problem is in fact a FV problem. if(P_INIT.order_h == 0 && P_INIT.order_v == 0) dp.set_fvm(); // Iteration number. int iteration = 0; // 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); // For testing purposes. double l2_norms[5][4]; for(unsigned int i = 0; i < 5; i++) for(unsigned int j = 0; j < 4; j++) l2_norms[i][j] = 0.0; double point_values[5][3]; for(unsigned int i = 0; i < 5; i++) for(unsigned int j = 0; j < 3; j++) point_values[i][j] = 0.0; // Calculate the special point where we will evaluate the solution. double x = 0.75; double y = sqrt((double)(1.-x*x)) + 0.001; for(unsigned int time_step = 0; time_step < 5; time_step++) { iteration++; bool rhs_only = (iteration == 1 ? false : true); // Assemble stiffness matrix and rhs or just rhs. 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); // Solve the matrix problem. info("Solving the matrix problem."); if(solver->solve()) Solution::vector_to_solutions(solver->get_solution(), Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), Hermes::vector<Solution *>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e)); else error ("Matrix solver failed.\n"); // Approximate the time derivative of the solution. if(CALC_TIME_DER) { Adapt *adapt_for_time_der_calc = new Adapt(Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e)); bool solutions_for_adapt = false; double difference = iteration == 1 ? 0 : adapt_for_time_der_calc->calc_err_est(Hermes::vector<Solution *>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), Hermes::vector<Solution *>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e), (Hermes::vector<double>*) NULL, solutions_for_adapt, HERMES_TOTAL_ERROR_ABS | HERMES_ELEMENT_ERROR_ABS) / TAU; delete adapt_for_time_der_calc; } // Determine the time step according to the CFL condition. // Only mean values on an element of each solution component are taken into account. double *solution_vector = solver->get_solution(); double min_condition = 0; Element *e; for (int _id = 0, _max = mesh.get_max_element_id(); _id < _max; _id++) \ if (((e) = mesh.get_element_fast(_id))->used) \ if ((e)->active) { AsmList al; space_rho.get_element_assembly_list(e, &al); double rho = solution_vector[al.dof[0]]; space_rho_v_x.get_element_assembly_list(e, &al); double v1 = solution_vector[al.dof[0]] / rho; space_rho_v_y.get_element_assembly_list(e, &al); double v2 = solution_vector[al.dof[0]] / rho; space_e.get_element_assembly_list(e, &al); double energy = solution_vector[al.dof[0]]; double condition = e->get_area() / (std::sqrt(v1*v1 + v2*v2) + calc_sound_speed(rho, rho*v1, rho*v2, energy)); if(condition < min_condition || min_condition == 0.) min_condition = condition; } if(TAU > min_condition) TAU = min_condition; if(TAU < min_condition * 0.9) TAU = min_condition; // Storing the testing values. for(unsigned int j = 0; j < 4; j++) for(unsigned int k = j*space_rho.get_num_dofs(); k < (j+1)*space_rho.get_num_dofs(); k++) l2_norms[time_step][j] += solver->get_solution()[k]; point_values[time_step][0] = sln_rho_v_x.get_pt_value(0.5, 0.001); point_values[time_step][1] = sln_rho_v_x.get_pt_value(x, y); point_values[time_step][2] = sln_rho_v_x.get_pt_value(1.5, 0.001); // Copy the solutions into the previous time level ones. prev_rho.copy(&sln_rho); prev_rho_v_x.copy(&sln_rho_v_x); prev_rho_v_y.copy(&sln_rho_v_y); prev_e.copy(&sln_e); } bool okay = true; switch(P_INIT.order_h* 10 + P_INIT.order_v) { case 0: if(std::abs(l2_norms[0][0] - 888.0) > 1E-8) okay = false; if(std::abs(l2_norms[0][1] - 1110) > 1E-8) okay = false; if(std::abs(l2_norms[0][2]) > 1E-8) okay = false; if(std::abs(l2_norms[0][3] - 6243.75) > 1E-8) okay = false; if(std::abs(l2_norms[1][0] - 887.99997637865545) > 1E-8) okay = false; if(std::abs(l2_norms[1][1] - 1109.9997956458228) > 1E-8) okay = false; if(std::abs(l2_norms[1][2] - 3.1927018090871903e-008) > 1E-8) okay = false; if(std::abs(l2_norms[1][3] - 6243.7496921971369) > 1E-8) okay = false; if(std::abs(l2_norms[2][0] - 887.99993429457072) > 1E-8) okay = false; if(std::abs(l2_norms[2][1] - 1109.9994322038613) > 1E-8) okay = false; if(std::abs(l2_norms[2][2] + 5.3556469633245445e-008) > 1E-8) okay = false; if(std::abs(l2_norms[2][3] - 6243.7491437826511) > 1E-8) okay = false; if(std::abs(l2_norms[3][0] - 887.99987376550200) > 1E-8) okay = false; if(std::abs(l2_norms[3][1] - 1109.9989102977672) > 1E-8) okay = false; if(std::abs(l2_norms[3][2] + 3.6958140470412712e-007) > 1E-8) okay = false; if(std::abs(l2_norms[3][3] - 6243.7483549661320) > 1E-8) okay = false; if(std::abs(l2_norms[4][0] - 887.99979481320088) > 1E-8) okay = false; if(std::abs(l2_norms[4][1] - 1109.9982305630808) > 1E-8) okay = false; if(std::abs(l2_norms[4][2] + 1.0303296924184822e-006) > 1E-8) okay = false; if(std::abs(l2_norms[4][3] - 6243.7473260085462) > 1E-8) okay = false; // points if(std::abs(point_values[0][0] - 1.25) > 1E-8) okay = false; if(std::abs(point_values[0][1] - 1.25) > 1E-8) okay = false; if(std::abs(point_values[0][2] - 1.2459744738974898) > 1E-8) okay = false; if(std::abs(point_values[1][0] - 1.2499951035194972) > 1E-8) okay = false; if(std::abs(point_values[1][1] - 1.25) > 1E-8) okay = false; if(std::abs(point_values[1][2] - 1.2428402692519325) > 1E-8) okay = false; if(std::abs(point_values[2][0] - 1.2499864002215795) > 1E-8) okay = false; if(std::abs(point_values[2][1] - 1.25) > 1E-8) okay = false; if(std::abs(point_values[2][2] - 1.2397180160697001) > 1E-8) okay = false; if(std::abs(point_values[3][0] - 1.2499739085927257) > 1E-8) okay = false; if(std::abs(point_values[3][1] - 1.25) > 1E-8) okay = false; if(std::abs(point_values[3][2] - 1.2366079101139087) > 1E-8) okay = false; if(std::abs(point_values[4][0] - 1.2499576472516911) > 1E-8) okay = false; if(std::abs(point_values[4][1] - 1.25) > 1E-8) okay = false; if(std::abs(point_values[4][2] - 1.2335101392959738) > 1E-8) okay = false; break; } if (okay) { // ndofs was 908 at the time this test was created printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Load the mesh Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); mesh.refine_all_elements(); // Initialize the shapeset and the cache H1Shapeset shapeset; PrecalcShapeset pss(&shapeset); // Create finite element space H1Space space(&mesh, &shapeset); space.set_bc_types(bc_types); space.set_bc_values(bc_values); space.set_uniform_order(P_INIT); // Enumerate basis functions space.assign_dofs(); // initialize the weak formulation WeakForm wf(1); wf.add_biform(0, 0, bilinear_form, bilinear_form_ord, SYM); wf.add_liform(0, linear_form, linear_form_ord); wf.add_liform_surf(0, linear_form_surf, linear_form_surf_ord, 2); // Visualize solution and mesh ScalarView sview("Coarse solution", 0, 100, 798, 700); OrderView oview("Polynomial orders", 800, 100, 798, 700); // Matrix solver UmfpackSolver solver; // DOF and CPU convergence graphs SimpleGraph graph_dof, graph_cpu; // Adaptivity loop int it = 1, ndofs; bool done = false; double cpu = 0.0; Solution sln_coarse, sln_fine; do { info("\n---- Adaptivity step %d ---------------------------------------------\n", it++); // Time measurement begin_time(); // Solve the coarse mesh problem LinSystem ls(&wf, &solver); ls.set_spaces(1, &space); ls.set_pss(1, &pss); ls.assemble(); ls.solve(1, &sln_coarse); // Time measurement cpu += end_time(); // View the solution and mesh sview.show(&sln_coarse); oview.show(&space); // Time measurement begin_time(); // Solve the fine mesh problem RefSystem rs(&ls); rs.assemble(); rs.solve(1, &sln_fine); // Calculate error estimate wrt. fine mesh solution H1OrthoHP hp(1, &space); double err_est = hp.calc_error(&sln_coarse, &sln_fine) * 100; info("Estimate of error: %g%%", err_est); // add entry to DOF convergence graph graph_dof.add_values(space.get_num_dofs(), err_est); graph_dof.save("conv_dof.dat"); // add entry to CPU convergence graph graph_cpu.add_values(cpu, err_est); graph_cpu.save("conv_cpu.dat"); // If err_est too large, adapt the mesh if (err_est < ERR_STOP) done = true; else { hp.adapt(THRESHOLD, STRATEGY, ADAPT_TYPE, ISO_ONLY, MESH_REGULARITY); ndofs = space.assign_dofs(); if (ndofs >= NDOF_STOP) done = true; } // Time measurement cpu += end_time(); } while (done == false); verbose("Total running time: %g sec", cpu); // Show the fine solution - this is the final result sview.set_title("Final solution"); sview.show(&sln_fine); // Wait for keyboard or mouse input View::wait("Waiting for all views to be closed."); return 0; }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("square_quad.mesh", &mesh); // quadrilaterals // mloader.load("square_tri.mesh", &mesh); // triangles // Perform initial mesh refinements. for (int i = 0; i<INIT_REF_NUM; i++) mesh.refine_all_elements(); // Define exact solution. CustomExactSolution exact_sln(&mesh, SLOPE); // Initialize the weak formulation. CustomWeakFormPoisson wf(SLOPE); // Initialize boundary conditions. DefaultEssentialBCNonConst bc_essential(BDY_DIRICHLET, &exact_sln); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 450, 350)); sview.show_mesh(false); sview.fix_scale_width(60); OrderView oview("Polynomial orders", new WinGeom(460, 0, 410, 350)); // 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 = Space::construct_refined_space(&space); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Assemble the reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. If successful, obtain the solution. Solution ref_sln; if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Project the fine mesh solution onto the coarse mesh. Solution sln; info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // View the coarse mesh solution and polynomial orders. sview.show(&sln); oview.show(&space); // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); Adapt* adaptivity = new Adapt(&space); double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Calculate exact error. double err_exact_rel = hermes2d.calc_rel_error(&sln, &exact_sln, HERMES_H1_NORM) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d.", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space)); info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof_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 too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) delete ref_space->get_mesh(); delete ref_space; delete dp; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); // Perform initial mesh refinements. mesh.refine_towards_vertex(3, CORNER_REF_LEVEL); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(BDY_INNER); bc_types.add_bc_neumann(Hermes::Tuple<int>(BDY_BOTTOM, BDY_OUTER, BDY_LEFT)); // Enter Dirichlet boudnary values. BCValues bc_values; bc_values.add_zero(BDY_INNER); // 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_vector_form(callback(linear_form)); wf.add_vector_form_surf(callback(linear_form_surf_bottom), BDY_BOTTOM); wf.add_vector_form_surf(callback(linear_form_surf_outer), BDY_OUTER); wf.add_vector_form_surf(callback(linear_form_surf_left), BDY_LEFT); // 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 approximation. 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::Tuple<MeshFunction *>(&sln, &sln), Hermes::Tuple<int>(H2D_FN_DX, H2D_FN_DY)); gradview.show(&grad); // Wait for the views to be closed. View::wait(); // Clean up. delete solver; delete matrix; delete rhs; 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("square.mesh", &mesh); // Perform initial mesh refinements. for (int i=0; i<INIT_REF; i++) mesh.refine_all_elements(); // Create an L2 space with default shapeset. L2Space space(&mesh, bc_types, NULL, Ord2(P_H, P_V)); 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_vector_form(callback(linear_form)); wf.add_matrix_form_surf(callback(bilinear_form_boundary), H2D_DG_BOUNDARY_EDGE); wf.add_vector_form_surf(callback(linear_form_boundary), H2D_DG_BOUNDARY_EDGE); wf.add_matrix_form_surf(callback(bilinear_form_interface), H2D_DG_INNER_EDGE); // 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). } // 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; info("ndof = %d", ndof); info("Coordinate ( 0.1, 0.1) value = %lf", sln.get_pt_value(0.1, 0.1)); info("Coordinate ( 0.3, 0.3) value = %lf", sln.get_pt_value(0.3, 0.3)); info("Coordinate ( 0.5, 0.5) value = %lf", sln.get_pt_value(0.5, 0.5)); info("Coordinate ( 0.7, 0.7) value = %lf", sln.get_pt_value(0.7, 0.7)); double coor_xy[4] = {0.1, 0.3, 0.5, 0.7}; double value[4] = {0.999885, 0.844340, 0.000000, 0.000000}; for (int i = 0; i < 4; i++) { if ((value[i] - sln.get_pt_value(coor_xy[i], coor_xy[i])) < 1E-6) { printf("Success!\n"); } else { printf("Failure!\n"); return ERR_FAILURE; } } return ERR_SUCCESS; }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("../domain.mesh", &mesh); // Perform uniform mesh refinement. mesh.refine_all_elements(); // Initialize boundary conditions. DefaultEssentialBCConst zero_disp("Bottom", 0.0); EssentialBCs bcs(&zero_disp); // Create x- and y- displacement space using the default H1 shapeset. H1Space u1_space(&mesh, &bcs, P_INIT); H1Space u2_space(&mesh, &bcs, P_INIT); info("ndof = %d.", Space::get_num_dofs(Hermes::vector<Space *>(&u1_space, &u2_space))); // Initialize the weak formulation. CustomWeakFormLinearElasticity wf(E, nu, rho*g1, "Top", f0, f1); // Testing n_dof and correctness of solution vector // for p_init = 1, 2, ..., 10 int success = 1; Solution xsln, ysln; for (int p_init = 1; p_init <= 6; p_init++) { printf("********* p_init = %d *********\n", p_init); u1_space.set_uniform_order(p_init); u2_space.set_uniform_order(p_init); int ndof = Space::get_num_dofs(Hermes::vector<Space *>(&u1_space, &u2_space)); info("ndof = %d", ndof); // Initialize the FE problem. DiscreteProblem dp(&wf, Hermes::vector<Space *>(&u1_space, &u2_space)); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof]; memset(coeff_vec, 0, ndof*sizeof(scalar)); // Perform Newton's iteration. bool verbose = true; bool jacobian_changed = true; if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs, jacobian_changed, NEWTON_TOL, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution u1_sln, u2_sln; Solution::vector_to_solutions(coeff_vec, Hermes::vector<Space *>(&u1_space, &u2_space), Hermes::vector<Solution *>(&u1_sln, &u2_sln)); double sum = 0; for (int i=0; i < ndof; i++) sum += coeff_vec[i]; printf("coefficient sum = %g\n", sum); // Actual test. The values of 'sum' depend on the // current shapeset. If you change the shapeset, // you need to correct these numbers. if (p_init == 1 && fabs(sum - 1.41886e-05) > 1e-5) success = 0; if (p_init == 2 && fabs(sum - 1.60006e-05) > 1e-5) success = 0; if (p_init == 3 && fabs(sum - 1.60810e-05) > 1e-5) success = 0; if (p_init == 4 && fabs(sum - 1.61106e-05) > 1e-5) success = 0; if (p_init == 5 && fabs(sum - 1.61065e-05) > 1e-5) success = 0; if (p_init == 6 && fabs(sum - 1.61112e-05) > 1e-5) success = 0; delete [] coeff_vec; delete solver; delete matrix; delete rhs; } 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 file Mesh mesh; H2DReader mloader; mloader.load("sample.mesh", &mesh); // initialize the shapeset and the cache H1Shapeset shapeset; PrecalcShapeset pss(&shapeset); // create the x displacement space H1Space xdisp(&mesh, &shapeset); xdisp.set_bc_types(bc_types); xdisp.set_bc_values(bc_values); // create the y displacement space H1Space ydisp(&mesh, &shapeset); ydisp.set_bc_types(bc_types); ydisp.set_bc_values(bc_values); // initialize the weak formulation WeakForm wf(2); wf.add_biform(0, 0, callback(bilinear_form_0_0), SYM); // Note that only one symmetric part is wf.add_biform(0, 1, callback(bilinear_form_0_1), SYM); // added in the case of symmetric bilinear wf.add_biform(1, 1, callback(bilinear_form_1_1), SYM); // forms. wf.add_liform_surf(0, callback(linear_form_surf_0), 3); wf.add_liform_surf(1, callback(linear_form_surf_1), 3); // initialize the linear system and solver UmfpackSolver umfpack; LinSystem sys(&wf, &umfpack); sys.set_spaces(2, &xdisp, &ydisp); sys.set_pss(1, &pss); // 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); xdisp.set_uniform_order(p_init); int ndofs = xdisp.assign_dofs(0); ydisp.set_uniform_order(p_init); ndofs += ydisp.assign_dofs(ndofs); // assemble the stiffness matrix and solve the system Solution xsln, ysln; sys.assemble(); sys.solve(2, &xsln, &ysln); scalar *sol_vector; int n_dof; sys.get_solution_vector(sol_vector, n_dof); printf("n_dof = %d\n", n_dof); double sum = 0; for (int i=0; i < n_dof; i++) sum += sol_vector[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 - 3.50185e-06) > 1e-3) success = 0; if (p_init == 2 && fabs(sum - 4.34916e-06) > 1e-3) success = 0; if (p_init == 3 && fabs(sum - 4.60553e-06) > 1e-3) success = 0; if (p_init == 4 && fabs(sum - 4.65616e-06) > 1e-3) success = 0; if (p_init == 5 && fabs(sum - 4.62893e-06) > 1e-3) success = 0; if (p_init == 6 && fabs(sum - 4.64336e-06) > 1e-3) success = 0; if (p_init == 7 && fabs(sum - 4.63724e-06) > 1e-3) success = 0; if (p_init == 8 && fabs(sum - 4.64491e-06) > 1e-3) success = 0; if (p_init == 9 && fabs(sum - 4.64582e-06) > 1e-3) success = 0; if (p_init == 10 && fabs(sum - 4.65028e-06) > 1e-3) success = 0; } #define ERROR_SUCCESS 0 #define ERROR_FAILURE -1 if (success == 1) { printf("Success!\n"); return ERROR_SUCCESS; } else { printf("Failure!\n"); return ERROR_FAILURE; } }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("../domain.mesh", &mesh); // Perform initial mesh refinements (optional). for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize the weak formulation. CustomWeakFormPoissonDirichlet wf("Aluminum", LAMBDA_AL, "Copper", LAMBDA_CU, VOLUME_HEAT_SRC); // Initialize boundary conditions. CustomDirichletCondition bc_essential(Hermes::vector<std::string>("Bottom", "Inner", "Outer", "Left"), BDY_A_PARAM, BDY_B_PARAM, BDY_C_PARAM); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the FE problem. DiscreteProblem dp(&wf, &space); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof]; memset(coeff_vec, 0, ndof*sizeof(scalar)); // Perform Newton's iteration. if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution sln; Solution::vector_to_solution(coeff_vec, &space, &sln); // VTK output. if (VTK_VISUALIZATION) { // Output solution in VTK format. Linearizer lin; bool mode_3D = true; lin.save_solution_vtk(&sln, "sln.vtk", "Temperature", mode_3D); info("Solution in VTK format saved to file %s.", "sln.vtk"); // Output mesh and element orders in VTK format. Orderizer ord; ord.save_orders_vtk(&space, "ord.vtk"); info("Element orders in VTK format saved to file %s.", "ord.vtk"); } ndof = Space::get_num_dofs(&space); printf("ndof = %d\n", ndof); double sum = 0; for (int i=0; i < ndof; i++) sum += coeff_vec[i]; printf("coefficient sum = %g\n", sum); bool success = true; if (fabs(sum + 4.2471) > 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[]) { // Initialize the library's global functions. Hermes2D hermes2D; // Load the mesh file. Mesh C_mesh, phi_mesh, u1_mesh, u2_mesh, basemesh; H2DReader mloader; mloader.load("small.mesh", &basemesh); #ifdef TWO_BASE_MESH Mesh basemesh_electrochem; // Base mesh to hold C and phi Mesh basemesh_deformation; // Base mesh for deformation displacements u1 and u2 basemesh_electrochem.copy(&basemesh); basemesh_deformation.copy(&basemesh); basemesh_electrochem.refine_towards_boundary(BDY_BOT, REF_INIT - 1); basemesh_electrochem.refine_all_elements(1); C_mesh.copy(&basemesh_electrochem); phi_mesh.copy(&basemesh_electrochem); for (int i = 0; i < REF_INIT - 1; i++) { basemesh_deformation.refine_all_elements(1); //horizontal basemesh_deformation.refine_all_elements(2); //vertical } u1_mesh.copy(&basemesh_deformation); u2_mesh.copy(&basemesh_deformation); #else basemesh.refine_towards_boundary(BDY_BOT, REF_INIT); basemesh.refine_towards_boundary(BDY_SIDE_FIXED, REF_INIT); basemesh.refine_towards_boundary(BDY_SIDE_FREE, REF_INIT - 1); basemesh.refine_all_elements(1); C_mesh.copy(&basemesh); phi_mesh.copy(&basemesh); u1_mesh.copy(&basemesh); u2_mesh.copy(&basemesh); #endif // Enter Dirichlet and Neumann boundary markers for Poisson. DefaultEssentialBCConst bc_phi_voltage(BDY_TOP, VOLTAGE); DefaultEssentialBCConst bc_phi_zero(BDY_BOT, 0.0); EssentialBCs bcs_phi(Hermes::vector<EssentialBC*>(&bc_phi_voltage, &bc_phi_zero)); DefaultEssentialBCConst bc_u1(BDY_SIDE_FIXED, 0.0); EssentialBCs bcs_u1(&bc_u1); DefaultEssentialBCConst bc_u2(BDY_SIDE_FIXED, 0.0); EssentialBCs bcs_u2(&bc_u2); // Spaces for concentration and the voltage. H1Space C_space(&C_mesh, P_INIT); H1Space phi_space(MULTIMESH ? &phi_mesh : &C_mesh, &bcs_phi, P_INIT); H1Space u1_space(MULTIMESH ? &u1_mesh : &C_mesh, &bcs_u1, P_INIT); H1Space u2_space(MULTIMESH ? &u2_mesh : &C_mesh, &bcs_u2, P_INIT); int ndof = Space::get_num_dofs(Hermes::vector<Space*>(&C_space, &phi_space, &u1_space, &u2_space)); Solution C_sln, C_ref_sln; Solution phi_sln, phi_ref_sln; Solution u1_sln, u1_ref_sln; Solution u2_sln, u2_ref_sln; // Assign initial condition to mesh. InitialSolutionConcentration C_prev_time(&C_mesh, C0); InitialSolutionVoltage phi_prev_time(MULTIMESH ? &phi_mesh : &C_mesh); InitialSolutionU1 u1_prev_time(MULTIMESH ? &u1_mesh : &C_mesh); InitialSolutionU2 u2_prev_time(MULTIMESH ? &u2_mesh : &C_mesh); // The weak form for 2 equations. CustomWeakFormNernstPlanckEuler wf(TAU, C0, lin_force_coup, mech_lambda, mech_mu, K, L, D, &C_prev_time); // Add the bilinear and linear forms. if (TIME_DISCR == 2) error("Crank-Nicholson forms are not implemented yet"); // 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(Hermes::vector<Space *>(&C_space, &phi_space, &u1_space, &u2_space), Hermes::vector<MeshFunction *>(&C_prev_time, &phi_prev_time, &u1_prev_time, &u2_prev_time), coeff_vec_coarse, matrix_solver); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp_coarse(&wf, Hermes::vector<Space *>(&C_space, &phi_space, &u1_space, &u2_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); // Visualization windows. char title[1000]; ScalarView Cview("Concentration [mol/m3]", new WinGeom(0, 0, 400, 300)); ScalarView phiview("Voltage [V]", new WinGeom(10, 0, 400, 300)); ScalarView u1view("X displacement [m]", new WinGeom(320, 0, 600, 400)); ScalarView u2view("Y displacement [m]", new WinGeom(830, 0, 600, 400)); OrderView Cordview("C order", new WinGeom(0, 470, 400, 300)); OrderView phiordview("Phi order", new WinGeom(10, 470, 400, 300)); OrderView u1ordview("u1 order", new WinGeom(320, 470, 600, 400)); OrderView u2ordview("u2 order", new WinGeom(830, 470, 600, 400)); // Visualize the solution. ScalarView deformationview("Von Mises stress [Pa]", new WinGeom(1240, 0, 300, 300)); Cview.show(&C_prev_time); Cordview.show(&C_space); phiview.show(&phi_prev_time); phiordview.show(&phi_space); u1view.show(&u1_prev_time); u1ordview.show(&u1_space); u2view.show(&u2_prev_time); u2ordview.show(&u2_space); // Newton's loop on the coarse mesh. info("Solving on coarse mesh:"); bool verbose = true; if (!hermes2D.solve_newton(coeff_vec_coarse, &dp_coarse, solver_coarse, matrix_coarse, rhs_coarse, NEWTON_TOL_COARSE, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution::vector_to_solutions(coeff_vec_coarse, Hermes::vector<Space *>(&C_space, &phi_space, &u1_space, &u2_space), Hermes::vector<Solution *>(&C_sln, &phi_sln, &u1_sln, &u2_sln)); Cview.show(&C_sln); phiview.show(&phi_sln); u1view.show(&u1_sln); u2view.show(&u2_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. PidTimestepController pid(T_FINAL, true, INIT_TAU); TAU = pid.timestep; info("Starting time iteration with the step %g", *TAU); do { pid.begin_step(); // Periodic global derefinements. if (pid.get_timestep_number() > 1 && pid.get_timestep_number() % UNREF_FREQ == 0) { info("Global mesh derefinement."); #ifdef TWO_BASE_MESH C_mesh.copy(&basemesh_electrochem); #else C_mesh.copy(&basemesh); #endif if (MULTIMESH) { #ifdef TWO_BASE_MESH phi_mesh.copy(&basemesh_electrochem); u1_mesh.copy(&basemesh_deformation); u2_mesh.copy(&basemesh_deformation); #else phi_mesh.copy(&basemesh); u1_mesh.copy(&basemesh); u2_mesh.copy(&basemesh); #endif } C_space.set_uniform_order(P_INIT); phi_space.set_uniform_order(P_INIT); u1_space.set_uniform_order(P_INIT); u2_space.set_uniform_order(P_INIT); // Project on globally derefined mesh. //info("Projecting previous fine mesh solution on derefined mesh."); //OGProjection::project_global(Hermes::vector<Space *>(&C, &phi), Hermes::vector<Solution *>(&C_ref_sln, &phi_ref_sln), // Hermes::vector<Solution *>(&C_sln, &phi_sln)); } // Adaptivity loop. Note: C_prev_time and Phi_prev_time must not be changed during spatial adaptivity. bool done = false; int as = 1; double err_est; do { info("Time step %d, adaptivity step %d:", pid.get_timestep_number(), as); // Construct globally refined reference mesh // and setup reference space. Hermes::vector<Space *>* ref_spaces = Space::construct_refined_spaces( Hermes::vector<Space *>(&C_space, &phi_space, &u1_space, &u2_space)); scalar* coeff_vec = new scalar[Space::get_num_dofs(*ref_spaces)]; DiscreteProblem dp(&wf, *ref_spaces, is_linear); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Calculate initial coefficient vector for Newton on the fine mesh. if (as == 1 && pid.get_timestep_number() == 1) { info("Projecting coarse mesh solution to obtain coefficient vector on new fine mesh."); OGProjection::project_global(*ref_spaces, Hermes::vector<MeshFunction *>(&C_sln, &phi_sln, &u1_sln, &u2_sln), coeff_vec, matrix_solver); } else { info("Projecting previous fine mesh solution to obtain coefficient vector on new fine mesh."); OGProjection::project_global(*ref_spaces, Hermes::vector<MeshFunction *>(&C_ref_sln, &phi_ref_sln, &u1_ref_sln, &u2_ref_sln), coeff_vec, matrix_solver); } if (as > 1) { // Now deallocate the previous mesh info("Delallocating the previous mesh"); delete C_ref_sln.get_mesh(); delete phi_ref_sln.get_mesh(); delete u1_ref_sln.get_mesh(); delete u2_ref_sln.get_mesh(); } // Newton's loop on the fine mesh. info("Solving on fine mesh:"); if (!hermes2D.solve_newton(coeff_vec, &dp, solver, matrix, rhs, NEWTON_TOL_FINE, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Store the result in ref_sln. Solution::vector_to_solutions(coeff_vec, *ref_spaces, Hermes::vector<Solution *>(&C_ref_sln, &phi_ref_sln, &u1_ref_sln, &u2_ref_sln)); // Projecting reference solution onto the coarse mesh info("Projecting fine mesh solution on coarse mesh."); OGProjection::project_global(Hermes::vector<Space *>(&C_space, &phi_space, &u1_space, &u2_space), Hermes::vector<Solution *>(&C_ref_sln, &phi_ref_sln, &u1_ref_sln, &u2_ref_sln), Hermes::vector<Solution *>(&C_sln, &phi_sln, &u1_sln, &u2_sln), matrix_solver); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt adaptivity (Hermes::vector<Space *>(&C_space, &phi_space, &u1_space, &u2_space)); Hermes::vector<double> err_est_rel; double err_est_rel_total = adaptivity.calc_err_est(Hermes::vector<Solution *>(&C_sln, &phi_sln, &u1_sln, &u2_sln), Hermes::vector<Solution *>(&C_ref_sln, &phi_ref_sln, &u1_ref_sln, &u2_ref_sln), &err_est_rel) * 100; // Report results. info("ndof_coarse[0]: %d, ndof_fine[0]: %d", C_space.get_num_dofs(), (*ref_spaces)[0]->get_num_dofs()); info("err_est_rel[0]: %g%%", err_est_rel[0]*100); info("ndof_coarse[1]: %d, ndof_fine[1]: %d", phi_space.get_num_dofs(), (*ref_spaces)[1]->get_num_dofs()); info("err_est_rel[1]: %g%%", err_est_rel[1]*100); info("ndof_coarse[2]: %d, ndof_fine[2]: %d", u1_space.get_num_dofs(), (*ref_spaces)[2]->get_num_dofs()); info("err_est_rel[2]: %g%%", err_est_rel[3]*100); info("ndof_coarse[3]: %d, ndof_fine[3]: %d", u2_space.get_num_dofs(), (*ref_spaces)[3]->get_num_dofs()); info("err_est_rel[3]: %g%%", err_est_rel[3]*100); // Report results. info("ndof_coarse_total: %d, ndof_fine_total: %d, err_est_rel: %g%%", Space::get_num_dofs(Hermes::vector<Space *>(&C_space, &phi_space, &u1_space, &u2_space)), Space::get_num_dofs(*ref_spaces), err_est_rel_total); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting the coarse mesh."); done = adaptivity.adapt(Hermes::vector<RefinementSelectors::Selector *>(&selector, &selector, &selector, &selector), THRESHOLD, STRATEGY, MESH_REGULARITY); info("Adapted..."); if (Space::get_num_dofs(Hermes::vector<Space *>(&C_space, &phi_space, &u1_space, &u2_space)) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } // Visualize the solution and mesh. info("Visualization procedures: C"); char title[100]; sprintf(title, "Solution[C], time step# %d, step size %g, time %g", pid.get_timestep_number(), *TAU, pid.get_time()); Cview.set_title(title); Cview.show(&C_ref_sln); sprintf(title, "Mesh[C], time step# %d, step size %g, time %g", pid.get_timestep_number(), *TAU, pid.get_time()); Cordview.set_title(title); Cordview.show(&C_space); info("Visualization procedures: phi"); sprintf(title, "Solution[phi], time step# %d, step size %g, time %g", pid.get_timestep_number(), *TAU, pid.get_time()); phiview.set_title(title); phiview.show(&phi_ref_sln); sprintf(title, "Mesh[phi], time step# %d, step size %g, time %g", pid.get_timestep_number(), *TAU, pid.get_time()); phiordview.set_title(title); phiordview.show(&phi_space); info("Visualization procedures: u1"); sprintf(title, "Solution[u1], time step# %d, step size %g, time %g", pid.get_timestep_number(), *TAU, pid.get_time()); u1view.set_title(title); u1view.show(&u1_ref_sln); sprintf(title, "Mesh[u1], time step# %d, step size %g, time %g", pid.get_timestep_number(), *TAU, pid.get_time()); u1ordview.set_title(title); u1ordview.show(&u1_space); info("Visualization procedures: u2"); sprintf(title, "Solution[u2], time step# %d, step size %g, time %g", pid.get_timestep_number(), *TAU, pid.get_time()); u2view.set_title(title); u2view.show(&u2_ref_sln); sprintf(title, "Mesh[u2], time step# %d, step size %g, time %g", pid.get_timestep_number(), *TAU, pid.get_time()); u2ordview.set_title(title); u2ordview.show(&u2_space); /* info("Von Mises filter"); VonMisesFilter stress(Hermes::vector<MeshFunction *>(&u1_prev_time, &u2_prev_time), mech_lambda, mech_mu); deformationview.show_mesh(false); deformationview.show(&stress, HERMES_EPS_HIGH, H2D_FN_VAL_0, &u1_prev_time, &u2_prev_time, 1.5e10); */ // Clean up. delete solver; delete matrix; delete rhs; delete ref_spaces; delete[] coeff_vec; } while (done == false); pid.end_step(Hermes::vector<Solution*> (&C_ref_sln, &phi_ref_sln, &u1_ref_sln, &u2_ref_sln), Hermes::vector<Solution*> (&C_prev_time, &phi_prev_time, &u1_prev_time, &u2_prev_time)); // TODO! Time step reduction when necessary. // Copy last reference solution into sln_prev_time. C_prev_time.copy(&C_ref_sln); phi_prev_time.copy(&phi_ref_sln); u1_prev_time.copy(&u1_ref_sln); u2_prev_time.copy(&u2_ref_sln); } while (pid.has_next()); // 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("domain.mesh", &mesh); // Perform initial mesh refinements. mesh.refine_all_elements(); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(BDY_HORIZONTAL); bc_types.add_bc_neumann(BDY_VERTICAL); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_function(BDY_HORIZONTAL, 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(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 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; // 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."); 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_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); } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if (done == false) delete ref_space->get_mesh(); delete ref_space; delete dp; // Increase counter. as++; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); int ndof = Space::get_num_dofs(&space); printf("ndof allowed = %d\n", 430); printf("ndof actual = %d\n", ndof); if (ndof < 430) { // ndofs was 414 at the time this test was created printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; // We load the mesh on a triangle [-1,-1][1,-1][-1,1] domain. mloader.load("ref_triangle.mesh", &mesh); // Initialize boundary conditions. // (If no markers are entered, default is a natural BC). BCTypes bc_types; // Create an H1 space with default shapeset, // natural BC, and linear elements. H1Space space(&mesh, &bc_types, P_INIT); // The type of element, mesh_mode = 3 means a triangle element. int mesh_mode = 3; int n = Space::get_num_dofs(&space); info("ndof = %d", n); int *fn_idx = new int [n]; int m = 0; int order = P_INIT; int vertex1 = 0; int vertex2 = 1; int vertex3 = 2; double x = 0.0, y = 0.0, value = 0.0; double x1 = -1.0, y1 = -1.0; double x2 = 1.0, y2 = -1.0; double x3 = -1.0, y3 = 1.0; info("Testing................"); // Check vertex functions. info("Check vertex functions."); for (int i = 0; i < mesh_mode; i++, m++) { fn_idx[m] = space.get_shapeset()->get_vertex_index(i); info("Check vertex function [%d]", m); if (i == vertex1) { // Vertices. value = space.get_shapeset()->get_fn_value(fn_idx[i], x2, y2, 0); if (value >= EPS) { printf("... Failed\n"); return ERR_FAILURE; } value = space.get_shapeset()->get_fn_value(fn_idx[i], x3, y3, 0); if (value >= EPS) { printf("... Failed\n"); return ERR_FAILURE; } printf("Vertices... Ok\n"); // Edges. printf("Edge 2."); for (int j = 0; j < order-1; j++) { x = x3 - (j+1)*(x3 - x2)/order; y = y3 - (j+1)*(y3 - y2)/order; value = space.get_shapeset()->get_fn_value(fn_idx[i], x, y, 0); if (value >= EPS) { printf("\nx = %f, y = %f, value = %.20lf", x, y, value); printf("... Failed\n"); return ERR_FAILURE; } } printf("... Ok\n"); } if (i == vertex2) { // Vertices. value = space.get_shapeset()->get_fn_value(fn_idx[i], x1, y1, 0); if (value >= EPS) { printf("... Failed\n"); return ERR_FAILURE; } value = space.get_shapeset()->get_fn_value(fn_idx[i], x3, y3, 0); if (value >= EPS) { printf("... Failed\n"); return ERR_FAILURE; } printf("Vertices... Ok\n"); // Edges. printf("Edge 3."); for (int j = 0; j < order-1; j++) { x = x3 - (j+1)*(x3 - x1)/order; y = y3 - (j+1)*(y3 - y1)/order; value = space.get_shapeset()->get_fn_value(fn_idx[i], x, y, 0); if (value >= EPS) { printf("\nx = %f, y = %f, value = %.20lf", x, y, value); printf("... Failed\n"); return ERR_FAILURE; } } printf("... Ok\n"); } if (i == vertex3) { // Vertices. value = space.get_shapeset()->get_fn_value(fn_idx[i], x1, y1, 0); if (value >= EPS) { printf("... Failed\n"); return ERR_FAILURE; } value = space.get_shapeset()->get_fn_value(fn_idx[i], x2, y2, 0); if (value >= EPS) { printf("... Failed\n"); return ERR_FAILURE; } printf("Vertices... Ok\n"); // Edges. printf("Edge 1."); for (int j = 0; j < order-1; j++) { x = x1 - (j+1)*(x1 - x2)/order; y = y1 - (j+1)*(y1 - y2)/order; value = space.get_shapeset()->get_fn_value(fn_idx[i], x, y, 0); if (value >= EPS) { printf("\nx = %f, y = %f, value = %.20lf", x, y, value); printf("... Failed\n"); return ERR_FAILURE; } } printf("... Ok\n"); } } // Check edge functions. info("Check edge functions."); for (int edge_order = 2; edge_order <= order; edge_order++) { for (int j = 0; j < mesh_mode; j++, m++) { fn_idx[m] = space.get_shapeset()->get_edge_index(j, 0, edge_order); info("Check edge function [%d]", m); // Vertices. value = space.get_shapeset()->get_fn_value(fn_idx[m], x1, y1, 0); if (value >= EPS) { printf("... Failed\n"); return ERR_FAILURE; } value = space.get_shapeset()->get_fn_value(fn_idx[m], x2, y2, 0); if (value >= EPS) { printf("... Failed\n"); return ERR_FAILURE; } value = space.get_shapeset()->get_fn_value(fn_idx[m], x3, y3, 0); if (value >= EPS) { printf("... Failed\n"); return ERR_FAILURE; } printf("Vertices... Ok\n"); // Edge 1. if (m%mesh_mode == 0) { printf("Edge 1."); // Check edge 2. for (int j = 0; j < order-1; j++) { x = x2 - (j+1)*(x2 - x3)/order; y = y2 - (j+1)*(y2 - y3)/order; value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0); if (value >= EPS) { printf("\nx = %f, y = %f, value = %.20lf", x, y, value); printf("... Failed\n"); return ERR_FAILURE; } } // Check edge 3. for (int j = 0; j < order-1; j++) { x = x3 - (j+1)*(x3 - x1)/order; y = y3 - (j+1)*(y3 - y1)/order; value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0); if (value >= EPS) { printf("\nx = %f, y = %f, value = %.20lf", x, y, value); printf("... Failed\n"); return ERR_FAILURE; } } printf("... Ok\n"); } // Edge 2. if (m%mesh_mode == 1) { printf("Edge 2."); // Check edge 1. for (int j = 0; j < order-1; j++) { x = x2 - (j+1)*(x2 - x1)/order; y = y2 - (j+1)*(y2 - y1)/order; value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0); if (value >= EPS) { printf("\nx = %f, y = %f, value = %.20lf", x, y, value); printf("... Failed\n"); return ERR_FAILURE; } } // Check edge 3. for (int j = 0; j < order-1; j++) { x = x3 - (j+1)*(x3 - x1)/order; y = y3 - (j+1)*(y3 - y1)/order; value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0); if (value >= EPS) { printf("\nx = %f, y = %f, value = %.20lf", x, y, value); printf("... Failed\n"); return ERR_FAILURE; } } printf("... Ok\n"); } // Edge 3. if (m%mesh_mode == 2) { printf("Edge 3."); // Check edge 2. for (int j = 0; j < order-1; j++) { x = x2 - (j+1)*(x2 - x3)/order; y = y2 - (j+1)*(y2 - y3)/order; value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0); if (value >= EPS) { printf("\nx = %f, y = %f, value = %.20lf", x, y, value); printf("... Failed\n"); return ERR_FAILURE; } } // Check edge 1. for (int j = 0; j < order-1; j++) { x = x1 - (j+1)*(x1 - x2)/order; y = y1 - (j+1)*(y1 - y2)/order; value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0); if (value >= EPS) { printf("\nx = %f, y = %f, value = %.20lf", x, y, value); printf("... Failed\n"); return ERR_FAILURE; } } printf("... Ok\n"); } } } // Check bubble functions. info("Check bubble functions."); int number_bubble = space.get_shapeset()->get_num_bubbles(order); int *bubble_idx = space.get_shapeset()->get_bubble_indices(order); for (int i = 0; i < number_bubble; i++, m++ ) { fn_idx[m] = bubble_idx[i]; info("Check bubble function [%d]", m); printf("Edge 1 and vertex 1."); // Check edge 1 and vertex 1. for (int j = 0; j < order; j++) { x = x1 - (j)*(x1 - x2)/order; y = y1 - (j)*(y1 - y2)/order; value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0); if (value >= EPS) { printf("\nx = %f, y = %f, value = %.20lf", x, y, value); printf("... Failed\n"); return ERR_FAILURE; } } printf("... Ok\n"); printf("Edge 2 and vertex 2."); // Check edge 2 and vertex 2. for (int j = 0; j < order; j++) { x = x2 - (j)*(x2 - x3)/order; y = y2 - (j)*(y2 - y3)/order; value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0); if (value >= EPS) { printf("\nx = %f, y = %f, value = %.20lf", x, y, value); printf("... Failed\n"); return ERR_FAILURE; } } printf("... Ok\n"); printf("Edge 3 and vertex 3."); // Check edge 3 and vertex 3. for (int j = 0; j < order; j++) { x = x3 - (j)*(x3 - x1)/order; y = y3 - (j)*(y3 - y1)/order; value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0); if (value >= EPS) { printf("\nx = %f, y = %f, value = %.20lf", x, y, value); printf("... Failed\n"); return ERR_FAILURE; } } printf("... Ok\n"); } info("ndof = %d", n); printf("Success!\n"); delete [] fn_idx; return ERR_SUCCESS; }
int main(int argc, char* argv[]) { Hermes2D hermes_2D; // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); // Initial mesh refinements. for (int i=0; i < 4; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(HERMES_ANY, 4); // Initialize boundary conditions. DefaultEssentialBCConst zero_vel_bc_x_brl(Hermes::vector<std::string>("Bottom", "Right", "Left"), 0.0); DefaultEssentialBCConst vel_bc_x_top(Hermes::vector<std::string>("Top"), XVEL_TOP); EssentialBCs bcs_vel_x(Hermes::vector<EssentialBoundaryCondition*>(&vel_bc_x_top, &zero_vel_bc_x_brl)); DefaultEssentialBCConst zero_vel_bc_y(Hermes::vector<std::string>("Bottom", "Right", "Top", "Left"), 0.0); EssentialBCs bcs_vel_y(&zero_vel_bc_y); EssentialBCs bcs_pressure; // Spaces for velocity components and pressure. H1Space xvel_space(&mesh, &bcs_vel_x, P_INIT_VEL); H1Space yvel_space(&mesh, &bcs_vel_y, P_INIT_VEL); #ifdef PRESSURE_IN_L2 L2Space p_space(&mesh, &bcs_pressure, P_INIT_PRESSURE); #else H1Space p_space(&mesh, &bcs_pressure, P_INIT_PRESSURE); #endif Hermes::vector<Space *> spaces = Hermes::vector<Space *>(&xvel_space, &yvel_space, &p_space); // Calculate and report the number of degrees of freedom. int ndof = Space::get_num_dofs(Hermes::vector<Space *>(&xvel_space, &yvel_space, &p_space)); info("ndof = %d.", ndof); // Define projection norms. ProjNormType vel_proj_norm = HERMES_H1_NORM; #ifdef PRESSURE_IN_L2 ProjNormType p_proj_norm = HERMES_L2_NORM; #else ProjNormType p_proj_norm = HERMES_H1_NORM; #endif ProjNormType t_proj_norm = HERMES_H1_NORM; // Solutions for the Newton's iteration and time stepping. info("Setting initial conditions."); Solution xvel_prev_time, yvel_prev_time, p_prev_time; xvel_prev_time.set_zero(&mesh); yvel_prev_time.set_zero(&mesh); p_prev_time.set_zero(&mesh); Hermes::vector<Solution*> slns = Hermes::vector<Solution*>(&xvel_prev_time, &yvel_prev_time, &p_prev_time); // Initialize weak formulation. WeakForm* wf = new WeakFormDrivenCavity(Re, "Top", time_step, &xvel_prev_time, &yvel_prev_time); // Initialize the FE problem. DiscreteProblem dp(wf, spaces); // 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. VectorView vview("velocity", new WinGeom(0, 0, 400, 400)); ScalarView pview("pressure", new WinGeom(410, 0, 400, 400)); //vview.set_min_max_range(0, 1.6); vview.fix_scale_width(80); pview.fix_scale_width(80); pview.show_mesh(true); // Project the initial condition on the FE space to obtain initial // coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[Space::get_num_dofs(spaces)]; info("Projecting initial condition to obtain initial vector for the Newton's method."); OGProjection::project_global(spaces, slns, coeff_vec, matrix_solver, Hermes::vector<ProjNormType>(vel_proj_norm, vel_proj_norm, p_proj_norm, t_proj_norm)); // Time-stepping loop: char title[100]; double current_time = 0; int num_time_steps = T_FINAL / time_step; for (int ts = 1; ts <= num_time_steps; ts++) { info("---- Time step %d, time = %g:", ts, current_time); // Perform Newton's iteration. info("Solving nonlinear problem:"); bool verbose = true; if (!hermes_2D.solve_newton(coeff_vec, &dp, solver, matrix, rhs, NEWTON_TOL, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Update previous time level solutions. Solution::vector_to_solutions(coeff_vec, spaces, slns); // Show the solution at the end of time step. sprintf(title, "Velocity, time %g", current_time); vview.set_title(title); vview.show(&xvel_prev_time, &yvel_prev_time); sprintf(title, "Pressure, time %g", current_time); pview.set_title(title); pview.show(&p_prev_time); // Update current time. current_time += time_step; } // Clean up. 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[]) { // 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)); // Initialize the linear system. LinSystem ls(&wf, &space); // Testing n_dof and correctness of solution vector // for p_init = 1, 2, ..., 10 int success = 1; Solution sln; for (int p_init = 1; p_init <= 10; p_init++) { printf("********* p_init = %d *********\n", p_init); space.set_uniform_order(p_init); // Assemble and solve the matrix problem. ls.assemble(); ls.solve(&sln); scalar *sol_vector; int n_dof; ls.get_solution_vector(sol_vector, n_dof); printf("n_dof = %d\n", n_dof); double sum = 0; for (int i=0; i < n_dof; i++) sum += sol_vector[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; } #define ERROR_SUCCESS 0 #define ERROR_FAILURE -1 if (success == 1) { printf("Success!\n"); return ERROR_SUCCESS; } else { printf("Failure!\n"); return ERROR_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); // Solution for the previous time level. Solution u_prev_time; // 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); } // Project the function init_cond() on the FE space // to obtain initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[Space::get_num_dofs(&space)]; info("Projecting initial condition to obtain initial vector for the Newton's method."); OGProjection::project_global(&space, init_cond, coeff_vec, matrix_solver); Solution::vector_to_solution(coeff_vec, &space, &u_prev_time); // Time stepping loop: double current_time = 0.0; int t_step = 1; do { info("---- Time step %d, t = %g s.", t_step, current_time); t_step++; // 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); // 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++; } // Translate the resulting coefficient vector into the Solution sln. Solution::vector_to_solution(coeff_vec, &space, &u_prev_time); // Cleanup. delete matrix; delete rhs; delete solver; // Update time. current_time += TAU; } while (current_time < T_FINAL); delete [] coeff_vec; info("Coordinate ( 0, 0) value = %lf", u_prev_time.get_pt_value(0.0, 0.0)); info("Coordinate ( 25, 25) value = %lf", u_prev_time.get_pt_value(25.0, 25.0)); info("Coordinate ( 50, 50) value = %lf", u_prev_time.get_pt_value(50.0, 50.0)); info("Coordinate ( 75, 75) value = %lf", u_prev_time.get_pt_value(75.0, 75.0)); info("Coordinate (100, 100) value = %lf", u_prev_time.get_pt_value(100.0, 100.0)); double coor_x_y[5] = {0.0, 25.0, 50.0, 75.0, 100.0}; double value[5] = {-1000.000000, -969.316013, -836.504249, -651.433710, -1000.000000}; for (int i = 0; i < 5; i++) { if ((value[i] - u_prev_time.get_pt_value(coor_x_y[i], coor_x_y[i])) < 1E-6) { } else { printf("Failure!\n"); return ERR_FAILURE; } } printf("Success!\n"); return ERR_SUCCESS; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; if (ALIGN_MESH) mloader.load("../oven_load_circle.mesh", &mesh); else mloader.load("../oven_load_square.mesh", &mesh); // Perform initial mesh refinemets. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize the weak formulation. CustomWeakForm wf(e_0, mu_0, mu_r, kappa, omega, J, ALIGN_MESH); // Initialize boundary conditions DefaultEssentialBCConst bc_essential(BDY_PERFECT_CONDUCTOR, std::complex<double>(0.0, 0.0)); EssentialBCs bcs(&bc_essential); // Create an Hcurl space with default shapeset. HcurlSpace space(&mesh, &bcs, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d", ndof); // Initialize coarse and reference mesh solution. Solution sln, ref_sln; // Initialize refinements selector. HcurlProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = Space::construct_refined_space(&space); // 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 the reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. // If successful, obtain the solution. if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // 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); ndof = Space::get_num_dofs(&space); int n_dof_allowed = 1230; printf("n_dof_actual = %d\n", ndof); // was 1218 at the time this test was last revisited printf("n_dof_allowed = %d\n", n_dof_allowed); if (ndof <= n_dof_allowed) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // 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) { // Instantiate a class with global functions. Hermes2D hermes2d; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("../square.mesh", &mesh); // Perform initial mesh refinemets. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Set exact solution. CustomExactSolution exact(&mesh); // Initialize the weak formulation. WeakFormPoisson wf1; // Initialize boundary conditions DefaultEssentialBCNonConst bc_essential(BDY_DIRICHLET, &exact); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof: %d", ndof); info("---- Assembling by DiscreteProblem, solving by %s:", MatrixSolverNames[matrix_solver].c_str()); // Initialize the solution. Solution sln1; // Initialize the linear discrete problem. bool is_linear = true; DiscreteProblem dp1(&wf1, &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); if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Begin time measurement of assembly. cpu_time.tick(HERMES_SKIP); // Assemble the stiffness matrix and right-hand side vector. info("Assembling the stiffness matrix and right-hand side vector."); dp1.assemble(matrix, rhs); // Record assembly time. double time1 = cpu_time.tick().last(); cpu_time.reset(); // Solve the linear system and if successful, obtain the solution. info("Solving the matrix problem by %s.", MatrixSolverNames[matrix_solver].c_str()); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln1); else error ("Matrix solver failed.\n"); // CPU time needed by UMFpack to solve the matrix problem. double time2 = cpu_time.tick().last(); // Calculate errors. double rel_err_1 = hermes2d.calc_rel_error(&sln1, &exact, HERMES_H1_NORM) * 100; info("Assembly time: %g s, matrix solver time: %g s.", time1, time2); info("Xxact H1 error: %g%%.", rel_err_1); delete(matrix); delete(rhs); delete(solver); // View the solution and mesh. //ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); //sview.show(&sln1); //OrderView oview("Polynomial orders", new WinGeom(450, 0, 400, 350)); //oview.show(&space); // TRILINOS PART: info("---- Assembling by DiscreteProblem, solving by NOX:"); // Initialize the weak formulation for Trilinos. bool is_matrix_free = JFNK; WeakFormPoissonNox wf2(is_matrix_free); // Initialize DiscreteProblem. is_linear = false; DiscreteProblem dp2(&wf2, &space, is_linear); // Time measurement. cpu_time.tick(HERMES_SKIP); // Set initial vector for NOX. info("Projecting to obtain initial vector for the Newton's method."); scalar* coeff_vec = new scalar[ndof]; Solution* init_sln = new Solution(&mesh, 0.0); OGProjection::project_global(&space, init_sln, coeff_vec); delete init_sln; // Measure the projection time. double proj_time = cpu_time.tick().last(); // Initialize the NOX solver with the vector "coeff_vec". info("Initializing NOX."); // "" stands for preconditioning that is set later. NoxSolver nox_solver(&dp2, message_type, "GMRES", "Newton", ls_tolerance, "", flag_absresid, abs_resid, flag_relresid, rel_resid, max_iters); nox_solver.set_init_sln(coeff_vec); delete coeff_vec; // Choose preconditioning. RCP<Precond> pc = rcp(new MlPrecond("sa")); if (PRECOND) { if (JFNK) nox_solver.set_precond(pc); else nox_solver.set_precond("ML"); } // Assemble and solve using NOX. Solution sln2; if (nox_solver.solve()) { Solution::vector_to_solution(nox_solver.get_solution(), &space, &sln2); info("Number of nonlin iterations: %d (norm of residual: %g)", nox_solver.get_num_iters(), nox_solver.get_residual()); info("Total number of iterations in linsolver: %d (achieved tolerance in the last step: %g)", nox_solver.get_num_lin_iters(), nox_solver.get_achieved_tol()); } else error("NOX failed"); // CPU time needed by NOX. time2 = cpu_time.tick().last(); // Show the NOX solution. //ScalarView view2("Solution 2", new WinGeom(450, 0, 440, 350)); //view2.show(&sln2); //view2.show(&exact); // Calculate errors. double rel_err_2 = hermes2d.calc_rel_error(&sln2, &exact, HERMES_H1_NORM) * 100; info("Projection time: %g s, NOX assembly/solution time: %g s.", proj_time, time2); info("Exact H1 error: %g%%.)", rel_err_2); /* TESTING */ info("Coordinate (-0.6, -0.6) hermes value = %lf", sln1.get_pt_value(-0.6, -0.6)); info("Coordinate ( 0.4, -0.6) hermes value = %lf", sln1.get_pt_value( 0.4, -0.6)); info("Coordinate ( 0.4, 0.4) hermes value = %lf", sln1.get_pt_value( 0.4, 0.4)); info("Coordinate (-0.6, 0.0) hermes value = %lf", sln1.get_pt_value(-0.6, 0.0)); info("Coordinate ( 0.0, 0.0) hermes value = %lf", sln1.get_pt_value( 0.0, 0.0)); info("Coordinate (-0.6, -0.6) nox value = %lf", sln2.get_pt_value(-0.6, -0.6)); info("Coordinate ( 0.4, -0.6) nox value = %lf", sln2.get_pt_value( 0.4, -0.6)); info("Coordinate ( 0.4, 0.4) nox value = %lf", sln2.get_pt_value( 0.4, 0.4)); info("Coordinate (-0.6, 0.0) nox value = %lf", sln2.get_pt_value(-0.6, 0.0)); info("Coordinate ( 0.0, 0.0) nox value = %lf", sln2.get_pt_value( 0.0, 0.0)); #define ERROR_SUCCESS 0 #define ERROR_FAILURE -1 int success = 1; double eps = 1e-5; if (fabs(sln2.get_pt_value(-0.6, -0.6) - 0.720000) > eps) { printf("Coordinate (-0.6, -0.6) nox value is %g\n", sln2.get_pt_value(-0.6, -0.6)); success = 0; } if (fabs(sln2.get_pt_value( 0.4, -0.6) - 0.520000) > eps) { printf("Coordinate ( 0.4, -0.6) nox value is %g\n", sln2.get_pt_value( 0.4, -0.6)); success = 0; } if (fabs(sln2.get_pt_value( 0.4, 0.4) - 0.320000) > eps) { printf("Coordinate ( 0.4, 0.4) nox value is %g\n", sln2.get_pt_value( 0.4, 0.4)); success = 0; } if (fabs(sln2.get_pt_value(-0.6, 0.0) - 0.360000) > eps) { printf("Coordinate (-0.6, 0.0) nox value is %g\n", sln2.get_pt_value(-0.6, 0.0)); success = 0; } if (fabs(sln2.get_pt_value( 0.0, 0.0) - 0.000000) > eps) { printf("Coordinate ( 0.0, 0.0) nox value is %g\n", sln2.get_pt_value( 0.0, 0.0)); success = 0; } if (fabs(sln1.get_pt_value(-0.6, -0.6) - 0.720000) > eps) { printf("Coordinate (-0.6, -0.6) hermes value is %g\n", sln1.get_pt_value(-0.6, -0.6)); success = 0; } if (fabs(sln1.get_pt_value( 0.4, -0.6) - 0.520000) > eps) { printf("Coordinate ( 0.4, -0.6) hermes value is %g\n", sln1.get_pt_value( 0.4, -0.6)); success = 0; } if (fabs(sln1.get_pt_value( 0.4, 0.4) - 0.320000) > eps) { printf("Coordinate ( 0.4, 0.4) hermes value is %g\n", sln1.get_pt_value( 0.4, 0.4)); success = 0; } if (fabs(sln1.get_pt_value(-0.6, 0.0) - 0.360000) > eps) { printf("Coordinate (-0.6, 0.0) hermes value is %g\n", sln1.get_pt_value(-0.6, 0.0)); success = 0; } if (fabs(sln1.get_pt_value( 0.0, 0.0) - 0.000000) > eps) { printf("Coordinate ( 0.0, 0.0) hermes value is %g\n", sln1.get_pt_value( 0.0, 0.0)); success = 0; } if (success == 1) { printf("Success!\n"); return ERROR_SUCCESS; } else { printf("Failure!\n"); return ERROR_FAILURE; } }
int main(int argc, char* argv[]) { // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); if (bt.is_explicit()) info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); // Perform initial mesh refinemets. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize solutions. CustomInitialConditionWave E_sln(&mesh); Solution F_sln(&mesh, 0.0, 0.0); Hermes::vector<Solution*> slns(&E_sln, &F_sln); // Initialize the weak formulation. CustomWeakFormWave wf(C_SQUARED); // Initialize boundary conditions DefaultEssentialBCConst bc_essential(BDY, 0.0); EssentialBCs bcs(&bc_essential); // Create x- and y- displacement space using the default H1 shapeset. HcurlSpace E_space(&mesh, &bcs, P_INIT); HcurlSpace F_space(&mesh, &bcs, P_INIT); Hermes::vector<Space *> spaces = Hermes::vector<Space *>(&E_space, &F_space); info("ndof = %d.", Space::get_num_dofs(spaces)); // Initialize the FE problem. DiscreteProblem dp(&wf, spaces); // Initialize views. ScalarView E1_view("Solution E1", new WinGeom(0, 0, 400, 350)); E1_view.fix_scale_width(50); ScalarView E2_view("Solution E2", new WinGeom(410, 0, 400, 350)); E2_view.fix_scale_width(50); // Initialize Runge-Kutta time stepping. RungeKutta runge_kutta(&dp, &bt, matrix_solver); // Time stepping loop. double current_time = 0; int ts = 1; do { // Perform one Runge-Kutta time step according to the selected Butcher's table. info("Runge-Kutta time step (t = %g s, time_step = %g s, stages: %d).", current_time, time_step, bt.get_size()); bool verbose = true; bool jacobian_changed = true; if (!runge_kutta.rk_time_step(current_time, time_step, slns, slns, jacobian_changed, verbose)) error("Runge-Kutta time step failed, try to decrease time step size."); // Visualize the solutions. char title[100]; sprintf(title, "E1, t = %g", current_time); E1_view.set_title(title); E1_view.show(&E_sln, HERMES_EPS_NORMAL, H2D_FN_VAL_0); sprintf(title, "E2, t = %g", current_time); E2_view.set_title(title); E2_view.show(&E_sln, HERMES_EPS_NORMAL, H2D_FN_VAL_1); // Update time. current_time += time_step; } while (current_time < T_FINAL); // Wait for the view to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("GAMM-channel.mesh", &mesh); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(0, true); mesh.refine_towards_boundary(BDY_SOLID_WALL_BOTTOM, INIT_REF_NUM_BOUNDARY_ANISO, true, false, true); mesh.refine_towards_boundary(BDY_SOLID_WALL_BOTTOM, INIT_REF_NUM_BOUNDARY_ISO, false, false, true); // Initialize boundary condition types and spaces with default shapesets. L2Space space_rho(&mesh, P_INIT); L2Space space_rho_v_x(&mesh, P_INIT); L2Space space_rho_v_y(&mesh,P_INIT); L2Space space_e(&mesh, P_INIT); int ndof = Space::get_num_dofs(Hermes::vector<Space*>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e)); info("ndof: %d", ndof); // Initialize solutions, set initial conditions. InitialSolutionEulerDensity sln_rho(&mesh, RHO_EXT); InitialSolutionEulerDensityVelX sln_rho_v_x(&mesh, RHO_EXT * V1_EXT); InitialSolutionEulerDensityVelY sln_rho_v_y(&mesh, RHO_EXT * V2_EXT); InitialSolutionEulerDensityEnergy sln_e(&mesh, QuantityCalculator::calc_energy(RHO_EXT, RHO_EXT * V1_EXT, RHO_EXT * V2_EXT, P_EXT, KAPPA)); InitialSolutionEulerDensity prev_rho(&mesh, RHO_EXT); InitialSolutionEulerDensityVelX prev_rho_v_x(&mesh, RHO_EXT * V1_EXT); InitialSolutionEulerDensityVelY prev_rho_v_y(&mesh, RHO_EXT * V2_EXT); InitialSolutionEulerDensityEnergy prev_e(&mesh, QuantityCalculator::calc_energy(RHO_EXT, RHO_EXT * V1_EXT, RHO_EXT * V2_EXT, P_EXT, KAPPA)); Solution rsln_rho, rsln_rho_v_x, rsln_rho_v_y, rsln_e; // Numerical flux. OsherSolomonNumericalFlux num_flux(KAPPA); // Initialize weak formulation. EulerEquationsWeakFormImplicitMultiComponent wf(&num_flux, KAPPA, RHO_EXT, V1_EXT, V2_EXT, P_EXT, BDY_SOLID_WALL_BOTTOM, BDY_SOLID_WALL_TOP, BDY_INLET, BDY_OUTLET, &prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e, PRECONDITIONING); wf.set_time_step(time_step); // Filters for visualization of Mach number, pressure and entropy. MachNumberFilter Mach_number(Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), KAPPA); PressureFilter pressure(Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), KAPPA); EntropyFilter entropy(Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), KAPPA, RHO_EXT, P_EXT); ScalarView pressure_view("Pressure", new WinGeom(0, 0, 600, 300)); ScalarView Mach_number_view("Mach number", new WinGeom(700, 0, 600, 300)); ScalarView entropy_production_view("Entropy estimate", new WinGeom(0, 400, 600, 300)); /* ScalarView s1("1", new WinGeom(0, 0, 600, 300)); ScalarView s2("2", new WinGeom(700, 0, 600, 300)); ScalarView s3("3", new WinGeom(0, 400, 600, 300)); ScalarView s4("4", new WinGeom(700, 400, 600, 300)); */ // Initialize refinement selector. L2ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Select preconditioner. RCP<Precond> pc = rcp(new IfpackPrecond("point-relax")); int iteration = 0; double t = 0; for(t = 0.0; t < 3.0; t += time_step) { info("---- Time step %d, time %3.5f.", iteration++, t); // Periodic global derefinements. if (iteration > 1 && iteration % UNREF_FREQ == 0 && REFINEMENT_COUNT > 0) { REFINEMENT_COUNT = 0; info("Global mesh derefinement."); mesh.unrefine_all_elements(); space_rho.adjust_element_order(-1, P_INIT); space_rho_v_x.adjust_element_order(-1, P_INIT); space_rho_v_y.adjust_element_order(-1, P_INIT); space_e.adjust_element_order(-1, P_INIT); } // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. // Global polynomial order increase; int order_increase = 1; Hermes::vector<Space *>* ref_spaces = Space::construct_refined_spaces(Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), order_increase); // Report NDOFs. info("ndof_coarse: %d, ndof_fine: %d.", Space::get_num_dofs(Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e)), Space::get_num_dofs(*ref_spaces)); // Project the previous time level solution onto the new fine mesh // in order to obtain initial vector for NOX. info("Projecting initial solution on the FE mesh."); scalar* coeff_vec = new scalar[Space::get_num_dofs(*ref_spaces)]; OGProjection::project_global(*ref_spaces, Hermes::vector<MeshFunction *>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), coeff_vec); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp(&wf, *ref_spaces, is_linear); // Initialize NOX solver. NoxSolver solver(&dp, NOX_MESSAGE_TYPE); solver.set_ls_tolerance(NOX_LINEAR_TOLERANCE); solver.disable_abs_resid(); solver.set_conv_rel_resid(NOX_NONLINEAR_TOLERANCE); if(PRECONDITIONING) solver.set_precond(pc); info("Assembling by DiscreteProblem, solving by NOX."); solver.set_init_sln(coeff_vec); scalar* solution_vector = NULL; if (solver.solve()) { solution_vector = solver.get_solution(); Solution::vector_to_solutions(solution_vector, *ref_spaces, Hermes::vector<Solution *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e)); } else error("NOX failed."); info("Number of nonlin iterations: %d (norm of residual: %g)", solver.get_num_iters(), solver.get_residual()); info("Total number of iterations in linsolver: %d (achieved tolerance in the last step: %g)", solver.get_num_lin_iters(), solver.get_achieved_tol()); if(SHOCK_CAPTURING) { DiscontinuityDetector discontinuity_detector(*ref_spaces, Hermes::vector<Solution *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e)); std::set<int> discontinuous_elements = discontinuity_detector.get_discontinuous_element_ids(DISCONTINUITY_DETECTOR_PARAM); FluxLimiter flux_limiter(solution_vector, *ref_spaces, Hermes::vector<Solution *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e)); flux_limiter.limit_according_to_detector(discontinuous_elements); } // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), Hermes::vector<Solution *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e), Hermes::vector<Solution *>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e), matrix_solver, Hermes::vector<ProjNormType>(HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM)); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt* adaptivity = new Adapt(Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), Hermes::vector<ProjNormType>(HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM)); double err_est_rel_total = adaptivity->calc_err_est(Hermes::vector<Solution *>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e), Hermes::vector<Solution *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e)) * 100; // Report results. info("err_est_rel: %g%%", err_est_rel_total); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(Hermes::vector<RefinementSelectors::Selector *>(&selector, &selector, &selector, &selector), THRESHOLD, STRATEGY, MESH_REGULARITY); REFINEMENT_COUNT++; if (Space::get_num_dofs(Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e)) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } // Clean up. delete adaptivity; if(!done) for(unsigned int i = 0; i < ref_spaces->size(); i++) delete (*ref_spaces)[i]->get_mesh(); for(unsigned int i = 0; i < ref_spaces->size(); i++) delete (*ref_spaces)[i]; } while (done == false); // Copy the solutions into the previous time level ones. prev_rho.copy(&rsln_rho); prev_rho_v_x.copy(&rsln_rho_v_x); prev_rho_v_y.copy(&rsln_rho_v_y); prev_e.copy(&rsln_e); // Visualization. if((iteration - 1) % EVERY_NTH_STEP == 0) { // Hermes visualization. if(HERMES_VISUALIZATION) { Mach_number.reinit(); pressure.reinit(); entropy.reinit(); pressure_view.show(&pressure); entropy_production_view.show(&entropy); Mach_number_view.show(&Mach_number); /* s1.show(&prev_rho); s2.show(&prev_rho_v_x); s3.show(&prev_rho_v_y); s4.show(&prev_e); */ } // Output solution in VTK format. if(VTK_VISUALIZATION) { pressure.reinit(); Mach_number.reinit(); Linearizer lin; char filename[40]; sprintf(filename, "pressure-%i.vtk", iteration - 1); lin.save_solution_vtk(&pressure, filename, "Pressure", false); sprintf(filename, "pressure-3D-%i.vtk", iteration - 1); lin.save_solution_vtk(&pressure, filename, "Pressure", true); sprintf(filename, "Mach number-%i.vtk", iteration - 1); lin.save_solution_vtk(&Mach_number, filename, "MachNumber", false); sprintf(filename, "Mach number-3D-%i.vtk", iteration - 1); lin.save_solution_vtk(&Mach_number, filename, "MachNumber", true); } } } pressure_view.close(); entropy_production_view.close(); Mach_number_view.close(); /* s1.close(); s2.close(); s3.close(); s4.close(); */ return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("../domain.mesh", &mesh); // Initialize boundary conditions. DefaultEssentialBCConst essential_bc(BDY_BOTTOM, 0.0); EssentialBCs bcs(&essential_bc); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); // Initialize the weak formulation. CustomWeakForm wf(A_SE, A_NE, A_SW, A_NW, RHS); // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // DOF and CPU convergence graphs. SimpleGraph graph_dof, graph_cpu; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = Space::construct_refined_space(&space); // Assemble the reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. If successful, obtain the solution. 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 the 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); printf("ndof allowed = %d\n", 210); printf("ndof actual = %d\n", ndof); if (ndof < 210) { // ndofs was 208 at the time this test was created printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("square.mesh", &mesh); // Perform initial mesh refinements. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(Hermes::vector<int>(BDY_BOTTOM, BDY_RIGHT, BDY_TOP, BDY_LEFT)); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_zero(Hermes::vector<int>(BDY_BOTTOM, BDY_RIGHT, BDY_TOP, BDY_LEFT)); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof: %d", ndof); info("Assembling by DiscreteProblem, solving by Umfpack:"); // Time measurement. cpu_time.tick(HERMES_SKIP); // Initialize weak formulation, WeakForm wf1; wf1.add_matrix_form(callback(jacobian_form_hermes), HERMES_NONSYM, HERMES_ANY); wf1.add_vector_form(callback(residual_form_hermes), HERMES_ANY); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp1(&wf1, &space, is_linear); // Set up the solver, matrix, and rhs for the coarse mesh 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_hermes; if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Project the initial condition on the FE space to obtain initial // coefficient vector for the Newton's method. info("Projecting to obtain initial vector for the Newton's method."); scalar* coeff_vec = new scalar[Space::get_num_dofs(&space)] ; Solution* sln_tmp = new Solution(&mesh, init_cond); OGProjection::project_global(&space, sln_tmp, coeff_vec, matrix_solver); delete sln_tmp; // 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. dp1.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). 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_vec[i] += solver->get_solution()[i]; if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); it++; } // Translate the resulting coefficient vector into the Solution sln_hermes. Solution::vector_to_solution(coeff_vec, &space, &sln_hermes); // Cleanup. delete(matrix); delete(rhs); delete(solver); // CPU time needed by UMFpack double umf_time = cpu_time.tick().last(); // Time measurement. cpu_time.tick(HERMES_SKIP); // TRILINOS PART: // Project the initial condition on the FE space. info("Projecting initial condition on the FE space."); // The NULL pointer means that we do not want the projection result as a Solution. sln_tmp = new Solution(&mesh, init_cond); OGProjection::project_global(&space, sln_tmp, coeff_vec, matrix_solver); delete sln_tmp; // Measure the projection time. double proj_time = cpu_time.tick().last(); // Initialize the weak formulation for Trilinos. WeakForm wf2(1, JFNK ? true : false); if (!JFNK || (JFNK && PRECOND == 1)) wf2.add_matrix_form(callback(jacobian_form_nox), HERMES_SYM); if (JFNK && PRECOND == 2) wf2.add_matrix_form(callback(precond_form_nox), HERMES_SYM); wf2.add_vector_form(callback(residual_form_nox)); // Initialize DiscreteProblem. DiscreteProblem dp2(&wf2, &space); // Initialize the NOX solver with the vector "coeff_vec". info("Initializing NOX."); NoxSolver nox_solver(&dp2); nox_solver.set_init_sln(coeff_vec); // Choose preconditioning. RCP<Precond> pc = rcp(new MlPrecond("sa")); if (PRECOND) { if (JFNK) nox_solver.set_precond(pc); else nox_solver.set_precond("ML"); } // Solve the matrix problem using NOX. info("Assembling by DiscreteProblem, solving by NOX."); bool solved = nox_solver.solve(); Solution sln_nox; if (solved) { double *coeffs = nox_solver.get_solution(); Solution::vector_to_solution(coeffs, &space, &sln_nox); info("Number of nonlin iterations: %d (norm of residual: %g)", nox_solver.get_num_iters(), nox_solver.get_residual()); info("Total number of iterations in linsolver: %d (achieved tolerance in the last step: %g)", nox_solver.get_num_lin_iters(), nox_solver.get_achieved_tol()); } else error("NOX failed."); // CPU time needed by NOX. double nox_time = cpu_time.tick().last(); // Calculate errors. Solution ex; ex.set_exact(&mesh, &exact); Adapt adaptivity(&space); bool solutions_for_adapt = false; double err_est_rel_1 = adaptivity.calc_err_exact(&sln_hermes, &ex, solutions_for_adapt) * 100; info("Solution 1 (DiscreteProblem + %s): exact H1 error: %g (time %g [s])", MatrixSolverNames[matrix_solver].c_str(), err_est_rel_1, umf_time); double err_est_rel_2 = adaptivity.calc_err_exact(&sln_nox, &ex, solutions_for_adapt) * 100; info("Solution 2 (DiscreteProblem + NOX): exact H1 error: %g (time %g + %g = %g [s])", err_est_rel_2, proj_time, nox_time, proj_time+nox_time); info("Coordinate ( 0.6, 0.6) sln_hermes value = %lf", sln_hermes.get_pt_value( 0.6, 0.6)); info("Coordinate ( 0.4, 0.6) sln_hermes value = %lf", sln_hermes.get_pt_value( 0.4, 0.6)); info("Coordinate ( 0.4, 0.4) sln_hermes value = %lf", sln_hermes.get_pt_value( 0.4, 0.4)); info("Coordinate ( 0.6, 0.0) sln_hermes value = %lf", sln_hermes.get_pt_value( 0.6, 0.0)); info("Coordinate ( 0.5, 0.5) sln_hermes value = %lf", sln_hermes.get_pt_value( 0.5, 0.5)); info("Coordinate ( 0.6, 0.6) sln_nox value = %lf", sln_nox.get_pt_value( 0.6, 0.6)); info("Coordinate ( 0.4, 0.6) sln_nox value = %lf", sln_nox.get_pt_value( 0.4, 0.6)); info("Coordinate ( 0.4, 0.4) sln_nox value = %lf", sln_nox.get_pt_value( 0.4, 0.4)); info("Coordinate ( 0.6, 0.0) sln_nox value = %lf", sln_nox.get_pt_value( 0.6, 0.0)); info("Coordinate ( 0.5, 0.5) sln_nox value = %lf", sln_nox.get_pt_value( 0.5, 0.5)); #define ERROR_SUCCESS 0 #define ERROR_FAILURE -1 int success = 1; double eps = 1e-5; if (fabs(sln_nox.get_pt_value(0.6, 0.6) - 0.057600) > eps) { printf("Coordinate (0.6, 0.6) sln_nox value is %g\n", sln_nox.get_pt_value(0.6, 0.6)); success = 0; } if (fabs(sln_nox.get_pt_value( 0.4, 0.6) - 0.057600) > eps) { printf("Coordinate ( 0.4, 0.6) sln_nox value is %g\n", sln_nox.get_pt_value( 0.4, 0.6)); success = 0; } if (fabs(sln_nox.get_pt_value( 0.4, 0.4) - 0.057600) > eps) { printf("Coordinate ( 0.4, 0.4) sln_nox value is %g\n", sln_nox.get_pt_value( 0.4, 0.4)); success = 0; } if (fabs(sln_nox.get_pt_value(0.6, 0.0) - 0.000000) > eps) { printf("Coordinate (0.6, 0.0) sln_nox value is %g\n", sln_nox.get_pt_value(0.6, 0.0)); success = 0; } if (fabs(sln_nox.get_pt_value( 0.5, 0.5) - 0.062500) > eps) { printf("Coordinate ( 0.5, 0.5) sln_nox value is %g\n", sln_nox.get_pt_value( 0.5, 0.5)); success = 0; } if (fabs(sln_hermes.get_pt_value(0.6, 0.6) - 0.057600) > eps) { printf("Coordinate (0.6, 0.6) sln_hermes value is %g\n", sln_hermes.get_pt_value(0.6, 0.6)); success = 0; } if (fabs(sln_hermes.get_pt_value( 0.4, 0.6) - 0.057600) > eps) { printf("Coordinate ( 0.4, 0.6) sln_hermes value is %g\n", sln_hermes.get_pt_value( 0.4, 0.6)); success = 0; } if (fabs(sln_hermes.get_pt_value( 0.4, 0.4) - 0.057600) > eps) { printf("Coordinate ( 0.4, 0.4) sln_hermes value is %g\n", sln_hermes.get_pt_value( 0.4, 0.4)); success = 0; } if (fabs(sln_hermes.get_pt_value(0.6, 0.0) - 0.000000) > eps) { printf("Coordinate (0.6, 0.0) sln_hermes value is %g\n", sln_hermes.get_pt_value(0.6, 0.0)); success = 0; } if (fabs(sln_hermes.get_pt_value( 0.5, 0.5) - 0.062500) > eps) { printf("Coordinate ( 0.5, 0.5) sln_hermes value is %g\n", sln_hermes.get_pt_value( 0.5, 0.5)); success = 0; } if (success == 1) { printf("Success!\n"); return ERROR_SUCCESS; } else { printf("Failure!\n"); return ERROR_FAILURE; } }
int main(int argc, char* argv[]) { // Load the mesh file. Mesh basemesh, mesh; H2DReader mloader; mloader.load("domain.mesh", &basemesh); // Master mesh. // Perform initial mesh refinements. for (int i=0; i < INIT_REF_NUM; i++) basemesh.refine_all_elements(); basemesh.refine_towards_boundary(bdy_obstacle, INIT_REF_NUM_BDY, false); // 'true' stands for anisotropic refinements, basemesh.refine_towards_boundary(bdy_top, INIT_REF_NUM_BDY, true); // 'false' for isotropic. basemesh.refine_towards_boundary(bdy_bottom, INIT_REF_NUM_BDY, true); mesh.copy(&basemesh); // Create spaces with default shapesets. H1Space* xvel_space = new H1Space(&mesh, xvel_bc_type, essential_bc_values_xvel, P_INIT_VEL); H1Space* yvel_space = new H1Space(&mesh, yvel_bc_type, essential_bc_values_yvel, P_INIT_VEL); #ifdef PRESSURE_IN_L2 L2Space* p_space = new L2Space(&mesh, P_INIT_PRESSURE); #else H1Space* p_space = new H1Space(&mesh, p_bc_type, NULL, P_INIT_PRESSURE); #endif // Calculate and report the number of degrees of freedom. int ndof = get_num_dofs(Tuple<Space *>(xvel_space, yvel_space, p_space)); info("ndof = %d.", ndof); // Define projection norms. int vel_proj_norm = H2D_H1_NORM; #ifdef PRESSURE_IN_L2 int p_proj_norm = H2D_L2_NORM; #else int p_proj_norm = H2D_H1_NORM; #endif // Solutions for the Newton's iteration and time stepping. info("Setting initial conditions."); // Solution xvel_fine, yvel_fine, p_fine; Solution xvel_sln, yvel_sln, p_sln; Solution xvel_ref_sln, yvel_ref_sln, p_ref_sln; Solution xvel_prev_time, yvel_prev_time, p_prev_time; // Define initial conditions on the coarse mesh. xvel_prev_time.set_zero(&mesh); yvel_prev_time.set_zero(&mesh); p_prev_time.set_zero(&mesh); // Initialize the weak formulation. WeakForm wf(3); wf.add_matrix_form(0, 0, callback(bilinear_form_sym_0_0_1_1), H2D_SYM); wf.add_matrix_form(0, 0, callback(newton_bilinear_form_unsym_0_0), H2D_UNSYM, H2D_ANY); wf.add_matrix_form(0, 1, callback(newton_bilinear_form_unsym_0_1), H2D_UNSYM, H2D_ANY); wf.add_matrix_form(0, 2, callback(bilinear_form_unsym_0_2), H2D_ANTISYM); wf.add_matrix_form(1, 0, callback(newton_bilinear_form_unsym_1_0), H2D_UNSYM, H2D_ANY); wf.add_matrix_form(1, 1, callback(bilinear_form_sym_0_0_1_1), H2D_SYM); wf.add_matrix_form(1, 1, callback(newton_bilinear_form_unsym_1_1), H2D_UNSYM, H2D_ANY); wf.add_matrix_form(1, 2, callback(bilinear_form_unsym_1_2), H2D_ANTISYM); wf.add_vector_form(0, callback(newton_F_0), H2D_ANY, Tuple<MeshFunction*>(&xvel_prev_time, &yvel_prev_time)); wf.add_vector_form(1, callback(newton_F_1), H2D_ANY, Tuple<MeshFunction*>(&xvel_prev_time, &yvel_prev_time)); wf.add_vector_form(2, callback(newton_F_2), H2D_ANY); // Initialize adaptivity parameters. AdaptivityParamType apt(ERR_STOP, NDOF_STOP, THRESHOLD, STRATEGY, MESH_REGULARITY); // Create a selector which will select optimal candidate. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Assign initial condition to mesh. Vector *coeff_vec = new AVector(ndof); // Time-stepping loop: char title[100]; 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); xvel_space->set_uniform_order(P_INIT_VEL); yvel_space->set_uniform_order(P_INIT_VEL); p_space->set_uniform_order(P_INIT_PRESSURE); } // Update the coefficient vector and u_prev_time. info("Projecting to obtain coefficient vector on coarse mesh."); project_global(Tuple<Space *>(xvel_space, yvel_space, p_space), Tuple<int>(vel_proj_norm, vel_proj_norm, p_proj_norm), Tuple<MeshFunction*>(&xvel_prev_time, &yvel_prev_time, &p_prev_time), Tuple<Solution*>(&xvel_prev_time, &yvel_prev_time, &p_prev_time), coeff_vec); // Adaptivity loop (in space): bool verbose = true; // 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(Tuple<Space *>(xvel_space, yvel_space, p_space), &wf, coeff_vec, matrix_solver, Tuple<int>(vel_proj_norm, vel_proj_norm, p_proj_norm), Tuple<Solution *>(&xvel_sln, &yvel_sln, &p_sln), Tuple<Solution *>(&xvel_ref_sln, &yvel_ref_sln, &p_ref_sln), Tuple<WinGeom *>(), Tuple<WinGeom *>(), Tuple<RefinementSelectors::Selector *>(&selector, &selector, &selector), &apt, NEWTON_TOL_COARSE, NEWTON_TOL_FINE, NEWTON_MAX_ITER, verbose); // Copy new time level reference solution into prev_time. xvel_prev_time.set_coeff_vector(xvel_space, coeff_vec); yvel_prev_time.set_coeff_vector(yvel_space, coeff_vec); p_prev_time.set_coeff_vector(p_space, coeff_vec); } ndof = get_num_dofs(Tuple<Space *>(xvel_space, yvel_space, p_space)); info("ndof = %d", ndof); // Waiting for tests. }
int main(int argc, char* argv[]) { // Choose a Butcher's table or define your own. ButcherTable bt(butcher_table_type); if (bt.is_explicit()) info("Using a %d-stage explicit R-K method.", bt.get_size()); if (bt.is_diagonally_implicit()) info("Using a %d-stage diagonally implicit R-K method.", bt.get_size()); if (bt.is_fully_implicit()) info("Using a %d-stage fully implicit R-K method.", bt.get_size()); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("../domain.mesh", &mesh); // Perform initial mesh refinemets. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize solutions. CustomInitialConditionWave E_sln(&mesh); Solution B_sln(&mesh, 0.0); Hermes::vector<Solution*> slns(&E_sln, &B_sln); // Initialize the weak formulation. CustomWeakFormWave wf(C_SQUARED); // Initialize boundary conditions DefaultEssentialBCConst bc_essential("Perfect conductor", 0.0); EssentialBCs bcs_E(&bc_essential); EssentialBCs bcs_B; // Create x- and y- displacement space using the default H1 shapeset. HcurlSpace E_space(&mesh, &bcs_E, P_INIT); H1Space B_space(&mesh, &bcs_B, P_INIT); //L2Space B_space(&mesh, P_INIT); Hermes::vector<Space *> spaces = Hermes::vector<Space *>(&E_space, &B_space); info("ndof = %d.", Space::get_num_dofs(spaces)); // Initialize the FE problem. DiscreteProblem dp(&wf, spaces); // Initialize Runge-Kutta time stepping. RungeKutta runge_kutta(&dp, &bt, matrix_solver); // Time stepping loop. double current_time = time_step; int ts = 1; do { // Perform one Runge-Kutta time step according to the selected Butcher's table. info("Runge-Kutta time step (t = %g s, time_step = %g s, stages: %d).", current_time, time_step, bt.get_size()); bool jacobian_changed = false; bool verbose = true; if (!runge_kutta.rk_time_step(current_time, time_step, slns, slns, jacobian_changed, verbose)) error("Runge-Kutta time step failed, try to decrease time step size."); // Update time. current_time += time_step; } while (current_time < T_FINAL); double coord_x[4] = {0.3, 0.6, 0.9, 1.4}; double coord_y[4] = {0, 0.3, 0.5, 0.7}; info("Coordinate (0.3, 0.0) value = %lf", B_sln.get_pt_value(coord_x[0], coord_y[0])); info("Coordinate (0.6, 0.3) value = %lf", B_sln.get_pt_value(coord_x[1], coord_y[1])); info("Coordinate (0.9, 0.5) value = %lf", B_sln.get_pt_value(coord_x[2], coord_y[2])); info("Coordinate (1.4, 0.7) value = %lf", B_sln.get_pt_value(coord_x[3], coord_y[3])); double t_value[4] = {0.0, -0.065100, -0.146515, -0.247677}; bool success = true; for (int i = 0; i < 4; i++) { if (fabs(t_value[i] - B_sln.get_pt_value(coord_x[i], coord_y[i])) > 1E-6) success = false; } if (success) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("../domain.mesh", &mesh); // Perform initial mesh refinements (optional). for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize the weak formulation. CustomWeakFormPoissonNeumann wf("Aluminum", LAMBDA_AL, "Copper", LAMBDA_CU, VOLUME_HEAT_SRC, "Outer", ALPHA, T_EXTERIOR); // Initialize boundary conditions. CustomDirichletCondition bc_essential(Hermes::vector<std::string>("Bottom", "Inner", "Left"), BDY_A_PARAM, BDY_B_PARAM, BDY_C_PARAM); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Testing n_dof and correctness of solution vector // for p_init = 1, 2, ..., 10 int success = 1; Solution sln; for (int p_init = 1; p_init <= 10; p_init++) { printf("********* p_init = %d *********\n", p_init); space.set_uniform_order(p_init); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the solution. Solution sln; // Assemble the stiffness matrix and right-hand side vector. info("Assembling the stiffness matrix and right-hand side vector."); bool rhsonly = false; dp.assemble(matrix, rhs, rhsonly); // Solve the linear system and if successful, obtain the solution. info("Solving the matrix problem."); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); int ndof = Space::get_num_dofs(&space); printf("ndof = %d\n", ndof); double sum = 0; for (int i=0; i < ndof; i++) sum += solver->get_solution()[i]; printf("coefficient sum = %g\n", sum); // Actual test. The values of 'sum' depend on the // current shapeset. If you change the shapeset, // you need to correct these numbers. if (p_init == 1 && fabs(sum - 61.8227) > 1e-1) success = 0; if (p_init == 2 && fabs(sum - 60.8105) > 1e-1) success = 0; if (p_init == 3 && fabs(sum - 61.5511) > 1e-1) success = 0; if (p_init == 4 && fabs(sum - 60.8191) > 1e-1) success = 0; if (p_init == 5 && fabs(sum - 61.5304) > 1e-1) success = 0; if (p_init == 6 && fabs(sum - 60.8064) > 1e-1) success = 0; if (p_init == 7 && fabs(sum - 61.5323) > 1e-1) success = 0; if (p_init == 8 && fabs(sum - 60.7863) > 1e-1) success = 0; if (p_init == 9 && fabs(sum - 61.5408) > 1e-1) success = 0; if (p_init == 10 && fabs(sum - 60.7637) > 1e-1) success = 0; } if (success == 1) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("square.mesh", &mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary("Bdy", INIT_BDY_REF_NUM); // Initialize boundary conditions. CustomEssentialBCNonConst bc_essential("Bdy"); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof: %d", ndof); // Initialize the weak formulation CustomNonlinearity lambda(alpha); HermesFunction src(-heat_src); WeakFormsH1::DefaultWeakFormPoisson wf(HERMES_ANY, &lambda, &src); // Initialize the FE problem. DiscreteProblem dp(&wf, &space); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Project the initial condition on the FE space to obtain initial // coefficient vector for the Newton's method. // NOTE: If you want to start from the zero vector, just define // coeff_vec to be a vector of ndof zeros (no projection is needed). info("Projecting to obtain initial vector for the Newton's method."); scalar* coeff_vec = new scalar[Space::get_num_dofs(&space)] ; CustomInitialCondition init_sln(&mesh); OGProjection::project_global(&space, &init_sln, coeff_vec, matrix_solver); // Perform Newton's iteration. bool verbose = true; bool jacobian_changed = true; if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs, jacobian_changed, NEWTON_TOL, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution sln; Solution::vector_to_solution(coeff_vec, &space, &sln); // Clean up. delete [] coeff_vec; delete matrix; delete rhs; delete solver; // Visualise the solution and mesh. ScalarView s_view("Solution", new WinGeom(0, 0, 440, 350)); s_view.show_mesh(false); s_view.show(&sln); OrderView o_view("Mesh", new WinGeom(450, 0, 400, 350)); o_view.show(&space); // 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::vector<int>(BDY_1, BDY_6)); bc_types.add_bc_newton(Hermes::vector<int>(BDY_2, BDY_3, BDY_4, BDY_5)); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_zero(Hermes::vector<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); // Initialize views. VectorView v_view("Solution (magnitude)", new WinGeom(0, 0, 460, 350)); v_view.set_min_max_range(0, 1.5); OrderView o_view("Polynomial orders", new WinGeom(470, 0, 400, 350)); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est, graph_dof_exact, graph_cpu_exact; // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* 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 the reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. If successful, obtain the solution. if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // View the coarse mesh solution and polynomial orders. v_view.show(&sln); o_view.show(&space); // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); Adapt* adaptivity = new Adapt(&space); double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100; // Calculate exact error, 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()); // Show the reference solution - the final result. v_view.set_title("Fine mesh solution (magnitude)"); v_view.show(&ref_sln); // Wait for all views to be closed. View::wait(); return 0; }