int main(int argc, char* argv[]) { Hermes2D hermes_2D; // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain-excentric.mesh", &mesh); //mloader.load("domain-concentric.mesh", &mesh); // Initial mesh refinements. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary("Inner", INIT_BDY_REF_NUM_INNER, false); // true for anisotropic refinements mesh.refine_towards_boundary("Outer", INIT_BDY_REF_NUM_OUTER, false); // false for isotropic refinements // Initialize boundary conditions. EssentialBCNonConstX bc_inner_vel_x(std::string("Inner"), VEL, STARTUP_TIME); EssentialBCNonConstY bc_inner_vel_y(std::string("Inner"), VEL, STARTUP_TIME); DefaultEssentialBCConst bc_outer_vel(std::string("Outer"), 0.0); EssentialBCs bcs_vel_x(Hermes::vector<EssentialBoundaryCondition *>(&bc_inner_vel_x, &bc_outer_vel)); EssentialBCs bcs_vel_y(Hermes::vector<EssentialBoundaryCondition *>(&bc_inner_vel_y, &bc_outer_vel)); 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(spaces); 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 // 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 WeakFormNSNewton(STOKES, RE, TAU, &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 [m/s]", new WinGeom(0, 0, 600, 500)); ScalarView pview("pressure [Pa]", new WinGeom(610, 0, 600, 500)); //vview.set_min_max_range(0, 1.6); vview.fix_scale_width(80); //pview.set_min_max_range(-0.9, 1.0); 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)]; // Newton's vector is set to zero (no OG projection needed). memset(coeff_vec, 0, ndof * sizeof(double)); /* // This can be used for more complicated initial conditions. 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)); */ // Time-stepping loop: char title[100]; int num_time_steps = T_FINAL / TAU; for (int ts = 1; ts <= num_time_steps; ts++) { current_time += TAU; info("---- Time step %d, time = %g:", ts, current_time); // Update time-dependent essential BCs. info("Updating time-dependent essential BC."); Space::update_essential_bc_values(Hermes::vector<Space *>(&xvel_space, &yvel_space, &p_space), current_time); // Perform Newton's iteration. info("Solving nonlinear problem:"); bool verbose = true; bool jacobian_changed = true; if (!hermes_2D.solve_newton(coeff_vec, &dp, solver, matrix, rhs, jacobian_changed, 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); } // 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[]) { // 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 CustomEssentialBCNonConst bc_essential("Boundary horizontal"); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); // Initialize the weak formulation. CustomWeakFormGeneral wf("Boundary vertical"); // Testing n_dof and correctness of solution vector // for p_init = 1, 2, ..., 10 int success = 1; for (int p_init = 1; p_init <= 10; p_init++) { printf("********* p_init = %d *********\n", p_init); space.set_uniform_order(p_init); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the FE problem. DiscreteProblem dp(&wf, &space); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof]; memset(coeff_vec, 0, ndof*sizeof(scalar)); // Perform Newton's iteration. if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution sln; Solution::vector_to_solution(coeff_vec, &space, &sln); double sum = 0; for (int i=0; i < ndof; i++) sum += coeff_vec[i]; printf("coefficient sum = %g\n", sum); // Actual test. The values of 'sum' depend on the // current shapeset. If you change the shapeset, // you need to correct these numbers. if (p_init == 1 && fabs(sum - 1.72173) > 1e-2) success = 0; if (p_init == 2 && fabs(sum - 0.639908) > 1e-2) success = 0; if (p_init == 3 && fabs(sum - 0.826367) > 1e-2) success = 0; if (p_init == 4 && fabs(sum - 0.629395) > 1e-2) success = 0; if (p_init == 5 && fabs(sum - 0.574235) > 1e-2) success = 0; if (p_init == 6 && fabs(sum - 0.62792) > 1e-2) success = 0; if (p_init == 7 && fabs(sum - 0.701982) > 1e-2) success = 0; if (p_init == 8 && fabs(sum - 0.7982) > 1e-2) success = 0; if (p_init == 9 && fabs(sum - 0.895069) > 1e-2) success = 0; if (p_init == 10 && fabs(sum - 1.03031) > 1e-2) success = 0; delete [] coeff_vec; } if (success == 1) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main() { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Create coarse mesh, set Dirichlet BC, enumerate basis functions. Space* space = new Space(A, B, NELEM, DIR_BC_LEFT, DIR_BC_RIGHT, P_INIT, NEQ, NEQ); // Enumerate basis functions, info for user. int ndof = Space::get_num_dofs(space); info("ndof: %d", ndof); // Initialize the weak formulation. WeakForm wf(2); wf.add_matrix_form(0, 0, jacobian_0_0); wf.add_matrix_form(0, 1, jacobian_0_1); wf.add_matrix_form(1, 0, jacobian_1_0); wf.add_matrix_form(1, 1, jacobian_1_1); wf.add_vector_form(0, residual_0); wf.add_vector_form(1, residual_1); // Initialize the FE problem. bool is_linear = false; DiscreteProblem *dp_coarse = new DiscreteProblem(&wf, space, is_linear); // Newton's loop on coarse mesh. // Fill vector coeff_vec using dof and coeffs arrays in elements. double *coeff_vec_coarse = new double[Space::get_num_dofs(space)]; get_coeff_vector(space, coeff_vec_coarse); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix_coarse = create_matrix(matrix_solver); Vector* rhs_coarse = create_vector(matrix_solver); Solver* solver_coarse = create_linear_solver(matrix_solver, matrix_coarse, rhs_coarse); int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof_coarse = Space::get_num_dofs(space); // Assemble the Jacobian matrix and residual vector. dp_coarse->assemble(coeff_vec_coarse, matrix_coarse, rhs_coarse); // Calculate the l2-norm of residual vector. double res_l2_norm = get_l2_norm(rhs_coarse); // Info for user. info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(space), res_l2_norm); // If l2 norm of the residual vector is within tolerance, then quit. // NOTE: at least one full iteration forced // here because sometimes the initial // residual on fine mesh is too small. if(res_l2_norm < NEWTON_TOL_COARSE && it > 1) break; // Multiply the residual vector with -1 since the matrix // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). for(int i=0; i<ndof_coarse; i++) rhs_coarse->set(i, -rhs_coarse->get(i)); // Solve the linear system. if(!solver_coarse->solve()) error ("Matrix solver failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof_coarse; i++) coeff_vec_coarse[i] += solver_coarse->get_solution()[i]; // If the maximum number of iteration has been reached, then quit. if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); // Copy coefficients from vector y to elements. set_coeff_vector(coeff_vec_coarse, space); it++; } // Cleanup. delete matrix_coarse; delete rhs_coarse; delete solver_coarse; delete [] coeff_vec_coarse; delete dp_coarse; // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est; SimpleGraph graph_dof_exact, graph_cpu_exact; // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(space); // Initialize the FE problem. bool is_linear = false; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Newton's loop on the fine mesh. info("Solving on fine mesh:"); // Fill vector coeff_vec using dof and coeffs arrays in elements. double *coeff_vec = new double[Space::get_num_dofs(ref_space)]; get_coeff_vector(ref_space, coeff_vec); int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(ref_space); // Assemble the Jacobian matrix and residual vector. dp->assemble(coeff_vec, matrix, rhs); // Calculate the l2-norm of residual vector. double res_l2_norm = get_l2_norm(rhs); // Info for user. info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(ref_space), res_l2_norm); // If l2 norm of the residual vector is within tolerance, then quit. // NOTE: at least one full iteration forced // here because sometimes the initial // residual on fine mesh is too small. if(res_l2_norm < NEWTON_TOL_REF && it > 1) break; // Multiply the residual vector with -1 since the matrix // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). for(int i=0; i<ndof; i++) rhs->set(i, -rhs->get(i)); // Solve the linear system. if(!solver->solve()) error ("Matrix solver failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof; i++) coeff_vec[i] += solver->get_solution()[i]; // If the maximum number of iteration has been reached, then quit. if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); // Copy coefficients from vector y to elements. set_coeff_vector(coeff_vec, ref_space); it++; } // Starting with second adaptivity step, obtain new coarse // mesh solution via projecting the fine mesh solution. if(as > 1) { info("Projecting the fine mesh solution onto the coarse mesh."); // Project the fine mesh solution (defined on space_ref) onto the coarse mesh (defined on space). OGProjection::project_global(space, ref_space, matrix_solver); } // Calculate element errors and total error estimate. info("Calculating error estimate."); double err_est_array[MAX_ELEM_NUM]; double err_est_rel = calc_err_est(NORM, space, ref_space, err_est_array) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space::get_num_dofs(space), Space::get_num_dofs(ref_space), err_est_rel); // Time measurement. cpu_time.tick(); // If exact solution available, also calculate exact error. if (EXACT_SOL_PROVIDED) { // Calculate element errors wrt. exact solution. double err_exact_rel = calc_err_exact(NORM, space, exact_sol, NEQ, A, B) * 100; // Info for user. info("Relative error (exact) = %g %%", err_exact_rel); // Add entry to DOF and CPU convergence graphs. graph_dof_exact.add_values(Space::get_num_dofs(space), err_exact_rel); graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel); } // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space::get_num_dofs(space), err_est_rel); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel); // Decide whether the relative error is sufficiently small. if(err_est_rel < TOL_ERR_REL) break; // Returns updated coarse and fine meshes, with the last // coarse and fine mesh solutions on them, respectively. // The coefficient vectors and numbers of degrees of freedom // on both meshes are also updated. adapt(NORM, ADAPT_TYPE, THRESHOLD, err_est_array, space, ref_space); as++; // Plot meshes, results, and errors. adapt_plotting(space, ref_space, NORM, EXACT_SOL_PROVIDED, exact_sol); // Cleanup. delete solver; delete matrix; delete rhs; delete ref_space; delete dp; delete [] coeff_vec; } while (done == false); info("Total running time: %g s", cpu_time.accumulated()); // Save convergence graphs. graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.save("conv_cpu_est.dat"); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.save("conv_cpu_exact.dat"); // Test variable. int success_test = 1; info("N_dof = %d.", Space::get_num_dofs(space)); if (Space::get_num_dofs(space) > 70) success_test = 0; if (success_test) { info("Success!"); return ERROR_SUCCESS; } else { info("Failure!"); return ERROR_FAILURE; } }
int main() { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Create space, set Dirichlet BC, enumerate basis functions. Space* space = new Space(A, B, NELEM, DIR_BC_LEFT, DIR_BC_RIGHT, P_INIT, NEQ, NEQ); // Enumerate basis functions, info for user. int ndof = Space::get_num_dofs(space); info("ndof: %d", ndof); // Initialize the weak formulation. WeakForm wf(2); wf.add_matrix_form(0, 0, jacobian_0_0); wf.add_matrix_form(0, 1, jacobian_0_1); wf.add_matrix_form(1, 0, jacobian_1_0); wf.add_matrix_form(1, 1, jacobian_1_1); wf.add_vector_form(0, residual_0); wf.add_vector_form(1, residual_1); // Initialize the FE problem. bool is_linear = false; DiscreteProblem *dp = new DiscreteProblem(&wf, space, is_linear); // Newton's loop. // Fill vector coeff_vec using dof and coeffs arrays in elements. double *coeff_vec = new double[Space::get_num_dofs(space)]; get_coeff_vector(space, coeff_vec); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); int it = 1; bool success = false; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(space); // Assemble the Jacobian matrix and residual vector. dp->assemble(coeff_vec, matrix, rhs); // Calculate the l2-norm of residual vector. double res_l2_norm = get_l2_norm(rhs); // Info for user. info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(space), res_l2_norm); // If l2 norm of the residual vector is within tolerance, then quit. // NOTE: at least one full iteration forced // here because sometimes the initial // residual on fine mesh is too small. if(res_l2_norm < NEWTON_TOL && it > 1) break; // Multiply the residual vector with -1 since the matrix // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). for(int i=0; i<ndof; i++) rhs->set(i, -rhs->get(i)); // Solve the linear system. if(!(success = solver->solve())) error ("Matrix solver failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof; i++) coeff_vec[i] += solver->get_solution()[i]; // If the maximum number of iteration has been reached, then quit. if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); // Copy coefficients from vector y to elements. set_coeff_vector(coeff_vec, space); it++; } info("Total running time: %g s", cpu_time.accumulated()); // Test variable. info("ndof = %d.", Space::get_num_dofs(space)); if (success) { info("Success!"); return ERROR_SUCCESS; } else { info("Failure!"); return ERROR_FAILURE; } }
int main(int argc, char **args) { // Test variable. int success_test = 1; if (argc < 2) error("Not enough parameters"); // Load the mesh. Mesh mesh; H3DReader mloader; if (!mloader.load(args[1], &mesh)) error("Loading mesh file '%s'\n", args[1]); // Initialize the space 1. Ord3 o1(2, 2, 2); H1Space space1(&mesh, bc_types, essential_bc_values_1, o1); // Initialize the space 2. Ord3 o2(4, 4, 4); H1Space space2(&mesh, bc_types, essential_bc_values_2, o2); // Initialize the weak formulation. WeakForm wf(2); wf.add_matrix_form(0, 0, bilinear_form_1<double, scalar>, bilinear_form_1<Ord, Ord>, HERMES_SYM); wf.add_vector_form(0, linear_form_1<double, scalar>, linear_form_1<Ord, Ord>); wf.add_matrix_form(1, 1, bilinear_form_2<double, scalar>, bilinear_form_2<Ord, Ord>, HERMES_SYM); wf.add_vector_form(1, linear_form_2<double, scalar>, linear_form_2<Ord, Ord>); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, Tuple<Space *>(&space1, &space2), is_linear); // Initialize the solver in the case of SOLVER_PETSC or SOLVER_MUMPS. initialize_solution_environment(matrix_solver, argc, args); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the preconditioner in the case of SOLVER_AZTECOO. if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Assemble the linear problem. info("Assembling (ndof: %d).", Space::get_num_dofs(Tuple<Space *>(&space1, &space2))); dp.assemble(matrix, rhs); // Solve the linear system. If successful, obtain the solution. info("Solving."); Solution sln1(&mesh); Solution sln2(&mesh); if(solver->solve()) Solution::vector_to_solutions(solver->get_solution(), Tuple<Space *>(&space1, &space2), Tuple<Solution *>(&sln1, &sln2)); else error ("Matrix solver failed.\n"); ExactSolution ex_sln1(&mesh, exact_sln_fn_1); ExactSolution ex_sln2(&mesh, exact_sln_fn_2); // Calculate exact error. info("Calculating exact error."); Adapt *adaptivity = new Adapt(Tuple<Space *>(&space1, &space2), Tuple<ProjNormType>(HERMES_H1_NORM, HERMES_H1_NORM)); bool solutions_for_adapt = false; double err_exact = adaptivity->calc_err_exact(Tuple<Solution *>(&sln1, &sln2), Tuple<Solution *>(&ex_sln1, &ex_sln2), solutions_for_adapt, HERMES_TOTAL_ERROR_ABS); if (err_exact > EPS) // Calculated solution is not precise enough. success_test = 0; // Clean up. delete matrix; delete rhs; delete solver; delete adaptivity; // Properly terminate the solver in the case of SOLVER_PETSC or SOLVER_MUMPS. finalize_solution_environment(matrix_solver); if (success_test) { info("Success!"); return ERR_SUCCESS; } else { info("Failure!"); return ERR_FAILURE; } }
int main(int argc, char **args) { // Test variable. int success_test = 1; if (argc < 5) error("Not enough parameters."); // Load the mesh. Mesh mesh; H3DReader mloader; if (!mloader.load(args[1], &mesh)) error("Loading mesh file '%s'.", args[1]); // Initialize the space according to the // command-line parameters passed. sscanf(args[2], "%d", &P_INIT_X); sscanf(args[3], "%d", &P_INIT_Y); sscanf(args[4], "%d", &P_INIT_Z); Ord3 order(P_INIT_X, P_INIT_Y, P_INIT_Z); H1Space space(&mesh, bc_types, essential_bc_values, order); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(bilinear_form<double, scalar>, bilinear_form<Ord, Ord>, HERMES_SYM, HERMES_ANY); wf.add_vector_form(linear_form<double, scalar>, linear_form<Ord, Ord>, HERMES_ANY); // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Initialize the solver in the case of SOLVER_PETSC or SOLVER_MUMPS. initialize_solution_environment(matrix_solver, argc, args); // Adaptivity loop. int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(&space,1 , H3D_H3D_H3D_REFT_HEX_XYZ); out_orders_vtk(ref_space, "space", as); // Initialize the FE problem. bool is_linear = true; DiscreteProblem lp(&wf, ref_space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the preconditioner in the case of SOLVER_AZTECOO. if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Assemble the reference problem. info("Assembling on reference mesh (ndof: %d).", Space::get_num_dofs(ref_space)); lp.assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system on reference mesh. If successful, obtain the solution. info("Solving on reference mesh."); Solution ref_sln(ref_space->get_mesh()); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else { printf("Matrix solver failed.\n"); success_test = 0; } // Time measurement. cpu_time.tick(); // Project the reference solution on the coarse mesh. Solution sln(space.get_mesh()); info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Time measurement. cpu_time.tick(); // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); Adapt *adaptivity = new Adapt(&space, HERMES_H1_NORM); bool solutions_for_adapt = true; double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt) * 100; // 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_est_rel); // If err_est_rel is too large, adapt the mesh. if (err_est_rel < ERR_STOP) { done = true; ExactSolution ex_sln(&mesh, exact_solution); // Calculate exact error. info("Calculating exact error."); Adapt *adaptivity = new Adapt(&space, HERMES_H1_NORM); bool solutions_for_adapt = false; double err_exact = adaptivity->calc_err_exact(&sln, &ex_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_ABS); if (err_exact > EPS) // Calculated solution is not precise enough. success_test = 0; break; } else { info("Adapting coarse mesh."); adaptivity->adapt(THRESHOLD); } // If we reached the maximum allowed number of degrees of freedom, set the return flag to failure. if (Space::get_num_dofs(&space) >= NDOF_STOP) { done = true; success_test = 0; } // Clean up. delete ref_space->get_mesh(); delete ref_space; delete matrix; delete rhs; delete solver; delete adaptivity; // Increase the counter of performed adaptivity steps. as++; } while (!done); // Properly terminate the solver in the case of SOLVER_PETSC or SOLVER_MUMPS. finalize_solution_environment(matrix_solver); if (success_test) { info("Success!"); return ERR_SUCCESS; } else { info("Failure!"); return ERR_FAILURE; } }
int main() { // Create space, set Dirichlet BC, enumerate basis functions. Space* space = new Space(A, B, NELEM, DIR_BC_LEFT, Hermes::vector<BCSpec *>(), P_INIT, NEQ, NEQ); // Enumerate basis functions, info for user. int ndof = Space::get_num_dofs(space); info("ndof: %d", ndof); // Initialize the weak formulation. WeakForm wf(2); wf.add_matrix_form(0, 0, jacobian_0_0); wf.add_matrix_form(0, 1, jacobian_0_1); wf.add_matrix_form(1, 0, jacobian_1_0); wf.add_matrix_form(1, 1, jacobian_1_1); wf.add_vector_form(0, residual_0); wf.add_vector_form(1, residual_1); // Initialize the FE problem. bool is_linear = false; DiscreteProblem *dp = new DiscreteProblem(&wf, space, is_linear); // Newton's loop. // Fill vector coeff_vec using dof and coeffs arrays in elements. double *coeff_vec = new double[Space::get_num_dofs(space)]; get_coeff_vector(space, coeff_vec); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(space); // Assemble the Jacobian matrix and residual vector. dp->assemble(coeff_vec, matrix, rhs); // Calculate the l2-norm of residual vector. double res_l2_norm = get_l2_norm(rhs); // Info for user. info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(space), res_l2_norm); // If l2 norm of the residual vector is within tolerance, then quit. // NOTE: at least one full iteration forced // here because sometimes the initial // residual on fine mesh is too small. if(res_l2_norm < NEWTON_TOL && it > 1) break; // Multiply the residual vector with -1 since the matrix // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). for(int i=0; i<ndof; i++) rhs->set(i, -rhs->get(i)); // Solve the linear system. if(!solver->solve()) error ("Matrix solver failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof; i++) coeff_vec[i] += solver->get_solution()[i]; // If the maximum number of iteration has been reached, then quit. if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); // Copy coefficients from vector y to elements. set_coeff_vector(coeff_vec, space); it++; } // Plot the solution. Linearizer l(space); l.plot_solution("solution.gp"); // Plot the resulting space. space->plot("space.gp"); // Cleanup. for(unsigned i = 0; i < DIR_BC_LEFT.size(); i++) delete DIR_BC_LEFT[i]; DIR_BC_LEFT.clear(); for(unsigned i = 0; i < DIR_BC_RIGHT.size(); i++) delete DIR_BC_RIGHT[i]; DIR_BC_RIGHT.clear(); delete matrix; delete rhs; delete solver; delete[] coeff_vec; delete dp; delete space; info("Done."); return 0; }
int main(int argc, char **args) { // Test variable. int success_test = 1; if (argc < 3) error("Not enough parameters."); if (strcmp(args[1], "h1") != 0 && strcmp(args[1], "h1-ipol")) error("Unknown type of the projection."); // Load the mesh. Mesh mesh; H3DReader mloader; if (!mloader.load(args[2], &mesh)) error("Loading mesh file '%s'.", args[1]); // Refine the mesh. mesh.refine_all_elements(H3D_H3D_H3D_REFT_HEX_XYZ); // Initialize the space. #if defined X2_Y2_Z2 Ord3 order(2, 2, 2); #elif defined X3_Y3_Z3 Ord3 order(3, 3, 3); #elif defined XN_YM_ZO Ord3 order(2, 3, 4); #endif H1Space space(&mesh, bc_types, essential_bc_values, order); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(bilinear_form<double, scalar>, bilinear_form<Ord, Ord>, HERMES_SYM, HERMES_ANY_INT); wf.add_vector_form(linear_form<double, scalar>, linear_form<Ord, Ord>, HERMES_ANY_INT); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the preconditioner in the case of SOLVER_AZTECOO. if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Assemble the linear problem. dp.assemble(matrix, rhs); // Solve the linear system. If successful, obtain the solution. info("Solving the linear problem."); Solution sln(&mesh); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else { info("Matrix solver failed."); success_test = 0; } unsigned int ne = mesh.get_num_base_elements(); for(std::map<unsigned int, Element*>::iterator it = mesh.elements.begin(); it != mesh.elements.end(); it++) { // We are done with base elements. if(it->first > ne) break; Element *e = it->second; Ord3 order(4, 4, 4); double error; Projection *proj; if (strcmp(args[1], "h1") == 0) proj = new H1Projection(&sln, e, space.get_shapeset()); else if (strcmp(args[1], "h1-ipol") == 0) proj = new H1ProjectionIpol(&sln, e, space.get_shapeset()); else success_test = 0; error = 0.0; error += proj->get_error(H3D_REFT_HEX_NONE, -1, order); error = sqrt(error); if (error > EPS) // Calculated solution is not precise enough. success_test = 0; // error = 0.0; error += proj->get_error(H3D_REFT_HEX_X, 20, order); error += proj->get_error(H3D_REFT_HEX_X, 21, order); error = sqrt(error); if (error > EPS) // Calculated solution is not precise enough. success_test = 0; // error = 0.0; error += proj->get_error(H3D_REFT_HEX_Y, 22, order); error += proj->get_error(H3D_REFT_HEX_Y, 23, order); error = sqrt(error); if (error > EPS) // Calculated solution is not precise enough. success_test = 0; // error = 0.0; error += proj->get_error(H3D_REFT_HEX_Z, 24, order); error += proj->get_error(H3D_REFT_HEX_Z, 25, order); error = sqrt(error); if (error > EPS) // Calculated solution is not precise enough. success_test = 0; // error = 0.0; error += proj->get_error(H3D_H3D_REFT_HEX_XY, 8, order); error += proj->get_error(H3D_H3D_REFT_HEX_XY, 9, order); error += proj->get_error(H3D_H3D_REFT_HEX_XY, 10, order); error += proj->get_error(H3D_H3D_REFT_HEX_XY, 11, order); error = sqrt(error); if (error > EPS) // Calculated solution is not precise enough. success_test = 0; // error = 0.0; error += proj->get_error(H3D_H3D_REFT_HEX_XZ, 12, order); error += proj->get_error(H3D_H3D_REFT_HEX_XZ, 13, order); error += proj->get_error(H3D_H3D_REFT_HEX_XZ, 14, order); error += proj->get_error(H3D_H3D_REFT_HEX_XZ, 15, order); error = sqrt(error); if (error > EPS) // Calculated solution is not precise enough. success_test = 0; // error = 0.0; error += proj->get_error(H3D_H3D_REFT_HEX_YZ, 16, order); error += proj->get_error(H3D_H3D_REFT_HEX_YZ, 17, order); error += proj->get_error(H3D_H3D_REFT_HEX_YZ, 18, order); error += proj->get_error(H3D_H3D_REFT_HEX_YZ, 19, order); error = sqrt(error); if (error > EPS) // Calculated solution is not precise enough. success_test = 0; // error = 0.0; for (int j = 0; j < 8; j++) error += proj->get_error(H3D_H3D_H3D_REFT_HEX_XYZ, j, order); error = sqrt(error); delete proj; if (error > EPS) // Calculated solution is not precise enough. success_test = 0; } if (success_test) { info("Success!"); return ERR_SUCCESS; } else { info("Failure!"); return ERR_FAILURE; } }
int main(int argc, char **args) { // Test variable. int success_test = 1; if (argc < 5) error("Not enough parameters."); // Load the mesh. Mesh mesh; H3DReader mloader; if (!mloader.load(args[1], &mesh)) error("Loading mesh file '%s'.", args[1]); // Initialize the space according to the // command-line parameters passed. sscanf(args[2], "%d", &m); sscanf(args[3], "%d", &n); sscanf(args[4], "%d", &o); int mx = maxn(4, m, n, o, 4); Ord3 order(mx, mx, mx); H1Space space(&mesh, bc_types, NULL, order); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(bilinear_form<double, scalar>, bilinear_form<Ord, Ord>, HERMES_SYM); wf.add_matrix_form_surf(bilinear_form_surf<double, scalar>, bilinear_form_surf<Ord, Ord>); wf.add_vector_form(linear_form<double, scalar>, linear_form<Ord, Ord>); wf.add_vector_form_surf(linear_form_surf<double, scalar>, linear_form_surf<Ord, Ord>); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the preconditioner in the case of SOLVER_AZTECOO. if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Assemble the linear problem. info("Assembling (ndof: %d).", Space::get_num_dofs(&space)); dp.assemble(matrix, rhs); // Solve the linear system. If successful, obtain the solution. info("Solving."); Solution sln(&mesh); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); ExactSolution ex_sln(&mesh, exact_solution); // Calculate exact error. info("Calculating exact error."); Adapt *adaptivity = new Adapt(&space, HERMES_H1_NORM); bool solutions_for_adapt = false; double err_exact = adaptivity->calc_err_exact(&sln, &ex_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_ABS); if (err_exact > EPS) // Calculated solution is not precise enough. success_test = 0; // Clean up. delete matrix; delete rhs; delete solver; delete adaptivity; if (success_test) { info("Success!"); return ERR_SUCCESS; } else { info("Failure!"); return ERR_FAILURE; } }
int main(int argc, char **args) { // Test variable. int success_test = 1; for (int i = 0; i < 48; i++) { for (int j = 0; j < 48; j++) { info("Config: %d, %d ", i, j); Mesh mesh; for (unsigned int k = 0; k < countof(vtcs); k++) mesh.add_vertex(vtcs[k].x, vtcs[k].y, vtcs[k].z); unsigned int h1[] = { hexs[0][i][0] + 1, hexs[0][i][1] + 1, hexs[0][i][2] + 1, hexs[0][i][3] + 1, hexs[0][i][4] + 1, hexs[0][i][5] + 1, hexs[0][i][6] + 1, hexs[0][i][7] + 1 }; mesh.add_hex(h1); unsigned int h2[] = { hexs[1][j][0] + 1, hexs[1][j][1] + 1, hexs[1][j][2] + 1, hexs[1][j][3] + 1, hexs[1][j][4] + 1, hexs[1][j][5] + 1, hexs[1][j][6] + 1, hexs[1][j][7] + 1 }; mesh.add_hex(h2); // bc for (unsigned int k = 0; k < countof(bnd); k++) { unsigned int facet_idxs[Quad::NUM_VERTICES] = { bnd[k][0] + 1, bnd[k][1] + 1, bnd[k][2] + 1, bnd[k][3] + 1 }; mesh.add_quad_boundary(facet_idxs, bnd[k][4]); } mesh.ugh(); // Initialize the space. H1Space space(&mesh, bc_types, essential_bc_values); #ifdef XM_YN_ZO Ord3 ord(4, 4, 4); #elif defined XM_YN_ZO_2 Ord3 ord(4, 4, 4); #elif defined X2_Y2_Z2 Ord3 ord(2, 2, 2); #endif space.set_uniform_order(ord); // Initialize the weak formulation. WeakForm wf; #ifdef DIRICHLET wf.add_matrix_form(bilinear_form<double, scalar>, bilinear_form<Ord, Ord>, HERMES_SYM); wf.add_vector_form(linear_form<double, scalar>, linear_form<Ord, Ord>); #elif defined NEWTON wf.add_matrix_form(bilinear_form<double, scalar>, bilinear_form<Ord, Ord>, HERMES_SYM); wf.add_matrix_form_surf(bilinear_form_surf<double, scalar>, bilinear_form_surf<Ord, Ord>); wf.add_vector_form(linear_form<double, scalar>, linear_form<Ord, Ord>); wf.add_vector_form_surf(linear_form_surf<double, scalar>, linear_form_surf<Ord, Ord>); #endif // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the preconditioner in the case of SOLVER_AZTECOO. if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Assemble the linear problem. info("Assembling (ndof: %d).", Space::get_num_dofs(&space)); dp.assemble(matrix, rhs); // Solve the linear system. If successful, obtain the solution. info("Solving."); Solution sln(space.get_mesh()); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); ExactSolution ex_sln(&mesh, exact_solution); // Calculate exact error. info("Calculating exact error."); Adapt *adaptivity = new Adapt(&space, HERMES_H1_NORM); bool solutions_for_adapt = false; double err_exact = adaptivity->calc_err_exact(&sln, &ex_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_ABS); if (err_exact > EPS) { // Calculated solution is not precise enough. success_test = 0; info("failed, error:%g", err_exact); } else info("passed"); // Clean up. delete matrix; delete rhs; delete solver; delete adaptivity; } } if (success_test) { info("Success!"); return ERR_SUCCESS; } else { info("Failure!"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.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::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. H1Space* phi_space = new H1Space(&mesh, &bc_types, &bc_values, P_INIT); H1Space* psi_space = new H1Space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(Hermes::vector<Space *>(phi_space, psi_space)); info("ndof = %d.", ndof); // Initialize previous time level solutions. Solution phi_prev_time, psi_prev_time; phi_prev_time.set_exact(&mesh, init_cond_phi); psi_prev_time.set_exact(&mesh, init_cond_psi); // Initialize the weak formulation. WeakForm wf(2); wf.add_matrix_form(0, 0, callback(biform_euler_0_0)); wf.add_matrix_form(0, 1, callback(biform_euler_0_1)); wf.add_matrix_form(1, 0, callback(biform_euler_1_0)); wf.add_matrix_form(1, 1, callback(biform_euler_1_1)); wf.add_vector_form(0, callback(liform_euler_0), HERMES_ANY, &phi_prev_time); wf.add_vector_form(1, callback(liform_euler_1), HERMES_ANY, &psi_prev_time); // Initialize views. ScalarView view("Psi", new WinGeom(0, 0, 600, 500)); view.fix_scale_width(80); // Time stepping loop: int nstep = (int)(T_FINAL/TAU + 0.5); for(int ts = 1; ts <= nstep; ts++) { info("Time step %d:", ts); info("Solving linear system."); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, Hermes::vector<Space *>(phi_space, psi_space), is_linear); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // 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_solutions(solver->get_solution(), Hermes::vector<Space *>(phi_space, psi_space), Hermes::vector<Solution *>(&phi_prev_time, &psi_prev_time)); else error ("Matrix solver failed.\n"); // Show the new time level solution. char title[100]; sprintf(title, "Time step %d", ts); view.set_title(title); view.show(&psi_prev_time); } // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("square.mesh", &mesh); // Initial mesh refinements. for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(BDY_DIRICHLET, INIT_BDY_REF_NUM); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(BDY_DIRICHLET); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_function(BDY_DIRICHLET, essential_bc_values); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); 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_NONSYM, 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_NONSYM, 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. bool verbose = true; if (!solve_newton(coeff_vec, &dp, solver, matrix, rhs, NEWTON_TOL, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution::vector_to_solution(coeff_vec, &space, &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}; bool success = true; for (int i = 0; i < 5; i++) { if (abs(value[i] - u_prev_time.get_pt_value(coor_x_y[i], coor_x_y[i])) > 1E-6) success = false; } if (success) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main() { // Three macroelements are defined above via the interfaces[] array. // poly_orders[]... initial poly degrees of macroelements. // material_markers[]... material markers of macroelements. // subdivisions[]... equidistant subdivision of macroelements. int poly_orders[N_MAT] = {P_init_inner, P_init_outer, P_init_reflector }; int material_markers[N_MAT] = {Marker_inner, Marker_outer, Marker_reflector }; int subdivisions[N_MAT] = {N_subdiv_inner, N_subdiv_outer, N_subdiv_reflector }; // Create space. Space* space = new Space(N_MAT, interfaces, poly_orders, material_markers, subdivisions, N_GRP, N_SLN); // Enumerate basis functions, info for user. info("N_dof = %d", Space::get_num_dofs(space)); // Initial approximation: u = 1. double K_EFF_old; double init_val = 1.0; set_vertex_dofs_constant(space, init_val, 0); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(jacobian_vol_inner, NULL, Marker_inner); wf.add_matrix_form(jacobian_vol_outer, NULL, Marker_outer); wf.add_matrix_form(jacobian_vol_reflector, NULL, Marker_reflector); wf.add_vector_form(residual_vol_inner, NULL, Marker_inner); wf.add_vector_form(residual_vol_outer, NULL, Marker_outer); wf.add_vector_form(residual_vol_reflector, NULL, Marker_reflector); wf.add_vector_form_surf(residual_surf_left, BOUNDARY_LEFT); wf.add_matrix_form_surf(jacobian_surf_right, BOUNDARY_RIGHT); wf.add_vector_form_surf(residual_surf_right, BOUNDARY_RIGHT); // Initialize the FE problem. bool is_linear = false; DiscreteProblem *dp = new DiscreteProblem(&wf, space, is_linear); // Source iteration (power method). for (int i = 0; i < Max_SI; i++) { // Obtain fission source. int current_solution = 0, previous_solution = 1; copy_dofs(current_solution, previous_solution, space); // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(space); // Fill vector coeff_vec using dof and coeffs arrays in elements. double *coeff_vec = new double[Space::get_num_dofs(space)]; solution_to_vector(space, coeff_vec); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(space); // Assemble the Jacobian matrix and residual vector. dp->assemble(matrix, rhs); // Calculate the l2-norm of residual vector. double res_norm = 0; for(int i=0; i<ndof; i++) res_norm += rhs->get(i)*rhs->get(i); res_norm = sqrt(res_norm); // Info for user. info("---- Newton iter %d, residual norm: %.15f", it, res_norm); // If l2 norm of the residual vector is within tolerance, then quit. // NOTE: at least one full iteration forced // here because sometimes the initial // residual on fine mesh is too small. if(res_norm < NEWTON_TOL && it > 1) break; // Multiply the residual vector with -1 since the matrix // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). for(int i=0; i<ndof; i++) rhs->set(i, -rhs->get(i)); // Solve the linear system. if(!solver->solve()) error ("Matrix solver failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof; i++) coeff_vec[i] += solver->get_solution()[i]; // If the maximum number of iteration has been reached, then quit. if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); // Copy coefficients from vector y to elements. vector_to_solution(coeff_vec, space); it++; } // Cleanup. delete matrix; delete rhs; delete solver; delete [] coeff_vec; // Update the eigenvalue. K_EFF_old = K_EFF; K_EFF = calc_fission_yield(space); info("K_EFF_%d = %f", i, K_EFF); if (fabs(K_EFF - K_EFF_old)/K_EFF < TOL_SI) break; } // Plot the critical (i.e. steady-state) neutron flux. Linearizer l(space); l.plot_solution("solution.gp"); // Normalize so that the absolute neutron flux generates 320 Watts of energy // (note that, using the symmetry condition at the origin, we've solved for // flux only in the right half of the reactor). normalize_to_power(space, 320/2.); // Plot the solution and space. l.plot_solution("solution_320W.gp"); space->plot("space.gp"); info("K_EFF = %f", K_EFF); info("Done."); return 1; }
int main() { // Create space, set Dirichlet BC, enumerate basis functions. Space* space = new Space(A, B, NELEM, DIR_BC_LEFT, DIR_BC_RIGHT, P_INIT, NEQ); int ndof = Space::get_num_dofs(space); info("ndof: %d", ndof); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(jacobian); wf.add_vector_form(residual); // Initialize the FE problem. bool is_linear = false; DiscreteProblem *dp = new DiscreteProblem(&wf, space, is_linear); // Set zero initial condition. double *coeff_vec = new double[ndof]; set_zero(coeff_vec, ndof); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(space); // Assemble the Jacobian matrix and residual vector. dp->assemble(coeff_vec, matrix, rhs); // Calculate the l2-norm of residual vector. double res_l2_norm = get_l2_norm(rhs); // Info for user. info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(space), res_l2_norm); // If l2 norm of the residual vector is within tolerance, then quit. // NOTE: at least one full iteration forced // here because sometimes the initial // residual on fine mesh is too small. if(res_l2_norm < NEWTON_TOL && it > 1) break; // Multiply the residual vector with -1 since the matrix // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). for(int i=0; i<ndof; i++) rhs->set(i, -rhs->get(i)); // Solve the linear system. if(!solver->solve()) error ("Matrix solver failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof; i++) coeff_vec[i] += solver->get_solution()[i]; // If the maximum number of iteration has been reached, then quit. if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); it++; } // Plot the solution. Linearizer l(space); l.plot_solution("solution.dat"); info("Done."); return 0; }
void compute_trajectory(Space *space, DiscreteProblem *dp) { info("alpha = (%g, %g, %g, %g), zeta = (%g, %g, %g, %g)", alpha_ctrl[0], alpha_ctrl[1], alpha_ctrl[2], alpha_ctrl[3], zeta_ctrl[0], zeta_ctrl[1], zeta_ctrl[2], zeta_ctrl[3]); // Newton's loop. // Fill vector coeff_vec using dof and coeffs arrays in elements. double *coeff_vec = new double[Space::get_num_dofs(space)]; get_coeff_vector(space, coeff_vec); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); int it = 1; while (true) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(space); // Assemble the Jacobian matrix and residual vector. dp->assemble(coeff_vec, matrix, rhs); // Calculate the l2-norm of residual vector. double res_l2_norm = get_l2_norm(rhs); // Info for user. info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(space), res_l2_norm); // If l2 norm of the residual vector is within tolerance, then quit. // NOTE: at least one full iteration forced // here because sometimes the initial // residual on fine mesh is too small. if(res_l2_norm < NEWTON_TOL && it > 1) break; // Multiply the residual vector with -1 since the matrix // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). for(int i = 0; i < ndof; i++) rhs->set(i, -rhs->get(i)); // Solve the linear system. if(!solver->solve()) error ("Matrix solver failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof; i++) coeff_vec[i] += solver->get_solution()[i]; // If the maximum number of iteration has been reached, then quit. if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); // Copy coefficients from vector y to elements. set_coeff_vector(coeff_vec, space); it++; } // Cleanup. delete matrix; delete rhs; delete solver; delete [] coeff_vec; }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("../domain.mesh", &mesh); // Perform initial mesh refinements (optional). for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize the weak formulation. CustomWeakFormPoisson wf("Aluminum", new HermesFunction(LAMBDA_AL), "Copper", new HermesFunction(LAMBDA_CU), new HermesFunction(-VOLUME_HEAT_SRC)); // Initialize boundary conditions. DefaultEssentialBCConst bc_essential(Hermes::vector<std::string>("Bottom", "Inner", "Outer", "Left"), FIXED_BDY_TEMP); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the FE problem. DiscreteProblem dp(&wf, &space); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof]; memset(coeff_vec, 0, ndof*sizeof(scalar)); // Perform Newton's iteration. if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution sln; Solution::vector_to_solution(coeff_vec, &space, &sln); // Actual test. The values of 'sum' depend on the // current shapeset. If you change the shapeset, // you need to correct these numbers. double sum = 0; for (int i=0; i < ndof; i++) sum += coeff_vec[i]; printf("coefficient sum = %g\n", sum); bool success = true; if (std::abs(sum + 0.357318) > 1e-4) success = false; if (success == true) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
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); // Initialize views. ScalarView sview("Solution", 0, 0, 500, 400); OrderView oview("Mesh", 520, 0, 450, 400); oview.show(&space); sview.show(&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; // Show the new time level solution. char title[100]; sprintf(title, "Solution, t = %g", current_time); sview.set_title(title); sview.show(&u_prev_time); } while (current_time < T_FINAL); delete [] coeff_vec; // Wait for all views to be closed. View::wait(); return 0; }
bool rk_time_step(double current_time, double time_step, ButcherTable* const bt, scalar* coeff_vec, scalar* err_vec, DiscreteProblem* dp, MatrixSolverType matrix_solver, bool verbose, bool is_linear, double newton_tol, int newton_max_iter, double newton_damping_coeff, double newton_max_allowed_residual_norm) { // Check for not implemented features. if (matrix_solver != SOLVER_UMFPACK) error("Sorry, rk_time_step() still only works with UMFpack."); if (dp->get_weak_formulation()->get_neq() > 1) error("Sorry, rk_time_step() does not work with systems yet."); // Get number of stages from the Butcher's table. int num_stages = bt->get_size(); // Check whether the user provided a second B-row if he wants // err_vec. if(err_vec != NULL) { double b2_coeff_sum = 0; for (int i=0; i < num_stages; i++) b2_coeff_sum += fabs(bt->get_B2(i)); if (b2_coeff_sum < 1e-10) error("err_vec != NULL but the B2 row in the Butcher's table is zero in rk_time_step()."); } // Matrix for the time derivative part of the equation (left-hand side). UMFPackMatrix* matrix_left = new UMFPackMatrix(); // Matrix and vector for the rest (right-hand side). UMFPackMatrix* matrix_right = new UMFPackMatrix(); UMFPackVector* vector_right = new UMFPackVector(); // Create matrix solver. Solver* solver = create_linear_solver(matrix_solver, matrix_right, vector_right); // Get original space, mesh, and ndof. dp->get_space(0); Mesh* mesh = dp->get_space(0)->get_mesh(); int ndof = dp->get_space(0)->get_num_dofs(); // Create spaces for stage solutions. This is necessary // to define a num_stages x num_stages block weak formulation. Hermes::vector<Space*> stage_spaces; stage_spaces.push_back(dp->get_space(0)); for (int i = 1; i < num_stages; i++) { stage_spaces.push_back(dp->get_space(0)->dup(mesh)); } Space::assign_dofs(stage_spaces); // Create a multistage weak formulation. WeakForm stage_wf_left; // For the matrix M (size ndof times ndof). WeakForm stage_wf_right(num_stages); // For the rest of equation (written on the right), // size num_stages*ndof times num_stages*ndof. create_stage_wf(current_time, time_step, bt, dp, &stage_wf_left, &stage_wf_right); // Initialize discrete problems for the assembling of the // matrix M and the stage Jacobian matrix and residual. DiscreteProblem stage_dp_left(&stage_wf_left, dp->get_space(0)); DiscreteProblem stage_dp_right(&stage_wf_right, stage_spaces); // Vector K_vector of length num_stages * ndof. will represent // the 'k_i' vectors in the usual R-K notation. scalar* K_vector = new scalar[num_stages*ndof]; memset(K_vector, 0, num_stages * ndof * sizeof(scalar)); // Vector u_prev_vec will represent y_n + h \sum_{j=1}^s a_{ij}k_i // in the usual R-K notation. scalar* u_prev_vec = new scalar[num_stages*ndof]; // Vector for the left part of the residual. scalar* vector_left = new scalar[num_stages*ndof]; // Prepare residuals of stage solutions. Hermes::vector<Solution*> residuals; Hermes::vector<bool> add_dir_lift; for (int i = 0; i < num_stages; i++) { residuals.push_back(new Solution(mesh)); add_dir_lift.push_back(false); } // Assemble the block-diagonal mass matrix M of size ndof times ndof. // The corresponding part of the global residual vector is obtained // just by multiplication. stage_dp_left.assemble(matrix_left); // The Newton's loop. double residual_norm; int it = 1; while (true) { // Prepare vector Y_n + h\sum_{j=1}^s a_{ij} K_j. for (int i = 0; i < num_stages; i++) { // block row for (int idx = 0; idx < ndof; idx++) { scalar increment = 0; for (int j = 0; j < num_stages; j++) { increment += bt->get_A(i, j) * K_vector[j*ndof + idx]; } u_prev_vec[i*ndof + idx] = coeff_vec[idx] + time_step * increment; } } multiply_as_diagonal_block_matrix(matrix_left, num_stages, K_vector, vector_left); // Assemble the block Jacobian matrix of the stationary residual F // Diagonal blocks are created even if empty, so that matrix_left // can be added later. bool rhs_only = false; bool force_diagonal_blocks = true; stage_dp_right.assemble(u_prev_vec, matrix_right, vector_right, rhs_only, force_diagonal_blocks); matrix_right->add_to_diagonal_blocks(num_stages, matrix_left); vector_right->add_vector(vector_left); // Multiply the residual vector with -1 since the matrix // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). vector_right->change_sign(); // Measure the residual norm. if (HERMES_RESIDUAL_AS_VECTOR_RK) { // Calculate the l2-norm of residual vector. residual_norm = get_l2_norm(vector_right); } else { // Translate residual vector into residual functions. Solution::vector_to_solutions(vector_right, stage_dp_right.get_spaces(), residuals, add_dir_lift); residual_norm = calc_norms(residuals); } // Info for the user. if (verbose) info("---- Newton iter %d, ndof %d, residual norm %g", it, ndof, residual_norm); // If maximum allowed residual norm is exceeded, fail. if (residual_norm > newton_max_allowed_residual_norm) { if (verbose) { info("Current residual norm: %g", residual_norm); info("Maximum allowed residual norm: %g", newton_max_allowed_residual_norm); info("Newton solve not successful, returning false."); } return false; } // If residual norm is within tolerance, or the maximum number // of iteration has been reached, or the problem is linear, then quit. if ((residual_norm < newton_tol || it > newton_max_iter) && it > 1) 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 < num_stages*ndof; i++) { K_vector[i] += newton_damping_coeff * solver->get_solution()[i]; } // If the problem is linear, quit. if (is_linear) { if (verbose) { info("Terminating Newton's loop as problem is linear."); } break; } // Increase iteration counter. it++; } // If max number of iterations was exceeded, fail. if (it >= newton_max_iter) { if (verbose) info("Maximum allowed number of Newton iterations exceeded, returning false."); return false; } // Calculate the vector \sum_{j=1}^s b_j k_j. Vector* rk_increment_vector = create_vector(matrix_solver); rk_increment_vector->alloc(ndof); for (int i = 0; i < ndof; i++) { rk_increment_vector->set(i, 0); for (int j = 0; j < num_stages; j++) { rk_increment_vector->add(i, bt->get_B(j) * K_vector[j*ndof + i]); } } // Calculate Y^{n+1} = Y^n + h \sum_{j=1}^s b_j k_j. for (int i = 0; i < ndof; i++) coeff_vec[i] += time_step * rk_increment_vector->get(i); // If err_vec is not NULL, use the second B-row in the Butcher's // table to calculate the second approximation Y_{n+1}. Then // subtract the original one from it, and return this as an // error vector err_vec. if (err_vec != NULL) { for (int i = 0; i < ndof; i++) { rk_increment_vector->set(i, 0); for (int j = 0; j < num_stages; j++) { rk_increment_vector->add(i, bt->get_B2(j) * K_vector[j*ndof + i]); } } for (int i = 0; i < ndof; i++) err_vec[i] = time_step * rk_increment_vector->get(i); for (int i = 0; i < ndof; i++) err_vec[i] = err_vec[i] - coeff_vec[i]; } // Clean up. delete matrix_left; delete matrix_right; delete vector_right; delete solver; delete rk_increment_vector; // Delete stage spaces, but not the first (original) one. for (int i = 1; i < num_stages; i++) delete stage_spaces[i]; // Delete all residuals. for (int i = 0; i < num_stages; i++) delete residuals[i]; // TODO: Delete stage_wf, in particular its external solutions // stage_time_sol[i], i = 0, 1, ..., num_stages-1. // Delete stage_vec and u_prev_vec. delete [] K_vector; delete [] u_prev_vec; // debug delete [] vector_left; return true; }
int main(int argc, char **args) { // Load the mesh. Mesh mesh; H3DReader mloader; mloader.load("fichera-corner.mesh3d", &mesh); // Perform initial mesh refinement. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(H3D_H3D_H3D_REFT_HEX_XYZ); // Create an H1 space with default shapeset. H1Space space(&mesh, bc_types, essential_bc_values, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); // Initialize weak formulation. WeakForm wf; wf.add_matrix_form(bilinear_form<double, double>, bilinear_form<Ord, Ord>, HERMES_SYM, HERMES_ANY_INT); wf.add_vector_form(linear_form<double, double>, linear_form<Ord, Ord>, HERMES_ANY_INT); // Set exact solution. ExactSolution exact(&mesh, fndd); // DOF and CPU convergence graphs. SimpleGraph graph_dof_est, graph_cpu_est, graph_dof_exact, graph_cpu_exact; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Adaptivity loop. int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = Space::construct_refined_space(&space, 1); // Initialize discrete problem. bool is_linear = true; DiscreteProblem dp(&wf, ref_space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the preconditioner in the case of SOLVER_AZTECOO. if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Assemble the reference problem. info("Assembling on reference mesh (ndof: %d).", Space::get_num_dofs(ref_space)); dp.assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system on reference mesh. If successful, obtain the solution. info("Solving on reference mesh."); Solution ref_sln(ref_space->get_mesh()); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Project the reference solution on the coarse mesh. Solution sln(space.get_mesh()); info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver, HERMES_H1_NORM); // Time measurement. cpu_time.tick(); // Output solution and mesh with polynomial orders. if (solution_output) { out_fn_vtk(&sln, "sln", as); out_orders_vtk(&space, "order", as); } // Skip the visualization time. cpu_time.tick(HERMES_SKIP); // Calculate element errors and total error estimate. info("Calculating error estimate and exact error."); Adapt *adaptivity = new Adapt(&space, HERMES_H1_NORM); bool solutions_for_adapt = true; double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt) * 100; // Calculate exact error. solutions_for_adapt = false; double err_exact_rel = adaptivity->calc_err_exact(&sln, &exact, solutions_for_adapt) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d.", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space)); info("err_est_rel: %g%%, err_exact_rel: %g%%.", err_est_rel, err_exact_rel); // Add entry to DOF and CPU convergence graphs. graph_dof_est.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof_est.save("conv_dof_est.dat"); graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu_est.save("conv_cpu_est.dat"); graph_dof_exact.add_values(Space::get_num_dofs(&space), err_exact_rel); graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel); graph_cpu_exact.save("conv_cpu_exact.dat"); // If err_est_rel is too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); adaptivity->adapt(THRESHOLD); } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete ref_space->get_mesh(); delete ref_space; delete matrix; delete rhs; delete solver; delete adaptivity; // Increase the counter of performed adaptivity steps. as++; } while (!done); return 0; }
int main(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(spaces); 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[ndof]; // Newton's vector is set to zero (no OG projection needed). memset(coeff_vec, 0, ndof * sizeof(double)); /* // This can be used for more complicated initial conditions. 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; bool jacobian_changed = true; if (!hermes_2D.solve_newton(coeff_vec, &dp, solver, matrix, rhs, jacobian_changed, 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. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions EssentialBCNonConst bc_essential(BDY_HORIZONTAL); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the weak formulation. CustomWeakFormGeneral wf; // Testing n_dof and correctness of solution vector // for p_init = 1, 2, ..., 10 int success = 1; Solution sln; for (int p_init = 1; p_init <= 10; p_init++) { printf("********* p_init = %d *********\n", p_init); space.set_uniform_order(p_init); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the solution. Solution sln; // Assemble the stiffness matrix and right-hand side vector. info("Assembling the stiffness matrix and right-hand side vector."); bool rhsonly = false; dp.assemble(matrix, rhs, rhsonly); // Solve the linear system and if successful, obtain the solution. info("Solving the matrix problem."); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); int ndof = Space::get_num_dofs(&space); printf("ndof = %d\n", ndof); double sum = 0; for (int i=0; i < ndof; i++) sum += solver->get_solution()[i]; printf("coefficient sum = %g\n", sum); // Actual test. The values of 'sum' depend on the // current shapeset. If you change the shapeset, // you need to correct these numbers. if (p_init == 1 && fabs(sum - 1.72173) > 1e-2) success = 0; if (p_init == 2 && fabs(sum - 0.639908) > 1e-2) success = 0; if (p_init == 3 && fabs(sum - 0.826367) > 1e-2) success = 0; if (p_init == 4 && fabs(sum - 0.629395) > 1e-2) success = 0; if (p_init == 5 && fabs(sum - 0.574235) > 1e-2) success = 0; if (p_init == 6 && fabs(sum - 0.62792) > 1e-2) success = 0; if (p_init == 7 && fabs(sum - 0.701982) > 1e-2) success = 0; if (p_init == 8 && fabs(sum - 0.7982) > 1e-2) success = 0; if (p_init == 9 && fabs(sum - 0.895069) > 1e-2) success = 0; if (p_init == 10 && fabs(sum - 1.03031) > 1e-2) success = 0; } if (success == 1) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Provide a possibility to change INITIAL_CONCENTRATION_STATE through an argument. if(argc > 1) INITIAL_CONCENTRATION_STATE = atoi(argv[1]); if(argc > 2) INIT_REF_NUM_FLOW = atoi(argv[2]); if(argc > 3) INIT_REF_NUM_CONCENTRATION = atoi(argv[3]); // Load the mesh. Mesh basemesh; H2DReader mloader; if(INITIAL_CONCENTRATION_STATE == 0) mloader.load("GAMM-channel-4-bnds.mesh", &basemesh); else mloader.load("channel-4-bnds.mesh", &basemesh); // Initialize the meshes. Mesh mesh_flow, mesh_concentration; mesh_flow.copy(&basemesh); mesh_concentration.copy(&basemesh); for(unsigned int i = 0; i < INIT_REF_NUM_CONCENTRATION; i++) mesh_concentration.refine_all_elements(); for(unsigned int i = 0; i < INIT_REF_NUM_FLOW; i++) mesh_flow.refine_all_elements(); // Initialize boundary condition types and spaces with default shapesets. BCTypes bc_types_euler; bc_types_euler.add_bc_neumann(Hermes::vector<int>(BDY_SOLID_WALL_TOP, BDY_SOLID_WALL_BOTTOM, BDY_INLET, BDY_OUTLET)); BCTypes bc_types_concentration; BCValues bc_values_concentration; switch(INITIAL_CONCENTRATION_STATE) { case 0: bc_types_concentration.add_bc_neumann(Hermes::vector<int>(BDY_INLET, BDY_OUTLET, BDY_SOLID_WALL_TOP)); bc_types_concentration.add_bc_dirichlet(Hermes::vector<int>(BDY_SOLID_WALL_BOTTOM)); bc_values_concentration.add_const(Hermes::vector<int>(BDY_SOLID_WALL_BOTTOM), CONCENTRATION_EXT); break; case 1: bc_types_concentration.add_bc_neumann(Hermes::vector<int>(BDY_INLET, BDY_OUTLET, BDY_SOLID_WALL_TOP)); bc_types_concentration.add_bc_dirichlet(Hermes::vector<int>(BDY_SOLID_WALL_BOTTOM)); bc_values_concentration.add_const(Hermes::vector<int>(BDY_SOLID_WALL_BOTTOM), CONCENTRATION_EXT); break; case 2: bc_types_concentration.add_bc_neumann(Hermes::vector<int>(BDY_SOLID_WALL_BOTTOM, BDY_OUTLET, BDY_SOLID_WALL_TOP)); bc_types_concentration.add_bc_dirichlet(Hermes::vector<int>(BDY_INLET)); bc_values_concentration.add_const(Hermes::vector<int>(BDY_INLET), CONCENTRATION_EXT); break; } L2Space space_rho(&mesh_flow, &bc_types_euler, P_INIT_FLOW); L2Space space_rho_v_x(&mesh_flow, &bc_types_euler, P_INIT_FLOW); L2Space space_rho_v_y(&mesh_flow, &bc_types_euler, P_INIT_FLOW); L2Space space_e(&mesh_flow, &bc_types_euler, P_INIT_FLOW); // Space for concentration. H1Space space_c(&mesh_concentration, &bc_types_concentration, &bc_values_concentration, P_INIT_CONCENTRATION); // Initialize solutions, set initial conditions. Solution sln_rho, sln_rho_v_x, sln_rho_v_y, sln_e, sln_c, prev_rho, prev_rho_v_x, prev_rho_v_y, prev_e, prev_c; sln_rho.set_exact(&mesh_flow, ic_density); sln_rho_v_x.set_exact(&mesh_flow, ic_density_vel_x); sln_rho_v_y.set_exact(&mesh_flow, ic_density_vel_y); sln_e.set_exact(&mesh_flow, ic_energy); sln_c.set_exact(&mesh_concentration, ic_concentration); prev_rho.set_exact(&mesh_flow, ic_density); prev_rho_v_x.set_exact(&mesh_flow, ic_density_vel_x); prev_rho_v_y.set_exact(&mesh_flow, ic_density_vel_y); prev_e.set_exact(&mesh_flow, ic_energy); prev_c.set_exact(&mesh_concentration, ic_concentration); // Initialize weak formulation. WeakForm wf(5); // Bilinear forms coming from time discretization by explicit Euler's method. wf.add_matrix_form(0, 0, callback(bilinear_form_time)); wf.add_matrix_form(1, 1, callback(bilinear_form_time)); wf.add_matrix_form(2, 2, callback(bilinear_form_time)); wf.add_matrix_form(3, 3, callback(bilinear_form_time)); wf.add_matrix_form(4, 4, callback(bilinear_form_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_FLOW.order_h > 0 || P_INIT_FLOW.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_time, linear_form_order, HERMES_ANY, &prev_rho); wf.add_vector_form(1, linear_form_time, linear_form_order, HERMES_ANY, &prev_rho_v_x); wf.add_vector_form(2, linear_form_time, linear_form_order, HERMES_ANY, &prev_rho_v_y); wf.add_vector_form(3, linear_form_time, linear_form_order, HERMES_ANY, &prev_e); wf.add_vector_form(4, callback(linear_form_time_concentration), HERMES_ANY, &prev_c); // 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, 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, 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, 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, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(0, bdy_flux_inlet_outlet_comp_0, linear_form_order, BDY_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_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_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_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_TOP, 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_TOP, 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_TOP, 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_TOP, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(0, bdy_flux_solid_wall_comp_0, linear_form_order, BDY_SOLID_WALL_BOTTOM, 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_BOTTOM, 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_BOTTOM, 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_BOTTOM, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); // Forms for concentration. wf.add_vector_form(4, callback(linear_form_concentration_grad_grad), HERMES_ANY, &prev_c); wf.add_vector_form(4, callback(linear_form_concentration_convective), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_c, &prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form_surf(4, callback(linear_form_concentration_inlet_outlet), BDY_INLET, Hermes::vector<MeshFunction*>(&prev_c, &prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form_surf(4, callback(linear_form_concentration_inlet_outlet), BDY_OUTLET, Hermes::vector<MeshFunction*>(&prev_c, &prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form_surf(4, callback(linear_form_concentration_inner_edges), H2D_DG_INNER_EDGE, Hermes::vector<MeshFunction*>(&prev_c, &prev_rho, &prev_rho_v_x, &prev_rho_v_y)); // 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, &space_c), is_linear); // Filters for visualization of pressure and the two components of velocity. /* SimpleFilter pressure(calc_pressure_func, Hermes::vector<MeshFunction*>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e)); SimpleFilter u(calc_u_func, Hermes::vector<MeshFunction*>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e)); SimpleFilter w(calc_w_func, Hermes::vector<MeshFunction*>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e)); SimpleFilter Mach_number(calc_Mach_func, Hermes::vector<MeshFunction*>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e)); SimpleFilter entropy_estimate(calc_entropy_estimate_func, Hermes::vector<MeshFunction*>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e)); 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)); VectorView vview("Velocity", new WinGeom(700, 400, 600, 300)); */ ScalarView s1("w0", new WinGeom(0, 0, 600, 300)); ScalarView s2("w1", new WinGeom(700, 0, 600, 300)); ScalarView s3("w2", new WinGeom(0, 400, 600, 300)); ScalarView s4("w3", new WinGeom(700, 400, 600, 300)); ScalarView s5("Concentration", new WinGeom(350, 200, 600, 300)); // 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); // Output of the approximate time derivative. std::ofstream time_der_out("time_der"); for(t = 0.0; t < 3.0; t += TAU) { info("---- Time step %d, time %3.5f.", iteration++, t); 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, &space_c), Hermes::vector<Solution *>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e, &sln_c)); else error ("Matrix solver failed.\n"); // 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); prev_c.copy(&sln_c); // Visualization. /* pressure.reinit(); u.reinit(); w.reinit(); Mach_number.reinit(); entropy_estimate.reinit(); pressure_view.show(&pressure); entropy_production_view.show(&entropy_estimate); Mach_number_view.show(&Mach_number); vview.show(&u, &w); */ // Visualization. if((iteration - 1) % EVERY_NTH_STEP == 0) { // Hermes visualization. if(HERMES_VISUALIZATION) { s1.show(&prev_rho); s2.show(&prev_rho_v_x); s3.show(&prev_rho_v_y); s4.show(&prev_e); s5.show(&prev_c); } // Output solution in VTK format. if(VTK_OUTPUT) { Linearizer lin; char filename[40]; sprintf(filename, "w0-%i.vtk", iteration - 1); lin.save_solution_vtk(&prev_rho, filename, "w0", false); sprintf(filename, "w1-%i.vtk", iteration - 1); lin.save_solution_vtk(&prev_rho_v_x, filename, "w1", false); sprintf(filename, "w2-%i.vtk", iteration - 1); lin.save_solution_vtk(&prev_rho_v_y, filename, "w2", false); sprintf(filename, "w3-%i.vtk", iteration - 1); lin.save_solution_vtk(&prev_e, filename, "w3", false); sprintf(filename, "concentration-%i.vtk", iteration - 1); lin.save_solution_vtk(&prev_c, filename, "concentration", false); } } } s1.close(); s2.close(); s3.close(); s4.close(); s5.close(); time_der_out.close(); return 0; }
int main(int argc, char **args) { // Test variable. int success_test = 1; // Load the mesh. Mesh mesh; ExodusIIReader mloader; mloader.load("brick_with_hole_hex.e", &mesh); // Perform initial mesh refinement. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(H3D_H3D_H3D_REFT_HEX_XYZ); // Create H1 space with default shapeset for x-displacement component. H1Space xdisp(&mesh, bc_types_x, essential_bc_values, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); // Create H1 space with default shapeset for y-displacement component. H1Space ydisp(&mesh, bc_types_y, essential_bc_values, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); // Create H1 space with default shapeset for z-displacement component. H1Space zdisp(&mesh, bc_types_z, essential_bc_values, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z)); // Initialize weak formulation. WeakForm wf(3); wf.add_matrix_form(0, 0, callback(bilinear_form_0_0), HERMES_SYM); wf.add_matrix_form(0, 1, callback(bilinear_form_0_1), HERMES_SYM); wf.add_matrix_form(0, 2, callback(bilinear_form_0_2), HERMES_SYM); wf.add_vector_form_surf(0, callback(surf_linear_form_x), bdy_force); wf.add_matrix_form(1, 1, callback(bilinear_form_1_1), HERMES_SYM); wf.add_matrix_form(1, 2, callback(bilinear_form_1_2), HERMES_SYM); wf.add_vector_form_surf(1, callback(surf_linear_form_y), bdy_force); wf.add_matrix_form(2, 2, callback(bilinear_form_2_2), HERMES_SYM); wf.add_vector_form_surf(2, callback(surf_linear_form_z), bdy_force); // Initialize discrete problem. bool is_linear = true; DiscreteProblem dp(&wf, Hermes::vector<Space *>(&xdisp, &ydisp, &zdisp), is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the preconditioner in the case of SOLVER_AZTECOO. if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Assemble stiffness matrix and load vector. info("Assembling the linear problem (ndof: %d).", Space::get_num_dofs(Hermes::vector<Space *>(&xdisp, &ydisp, &zdisp))); dp.assemble(matrix, rhs); // Solve the linear system. If successful, obtain the solution. info("Solving the linear problem."); Solution xsln(xdisp.get_mesh()); Solution ysln(ydisp.get_mesh()); Solution zsln(zdisp.get_mesh()); if(solver->solve()) Solution::vector_to_solutions(solver->get_solution(), Hermes::vector<Space *>(&xdisp, &ydisp, &zdisp), Hermes::vector<Solution *>(&xsln, &ysln, &zsln)); else error ("Matrix solver failed.\n"); // Output all components of the solution. if (solution_output) out_fn_vtk(&xsln, &ysln, &zsln, "sln"); double sum = 0; for(int i = 0; i < Space::get_num_dofs(Hermes::vector<Space *>(&xdisp, &ydisp, &zdisp)); i++) sum += solver->get_solution()[i]; if (abs(sum - 0.00037) / sum > 0.01) success_test = 0; // Clean up. delete matrix; delete rhs; delete solver; // if (success_test) { info("Success!"); return ERR_SUCCESS; } else { info("Failure!"); return ERR_FAILURE; } return 0; }
int main() { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Create coarse mesh, set Dirichlet BC, enumerate basis functions. Space* space = new Space(A, B, NELEM, DIR_BC_LEFT, DIR_BC_RIGHT, P_INIT, NEQ); info("N_dof = %d.", Space::get_num_dofs(space)); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(jacobian); wf.add_vector_form(residual); double elem_errors[MAX_ELEM_NUM]; // This array decides what // elements will be refined. ElemPtr2 ref_elem_pairs[MAX_ELEM_NUM]; // To store element pairs from the // FTR solution. Decides how // elements will be hp-refined. for (int i=0; i < MAX_ELEM_NUM; i++) { ref_elem_pairs[i][0] = new Element(); ref_elem_pairs[i][1] = new Element(); } // DOF and CPU convergence graphs. SimpleGraph graph_dof_exact, graph_cpu_exact; // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Initialize the FE problem. bool is_linear = false; DiscreteProblem *dp_coarse = new DiscreteProblem(&wf, space, is_linear); // Newton's loop on coarse mesh. // Fill vector coeff_vec using dof and coeffs arrays in elements. double *coeff_vec_coarse = new double[Space::get_num_dofs(space)]; get_coeff_vector(space, coeff_vec_coarse); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix_coarse = create_matrix(matrix_solver); Vector* rhs_coarse = create_vector(matrix_solver); Solver* solver_coarse = create_linear_solver(matrix_solver, matrix_coarse, rhs_coarse); int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof_coarse = Space::get_num_dofs(space); // Assemble the Jacobian matrix and residual vector. dp_coarse->assemble(matrix_coarse, rhs_coarse); // Calculate the l2-norm of residual vector. double res_l2_norm = get_l2_norm(rhs_coarse); // Info for user. info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(space), res_l2_norm); // If l2 norm of the residual vector is within tolerance, then quit. // NOTE: at least one full iteration forced // here because sometimes the initial // residual on fine mesh is too small. if(res_l2_norm < NEWTON_TOL_COARSE && it > 1) break; // Multiply the residual vector with -1 since the matrix // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). for(int i=0; i<ndof_coarse; i++) rhs_coarse->set(i, -rhs_coarse->get(i)); // Solve the linear system. if(!solver_coarse->solve()) error ("Matrix solver failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof_coarse; i++) coeff_vec_coarse[i] += solver_coarse->get_solution()[i]; // If the maximum number of iteration has been reached, then quit. if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); // Copy coefficients from vector y to elements. set_coeff_vector(coeff_vec_coarse, space); it++; } // Cleanup. delete matrix_coarse; delete rhs_coarse; delete solver_coarse; delete [] coeff_vec_coarse; delete dp_coarse; // For every element perform its fast trial refinement (FTR), // calculate the norm of the difference between the FTR // solution and the coarse space solution, and store the // error in the elem_errors[] array. int n_elem = space->get_n_active_elem(); for (int i=0; i < n_elem; i++) { info("=== Starting FTR of Elem [%d].", i); // Replicate coarse space including solution. Space *space_ref_local = space->replicate(); // Perform FTR of element 'i' space_ref_local->reference_refinement(i, 1); info("Elem [%d]: fine space created (%d DOF).", i, space_ref_local->assign_dofs()); // Initialize the FE problem. bool is_linear = false; DiscreteProblem* dp = new DiscreteProblem(&wf, space_ref_local, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Newton's loop on the FTR space. // Fill vector coeff_vec using dof and coeffs arrays in elements. double *coeff_vec = new double[Space::get_num_dofs(space_ref_local)]; get_coeff_vector(space_ref_local, coeff_vec); memset(coeff_vec, 0, Space::get_num_dofs(space_ref_local)*sizeof(double)); int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(space_ref_local); // Assemble the Jacobian matrix and residual vector. dp->assemble(matrix, rhs); // Calculate the l2-norm of residual vector. double res_l2_norm = get_l2_norm(rhs); // Info for user. info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(space_ref_local), res_l2_norm); // If l2 norm of the residual vector is within tolerance, then quit. // NOTE: at least one full iteration forced // here because sometimes the initial // residual on fine mesh is too small. if(res_l2_norm < NEWTON_TOL_REF && it > 1) break; // Multiply the residual vector with -1 since the matrix // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). for(int i=0; i<ndof; i++) rhs->set(i, -rhs->get(i)); // Solve the linear system. if(!solver->solve()) error ("Matrix solver failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof; i++) coeff_vec[i] += solver->get_solution()[i]; // If the maximum number of iteration has been reached, then quit. if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); // Copy coefficients from vector y to elements. set_coeff_vector(coeff_vec, space_ref_local); it++; } // Cleanup. delete matrix; delete rhs; delete solver; delete dp; delete [] coeff_vec; // Print FTR solution (enumerated). Linearizer *lxx = new Linearizer(space_ref_local); char out_filename[255]; sprintf(out_filename, "solution_ref_%d.gp", i); lxx->plot_solution(out_filename); delete lxx; // Calculate norm of the difference between the coarse space // and FTR solutions. // NOTE: later we want to look at the difference in some quantity // of interest rather than error in global norm. double err_est_array[MAX_ELEM_NUM]; elem_errors[i] = calc_err_est(NORM, space, space_ref_local, err_est_array) * 100; info("Elem [%d]: absolute error (est) = %g%%", i, elem_errors[i]); // Copy the reference element pair for element 'i'. // into the ref_elem_pairs[i][] array Iterator *I = new Iterator(space); Iterator *I_ref = new Iterator(space_ref_local); Element *e, *e_ref; while (1) { e = I->next_active_element(); e_ref = I_ref->next_active_element(); if (e->id == i) { e_ref->copy_into(ref_elem_pairs[e->id][0]); // coarse element 'e' was split in space. if (e->level != e_ref->level) { e_ref = I_ref->next_active_element(); e_ref->copy_into(ref_elem_pairs[e->id][1]); } break; } } delete I; delete I_ref; delete space_ref_local; } // Time measurement. cpu_time.tick(); // If exact solution available, also calculate exact error. if (EXACT_SOL_PROVIDED) { // Calculate element errors wrt. exact solution. double err_exact_rel = calc_err_exact(NORM, space, exact_sol, NEQ, A, B) * 100; // Info for user. info("Relative error (exact) = %g %%", err_exact_rel); // Add entry to DOF and CPU convergence graphs. graph_dof_exact.add_values(Space::get_num_dofs(space), err_exact_rel); graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel); } // Calculate max FTR error. double max_ftr_error = 0; for (int i=0; i < space->get_n_active_elem(); i++) { if (elem_errors[i] > max_ftr_error) max_ftr_error = elem_errors[i]; } info("Max FTR error = %g%%.", max_ftr_error); // Decide whether the max. FTR error is sufficiently small. if(max_ftr_error < TOL_ERR_FTR) break; // debug //if (as == 4) break; // Returns updated coarse space with the last solution on it. adapt(NORM, ADAPT_TYPE, THRESHOLD, elem_errors, space, ref_elem_pairs); // Plot spaces, results, and errors. adapt_plotting(space, ref_elem_pairs, NORM, EXACT_SOL_PROVIDED, exact_sol); as++; } while (done == false); info("Total running time: %g s", cpu_time.accumulated()); // Save convergence graphs. graph_dof_exact.save("conv_dof_exact.dat"); graph_cpu_exact.save("conv_cpu_exact.dat"); return 0; }
int main(int argc, char* argv[]) { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); info("TIME_MAX_ITER = %d", TIME_MAX_ITER); // Load the mesh file. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); // Perform initial mesh refinements. for (int i=0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(1, INIT_BDY_REF_NUM); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(BDY_DIRICHLET); // Enter Dirichlet boudnary values. BCValues bc_values; bc_values.add_zero(BDY_DIRICHLET); // Create H1 spaces with default shapesets. H1Space space_T(&mesh, &bc_types, &bc_values, P_INIT); H1Space space_phi(&mesh, &bc_types, &bc_values, P_INIT); Hermes::vector<Space*> spaces(&space_T, &space_phi); // Exact solutions for error evaluation. ExactSolution T_exact_solution(&mesh, T_exact), phi_exact_solution(&mesh, phi_exact); // Solutions in the previous time step. Solution T_prev_time, phi_prev_time; Hermes::vector<MeshFunction*> time_iterates(&T_prev_time, &phi_prev_time); // Solutions in the previous Newton's iteration. Solution T_prev_newton, phi_prev_newton; Hermes::vector<Solution*> newton_iterates(&T_prev_newton, &phi_prev_newton); // Initialize the weak formulation. WeakForm wf(2); wf.add_matrix_form(0, 0, jac_TT, jac_TT_ord); wf.add_matrix_form(0, 1, jac_Tphi, jac_Tphi_ord); wf.add_vector_form(0, res_T, res_T_ord, HERMES_ANY, &T_prev_time); wf.add_matrix_form(1, 0, jac_phiT, jac_phiT_ord); wf.add_matrix_form(1, 1, jac_phiphi, jac_phiphi_ord); wf.add_vector_form(1, res_phi, res_phi_ord, HERMES_ANY, &phi_prev_time); // Set initial conditions. T_prev_time.set_exact(&mesh, T_exact); phi_prev_time.set_exact(&mesh, phi_exact); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); solver->set_factorization_scheme(HERMES_REUSE_MATRIX_REORDERING); // Time stepping. int t_step = 1; do { TIME += TAU; info("---- Time step %d, t = %g s:", t_step, TIME); t_step++; info("Projecting to obtain initial vector for the Newton's method."); scalar* coeff_vec = new scalar[Space::get_num_dofs(spaces)]; OGProjection::project_global(spaces, time_iterates, coeff_vec, matrix_solver); Solution::vector_to_solutions(coeff_vec, Hermes::vector<Space*>(&space_T, &space_phi), Hermes::vector<Solution*>(&T_prev_newton, &phi_prev_newton)); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp(&wf, spaces, is_linear); // Perform Newton's iteration. info("Newton's iteration..."); bool verbose = false; if(!solve_newton(coeff_vec, &dp, solver, matrix, rhs, NEWTON_TOL, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution::vector_to_solutions(coeff_vec, spaces, newton_iterates); delete [] coeff_vec; // Exact solution for comparison with computational results. T_exact_solution.update(&mesh, T_exact); phi_exact_solution.update(&mesh, phi_exact); // Calculate exact error. info("Calculating error (exact)."); Hermes::vector<double> exact_errors; Adapt adaptivity_exact(spaces); bool solutions_for_adapt = false; adaptivity_exact.calc_err_exact(Hermes::vector<Solution *>(&T_prev_newton, &phi_prev_newton), Hermes::vector<Solution *>(&T_exact_solution, &phi_exact_solution), &exact_errors, solutions_for_adapt); double maxerr = std::max(exact_errors[0], exact_errors[1])*100; info("Exact solution error for T (H1 norm): %g %%", exact_errors[0]*100); info("Exact solution error for phi (H1 norm): %g %%", exact_errors[1]*100); info("Exact solution error (maximum): %g %%", maxerr); // Prepare previous time level solution for the next time step. T_prev_time.copy(&T_prev_newton); phi_prev_time.copy(&phi_prev_newton); } while (t_step <= TIME_MAX_ITER); // Cleanup. delete matrix; delete rhs; delete solver; info("Coordinate ( 0, 0) T value = %lf", T_prev_time.get_pt_value(0.0, 0.0)); info("Coordinate ( 25, 25) T value = %lf", T_prev_time.get_pt_value(25.0, 25.0)); info("Coordinate ( 75, 25) T value = %lf", T_prev_time.get_pt_value(75.0, 25.0)); info("Coordinate ( 25, 75) T value = %lf", T_prev_time.get_pt_value(25.0, 75.0)); info("Coordinate ( 75, 75) T value = %lf", T_prev_time.get_pt_value(75.0, 75.0)); info("Coordinate ( 0, 0) phi value = %lf", phi_prev_time.get_pt_value(0.0, 0.0)); info("Coordinate ( 25, 25) phi value = %lf", phi_prev_time.get_pt_value(25.0, 25.0)); info("Coordinate ( 75, 25) phi value = %lf", phi_prev_time.get_pt_value(75.0, 25.0)); info("Coordinate ( 25, 75) phi value = %lf", phi_prev_time.get_pt_value(25.0, 75.0)); info("Coordinate ( 75, 75) phi value = %lf", phi_prev_time.get_pt_value(75.0, 75.0)); int success = 1; double eps = 1e-5; if (fabs(T_prev_time.get_pt_value(0.0, 0.0) - 0.000000) > eps) { printf("Coordinate ( 0, 0) T value = %lf\n", T_prev_time.get_pt_value(0.0, 0.0)); success = 0; } if (fabs(T_prev_time.get_pt_value(25.0, 25.0) - 0.915885) > eps) { printf("Coordinate ( 25, 25) T value = %lf\n", T_prev_time.get_pt_value(25.0, 25.0)); success = 0; } if (fabs(T_prev_time.get_pt_value(75.0, 25.0) - 0.915885) > eps) { printf("Coordinate ( 75, 25) T value = %lf\n", T_prev_time.get_pt_value(75.0, 25.0)); success = 0; } if (fabs(T_prev_time.get_pt_value(25.0, 75.0) - 0.915885) > eps) { printf("Coordinate ( 25, 75) T value = %lf\n", T_prev_time.get_pt_value(25.0, 75.0)); success = 0; } if (fabs(T_prev_time.get_pt_value(75.0, 75.0) - 0.915885) > eps) { printf("Coordinate ( 75, 75) T value = %lf\n", T_prev_time.get_pt_value(75.0, 75.0)); success = 0; } if (fabs(phi_prev_time.get_pt_value(0.0, 0.0) - 0.000000) > eps) { printf("Coordinate ( 0, 0) phi value = %lf\n", phi_prev_time.get_pt_value(0.0, 0.0)); success = 0; } if (fabs(phi_prev_time.get_pt_value(25.0, 25.0) - 0.071349) > eps) { printf("Coordinate ( 25, 25) phi value = %lf\n", phi_prev_time.get_pt_value(25.0, 25.0)); success = 0; } if (fabs(phi_prev_time.get_pt_value(75.0, 25.0) - 0.214063) > eps) { printf("Coordinate ( 75, 25) phi value = %lf\n", phi_prev_time.get_pt_value(75.0, 25.0)); success = 0; } if (fabs(phi_prev_time.get_pt_value(25.0, 75.0) - 0.214063) > eps) { printf("Coordinate ( 25, 75) phi value = %lf\n", phi_prev_time.get_pt_value(25.0, 75.0)); success = 0; } if (fabs(phi_prev_time.get_pt_value(75.0, 75.0) - 0.642226) > eps) { printf("Coordinate ( 75, 75) phi value = %lf\n", phi_prev_time.get_pt_value(75.0, 75.0)); success = 0; } if (success == 1) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); // Perform initial mesh refinements. for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Create an H1 space with default shapeset. H1Space space(&mesh, bc_types, essential_bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d", ndof); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(bilinear_form, bilinear_form_ord, HERMES_SYM); wf.add_vector_form(linear_form, linear_form_ord); wf.add_vector_form_surf(linear_form_surf, linear_form_surf_ord, BDY_VERTICAL); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); initialize_solution_environment(matrix_solver, argc, argv); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Initialize the solution. Solution sln; // Assemble the stiffness matrix and right-hand side vector. info("Assembling the stiffness matrix and right-hand side vector."); dp.assemble(matrix, rhs); // Solve the linear system and if successful, obtain the solution. info("Solving the matrix problem."); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Clean up. delete solver; delete matrix; delete rhs; finalize_solution_environment(matrix_solver); // View the solution and mesh. ScalarView sview("Solution", new WinGeom(0, 0, 440, 350)); sview.show(&sln); OrderView oview("Polynomial orders", new WinGeom(450, 0, 400, 350)); oview.show(&space); // Skip visualization time. cpu_time.tick(HERMES_SKIP); // Print timing information. verbose("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. View::wait(); return 0; }
int main() { // Create space. // Transform input data to the format used by the "Space" constructor. SpaceData *md = new SpaceData(verbose); Space* space = new Space(md->N_macroel, md->interfaces, md->poly_orders, md->material_markers, md->subdivisions, N_GRP, N_SLN); delete md; // Enumerate basis functions, info for user. int ndof = Space::get_num_dofs(space); info("ndof: %d", ndof); // Plot the space. space->plot("space.gp"); // Initial approximation of the dominant eigenvalue. double K_EFF = 1.0; // Initial approximation of the dominant eigenvector. double init_val = 1.0; for (int g = 0; g < N_GRP; g++) { set_vertex_dofs_constant(space, init_val, g); space->set_bc_right_dirichlet(g, flux_right_surf[g]); } // Initialize the weak formulation. WeakForm wf(2); wf.add_matrix_form(0, 0, jacobian_fuel_0_0, NULL, fuel); wf.add_matrix_form(0, 0, jacobian_water_0_0, NULL, water); wf.add_matrix_form(0, 1, jacobian_fuel_0_1, NULL, fuel); wf.add_matrix_form(0, 1, jacobian_water_0_1, NULL, water); wf.add_matrix_form(1, 0, jacobian_fuel_1_0, NULL, fuel); wf.add_matrix_form(1, 0, jacobian_water_1_0, NULL, water); wf.add_matrix_form(1, 1, jacobian_fuel_1_1, NULL, fuel); wf.add_matrix_form(1, 1, jacobian_water_1_1, NULL, water); wf.add_vector_form(0, residual_fuel_0, NULL, fuel); wf.add_vector_form(0, residual_water_0, NULL, water); wf.add_vector_form(1, residual_fuel_1, NULL, fuel); wf.add_vector_form(1, residual_water_1, NULL, water); wf.add_vector_form_surf(0, residual_surf_left_0, BOUNDARY_LEFT); wf.add_vector_form_surf(1, residual_surf_left_1, BOUNDARY_LEFT); // Initialize the FE problem. bool is_linear = false; DiscreteProblem *dp = new DiscreteProblem(&wf, space, is_linear); Linearizer l(space); char solution_file[32]; // Source iteration int i; int current_solution = 0, previous_solution = 1; double K_EFF_old; for (i = 0; i < Max_SI; i++) { // Plot the critical (i.e. steady-state) flux in the actual iteration. sprintf(solution_file, "solution_%d.gp", i); l.plot_solution(solution_file); // Store the previous solution (used at the right-hand side). for (int g = 0; g < N_GRP; g++) copy_dofs(current_solution, previous_solution, space, g); // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(space); // Fill vector coeff_vec using dof and coeffs arrays in elements. double *coeff_vec = new double[Space::get_num_dofs(space)]; get_coeff_vector(space, coeff_vec); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); int it = 1; while (1) { // Obtain the number of degrees of freedom. int ndof = Space::get_num_dofs(space); // Assemble the Jacobian matrix and residual vector. dp->assemble(coeff_vec, matrix, rhs); // Calculate the l2-norm of residual vector. double res_l2_norm = get_l2_norm(rhs); // Info for user. info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(space), res_l2_norm); // If l2 norm of the residual vector is within tolerance, then quit. // NOTE: at least one full iteration forced // here because sometimes the initial // residual on fine mesh is too small. if(res_l2_norm < NEWTON_TOL && it > 1) break; // Multiply the residual vector with -1 since the matrix // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). for(int i=0; i<ndof; i++) rhs->set(i, -rhs->get(i)); // Solve the linear system. if(!solver->solve()) error ("Matrix solver failed.\n"); // Add \deltaY^{n+1} to Y^n. for (int i = 0; i < ndof; i++) coeff_vec[i] += solver->get_solution()[i]; // If the maximum number of iteration has been reached, then quit. if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge."); // Copy coefficients from vector y to elements. set_coeff_vector(coeff_vec, space); it++; } // Cleanup. delete matrix; delete rhs; delete solver; delete [] coeff_vec; // Update the eigenvalue. K_EFF_old = K_EFF; K_EFF = calc_total_reaction_rate(space, nSf, 0., 40.); // Convergence test. if (fabs(K_EFF - K_EFF_old)/K_EFF < TOL_SI) break; // Normalize total neutron flux to one fission neutron. multiply_dofs_with_constant(space, 1./K_EFF, current_solution); if (verbose) info("K_EFF_%d = %.8f", i+1, K_EFF); } // Print the converged eigenvalue. info("K_EFF = %.8f, err= %.8f%%", K_EFF, 100*(K_EFF-1)); // Plot the converged critical neutron flux. sprintf(solution_file, "solution.gp"); l.plot_solution(solution_file); // Comparison with analytical results (see the reference above). double flux[N_GRP], J[N_GRP], R; get_solution_at_point(space, 0.0, flux, J); R = flux[0]/flux[1]; info("phi_fast/phi_therm at x=0 : %.4f, err = %.2f%%", R, 100*(R-2.5332)/2.5332); get_solution_at_point(space, 40.0, flux, J); R = flux[0]/flux[1]; info("phi_fast/phi_therm at x=40 : %.4f, err = %.2f%%", R, 100*(R-1.5162)/1.5162); info("Done."); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); // Perform initial mesh refinements. for(int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(Hermes::vector<int>(BDY_BOTTOM, BDY_OUTER, BDY_LEFT, BDY_INNER)); // Enter Dirichlet boudnary values. BCValues bc_values; bc_values.add_function(Hermes::vector<int>(BDY_BOTTOM, BDY_OUTER, BDY_LEFT, BDY_INNER), essential_bc_values); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d", ndof); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(bilinear_form)); wf.add_vector_form(callback(linear_form)); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the 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 and solution. info("Solving the matrix problem."); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); // Visualize the solution. ScalarView view("Solution", new WinGeom(0, 0, 440, 350)); view.show(&sln); // Wait for the view to be closed. View::wait(); // Clean up. delete solver; delete matrix; delete rhs; return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("cathedral.mesh", &mesh); // Perform initial mesh refinements. for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(BDY_AIR, INIT_REF_NUM_BDY); mesh.refine_towards_boundary(BDY_GROUND, INIT_REF_NUM_BDY); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(Hermes::vector<std::string>(BDY_GROUND)); bc_types.add_bc_newton(BDY_AIR); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_const(BDY_GROUND, TEMP_INIT); // Initialize an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d.", ndof); // Previous time level solution (initialized by the external temperature). Solution tsln(&mesh, TEMP_INIT); // Initialize weak formulation. WeakForm wf; wf.add_matrix_form(callback(bilinear_form)); wf.add_matrix_form_surf(callback(bilinear_form_surf), BDY_AIR); wf.add_vector_form(callback(linear_form), HERMES_ANY, &tsln); wf.add_vector_form_surf(callback(linear_form_surf), BDY_AIR); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); solver->set_factorization_scheme(HERMES_REUSE_FACTORIZATION_COMPLETELY); // Initialize views. ScalarView Tview("Temperature", new WinGeom(0, 0, 450, 600)); Tview.set_min_max_range(0,20); Tview.fix_scale_width(30); // Time stepping: int ts = 1; bool rhs_only = false; do { info("---- Time step %d, time %3.5f s, ext_temp %g C", ts, current_time, temp_ext(current_time)); // First time assemble both the stiffness matrix and right-hand side vector, // then just the right-hand side vector. if (rhs_only == false) info("Assembling the stiffness matrix and right-hand side vector."); else info("Assembling the right-hand side vector (only)."); dp.assemble(matrix, rhs, rhs_only); rhs_only = true; // Solve the linear system and if successful, obtain the solution. info("Solving the matrix problem."); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &tsln); else error ("Matrix solver failed.\n"); // Visualize the solution. char title[100]; sprintf(title, "Time %3.2f s, exterior temperature %3.5f C", current_time, temp_ext(current_time)); Tview.set_title(title); Tview.show(&tsln); // Increase current time and time step counter. current_time += time_step; ts++; } while (current_time < T_FINAL); // Wait for the view to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh basemesh; H2DReader mloader; mloader.load("GAMM-channel.mesh", &basemesh); // Initialize the meshes. Mesh mesh_flow, mesh_concentration; mesh_flow.copy(&basemesh); mesh_concentration.copy(&basemesh); for(unsigned int i = 0; i < INIT_REF_NUM_CONCENTRATION; i++) mesh_concentration.refine_all_elements(); mesh_concentration.refine_towards_boundary(BDY_DIRICHLET_CONCENTRATION, INIT_REF_NUM_CONCENTRATION_BDY); mesh_flow.refine_towards_boundary(BDY_DIRICHLET_CONCENTRATION, INIT_REF_NUM_CONCENTRATION_BDY); for(unsigned int i = 0; i < INIT_REF_NUM_FLOW; i++) mesh_flow.refine_all_elements(); // Initialize boundary condition types and spaces with default shapesets. // For the concentration. EssentialBCs bcs_concentration; bcs_concentration.add_boundary_condition(new ConcentrationTimedepEssentialBC(BDY_DIRICHLET_CONCENTRATION, CONCENTRATION_EXT, CONCENTRATION_EXT_STARTUP_TIME)); bcs_concentration.add_boundary_condition(new ConcentrationTimedepEssentialBC(BDY_SOLID_WALL_TOP, 0.0, CONCENTRATION_EXT_STARTUP_TIME)); L2Space space_rho(&mesh_flow, P_INIT_FLOW); L2Space space_rho_v_x(&mesh_flow, P_INIT_FLOW); L2Space space_rho_v_y(&mesh_flow, P_INIT_FLOW); L2Space space_e(&mesh_flow, P_INIT_FLOW); // Space for concentration. H1Space space_c(&mesh_concentration, &bcs_concentration, P_INIT_CONCENTRATION); int ndof = Space::get_num_dofs(Hermes::vector<Space*>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e, &space_c)); info("ndof: %d", ndof); // Initialize solutions, set initial conditions. InitialSolutionEulerDensity prev_rho(&mesh_flow, RHO_EXT); InitialSolutionEulerDensityVelX prev_rho_v_x(&mesh_flow, RHO_EXT * V1_EXT); InitialSolutionEulerDensityVelY prev_rho_v_y(&mesh_flow, RHO_EXT * V2_EXT); InitialSolutionEulerDensityEnergy prev_e(&mesh_flow, QuantityCalculator::calc_energy(RHO_EXT, RHO_EXT * V1_EXT, RHO_EXT * V2_EXT, P_EXT, KAPPA)); InitialSolutionConcentration prev_c(&mesh_concentration, 0.0); // Numerical flux. OsherSolomonNumericalFlux num_flux(KAPPA); // Initialize weak formulation. EulerEquationsWeakFormSemiImplicitCoupled wf(&num_flux, KAPPA, RHO_EXT, V1_EXT, V2_EXT, P_EXT, BDY_SOLID_WALL_BOTTOM, BDY_SOLID_WALL_TOP, BDY_INLET, BDY_OUTLET, BDY_NATURAL_CONCENTRATION, &prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e, &prev_c, EPSILON, (P_INIT_FLOW == 0)); wf.set_time_step(time_step); // Initialize the FE problem. DiscreteProblem dp(&wf, Hermes::vector<Space*>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e, &space_c)); // If the FE problem is in fact a FV problem. //if(P_INIT == 0) dp.set_fvm(); // 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 s5("Concentration", new WinGeom(700, 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)); ScalarView s5("Concentration", new WinGeom(350, 200, 600, 300)); // 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); // Set up CFL calculation class. CFLCalculation CFL(CFL_NUMBER, KAPPA); // Set up Advection-Diffusion-Equation stability calculation class. ADEStabilityCalculation ADES(ADVECTION_STABILITY_CONSTANT, DIFFUSION_STABILITY_CONSTANT, EPSILON); int iteration = 0; double t = 0; for(t = 0.0; t < 100.0; t += time_step) { info("---- Time step %d, time %3.5f.", iteration++, t); // Set the current time step. wf.set_time_step(time_step); Space::update_essential_bc_values(&space_c, t); // Assemble stiffness matrix and rhs. info("Assembling the stiffness matrix and right-hand side vector."); dp.assemble(matrix, rhs); // Solve the matrix problem. info("Solving the matrix problem."); scalar* solution_vector = NULL; if(solver->solve()) { solution_vector = solver->get_solution(); Solution::vector_to_solutions(solution_vector, Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e, &space_c), Hermes::vector<Solution *>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e, &prev_c)); } else error ("Matrix solver failed.\n"); if(SHOCK_CAPTURING) { DiscontinuityDetector discontinuity_detector(Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), Hermes::vector<Solution *>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); std::set<int> discontinuous_elements = discontinuity_detector.get_discontinuous_element_ids(DISCONTINUITY_DETECTOR_PARAM); FluxLimiter flux_limiter(solution_vector, Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), Hermes::vector<Solution *>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); flux_limiter.limit_according_to_detector(discontinuous_elements); } util_time_step = time_step; CFL.calculate_semi_implicit(Hermes::vector<Solution *>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), &mesh_flow, util_time_step); time_step = util_time_step; ADES.calculate(Hermes::vector<Solution *>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y), &mesh_concentration, util_time_step); if(util_time_step < time_step) time_step = util_time_step; // 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); s5.show(&prev_c); */ s1.show(&prev_rho); s2.show(&prev_rho_v_x); s3.show(&prev_rho_v_y); s4.show(&prev_e); s5.show(&prev_c); /* s1.save_numbered_screenshot("density%i.bmp", iteration, true); s2.save_numbered_screenshot("density_v_x%i.bmp", iteration, true); s3.save_numbered_screenshot("density_v_y%i.bmp", iteration, true); s4.save_numbered_screenshot("energy%i.bmp", iteration, true); s5.save_numbered_screenshot("concentration%i.bmp", iteration, true); */ //s5.wait_for_close(); } // 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); sprintf(filename, "Concentration-%i.vtk", iteration - 1); lin.save_solution_vtk(&prev_c, filename, "Concentration", true); sprintf(filename, "Concentration-3D-%i.vtk", iteration - 1); lin.save_solution_vtk(&prev_c, filename, "Concentration", true); } } } /* pressure_view.close(); entropy_production_view.close(); Mach_number_view.close(); s5.close(); */ s1.close(); s2.close(); s3.close(); s4.close(); s5.close(); return 0; }