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; }
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* argv[]) { bool success = true; HermesCommonApi.set_integral_param_value(numThreads, 1); // Load the mesh. MeshSharedPtr mesh(new Mesh); Hermes::Hermes2D::MeshReaderH2DXML mloader; mloader.load("domain.xml", mesh); mesh->refine_element_id(0); mesh->refine_element_id(2, 1); mesh->refine_all_elements(); mesh->refine_all_elements(); mesh->refine_all_elements(); // Initialize essential boundary conditions. Hermes::Hermes2D::DefaultEssentialBCConst<double> bc_essential_r("Bdy", 0.); Hermes::Hermes2D::DefaultEssentialBCConst<complex> bc_essential_c("Bdy", complex(.132, -.12)); Hermes::Hermes2D::EssentialBCs<double> bcs_r(&bc_essential_r); Hermes::Hermes2D::EssentialBCs<complex> bcs_c(&bc_essential_c); // Initialize space. SpaceSharedPtr<double> space_r( new Hermes::Hermes2D::H1Space<double>(mesh, &bcs_r, 2)); SpaceSharedPtr<double> space_l2( new Hermes::Hermes2D::L2Space<double>(mesh, 0)); SpaceSharedPtr<complex> space_c( new Hermes::Hermes2D::H1Space<complex>(mesh, &bcs_c, 2)); // Initialize the weak formulation. WeakFormsH1::DefaultWeakFormPoissonLinear<double> wf_r(HERMES_ANY, nullptr); WeakFormsH1::DefaultWeakFormPoissonLinear<complex> wf_c(HERMES_ANY, nullptr); // Initialize the solution. MeshFunctionSharedPtr<double> sln_r(new Solution<double>); MeshFunctionSharedPtr<double> sln1_r(new Solution<double>); MeshFunctionSharedPtr<double> sln2_r(new Solution<double>); MeshFunctionSharedPtr<complex> sln_c(new Solution<complex>); MeshFunctionSharedPtr<complex> sln1_c(new Solution<complex>); MeshFunctionSharedPtr<complex> sln2_c(new Solution<complex>); // Initialize linear solver. Hermes::Hermes2D::LinearSolver<double> linear_solver_r(&wf_r, space_r); Hermes::Hermes2D::LinearSolver<complex> linear_solver_c(&wf_c, space_c); #ifdef SHOW_OUTPUT Views::ScalarView s; #endif // 1st - save & load real solution. linear_solver_r.solve(); Solution<double>::vector_to_solution(linear_solver_r.get_sln_vector(), space_r, sln_r); sln_r.get_solution()->save("saved_sln_r.xml"); sln1_r.get_solution()->load("saved_sln_r.xml", space_r); sln1_r.get_solution()->save("saved_sln_r-final.xml"); #ifdef SHOW_OUTPUT s.set_title("Real - Original"); s.show(sln_r); s.wait_for_keypress(); s.set_title("Real - XML"); s.show(sln1_r); s.wait_for_keypress(); #endif #ifdef WITH_BSON sln1_r.get_solution()->save_bson("saved_sln_r.bson"); sln2_r.get_solution()->load_bson("saved_sln_r.bson", space_r); sln2_r.get_solution()->save_bson("saved_sln_r-final.bson"); #ifdef SHOW_OUTPUT s.set_title("Real - BSON"); s.show(sln2_r); s.wait_for_keypress(); #endif #endif // 2nd - save & load complex one. linear_solver_c.solve(); Solution<complex>::vector_to_solution(linear_solver_c.get_sln_vector(), space_c, sln_c); sln_c.get_solution()->save("saved_sln_c.xml"); sln1_c.get_solution()->load("saved_sln_c.xml", space_c); sln1_c.get_solution()->save("saved_sln_c-final.xml"); #ifdef SHOW_OUTPUT MeshFunctionSharedPtr<double> filter(new RealFilter(sln_c)); MeshFunctionSharedPtr<double> filter_1(new RealFilter(sln1_c)); s.set_title("Complex - Original"); s.show(filter); s.wait_for_keypress(); s.set_title("Complex - XML"); s.show(filter_1); s.wait_for_keypress(); #endif #ifdef WITH_BSON sln1_c.get_solution()->save_bson("saved_sln_c.bson"); sln2_c.get_solution()->load_bson("saved_sln_c.bson", space_c); sln2_c.get_solution()->save_bson("saved_sln_c-final.bson"); MeshFunctionSharedPtr<double> filter_2(new RealFilter(sln2_c)); #ifdef SHOW_OUTPUT s.set_title("Complex - BSON"); s.show(filter_2); s.wait_for_keypress(); #endif #endif // 3th - save & load constant one. // 3.1 - bad one. MeshFunctionSharedPtr<double> initial_condition_bad(new CustomInitialCondition(mesh)); bool local_success = false; try { initial_condition_bad.get_solution()->save("this-will-fail"); } catch(Hermes::Exceptions::Exception& e) { local_success = true; std::string s = "Arbitrary exact solution can not be saved to disk. Only constant one can. Project to a space to get a saveable solution."; std::string s1 = e.info(); if(s.compare(s1)) success = false; } if(!local_success) { throw Exceptions::Exception("Exception not caught correctly."); success = false; } // 3.2 - good one. MeshFunctionSharedPtr<double> initial_condition_good(new ConstantSolution<double>(mesh, 3.1415926)); MeshFunctionSharedPtr<double> test_solution_1(new Solution<double>()); MeshFunctionSharedPtr<double> test_solution_2(new Solution<double>()); initial_condition_good.get_solution()->save("constant_sln.xml"); test_solution_1.get_solution()->load("constant_sln.xml", space_l2); test_solution_1.get_solution()->save("constant_sln-final.xml"); #ifdef SHOW_OUTPUT s.set_title("Exact - Original"); s.show(initial_condition_good); s.wait_for_keypress(); s.set_title("Exact - XML"); s.show(test_solution_1); s.wait_for_keypress(); #endif #ifdef WITH_BSON initial_condition_good.get_solution()->save_bson("constant_sln.bson"); test_solution_2.get_solution()->load_bson("constant_sln.bson", space_l2); test_solution_2.get_solution()->save_bson("constant_sln-final.bson"); #ifdef SHOW_OUTPUT s.set_title("Exact - BSON"); s.show(test_solution_2); s.wait_for_keypress(); #endif #endif /// \todo re-do the test files, but with some higher precision of stored numbers, this way it usually crashes on different truncation /* #if defined (_WINDOWS) || defined (WIN32) || defined (_MSC_VER) success = Testing::compare_files("saved_sln_r-final.xml", "win\\saved_sln_r-template.xml") && success; success = Testing::compare_files("saved_sln_r-final.bson", "win\\saved_sln_r-template.bson") && success; success = Testing::compare_files("saved_sln_c-final.xml", "win\\saved_sln_c-template.xml") && success; success = Testing::compare_files("saved_sln_c-final.bson", "win\\saved_sln_c-template.bson") && success; success = Testing::compare_files("constant_sln-final.xml", "win\\constant_sln-template.xml") && success; success = Testing::compare_files("constant_sln-final.bson", "win\\constant_sln-template.bson") && success; #else success = Testing::compare_files("saved_sln_r-final.xml", "linux/saved_sln_r-template.xml") && success; success = Testing::compare_files("saved_sln_r-final.bson", "linux/saved_sln_r-template.bson") && success; success = Testing::compare_files("saved_sln_c-final.xml", "linux/saved_sln_c-template.xml") && success; success = Testing::compare_files("saved_sln_c-final.bson", "linux/saved_sln_c-template.bson") && success; success = Testing::compare_files("constant_sln-final.xml", "linux/constant_sln-template.xml") && success; success = Testing::compare_files("constant_sln-final.bson", "linux/constant_sln-template.bson") && success; #endif */ if(success) { printf("Success!"); return 0; } else { printf("Failure!"); return -1; } }