int main(int argc, char* argv[]) { // Load the mesh. MeshSharedPtr mesh(new Mesh); if (USE_XML_FORMAT == true) { MeshReaderH2DXML mloader; Hermes::Mixins::Loggable::Static::info("Reading mesh in XML format."); try { mloader.load("domain.xml", mesh); } catch(Hermes::Exceptions::Exception& e) { e.print_msg(); } } else { MeshReaderH2D mloader; Hermes::Mixins::Loggable::Static::info("Reading mesh in original format."); 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 Hermes1DFunction<double>(LAMBDA_AL), "Copper", new Hermes1DFunction<double>(LAMBDA_CU), new Hermes2DFunction<double>(-VOLUME_HEAT_SRC)); // Initialize essential boundary conditions. DefaultEssentialBCConst<double> bc_essential( Hermes::vector<std::string>("Bottom", "Inner", "Outer", "Left"), FIXED_BDY_TEMP); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT)); int ndof = space->get_num_dofs(); Hermes::Mixins::Loggable::Static::info("ndof = %d", ndof); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, space); // Initialize Newton solver. NewtonSolver<double> newton(&dp); // Perform Newton's iteration. try { // When newton.solve() is used without any parameters, this means that the initial coefficient // vector will be the zero vector, tolerance will be 1e-8, maximum allowed number of iterations // will be 100, and residual will be measured using Euclidean vector norm. newton.solve(); } catch(std::exception& e) { std::cout << e.what(); } // Translate the resulting coefficient vector into a Solution. MeshFunctionSharedPtr<double> sln(new Solution<double>); Solution<double>::vector_to_solution(newton.get_sln_vector(), space, sln); // VTK output. if (VTK_VISUALIZATION) { // Output solution in VTK format. Linearizer lin; bool mode_3D = true; lin.save_solution_vtk(sln, "sln.vtk", "Temperature", mode_3D); Hermes::Mixins::Loggable::Static::info("Solution in VTK format saved to file %s.", "sln.vtk"); // Output mesh and element orders in VTK format. Orderizer ord; ord.save_orders_vtk(space, "ord.vtk"); Hermes::Mixins::Loggable::Static::info("Element orders in VTK format saved to file %s.", "ord.vtk"); } // Visualize the solution. if (HERMES_VISUALIZATION) { ScalarView view("Solution", new WinGeom(0, 0, 440, 350)); // Hermes uses adaptive FEM to approximate higher-order FE solutions with linear // triangles for OpenGL. The second parameter of View::show() sets the error // tolerance for that. Options are HERMES_EPS_LOW, HERMES_EPS_NORMAL (default), // HERMES_EPS_HIGH and HERMES_EPS_VERYHIGH. The size of the graphics file grows // considerably with more accurate representation, so use it wisely. view.show(sln, HERMES_EPS_HIGH); View::wait(); } return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("motor.mesh", &mesh); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_dirichlet(Hermes::vector<int>(OUTER_BDY, STATOR_BDY)); // Enter Dirichlet boundary values. BCValues bc_values; bc_values.add_const(STATOR_BDY, VOLTAGE); bc_values.add_const(OUTER_BDY, 0.0); // Create an H1 space with default shapeset. H1Space space(&mesh, &bc_types, &bc_values, P_INIT); // Initialize the weak formulation. int adapt_order_increase = 1; double adapt_rel_error_tol = 1e1; WeakForm wf; if (ADAPTIVE_QUADRATURE) { info("Adaptive quadrature ON."); wf.add_matrix_form(biform1, HERMES_SYM, MATERIAL_1, Hermes::vector<MeshFunction*>(), adapt_order_increase, adapt_rel_error_tol); wf.add_matrix_form(biform2, HERMES_SYM, MATERIAL_2, Hermes::vector<MeshFunction*>(), adapt_order_increase, adapt_rel_error_tol); } else { info("Adaptive quadrature OFF."); wf.add_matrix_form(callback(biform1), HERMES_SYM, MATERIAL_1); wf.add_matrix_form(callback(biform2), HERMES_SYM, MATERIAL_2); } // Initialize coarse and reference mesh solution. Solution sln, ref_sln; // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 410, 600)); sview.fix_scale_width(50); sview.show_mesh(false); OrderView oview("Polynomial orders", new WinGeom(420, 0, 400, 600)); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = construct_refined_space(&space); // Initialize matrix solver. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Assemble reference problem. info("Solving on reference mesh."); bool is_linear = true; DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear); dp->assemble(matrix, rhs); // Time measurement. cpu_time.tick(); // Solve the linear system of the reference problem. // If successful, obtain the solution. if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln); else error ("Matrix solver failed.\n"); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Time measurement. cpu_time.tick(); // VTK output. if (VTK_OUTPUT) { // Output solution in VTK format. Linearizer lin; char* title = new char[100]; sprintf(title, "sln-%d.vtk", as); lin.save_solution_vtk(&sln, title, "Potential", false); info("Solution in VTK format saved to file %s.", title); // Output mesh and element orders in VTK format. Orderizer ord; sprintf(title, "ord-%d.vtk", as); ord.save_orders_vtk(&space, title); info("Element orders in VTK format saved to file %s.", title); } // View the coarse mesh solution and polynomial orders. if (HERMES_VISUALIZATION) { sview.show(&sln); oview.show(&space); } // Skip visualization time. cpu_time.tick(HERMES_SKIP); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt* adaptivity = new Adapt(&space); bool solutions_for_adapt = true; // In the following function, the Boolean parameter "solutions_for_adapt" determines whether // the calculated errors are intended for use with adaptivity (this may not be the case, for example, // when error wrt. an exact solution is calculated). The default value is solutions_for_adapt = true, // The last parameter "error_flags" determine whether the total and element errors are treated as // absolute or relative. Its default value is error_flags = HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL. // In subsequent examples and benchmarks, these two parameters will be often used with // their default values, and thus they will not be present in the code explicitly. double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_est_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) delete ref_space->get_mesh(); delete ref_space; delete dp; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); // Show the reference solution - the final result. sview.set_title("Fine mesh solution"); sview.show_mesh(false); sview.show(&ref_sln); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; if (USE_XML_FORMAT == true) { MeshReaderH2DXML mloader; info("Reading mesh in XML format."); mloader.load("domain.xml", &mesh); } else { MeshReaderH2D mloader; info("Reading mesh in original format."); mloader.load("domain.mesh", &mesh); } // Perform initial mesh refinements. for(int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize boundary conditions DefaultEssentialBCConst<double> bc_essential("Bottom", T1); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the weak formulation. CustomWeakFormPoissonNewton wf(LAMBDA, ALPHA, T0, "Heat_flux"); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, &space); // Initial coefficient vector for the Newton's method. double* coeff_vec = new double[ndof]; memset(coeff_vec, 0, ndof*sizeof(double)); // Initialize Newton solver. NewtonSolver<double> newton(&dp, matrix_solver); // Perform Newton's iteration. try { newton.solve(coeff_vec); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); error("Newton's iteration failed."); } // Translate the resulting coefficient vector into a Solution. Solution<double> sln; Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln); // VTK output. if (VTK_VISUALIZATION) { // Output solution in VTK format. Linearizer lin; bool mode_3D = true; lin.save_solution_vtk(&sln, "sln.vtk", "Temperature", mode_3D); info("Solution in VTK format saved to file %s.", "sln.vtk"); // Output mesh and element orders in VTK format. Orderizer ord; ord.save_orders_vtk(&space, "ord.vtk"); info("Element orders in VTK format saved to file %s.", "ord.vtk"); } // Visualize the solution. if (HERMES_VISUALIZATION) { ScalarView view("Solution", new WinGeom(0, 0, 440, 350)); // Hermes uses adaptive FEM to approximate higher-order FE solutions with linear // triangles for OpenGL. The second parameter of View::show() sets the error // tolerance for that. Options are HERMES_EPS_LOW, HERMES_EPS_NORMAL (default), // HERMES_EPS_HIGH and HERMES_EPS_VERYHIGH. The size of the graphics file grows // considerably with more accurate representation, so use it wisely. view.show(&sln, HERMES_EPS_HIGH); View::wait(); } // Clean up. delete [] coeff_vec; return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh, basemesh; MeshReaderH2D mloader; mloader.load("domain.mesh", &basemesh); /* MeshView meshview("mesh", new WinGeom(0, 0, 500, 400)); meshview.show(&basemesh); View::wait();*/ // Perform initial mesh refinements (optional). for (int i=0; i < INIT_REF_NUM; i++) basemesh.refine_all_elements(); mesh.copy(&basemesh); // Initialize boundary conditions. DefaultEssentialBCConst<double> bc_essential(BDY_IN, 0.0); EssentialBCs<double> bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space<double> space(&mesh, &bcs, P_INIT); // Initialize solution of lower & higher order Solution<double> low_sln, ref_sln, high_sln, sln; PrevSolution u_prev_time; // Previous time level solution (initialized by the initial condition). CustomInitialCondition initial_condition(&mesh); // Initialize the weak formulation. CustomWeakFormMassmatrix massmatrix(time_step); CustomWeakFormConvection convection; // Initialize views. ScalarView sview("Solution", new WinGeom(0, 500, 500, 400)); OrderView mview("mesh", new WinGeom(0, 0, 500, 400)); OrderView ref_mview("ref_mesh", new WinGeom(500, 0, 500, 400)); char title[100]; // Output solution in VTK format. Linearizer lin; Orderizer ord; bool mode_3D = true; // Create a refinement selector. H1ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); //Initialize UMFPackMatrix<double> * mass_matrix = new UMFPackMatrix<double> ; //M_c/tau UMFPackMatrix<double> * conv_matrix = new UMFPackMatrix<double> ; //K double* u_L = NULL; double* u_H =NULL; double* ref_sln_double =NULL; int ref_ndof, ndof; double err_est_rel_total; Adapt<double> adaptivity(&space, HERMES_L2_NORM); OGProjection<double> ogProjection; Lumped_Projection lumpedProjection; Low_Order lowOrder(theta); High_Order highOrd(theta); Flux_Correction fluxCorrection(theta); Regularity_Estimator regEst(EPS_smooth); DiscreteProblem<double> dp_mass(&massmatrix, &space); DiscreteProblem<double> dp_convection(&convection, &space); // Time stepping loop: double current_time = 0.0; int ts = 1; do { Hermes::Mixins::Loggable::Static::info("Time step %d, time %3.5f", ts, current_time); Hermes::Hermes2D::Hermes2DApi.set_integral_param_value(Hermes::Hermes2D::numThreads,1); // Periodic global derefinement. if ((ts > 1 && ts % UNREF_FREQ == 0)||(space.get_num_dofs() >= NDOF_STOP)) { Hermes::Mixins::Loggable::Static::info("Global mesh derefinement."); switch (UNREF_METHOD) { case 1: mesh.copy(&basemesh); space.set_uniform_order(P_INIT); break; case 2: mesh.unrefine_all_elements(); space.set_uniform_order(P_INIT); break; case 3: mesh.unrefine_all_elements(); space.adjust_element_order(-1, -1, P_INIT, P_INIT); break; default: Exceptions::Exception("Wrong global derefinement method."); } } bool done = false; int as = 1; do { Hermes::Mixins::Loggable::Static::info("Time step %i, adap_step %i", ts, as); ndof = space.get_num_dofs(); //Unrefinement step /* if(as==1) { double* coeff_vec_smooth = new double[ndof]; if(ts==1) ogProjection.project_global(&space,&initial_condition, coeff_vec_smooth, HERMES_L2_NORM); else ogProjection.project_global(&space,&u_prev_time, coeff_vec_smooth, HERMES_L2_NORM); Solution<double>::vector_to_solution(coeff_vec_smooth, &space, &low_sln); // Calculate element errors and total error estimate. if(ts==1) err_est_rel_total = adaptivity.calc_err_est(&low_sln, &initial_condition) * 100; else err_est_rel_total = adaptivity.calc_err_est(&low_sln, &u_prev_time) * 100; adaptivity.unrefine(THRESHOLD_UNREF); delete [] coeff_vec_smooth; // Visualize the solution. if(HERMES_VISUALIZATION) { sprintf(title, "unrefined Mesh: Time %3.2f,timestep %i", current_time,ts); mview.set_title(title); mview.show(&space); } } */ ndof = space.get_num_dofs(); double* coeff_vec_smooth = new double[ndof]; int* smooth_elem_ref; //smoothness-check for projected data Hermes::Mixins::Loggable::Static::info("Projecting..."); if(ts==1) ogProjection.project_global(&space,&initial_condition, coeff_vec_smooth, HERMES_L2_NORM); else ogProjection.project_global(&space,&u_prev_time, coeff_vec_smooth, HERMES_L2_NORM); Hermes::Mixins::Loggable::Static::info("Calling get_smooth_elems()..."); smooth_elem_ref = regEst.get_smooth_elems(&space,coeff_vec_smooth); // Construct reference mesh and setup reference space. Mesh* ref_mesh = new Mesh; ref_mesh->copy(space.get_mesh()); Space<double>::ReferenceSpaceCreator ref_space_creator(&space, ref_mesh, 0); Space<double>* ref_space = ref_space_creator.create_ref_space(); HPAdapt * adapting = new HPAdapt(ref_space, HERMES_L2_NORM); // increase p in smooth regions, h refine in non-smooth regions Hermes::Mixins::Loggable::Static::info("Calling adapt_smooth()..."); if(adapting->adapt_smooth(smooth_elem_ref, P_MAX)==false) throw Exceptions::Exception("reference space couldn't be constructed"); delete adapting; delete [] coeff_vec_smooth; ref_ndof = ref_space->get_num_dofs(); Hermes::Mixins::Loggable::Static::info("Visualization..."); if(HERMES_VISUALIZATION) { sprintf(title, "Ref_Mesh: Time %3.2f,timestep %i,as=%i,", current_time,ts,as); ref_mview.set_title(title); ref_mview.show(ref_space); } dp_mass.set_space(ref_space); dp_convection.set_space(ref_space); fluxCorrection.init(ref_space); double* coeff_vec = new double[ref_ndof]; double* coeff_vec_2 = new double[ref_ndof]; double* limited_flux = new double[ref_ndof]; dp_mass.assemble(mass_matrix); //M_c/tau dp_convection.assemble(conv_matrix, NULL,true); //K //----------------------MassLumping & Artificial Diffusion -------------------------------------------------------------------- UMFPackMatrix<double>* lumped_matrix = fluxCorrection.massLumping(mass_matrix); // M_L/tau UMFPackMatrix<double>* diffusion = fluxCorrection.artificialDiffusion(conv_matrix); //-----------------Assembling of matrices --------------------------------------------------------------------- lowOrder.assemble_Low_Order(conv_matrix,diffusion,lumped_matrix); highOrd.assemble_High_Order(conv_matrix,mass_matrix); mass_matrix->multiply_with_Scalar(time_step); // massmatrix = M_C lumped_matrix->multiply_with_Scalar(time_step); // M_L //--------- Project the previous timestep solution on the FE space (FCT is applied )---------------- // coeff_vec : FCT -Projection, coeff_vec_2: L2 Projection (ogProjection) if(ts==1) fluxCorrection.project_FCT(&initial_condition, coeff_vec, coeff_vec_2,mass_matrix,lumped_matrix,time_step,&ogProjection,&lumpedProjection, ®Est); else fluxCorrection.project_FCT(&u_prev_time, coeff_vec, coeff_vec_2,mass_matrix,lumped_matrix,time_step,&ogProjection,&lumpedProjection, ®Est); //------------------------- lower order solution------------ u_L = lowOrder.solve_Low_Order(lumped_matrix, coeff_vec,time_step); //-------------high order solution (standard galerkin) ------ u_H = highOrd.solve_High_Order(coeff_vec); //------------------------------Assemble antidiffusive fluxes and limit these----------------------------------- fluxCorrection.antidiffusiveFlux(mass_matrix,lumped_matrix,conv_matrix,diffusion,u_H, u_L,coeff_vec, limited_flux,time_step,®Est); //-------------Compute final solution --------------- ref_sln_double = lowOrder.explicit_Correction(limited_flux); Solution<double> ::vector_to_solution(ref_sln_double, ref_space, &ref_sln); // Project the fine mesh solution onto the coarse mesh. ogProjection.project_global(&space, &ref_sln, &sln, HERMES_L2_NORM); // Calculate element errors and total error estimate. err_est_rel_total = adaptivity.calc_err_est(&sln, &ref_sln) * 100; // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", ndof,ref_ndof, err_est_rel_total); // If err_est_rel too large, adapt the mesh. if((err_est_rel_total < ERR_STOP)||(as>=ADAPSTEP_MAX)) done = true; else { done = adaptivity.adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if(done == false) as++; } if(space.get_num_dofs() >= NDOF_STOP) done = true; if(done) { u_prev_time.copy(&ref_sln); u_prev_time.set_own_mesh(ref_mesh); //ref_mesh can be deleted } // Visualize the solution and mesh. if(HERMES_VISUALIZATION) { sprintf(title, "Ref-Loesung: Time %3.2f,timestep %i,as=%i,", current_time,ts,as); sview.set_title(title); sview.show(&ref_sln); sprintf(title, "Mesh: Time %3.2f,timestep %i,as=%i,", current_time,ts,as); mview.set_title(title); mview.show(&space); } if((VTK_VISUALIZATION) &&((done==true)&&(ts % VTK_FREQ == 0))) { // Output solution in VTK format. char filename[40]; sprintf(filename, "solution-%i.vtk", ts ); lin.save_solution_vtk(&u_prev_time, filename, "solution", mode_3D); sprintf(filename, "ref_space_order-%i.vtk", ts); ord.save_orders_vtk(ref_space, filename); sprintf(filename, "ref_mesh-%i.vtk", ts ); ord.save_mesh_vtk(ref_space, filename); } // Clean up. delete lumped_matrix; delete diffusion; delete [] coeff_vec_2; delete [] coeff_vec; delete [] limited_flux; delete ref_mesh; delete ref_space; } while (done == false); // Update global time. current_time += time_step; // Increase time step counter ts++; } while (current_time < T_FINAL); // Visualize the solution. if(VTK_VISUALIZATION) { lin.save_solution_vtk(&u_prev_time, "end_solution.vtk", "solution", mode_3D); ord.save_mesh_vtk(&space, "end_mesh"); ord.save_orders_vtk(&space, "end_order.vtk"); } delete mass_matrix; delete conv_matrix; // Wait for the view to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { Hermes::vector<std::string> BDY_NATURAL_CONCENTRATION; BDY_NATURAL_CONCENTRATION.push_back("2"); std::ofstream time_step_out("time_step"); // 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(0, true); mesh_concentration.refine_towards_boundary(BDY_DIRICHLET_CONCENTRATION, INIT_REF_NUM_CONCENTRATION_BDY, true); //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(0, true); // Initialize boundary condition types and spaces with default shapesets. // For the concentration. EssentialBCs<double> 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)); bcs_concentration.add_boundary_condition(new ConcentrationTimedepEssentialBC(BDY_INLET, 0.0, CONCENTRATION_EXT_STARTUP_TIME)); L2Space<double>space_rho(&mesh_flow, P_INIT_FLOW); L2Space<double>space_rho_v_x(&mesh_flow, P_INIT_FLOW); L2Space<double>space_rho_v_y(&mesh_flow, P_INIT_FLOW); L2Space<double>space_e(&mesh_flow, P_INIT_FLOW); // Space<double> for concentration. H1Space<double> space_c(&mesh_concentration, &bcs_concentration, P_INIT_CONCENTRATION); int ndof = Space<double>::get_num_dofs(Hermes::vector<Space<double>*>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e, &space_c)); info("ndof: %d", ndof); // Initialize solutions, set initial conditions. InitialSolutionEulerDensity sln_rho(&mesh_flow, RHO_EXT); InitialSolutionEulerDensityVelX sln_rho_v_x(&mesh_flow, RHO_EXT * V1_EXT); InitialSolutionEulerDensityVelY sln_rho_v_y(&mesh_flow, RHO_EXT * V2_EXT); InitialSolutionEulerDensityEnergy sln_e(&mesh_flow, QuantityCalculator::calc_energy(RHO_EXT, RHO_EXT * V1_EXT, RHO_EXT * V2_EXT, P_EXT, KAPPA)); InitialSolutionConcentration sln_c(&mesh_concentration, 0.0); 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); Solution<double> rsln_rho, rsln_rho_v_x, rsln_rho_v_y, rsln_e, rsln_c; // Numerical flux. OsherSolomonNumericalFlux num_flux(KAPPA); // Initialize weak formulation. WeakForm<double>* wf = NULL; if(SEMI_IMPLICIT) wf = new EulerEquationsWeakFormSemiImplicitCoupled(&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 && CAND_LIST_FLOW == H2D_H_ANISO)); else wf = new EulerEquationsWeakFormExplicitCoupled(&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 && CAND_LIST_FLOW == H2D_H_ANISO)); // Filters for visualization of Mach number, pressure and entropy. MachNumberFilter Mach_number(Hermes::vector<MeshFunction<double>*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), KAPPA); PressureFilter pressure(Hermes::vector<MeshFunction<double>*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), KAPPA); EntropyFilter entropy(Hermes::vector<MeshFunction<double>*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), KAPPA, RHO_EXT, P_EXT); ScalarView<double> pressure_view("Pressure", new WinGeom(0, 0, 600, 400)); ScalarView<double> Mach_number_view("Mach number", new WinGeom(700, 0, 600, 400)); ScalarView<double> s5("Concentration", new WinGeom(700, 400, 600, 400)); OrderView<double> order_view_flow("Orders - flow", new WinGeom(700, 350, 600, 400)); OrderView<double> order_view_conc("Orders - concentration", new WinGeom(700, 700, 600, 400)); // Initialize refinement selector. L2ProjBasedSelector<double> l2selector_flow(CAND_LIST_FLOW, CONV_EXP, H2DRS_DEFAULT_ORDER); L2ProjBasedSelector<double> l2selector_concentration(CAND_LIST_CONCENTRATION, CONV_EXP, H2DRS_DEFAULT_ORDER); // 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) { time_step_out << time_step << std::endl; info("---- Time step %d, time %3.5f.", iteration++, t); if(iteration == 2) { ERR_STOP_FLOW = 0.55; ERR_STOP_CONCENTRATION = 8.3; } // Periodic global derefinements. if (iteration > 1 && iteration % UNREF_FREQ == 0 && (REFINEMENT_COUNT_FLOW > 0 || REFINEMENT_COUNT_CONCENTRATION > 0)) { info("Global mesh derefinement."); if(REFINEMENT_COUNT_FLOW > 0) { REFINEMENT_COUNT_FLOW = 0; space_rho.unrefine_all_mesh_elements(); if(CAND_LIST_FLOW == H2D_HP_ANISO) space_rho.adjust_element_order(-1, P_INIT_FLOW); space_rho_v_x.copy_orders(&space_rho); space_rho_v_y.copy_orders(&space_rho); space_e.copy_orders(&space_rho); } if(REFINEMENT_COUNT_CONCENTRATION > 0) { REFINEMENT_COUNT_CONCENTRATION = 0; space_c.unrefine_all_mesh_elements(); space_c.adjust_element_order(-1, P_INIT_CONCENTRATION); } } // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. int order_increase = 0; if(CAND_LIST_FLOW == H2D_HP_ANISO) order_increase = 1; Hermes::vector<Space<double> *>* ref_spaces = Space<double>::construct_refined_spaces(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e, &space_c), order_increase); if(CAND_LIST_FLOW != H2D_HP_ANISO) (*ref_spaces)[4]->adjust_element_order(+1, P_INIT_CONCENTRATION); // Project the previous time level solution onto the new fine mesh. info("Projecting the previous time level solution onto the new fine mesh."); OGProjection<double>::project_global(*ref_spaces, Hermes::vector<Solution<double>*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e, &prev_c), Hermes::vector<Solution<double>*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e, &prev_c), matrix_solver_type); if(iteration == 1) { if(CAND_LIST_FLOW == H2D_HP_ANISO) { prev_rho.set_const((*ref_spaces)[4]->get_mesh(), RHO_EXT); prev_rho_v_x.set_const((*ref_spaces)[4]->get_mesh(), RHO_EXT * V1_EXT); prev_rho_v_y.set_const((*ref_spaces)[4]->get_mesh(), RHO_EXT * V2_EXT); prev_e.set_const((*ref_spaces)[4]->get_mesh(), QuantityCalculator::calc_energy(RHO_EXT, RHO_EXT * V1_EXT, RHO_EXT * V2_EXT, P_EXT, KAPPA)); } prev_c.set_const((*ref_spaces)[4]->get_mesh(), 0.0); } if(as > 1) { delete rsln_rho.get_mesh(); delete rsln_rho_v_x.get_mesh(); delete rsln_rho_v_y.get_mesh(); delete rsln_e.get_mesh(); delete rsln_c.get_mesh(); } // Report NDOFs. info("ndof_coarse: %d, ndof_fine: %d.", Space<double>::get_num_dofs(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e, &space_c)), Space<double>::get_num_dofs(*ref_spaces)); // Very imporant, set the meshes for the flow as the same. (*ref_spaces)[1]->get_mesh()->set_seq((*ref_spaces)[0]->get_mesh()->get_seq()); (*ref_spaces)[2]->get_mesh()->set_seq((*ref_spaces)[0]->get_mesh()->get_seq()); (*ref_spaces)[3]->get_mesh()->set_seq((*ref_spaces)[0]->get_mesh()->get_seq()); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix<double>* matrix = create_matrix<double>(matrix_solver_type); Vector<double>* rhs = create_vector<double>(matrix_solver_type); LinearSolver<double>* solver = create_linear_solver<double>(matrix_solver_type, matrix, rhs); // Initialize the FE problem. bool is_linear = true; DiscreteProblem<double> dp(wf, *ref_spaces); if(SEMI_IMPLICIT) static_cast<EulerEquationsWeakFormSemiImplicitCoupled*>(wf)->set_time_step(time_step); else static_cast<EulerEquationsWeakFormExplicitCoupled*>(wf)->set_time_step(time_step); // 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."); if (solver->solve()) Solution<double>::vector_to_solutions(solver->get_sln_vector(), *ref_spaces, Hermes::vector<Solution<double>*>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e, &rsln_c)); else error ("Matrix solver failed.\n"); Hermes::vector<Space<double>*> flow_spaces((*ref_spaces)[0], (*ref_spaces)[1], (*ref_spaces)[2], (*ref_spaces)[3]); double* flow_solution_vector = new double[Space<double>::get_num_dofs(flow_spaces)]; OGProjection<double>::project_global(flow_spaces, Hermes::vector<MeshFunction<double> *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e), flow_solution_vector); FluxLimiter flux_limiter(FluxLimiter::Krivodonova, flow_solution_vector, flow_spaces); flux_limiter.limit_according_to_detector(); flux_limiter.get_limited_solutions(Hermes::vector<Solution<double> *>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e)); if(SHOCK_CAPTURING) flux_limiter.get_limited_solutions(Hermes::vector<Solution<double>*>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e)); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection<double>::project_global(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e, &space_c), Hermes::vector<Solution<double>*>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e, &rsln_c), Hermes::vector<Solution<double>*>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e, &sln_c), matrix_solver_type, Hermes::vector<ProjNormType>(HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM)); util_time_step = time_step; if(SEMI_IMPLICIT) CFL.calculate_semi_implicit(Hermes::vector<Solution<double>*>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e), &mesh_flow, util_time_step); else CFL.calculate(Hermes::vector<Solution<double>*>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e), &mesh_flow, util_time_step); time_step = util_time_step; ADES.calculate(Hermes::vector<Solution<double>*>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y), &mesh_concentration, util_time_step); // Calculate element errors and total error estimate. info("Calculating error estimates."); Adapt<double> adaptivity_flow(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), Hermes::vector<ProjNormType>(HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM)); double err_est_rel_total_flow = adaptivity_flow.calc_err_est(Hermes::vector<Solution<double>*>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e), Hermes::vector<Solution<double>*>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e)) * 100; Adapt<double> adaptivity_concentration(&space_c, HERMES_L2_NORM); double err_est_rel_total_concentration = adaptivity_concentration.calc_err_est(&sln_c, &rsln_c) * 100; // Report results. info("Error estimate for the flow part: %g%%", err_est_rel_total_flow); info("Error estimate for the concentration part: %g%%", err_est_rel_total_concentration); // If err_est too large, adapt the mesh. if (err_est_rel_total_flow < ERR_STOP_FLOW && err_est_rel_total_concentration < ERR_STOP_CONCENTRATION) { done = true; if(SHOCK_CAPTURING) flux_limiter.limit_according_to_detector(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e)); } else { info("Adapting coarse meshes."); if(err_est_rel_total_flow > ERR_STOP_FLOW) { done = adaptivity_flow.adapt(Hermes::vector<RefinementSelectors::Selector<double> *>(&l2selector_flow, &l2selector_flow, &l2selector_flow, &l2selector_flow), THRESHOLD, STRATEGY, MESH_REGULARITY); REFINEMENT_COUNT_FLOW++; } else done = true; if(err_est_rel_total_concentration > ERR_STOP_CONCENTRATION) { if(!adaptivity_concentration.adapt(&l2selector_concentration, THRESHOLD, STRATEGY, MESH_REGULARITY)) done = false; REFINEMENT_COUNT_CONCENTRATION++; } if (Space<double>::get_num_dofs(Hermes::vector<Space<double> *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e, &space_c)) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } // Save orders. if((iteration - 1) % EVERY_NTH_STEP == 0 && done) { if(HERMES_VISUALIZATION) { Hermes::vector<Space<double> *>* ref_spaces_local = Space<double>::construct_refined_spaces(Hermes::vector<Space<double> *>(&space_rho, &space_c), 0); order_view_flow.show((*ref_spaces_local)[0]); order_view_conc.show((*ref_spaces_local)[1]); order_view_flow.save_numbered_screenshot("FlowMesh%i.bmp", (int)(iteration / 5), true); order_view_conc.save_numbered_screenshot("ConcentrationMesh%i.bmp", (int)(iteration / 5), true); for(unsigned int i = 0; i < ref_spaces_local->size(); i++) { delete (*ref_spaces_local)[i]->get_mesh(); delete (*ref_spaces_local)[i]; } } if(VTK_VISUALIZATION) { Orderizer ord; char filename[40]; sprintf(filename, "Flow-mesh-%i.vtk", iteration - 1); ord.save_orders_vtk((*ref_spaces)[0], filename); sprintf(filename, "Concentration-mesh-%i.vtk", iteration - 1); ord.save_orders_vtk((*ref_spaces)[4], filename); } } // Clean up. delete solver; delete matrix; delete rhs; for(unsigned int i = 0; i < ref_spaces->size(); i++) delete (*ref_spaces)[i]; } while (done == false); // Copy the solutions into the previous time level ones. prev_rho.copy(&rsln_rho); prev_rho_v_x.copy(&rsln_rho_v_x); prev_rho_v_y.copy(&rsln_rho_v_y); prev_e.copy(&rsln_e); prev_c.copy(&rsln_c); delete rsln_rho.get_mesh(); delete rsln_rho_v_x.get_mesh(); delete rsln_rho_v_y.get_mesh(); delete rsln_e.get_mesh(); delete rsln_c.get_mesh(); // Visualization. if((iteration - 1) % EVERY_NTH_STEP == 0) { // Hermes visualization. if(HERMES_VISUALIZATION) { Mach_number.reinit(); pressure.reinit(); pressure_view.show_mesh(false); pressure_view.show(&pressure); pressure_view.set_scale_format("%1.3f"); Mach_number_view.show_mesh(false); Mach_number_view.set_scale_format("%1.3f"); Mach_number_view.show(&Mach_number); s5.show_mesh(false); s5.set_scale_format("%0.3f"); s5.show(&prev_c); pressure_view.save_numbered_screenshot("pressure%i.bmp", (int)(iteration / 5), true); Mach_number_view.save_numbered_screenshot("Mach_number%i.bmp", (int)(iteration / 5), true); s5.save_numbered_screenshot("concentration%i.bmp", (int)(iteration / 5), true); } // Output solution in VTK format. if(VTK_VISUALIZATION) { pressure.reinit(); Mach_number.reinit(); Linearizer<double> 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(); */ return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("domain.mesh", &mesh); // Perform initial mesh refinements (optional). //mesh.refine_all_elements(); // Initialize boundary conditions DefaultEssentialBCConst bc_essential(Hermes::vector<std::string>(BDY_BOTTOM, BDY_OUTER, BDY_LEFT, BDY_INNER), 0.0); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = Space::get_num_dofs(&space); info("ndof = %d", ndof); // Initialize the weak formulation. Not providing the order determination form // (or callback) turns on adaptive numerical quadrature. The quadrature begins // with using a first-order rule in the entire element. Then the element is split // uniformly in space and the quadrature order is increased by "adapt_order_increase". // Then the form is calculated again by employing the new quadrature in subelements. // This provides a more accurate result. If relative error is less than // "adapt_rel_error_tol", the computation stops, otherwise the same procedure is // applied recursively to all four subelements. int adapt_order_increase = 1; double adapt_rel_error_tol = 1e1; WeakFormPoisson wf(CONST_F, ADAPTIVE_QUADRATURE, adapt_order_increase, adapt_rel_error_tol); if (ADAPTIVE_QUADRATURE) info("Adaptive quadrature ON."); else info("Adaptive quadrature OFF."); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, &space, is_linear); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize the solution. Solution sln; // Assemble the stiffness matrix and right-hand side vector. info("Assembling the stiffness matrix and right-hand side vector."); dp.assemble(matrix, rhs); // Solve the linear system and if successful, obtain the solution. info("Solving the matrix problem."); if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln); else error ("Matrix solver failed.\n"); // VTK output. if (VTK_VISUALIZATION) { // Output solution in VTK format. Linearizer lin; bool mode_3D = true; lin.save_solution_vtk(&sln, "sln.vtk", "Temperature", mode_3D); info("Solution in VTK format saved to file %s.", "sln.vtk"); // Output mesh and element orders in VTK format. Orderizer ord; ord.save_orders_vtk(&space, "ord.vtk"); info("Element orders in VTK format saved to file %s.", "ord.vtk"); } // Visualize the solution. if (HERMES_VISUALIZATION) { ScalarView view("Solution", new WinGeom(0, 0, 440, 350)); view.show(&sln); View::wait(); } // Clean up. delete solver; delete matrix; delete rhs; return 0; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh basemesh; H2DReader mloader; mloader.load("domain.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); 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 DefaultEssentialBCConst(BDY_DIRICHLET_CONCENTRATION, CONCENTRATION_EXT)); 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 sln_rho(&mesh_flow, RHO_EXT); InitialSolutionEulerDensityVelX sln_rho_v_x(&mesh_flow, RHO_EXT * V1_EXT); InitialSolutionEulerDensityVelY sln_rho_v_y(&mesh_flow, RHO_EXT * V2_EXT); InitialSolutionEulerDensityEnergy sln_e(&mesh_flow, QuantityCalculator::calc_energy(RHO_EXT, RHO_EXT * V1_EXT, RHO_EXT * V2_EXT, P_EXT, KAPPA)); InitialSolutionConcentration sln_c(&mesh_concentration, 0.0); 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); Solution rsln_rho, rsln_rho_v_x, rsln_rho_v_y, rsln_e, rsln_c; // Numerical flux. OsherSolomonNumericalFlux num_flux(KAPPA); // Initialize weak formulation. EulerEquationsWeakFormImplicitCoupled wf(&num_flux, KAPPA, RHO_EXT, V1_EXT, V2_EXT, P_EXT, BDY_SOLID_WALL, BDY_INLET, BDY_OUTLET, BDY_NATURAL_CONCENTRATION, &prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e, &prev_c, PRECONDITIONING, EPSILON); wf.set_time_step(time_step); // Filters for visualization of Mach number, pressure and entropy. MachNumberFilter Mach_number(Hermes::vector<MeshFunction*>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e), KAPPA); PressureFilter pressure(Hermes::vector<MeshFunction*>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e), KAPPA); EntropyFilter entropy(Hermes::vector<MeshFunction*>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_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)); */ // Initialize refinement selector. L2ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Select preconditioner. RCP<Precond> pc = rcp(new IfpackPrecond("point-relax")); int iteration = 0; double t = 0; for(t = 0.0; t < 3.0; t += time_step) { info("---- Time step %d, time %3.5f.", iteration++, t); // Periodic global derefinements. if (iteration > 1 && iteration % UNREF_FREQ == 0 && REFINEMENT_COUNT > 0) { REFINEMENT_COUNT = 0; info("Global mesh derefinement."); mesh_flow.unrefine_all_elements(); mesh_concentration.unrefine_all_elements(); space_rho.adjust_element_order(-1, P_INIT_FLOW); space_rho_v_x.adjust_element_order(-1, P_INIT_FLOW); space_rho_v_y.adjust_element_order(-1, P_INIT_FLOW); space_e.adjust_element_order(-1, P_INIT_FLOW); space_c.adjust_element_order(-1, P_INIT_CONCENTRATION); } // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. int order_increase = 0; Hermes::vector<Space *>* ref_spaces = Space::construct_refined_spaces(Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e, &space_c), order_increase); // Report NDOFs. info("ndof_coarse: %d, ndof_fine: %d.", Space::get_num_dofs(Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e, &space_c)), Space::get_num_dofs(*ref_spaces)); // Very imporant, set the meshes for the flow as the same. (*ref_spaces)[1]->get_mesh()->set_seq((*ref_spaces)[0]->get_mesh()->get_seq()); (*ref_spaces)[2]->get_mesh()->set_seq((*ref_spaces)[0]->get_mesh()->get_seq()); (*ref_spaces)[3]->get_mesh()->set_seq((*ref_spaces)[0]->get_mesh()->get_seq()); // Project the previous time level solution onto the new fine mesh // in order to obtain initial vector for NOX. info("Projecting initial solution on the FE mesh."); scalar* coeff_vec = new scalar[Space::get_num_dofs(*ref_spaces)]; OGProjection::project_global(*ref_spaces, Hermes::vector<MeshFunction *>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e, &prev_c), coeff_vec); // Initialize the FE problem. bool is_linear = false; DiscreteProblem dp(&wf, *ref_spaces, is_linear); // Initialize NOX solver. NoxSolver solver(&dp, NOX_MESSAGE_TYPE, "GMRES", "Newton", NOX_LINEAR_TOLERANCE, "None", 0, 0, 1, NOX_NONLINEAR_TOLERANCE); solver.set_init_sln(coeff_vec); if(PRECONDITIONING) solver.set_precond(pc); info("Assembling by DiscreteProblem, solving by NOX."); if (solver.solve()) Solution::vector_to_solutions(solver.get_solution(), *ref_spaces, Hermes::vector<Solution *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e, &rsln_c)); else error("NOX failed."); info("Number of nonlin iterations: %d (norm of residual: %g)", solver.get_num_iters(), solver.get_residual()); info("Total number of iterations in linsolver: %d (achieved tolerance in the last step: %g)", solver.get_num_lin_iters(), solver.get_achieved_tol()); if(SHOCK_CAPTURING) { Hermes::vector<Space*> flow_spaces((*ref_spaces)[0], (*ref_spaces)[1], (*ref_spaces)[2], (*ref_spaces)[3]); scalar* flow_solution_vector = new scalar[Space::get_num_dofs(flow_spaces)]; OGProjection::project_global(flow_spaces, Hermes::vector<MeshFunction *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e), flow_solution_vector); DiscontinuityDetector discontinuity_detector(flow_spaces, Hermes::vector<Solution *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e)); std::set<int> discontinuous_elements = discontinuity_detector.get_discontinuous_element_ids(DISCONTINUITY_DETECTOR_PARAM); FluxLimiter flux_limiter(flow_solution_vector, flow_spaces, Hermes::vector<Solution *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e)); flux_limiter.limit_according_to_detector(discontinuous_elements); } // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e, &space_c), Hermes::vector<Solution *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e, &rsln_c), Hermes::vector<Solution *>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e, &sln_c), matrix_solver, Hermes::vector<ProjNormType>(HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM, HERMES_H1_NORM)); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt* adaptivity = new Adapt(Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e, &space_c), Hermes::vector<ProjNormType>(HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM, HERMES_H1_NORM)); double err_est_rel_total = adaptivity->calc_err_est(Hermes::vector<Solution *>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e, &sln_c), Hermes::vector<Solution *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e, &rsln_c)) * 100; // Report results. info("err_est_rel: %g%%", err_est_rel_total); // If err_est too large, adapt the mesh. if (err_est_rel_total < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(Hermes::vector<RefinementSelectors::Selector *>(&selector, &selector, &selector, &selector, &selector), THRESHOLD, STRATEGY, MESH_REGULARITY); REFINEMENT_COUNT++; if (Space::get_num_dofs(Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e, &space_c)) >= NDOF_STOP) done = true; else // Increase the counter of performed adaptivity steps. as++; } // Save orders. Orderizer ord; char filename[40]; sprintf(filename, "Flow-mesh-%i-%i.vtk", iteration - 1, as - 1); ord.save_orders_vtk((*ref_spaces)[0], filename); sprintf(filename, "Concentration-mesh-%i-%i.vtk", iteration - 1, as - 1); ord.save_orders_vtk((*ref_spaces)[4], filename); // Clean up. delete adaptivity; if(!done) for(unsigned int i = 0; i < ref_spaces->size(); i++) delete (*ref_spaces)[i]->get_mesh(); for(unsigned int i = 0; i < ref_spaces->size(); i++) delete (*ref_spaces)[i]; } while (done == false); // Copy the solutions into previous time level ones. prev_rho.copy(&rsln_rho); prev_rho_v_x.copy(&rsln_rho_v_x); prev_rho_v_y.copy(&rsln_rho_v_y); prev_e.copy(&rsln_e); prev_c.copy(&rsln_c); // 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); */ } // 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(); */ 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 (optional). for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize the weak formulation. CustomWeakForm wf; // Initialize boundary conditions. CustomDirichletCondition bc_essential(Hermes::vector<std::string>("Bdy"), BDY_A_PARAM, BDY_B_PARAM, BDY_C_PARAM); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the FE problem. DiscreteProblem dp(&wf, &space); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof]; memset(coeff_vec, 0, ndof*sizeof(scalar)); // Perform Newton's iteration. bool jacobian_changed = true; double newton_tol = 1e-8; int newton_max_iter = 100; bool verbose = true; if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs, jacobian_changed, newton_tol, newton_max_iter, verbose)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution sln; Solution::vector_to_solution(coeff_vec, &space, &sln); // VTK output. if (VTK_VISUALIZATION) { // Output solution in VTK format. Linearizer lin; bool mode_3D = true; lin.save_solution_vtk(&sln, "sln.vtk", "Temperature", mode_3D); info("Solution in VTK format saved to file %s.", "sln.vtk"); // Output mesh and element orders in VTK format. Orderizer ord; ord.save_orders_vtk(&space, "ord.vtk"); info("Element orders in VTK format saved to file %s.", "ord.vtk"); } // Visualize the solution. if (HERMES_VISUALIZATION) { ScalarView view("Solution", new WinGeom(0, 0, 440, 350)); view.show(&sln, HERMES_EPS_HIGH); View::wait(); } // Clean up. delete solver; delete matrix; delete rhs; delete [] coeff_vec; 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 (optional). for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Initialize the weak formulation. CustomWeakFormPoissonDirichlet wf("Aluminum", LAMBDA_AL, "Copper", LAMBDA_CU, VOLUME_HEAT_SRC); // Initialize boundary conditions. CustomDirichletCondition bc_essential(Hermes::vector<std::string>("Bottom", "Inner", "Outer", "Left"), BDY_A_PARAM, BDY_B_PARAM, BDY_C_PARAM); EssentialBCs bcs(&bc_essential); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); int ndof = space.get_num_dofs(); info("ndof = %d", ndof); // Initialize the FE problem. DiscreteProblem dp(&wf, &space); // Set up the solver, matrix, and rhs according to the solver selection. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof]; memset(coeff_vec, 0, ndof*sizeof(scalar)); // Perform Newton's iteration. if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs)) error("Newton's iteration failed."); // Translate the resulting coefficient vector into the Solution sln. Solution sln; Solution::vector_to_solution(coeff_vec, &space, &sln); // VTK output. if (VTK_VISUALIZATION) { // Output solution in VTK format. Linearizer lin; bool mode_3D = true; lin.save_solution_vtk(&sln, "sln.vtk", "Temperature", mode_3D); info("Solution in VTK format saved to file %s.", "sln.vtk"); // Output mesh and element orders in VTK format. Orderizer ord; ord.save_orders_vtk(&space, "ord.vtk"); info("Element orders in VTK format saved to file %s.", "ord.vtk"); } ndof = Space::get_num_dofs(&space); printf("ndof = %d\n", ndof); double sum = 0; for (int i=0; i < ndof; i++) sum += coeff_vec[i]; printf("coefficient sum = %g\n", sum); bool success = true; if (fabs(sum + 4.2471) > 1e-3) success = 0; if (success == 1) { printf("Success!\n"); return ERR_SUCCESS; } else { printf("Failure!\n"); return ERR_FAILURE; } }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("motor.mesh", &mesh); // Initialize the weak formulation. CustomWeakFormPoisson wf("Motor", EPS_MOTOR, "Air", EPS_AIR); // Initialize boundary conditions DefaultEssentialBCConst bc_essential_out("Outer", 0.0); DefaultEssentialBCConst bc_essential_stator("Stator", VOLTAGE); EssentialBCs bcs(Hermes::vector<EssentialBoundaryCondition *>(&bc_essential_out, &bc_essential_stator)); // Create an H1 space with default shapeset. H1Space space(&mesh, &bcs, P_INIT); // Initialize coarse and reference mesh solution. Solution sln, ref_sln; // Initialize refinement selector. H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); // Initialize views. ScalarView sview("Solution", new WinGeom(0, 0, 410, 600)); sview.fix_scale_width(50); sview.show_mesh(false); OrderView oview("Polynomial orders", new WinGeom(420, 0, 400, 600)); // DOF and CPU convergence graphs initialization. SimpleGraph graph_dof, graph_cpu; // Time measurement. TimePeriod cpu_time; cpu_time.tick(); // Adaptivity loop: int as = 1; bool done = false; do { info("---- Adaptivity step %d:", as); // Construct globally refined reference mesh and setup reference space. Space* ref_space = Space::construct_refined_space(&space); int ndof_ref = Space::get_num_dofs(ref_space); // Initialize matrix solver. SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); // Initialize reference problem. info("Solving on reference mesh."); DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space); // Time measurement. cpu_time.tick(); // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof_ref]; memset(coeff_vec, 0, ndof_ref * 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::vector_to_solution(coeff_vec, ref_space, &ref_sln); // Project the fine mesh solution onto the coarse mesh. info("Projecting reference solution on coarse mesh."); OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); // Time measurement. cpu_time.tick(); // VTK output. if (VTK_VISUALIZATION) { // Output solution in VTK format. Linearizer lin; char* title = new char[100]; sprintf(title, "sln-%d.vtk", as); lin.save_solution_vtk(&sln, title, "Potential", false); info("Solution in VTK format saved to file %s.", title); // Output mesh and element orders in VTK format. Orderizer ord; sprintf(title, "ord-%d.vtk", as); ord.save_orders_vtk(&space, title); info("Element orders in VTK format saved to file %s.", title); } // View the coarse mesh solution and polynomial orders. if (HERMES_VISUALIZATION) { sview.show(&sln); oview.show(&space); } // Skip visualization time. cpu_time.tick(HERMES_SKIP); // Calculate element errors and total error estimate. info("Calculating error estimate."); Adapt* adaptivity = new Adapt(&space); bool solutions_for_adapt = true; // In the following function, the Boolean parameter "solutions_for_adapt" determines whether // the calculated errors are intended for use with adaptivity (this may not be the case, for example, // when error wrt. an exact solution is calculated). The default value is solutions_for_adapt = true, // The last parameter "error_flags" determine whether the total and element errors are treated as // absolute or relative. Its default value is error_flags = HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL. // In subsequent examples and benchmarks, these two parameters will be often used with // their default values, and thus they will not be present in the code explicitly. double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100; // Report results. info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_est_rel); // Time measurement. cpu_time.tick(); // Add entry to DOF and CPU convergence graphs. graph_dof.add_values(Space::get_num_dofs(&space), err_est_rel); graph_dof.save("conv_dof_est.dat"); graph_cpu.add_values(cpu_time.accumulated(), err_est_rel); graph_cpu.save("conv_cpu_est.dat"); // If err_est too large, adapt the mesh. if (err_est_rel < ERR_STOP) done = true; else { info("Adapting coarse mesh."); done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY); // Increase the counter of performed adaptivity steps. if (done == false) as++; } if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true; // Clean up. delete [] coeff_vec; delete solver; delete matrix; delete rhs; delete adaptivity; if(done == false) delete ref_space->get_mesh(); delete ref_space; delete dp; } while (done == false); verbose("Total running time: %g s", cpu_time.accumulated()); // Show the reference solution - the final result. sview.set_title("Fine mesh solution"); sview.show_mesh(false); sview.show(&ref_sln); // Wait for all views to be closed. View::wait(); return 0; }