L2Space::L2Space(Mesh* mesh, int p_init, Shapeset* shapeset) : Space(mesh, shapeset, NULL, NULL, Ord2(p_init, p_init)) { if (shapeset == NULL) this->shapeset = new L2Shapeset; ldata = NULL; lsize = 0; // set uniform poly order in elements if (p_init < 0) error("P_INIT must be >= 0 in an L2 space."); else this->set_uniform_order_internal(Ord2(p_init, p_init)); // enumerate basis functions this->assign_dofs(); }
// the following constructors are DEPRECATED. HdivSpace::HdivSpace(Mesh* mesh, BCTypes* bc_types, scalar (*bc_value_callback_by_coord)(int, double, double), int p_init, Shapeset* shapeset) : Space(mesh, shapeset, bc_types, bc_value_callback_by_coord, Ord2(p_init, p_init)) { if (shapeset == NULL) { this->shapeset = new HdivShapeset; own_shapeset = true; } if (this->shapeset->get_num_components() < 2) error("HdivSpace requires a vector shapeset."); if (!hdiv_proj_ref++) { precalculate_projection_matrix(0, hdiv_proj_mat, hdiv_chol_p); } proj_mat = hdiv_proj_mat; chol_p = hdiv_chol_p; // set uniform poly order in elements if (p_init < 0) error("P_INIT must be >= 0 in an Hdiv space."); else this->set_uniform_order_internal(Ord2(p_init, p_init)); // enumerate basis functions this->assign_dofs(); }
// DEPRECATED H1Space::H1Space(Mesh* mesh, BCType (*bc_type_callback)(int), scalar (*bc_value_callback_by_coord)(int, double, double), int p_init, Shapeset* shapeset) : Space(mesh, shapeset, bc_type_callback, bc_value_callback_by_coord, Ord2(p_init, p_init)) { _F_ if (shapeset == NULL) { this->shapeset = new H1Shapeset; own_shapeset = true; } if (!h1_proj_ref++) { // FIXME: separate projection matrices for different shapesets precalculate_projection_matrix(2, h1_proj_mat, h1_chol_p); } proj_mat = h1_proj_mat; chol_p = h1_chol_p; // set uniform poly order in elements if (p_init < 1) error("P_INIT must be >= 1 in an H1 space."); else this->set_uniform_order_internal(Ord2(p_init, p_init)); // enumerate basis functions this->assign_dofs(); }
Space* HdivSpace::dup(Mesh* mesh) const { HdivSpace* space = new HdivSpace(mesh, this->bc_types, this->bc_value_callback_by_coord, Ord2(0,0), this->shapeset); space->copy_callbacks(this); return space; }
int test_order_hex() { info("test_order_hex."); Ord3 a(1, 2, 3), b(3, 4, 2); Ord3 x; Ord3 c = a + b; if (c.x != 4 || c.y != 6 || c.z != 5) return ERR_FAILURE; Ord3 d = a; d += b; if (d.x != 4 || d.y != 6 || c.z != 5) return ERR_FAILURE; Ord3 e = b * 6; if (e.x != 18 || e.y != 24 || e.z != 12) return ERR_FAILURE; Ord3 f = b * Ord3(2, 3, 4); if (f.x != 6 || f.y != 12 || f.z != 8) return ERR_FAILURE; Ord3 m = max(b, e); if (m.x != e.x || m.y != e.y || m.z != e.z) return ERR_FAILURE; Ord3 z(2, 1, 4); x = a + b + z; if (x.x != 6 || x.y != 7 || x.z != 9) return ERR_FAILURE; if (c == Ord3(4, 6, 5)) ; else return ERR_FAILURE; if (c != Ord3(4, 6, 5)) return ERR_FAILURE; Ord1 edge_ref_order[] = { 3, 4, 3, 4, 2, 2, 2, 2, 3, 4, 3, 4 }; for (int iedge = 0; iedge < Hex::NUM_EDGES; iedge++) { if (b.get_edge_order(iedge) != edge_ref_order[iedge]) return ERR_FAILURE; } Ord2 face_ref_order[] = { Ord2(4, 2), Ord2(4, 2), Ord2(3, 2), Ord2(3, 2), Ord2(3, 4), Ord2(3, 4) }; for (int iface = 0; iface < Hex::NUM_FACES; iface++) { if (b.get_face_order(iface) != face_ref_order[iface]) return ERR_FAILURE; } return ERR_SUCCESS; }
int test_order_quad() { info("test_order_quad."); Ord2 a(1, 2), b(3, 4); Ord2 c = a + b; if (c.x != 4 || c.y != 6) return ERR_FAILURE; Ord2 d = a; d += b; if (d.x != 4 || d.y != 6) return ERR_FAILURE; Ord2 e = b * 6; if (e.x != 18 || e.y != 24) return ERR_FAILURE; Ord2 f = b * Ord2(2, 3); if (f.x != 6 || f.y != 12) return ERR_FAILURE; Ord2 m = max(b, e); if (m.x != e.x || m.y != e.y) return ERR_FAILURE; return ERR_SUCCESS; }
int test_quadrature_3d_hex_surf(fn3d_t fn, double exact, int min_h, int min_v, int min_u, const char *fn_name) { info(" * f(x,y) = %s", fn_name); QuadStdHex quad; for (int horder = min_h; horder <= H3D_MAX_QUAD_ORDER; horder++) { for (int vorder = min_v; vorder <= H3D_MAX_QUAD_ORDER; vorder++) { for (int uorder = min_u; uorder <= H3D_MAX_QUAD_ORDER; uorder++) { Ord2 face_order[] = { Ord2(vorder, uorder), Ord2(vorder, uorder), Ord2(horder, uorder), Ord2(horder, uorder), Ord2(horder, vorder), Ord2(horder, vorder) }; double integral = 0; for (int face = 0; face < Hex::NUM_FACES; face++) { Ord2 order = face_order[face]; int np = quad.get_face_num_points(face, order); QuadPt3D *pt = quad.get_face_points(face, order); for (int i = 0; i < np; i++) integral += fn(pt[i].x, pt[i].y, pt[i].z) * pt[i].w; } double err = fabs(exact - integral); if (err >= EPS) { info(" ... failed for order (h = %d, v = %d, u = %d), integral = %lf, expected = %lf (diff = %e).", horder, vorder, uorder, integral, exact, fabs(integral - exact)); return ERR_FAILURE; } } } } info(" ... OK."); return ERR_SUCCESS; }
// // BC: Normal velocity component is zero on solid walls. // Subsonic state prescribed on inlet and outlet. // // IC: Constant subsonic state identical to inlet. // // The following parameters can be changed: // Experimental caching of vector valued (vector) forms. #define HERMES_USE_VECTOR_VALUED_FORMS // Calculation of approximation of time derivative (and its output). // Setting this option to false saves the computation time. const bool CALC_TIME_DER = true; const Ord2 P_INIT = Ord2(0,0); // Initial polynomial degree. const int INIT_REF_NUM = 4; // Number of initial uniform mesh refinements. double CFL = 0.8; // CFL value. double TAU = 1E-4; // Time step. MatrixSolverType matrix_solver = SOLVER_UMFPACK; // Possibilities: SOLVER_AMESOS, SOLVER_AZTECOO, SOLVER_MUMPS, // SOLVER_PARDISO, SOLVER_PETSC, SOLVER_SUPERLU, SOLVER_UMFPACK. // Equation parameters. double P_EXT = 2.5; // Exterior pressure (dimensionless). double RHO_EXT = 1.0; // Inlet density (dimensionless). double V1_EXT = 1.25; // Inlet x-velocity (dimensionless). double V2_EXT = 0.0; // Inlet y-velocity (dimensionless). double KAPPA = 1.4; // Kappa. double t = 0;
HcurlSpace::HcurlSpace(Mesh* mesh, int p_init, Shapeset* shapeset) : Space(mesh, shapeset, NULL, Ord2(p_init, p_init)) { _F_ init(shapeset, Ord2(p_init, p_init)); }
HcurlSpace::HcurlSpace(Mesh* mesh, EssentialBCs* essential_bcs, int p_init, Shapeset* shapeset) : Space(mesh, shapeset, essential_bcs, Ord2(p_init, p_init)) { _F_ init(shapeset, Ord2(p_init, p_init)); }
// Meaning: 0 - concentration is kept constant at the bottom of the domain. // at the beginning, concentration is equal throughout the whole // domain and is equal to the value at the bottom. // 1 - concentration is kept constant at the bottom of the domain. // at the beginning, concentration is zero throughout the domain. // 2 - concentration is kept constant at the inlet part of the domain. // at the beginning, concentration is zero throughout the domain. // If not said otherwise, zero Neumann condition is imposed on all parts of the boundary. unsigned int INITIAL_CONCENTRATION_STATE = 0; // Visualization. const bool HERMES_VISUALIZATION = false; // Set to "true" to enable Hermes OpenGL visualization. const bool VTK_OUTPUT = true; // Set to "true" to enable VTK output. const unsigned int EVERY_NTH_STEP = 50; // Set visual output for every nth step. const Ord2 P_INIT_FLOW = Ord2(0,0); // Polynomial degree for the Euler equations (for the flow). const Ord2 P_INIT_CONCENTRATION = Ord2(1,1); // Polynomial degree for the concentration. double CFL = 0.8; // CFL value. double TAU = 1E-4; // Time step. const MatrixSolverType matrix_solver = SOLVER_UMFPACK; // Possibilities: SOLVER_AMESOS, SOLVER_AZTECOO, SOLVER_MUMPS, // SOLVER_PETSC, SOLVER_SUPERLU, SOLVER_UMFPACK. unsigned int INIT_REF_NUM_FLOW = 2; // Number of initial uniform mesh refinements of the mesh for the flow. unsigned int INIT_REF_NUM_CONCENTRATION = 4;// Number of initial uniform mesh refinements of the mesh for the concentration. // Equation parameters. const double P_EXT = 2.5; // Exterior pressure (dimensionless). const double RHO_EXT = 1.0; // Inlet density (dimensionless). const double V1_EXT = 1.25; // Inlet x-velocity (dimensionless). const double V2_EXT = 0.0; // Inlet y-velocity (dimensionless).
H1Space::H1Space(Mesh* mesh, BCTypes* bc_types, BCValues* bc_values, int p_init, Shapeset* shapeset) : Space(mesh, shapeset, bc_types, bc_values, Ord2(p_init, p_init)) { _F_ init(shapeset, Ord2(p_init, p_init)); }
HdivSpace::HdivSpace(Mesh* mesh, BCTypes* bc_types, int p_init, Shapeset* shapeset) : Space(mesh, shapeset, bc_types, (BCValues*) NULL, Ord2(p_init, p_init)) { init(shapeset, Ord2(p_init, p_init)); }
int main(int argc, char* argv[]) { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("square.mesh", &mesh); //mloader.load("square-tri.mesh", &mesh); // Perform initial mesh refinements. for (int i=0; i<INIT_REF; i++) mesh.refine_all_elements(); // Create an L2 space with default shapeset. L2Space space(&mesh, bc_types, NULL, Ord2(P_H, P_V)); int ndof = Space::get_num_dofs(&space); info("ndof = %d", ndof); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(bilinear_form)); wf.add_vector_form(callback(linear_form)); wf.add_matrix_form_surf(callback(bilinear_form_boundary), H2D_DG_BOUNDARY_EDGE); wf.add_vector_form_surf(callback(linear_form_boundary), H2D_DG_BOUNDARY_EDGE); wf.add_matrix_form_surf(callback(bilinear_form_interface), H2D_DG_INNER_EDGE); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the preconditioner in the case of SOLVER_AZTECOO. if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Initialize the solution. Solution sln; // Assemble the stiffness matrix and right-hand side vector. info("Assembling the stiffness matrix and right-hand side vector."); dp.assemble(matrix, rhs); // Solve the linear system and if successful, obtain the solution. info("Solving the matrix problem."); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Clean up. delete solver; delete matrix; delete rhs; // Visualize the solution. ScalarView view1("Solution", new WinGeom(860, 0, 400, 350)); view1.show(&sln); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { /* So far the DG assembling is very slow for higher order polynomials, so only constant functions are used here. if(argc < 3) error("Too few arguments in example-euler-gamm-explicit"); Ord2 P_INIT= Ord2(atoi(argv[1]), atoi(argv[2])); */ Ord2 P_INIT= Ord2(0, 0); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("GAMM-channel.mesh", &mesh); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); mesh.refine_towards_boundary(1, 1); mesh.refine_element_id(1053); mesh.refine_element_id(1054); mesh.refine_element_id(1087); mesh.refine_element_id(1088); mesh.refine_element_id(1117); mesh.refine_element_id(1118); mesh.refine_element_id(1151); mesh.refine_element_id(1152); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_neumann(Hermes::vector<int>(BDY_SOLID_WALL, BDY_INLET_OUTLET)); // Create L2 spaces with default shapesets. L2Space space_rho(&mesh, &bc_types, P_INIT); L2Space space_rho_v_x(&mesh, &bc_types, P_INIT); L2Space space_rho_v_y(&mesh, &bc_types, P_INIT); L2Space space_e(&mesh, &bc_types, P_INIT); // Initialize solutions, set initial conditions. Solution sln_rho, sln_rho_v_x, sln_rho_v_y, sln_e, prev_rho, prev_rho_v_x, prev_rho_v_y, prev_e; sln_rho.set_exact(&mesh, ic_density); sln_rho_v_x.set_exact(&mesh, ic_density_vel_x); sln_rho_v_y.set_exact(&mesh, ic_density_vel_y); sln_e.set_exact(&mesh, ic_energy); prev_rho.set_exact(&mesh, ic_density); prev_rho_v_x.set_exact(&mesh, ic_density_vel_x); prev_rho_v_y.set_exact(&mesh, ic_density_vel_y); prev_e.set_exact(&mesh, ic_energy); // Initialize weak formulation. WeakForm wf(4); // Bilinear forms coming from time discretization by explicit Euler's method. wf.add_matrix_form(0, 0, callback(bilinear_form_0_0_time)); wf.add_matrix_form(1, 1, callback(bilinear_form_1_1_time)); wf.add_matrix_form(2, 2, callback(bilinear_form_2_2_time)); wf.add_matrix_form(3, 3, callback(bilinear_form_3_3_time)); // Volumetric linear forms. // Linear forms coming from the linearization by taking the Eulerian fluxes' Jacobian matrices // from the previous time step. // Unnecessary for FVM. if(P_INIT.order_h > 0 || P_INIT.order_v > 0) { // First flux. wf.add_vector_form(0, callback(linear_form_0_1), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho_v_x)); wf.add_vector_form(1, callback(linear_form_1_0_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(1, callback(linear_form_1_1_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(1, callback(linear_form_1_2_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(1, callback(linear_form_1_3_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(2, callback(linear_form_2_0_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(2, callback(linear_form_2_1_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(2, callback(linear_form_2_2_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(2, callback(linear_form_2_3_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(3, callback(linear_form_3_0_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(3, callback(linear_form_3_1_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(3, callback(linear_form_3_2_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(3, callback(linear_form_3_3_first_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); // Second flux. wf.add_vector_form(0, callback(linear_form_0_2), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho_v_y)); wf.add_vector_form(1, callback(linear_form_1_0_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(1, callback(linear_form_1_1_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(1, callback(linear_form_1_2_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(1, callback(linear_form_1_3_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(2, callback(linear_form_2_0_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(2, callback(linear_form_2_1_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(2, callback(linear_form_2_2_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y)); wf.add_vector_form(2, callback(linear_form_2_3_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(3, callback(linear_form_3_0_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(3, callback(linear_form_3_1_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(3, callback(linear_form_3_2_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form(3, callback(linear_form_3_3_second_flux), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); } // Volumetric linear forms coming from the time discretization. wf.add_vector_form(0, linear_form, linear_form_order, HERMES_ANY, &prev_rho); wf.add_vector_form(1, linear_form, linear_form_order, HERMES_ANY, &prev_rho_v_x); wf.add_vector_form(2, linear_form, linear_form_order, HERMES_ANY, &prev_rho_v_y); wf.add_vector_form(3, linear_form, linear_form_order, HERMES_ANY, &prev_e); // Surface linear forms - inner edges coming from the DG formulation. wf.add_vector_form_surf(0, linear_form_interface_0, linear_form_order, H2D_DG_INNER_EDGE, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(1, linear_form_interface_1, linear_form_order, H2D_DG_INNER_EDGE, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(2, linear_form_interface_2, linear_form_order, H2D_DG_INNER_EDGE, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(3, linear_form_interface_3, linear_form_order, H2D_DG_INNER_EDGE, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); // Surface linear forms - inlet / outlet edges. wf.add_vector_form_surf(0, bdy_flux_inlet_outlet_comp_0, linear_form_order, BDY_INLET_OUTLET, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(1, bdy_flux_inlet_outlet_comp_1, linear_form_order, BDY_INLET_OUTLET, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(2, bdy_flux_inlet_outlet_comp_2, linear_form_order, BDY_INLET_OUTLET, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(3, bdy_flux_inlet_outlet_comp_3, linear_form_order, BDY_INLET_OUTLET, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); // Surface linear forms - Solid wall edges. wf.add_vector_form_surf(0, bdy_flux_solid_wall_comp_0, linear_form_order, BDY_SOLID_WALL, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(1, bdy_flux_solid_wall_comp_1, linear_form_order, BDY_SOLID_WALL, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(2, bdy_flux_solid_wall_comp_2, linear_form_order, BDY_SOLID_WALL, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); wf.add_vector_form_surf(3, bdy_flux_solid_wall_comp_3, linear_form_order, BDY_SOLID_WALL, Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, Hermes::vector<Space*>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), is_linear); // If the FE problem is in fact a FV problem. if(P_INIT.order_h == 0 && P_INIT.order_v == 0) dp.set_fvm(); // Iteration number. int iteration = 0; // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // For testing purposes. double l2_norms[5][4]; for(unsigned int i = 0; i < 5; i++) for(unsigned int j = 0; j < 4; j++) l2_norms[i][j] = 0.0; double point_values[5][3]; for(unsigned int i = 0; i < 5; i++) for(unsigned int j = 0; j < 3; j++) point_values[i][j] = 0.0; // Calculate the special point where we will evaluate the solution. double x = 0.75; double y = sqrt((double)(1.-x*x)) + 0.001; for(unsigned int time_step = 0; time_step < 5; time_step++) { iteration++; bool rhs_only = (iteration == 1 ? false : true); // Assemble stiffness matrix and rhs or just rhs. if (rhs_only == false) info("Assembling the stiffness matrix and right-hand side vector."); else info("Assembling the right-hand side vector (only)."); dp.assemble(matrix, rhs, rhs_only); // Solve the matrix problem. info("Solving the matrix problem."); if(solver->solve()) Solution::vector_to_solutions(solver->get_solution(), Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), Hermes::vector<Solution *>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e)); else error ("Matrix solver failed.\n"); // Approximate the time derivative of the solution. if(CALC_TIME_DER) { Adapt *adapt_for_time_der_calc = new Adapt(Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e)); bool solutions_for_adapt = false; double difference = iteration == 1 ? 0 : adapt_for_time_der_calc->calc_err_est(Hermes::vector<Solution *>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), Hermes::vector<Solution *>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e), (Hermes::vector<double>*) NULL, solutions_for_adapt, HERMES_TOTAL_ERROR_ABS | HERMES_ELEMENT_ERROR_ABS) / TAU; delete adapt_for_time_der_calc; } // Determine the time step according to the CFL condition. // Only mean values on an element of each solution component are taken into account. double *solution_vector = solver->get_solution(); double min_condition = 0; Element *e; for (int _id = 0, _max = mesh.get_max_element_id(); _id < _max; _id++) \ if (((e) = mesh.get_element_fast(_id))->used) \ if ((e)->active) { AsmList al; space_rho.get_element_assembly_list(e, &al); double rho = solution_vector[al.dof[0]]; space_rho_v_x.get_element_assembly_list(e, &al); double v1 = solution_vector[al.dof[0]] / rho; space_rho_v_y.get_element_assembly_list(e, &al); double v2 = solution_vector[al.dof[0]] / rho; space_e.get_element_assembly_list(e, &al); double energy = solution_vector[al.dof[0]]; double condition = e->get_area() / (std::sqrt(v1*v1 + v2*v2) + calc_sound_speed(rho, rho*v1, rho*v2, energy)); if(condition < min_condition || min_condition == 0.) min_condition = condition; } if(TAU > min_condition) TAU = min_condition; if(TAU < min_condition * 0.9) TAU = min_condition; // Storing the testing values. for(unsigned int j = 0; j < 4; j++) for(unsigned int k = j*space_rho.get_num_dofs(); k < (j+1)*space_rho.get_num_dofs(); k++) l2_norms[time_step][j] += solver->get_solution()[k]; point_values[time_step][0] = sln_rho_v_x.get_pt_value(0.5, 0.001); point_values[time_step][1] = sln_rho_v_x.get_pt_value(x, y); point_values[time_step][2] = sln_rho_v_x.get_pt_value(1.5, 0.001); // Copy the solutions into the previous time level ones. prev_rho.copy(&sln_rho); prev_rho_v_x.copy(&sln_rho_v_x); prev_rho_v_y.copy(&sln_rho_v_y); prev_e.copy(&sln_e); } bool okay = true; switch(P_INIT.order_h* 10 + P_INIT.order_v) { case 0: if(std::abs(l2_norms[0][0] - 888.0) > 1E-8) okay = false; if(std::abs(l2_norms[0][1] - 1110) > 1E-8) okay = false; if(std::abs(l2_norms[0][2]) > 1E-8) okay = false; if(std::abs(l2_norms[0][3] - 6243.75) > 1E-8) okay = false; if(std::abs(l2_norms[1][0] - 887.99997637865545) > 1E-8) okay = false; if(std::abs(l2_norms[1][1] - 1109.9997956458228) > 1E-8) okay = false; if(std::abs(l2_norms[1][2] - 3.1927018090871903e-008) > 1E-8) okay = false; if(std::abs(l2_norms[1][3] - 6243.7496921971369) > 1E-8) okay = false; if(std::abs(l2_norms[2][0] - 887.99993429457072) > 1E-8) okay = false; if(std::abs(l2_norms[2][1] - 1109.9994322038613) > 1E-8) okay = false; if(std::abs(l2_norms[2][2] + 5.3556469633245445e-008) > 1E-8) okay = false; if(std::abs(l2_norms[2][3] - 6243.7491437826511) > 1E-8) okay = false; if(std::abs(l2_norms[3][0] - 887.99987376550200) > 1E-8) okay = false; if(std::abs(l2_norms[3][1] - 1109.9989102977672) > 1E-8) okay = false; if(std::abs(l2_norms[3][2] + 3.6958140470412712e-007) > 1E-8) okay = false; if(std::abs(l2_norms[3][3] - 6243.7483549661320) > 1E-8) okay = false; if(std::abs(l2_norms[4][0] - 887.99979481320088) > 1E-8) okay = false; if(std::abs(l2_norms[4][1] - 1109.9982305630808) > 1E-8) okay = false; if(std::abs(l2_norms[4][2] + 1.0303296924184822e-006) > 1E-8) okay = false; if(std::abs(l2_norms[4][3] - 6243.7473260085462) > 1E-8) okay = false; // points if(std::abs(point_values[0][0] - 1.25) > 1E-8) okay = false; if(std::abs(point_values[0][1] - 1.25) > 1E-8) okay = false; if(std::abs(point_values[0][2] - 1.2459744738974898) > 1E-8) okay = false; if(std::abs(point_values[1][0] - 1.2499951035194972) > 1E-8) okay = false; if(std::abs(point_values[1][1] - 1.25) > 1E-8) okay = false; if(std::abs(point_values[1][2] - 1.2428402692519325) > 1E-8) okay = false; if(std::abs(point_values[2][0] - 1.2499864002215795) > 1E-8) okay = false; if(std::abs(point_values[2][1] - 1.25) > 1E-8) okay = false; if(std::abs(point_values[2][2] - 1.2397180160697001) > 1E-8) okay = false; if(std::abs(point_values[3][0] - 1.2499739085927257) > 1E-8) okay = false; if(std::abs(point_values[3][1] - 1.25) > 1E-8) okay = false; if(std::abs(point_values[3][2] - 1.2366079101139087) > 1E-8) okay = false; if(std::abs(point_values[4][0] - 1.2499576472516911) > 1E-8) okay = false; if(std::abs(point_values[4][1] - 1.25) > 1E-8) okay = false; if(std::abs(point_values[4][2] - 1.2335101392959738) > 1E-8) okay = false; break; } if (okay) { // ndofs was 908 at the time this test was created printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("square.mesh", &mesh); // Perform initial mesh refinements. for (int i=0; i<INIT_REF; i++) mesh.refine_all_elements(); // Create an L2 space with default shapeset. L2Space space(&mesh, bc_types, NULL, Ord2(P_H, P_V)); int ndof = Space::get_num_dofs(&space); info("ndof = %d", ndof); // Initialize the weak formulation. WeakForm wf; wf.add_matrix_form(callback(bilinear_form)); wf.add_vector_form(callback(linear_form)); wf.add_matrix_form_surf(callback(bilinear_form_boundary), H2D_DG_BOUNDARY_EDGE); wf.add_vector_form_surf(callback(linear_form_boundary), H2D_DG_BOUNDARY_EDGE); wf.add_matrix_form_surf(callback(bilinear_form_interface), H2D_DG_INNER_EDGE); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the preconditioner in the case of SOLVER_AZTECOO. if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Initialize the solution. Solution sln; // Assemble the stiffness matrix and right-hand side vector. info("Assembling the stiffness matrix and right-hand side vector."); dp.assemble(matrix, rhs); // Solve the linear system and if successful, obtain the solution. info("Solving the matrix problem."); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); // Time measurement. cpu_time.tick(); // Clean up. delete solver; delete matrix; delete rhs; info("ndof = %d", ndof); info("Coordinate ( 0.1, 0.1) value = %lf", sln.get_pt_value(0.1, 0.1)); info("Coordinate ( 0.3, 0.3) value = %lf", sln.get_pt_value(0.3, 0.3)); info("Coordinate ( 0.5, 0.5) value = %lf", sln.get_pt_value(0.5, 0.5)); info("Coordinate ( 0.7, 0.7) value = %lf", sln.get_pt_value(0.7, 0.7)); double coor_xy[4] = {0.1, 0.3, 0.5, 0.7}; double value[4] = {0.999885, 0.844340, 0.000000, 0.000000}; for (int i = 0; i < 4; i++) { if ((value[i] - sln.get_pt_value(coor_xy[i], coor_xy[i])) < 1E-6) { printf("Success!\n"); } else { printf("Failure!\n"); return ERR_FAILURE; } } return ERR_SUCCESS; }