void Positives() { std::string_view view1 = std::string(); // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives its value [bugprone-dangling-handle] std::string_view view_2 = ReturnsAString(); // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives view1 = std::string(); // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives const std::string& str_ref = ""; std::string_view view3 = true ? "A" : str_ref; // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives view3 = true ? "A" : str_ref; // CHECK-MESSAGES: [[@LINE-1]]:3: warning: std::basic_string_view outlives std::string_view view4(ReturnsAString()); // CHECK-MESSAGES: [[@LINE-1]]:20: warning: std::basic_string_view outlives }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; MeshReaderH2D mloader; mloader.load(mesh_file.c_str(), &mesh); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Solution variables. Solution<double> sln1, sln2, sln3, sln4; Hermes::vector<Solution<double>*> solutions(&sln1, &sln2, &sln3, &sln4); // Define initial conditions. Hermes::Mixins::Loggable::Static::info("Setting initial conditions."); ConstantSolution<double> iter1(&mesh, 1.00), iter2(&mesh, 1.00), iter3(&mesh, 1.00), iter4(&mesh, 1.00); Hermes::vector<MeshFunction<double>*> iterates(&iter1, &iter2, &iter3, &iter4); // Create H1 spaces with default shapesets. H1Space<double> space1(&mesh, P_INIT_1); H1Space<double> space2(&mesh, P_INIT_2); H1Space<double> space3(&mesh, P_INIT_3); H1Space<double> space4(&mesh, P_INIT_4); Hermes::vector<const Space<double>* > spaces(&space1, &space2, &space3, &space4); int ndof = Space<double>::get_num_dofs(spaces); Hermes::Mixins::Loggable::Static::info("ndof = %d", ndof); // Initialize views. ScalarView view1("Neutron flux 1", new WinGeom(0, 0, 320, 600)); ScalarView view2("Neutron flux 2", new WinGeom(350, 0, 320, 600)); ScalarView view3("Neutron flux 3", new WinGeom(700, 0, 320, 600)); ScalarView view4("Neutron flux 4", new WinGeom(1050, 0, 320, 600)); // Do not show meshes, set 3D mode. view1.show_mesh(false); view1.set_3d_mode(true); view2.show_mesh(false); view2.set_3d_mode(true); view3.show_mesh(false); view3.set_3d_mode(true); view4.show_mesh(false); view4.set_3d_mode(true); // Load physical data of the problem for the 4 energy groups. Hermes::Hermes2D::WeakFormsNeutronics::Multigroup::MaterialProperties::Diffusion::MaterialPropertyMaps matprop(4); matprop.set_D(D); matprop.set_Sigma_r(Sr); matprop.set_Sigma_s(Ss); matprop.set_Sigma_a(Sa); matprop.set_Sigma_f(Sf); matprop.set_nu(nu); matprop.set_chi(chi); matprop.validate(); // Printing table of material properties. std::cout << matprop; // Initialize the weak formulation. CustomWeakForm wf(matprop, iterates, k_eff, bdy_vacuum); // Initialize the FE problem. DiscreteProblem<double> dp(&wf, spaces); // Initialize Newton solver. NewtonSolver<double> newton(&dp); // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; // Main power iteration loop: int it = 1; bool done = false; do { Hermes::Mixins::Loggable::Static::info("------------ Power iteration %d:", it); Hermes::Mixins::Loggable::Static::info("Newton's method."); // Perform Newton's iteration. try { newton.set_newton_max_iter(NEWTON_MAX_ITER); newton.set_newton_tol(NEWTON_TOL); newton.solve_keep_jacobian(); } catch(Hermes::Exceptions::Exception e) { e.printMsg(); throw Hermes::Exceptions::Exception("Newton's iteration failed."); } // Debug. //printf("\n=================================================\n"); //for (int d = 0; d < ndof; d++) printf("%g ", newton.get_sln_vector()[d]); // Translate the resulting coefficient vector into a Solution. Solution<double>::vector_to_solutions(newton.get_sln_vector(), spaces, solutions); // Show intermediate solutions. view1.show(&sln1); view2.show(&sln2); view3.show(&sln3); view4.show(&sln4); // Compute eigenvalue. SourceFilter source(solutions, &matprop, core); SourceFilter source_prev(iterates, &matprop, core); double k_new = k_eff * (integrate(&source, core) / integrate(&source_prev, core)); Hermes::Mixins::Loggable::Static::info("Largest eigenvalue: %.8g, rel. difference from previous it.: %g", k_new, fabs((k_eff - k_new) / k_new)); // Stopping criterion. if (fabs((k_eff - k_new) / k_new) < ERROR_STOP) done = true; // Update eigenvalue. k_eff = k_new; wf.update_keff(k_eff); if (!done) { // Save solutions for the next iteration. iter1.copy(&sln1); iter2.copy(&sln2); iter3.copy(&sln3); iter4.copy(&sln4); it++; } } while (!done); // Time measurement. cpu_time.tick(); // Show solutions. view1.show(&sln1); view2.show(&sln2); view3.show(&sln3); view4.show(&sln4); // Skip visualization time. cpu_time.tick(Hermes::Mixins::TimeMeasurable::HERMES_SKIP); // Print timing information. Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. View::wait(); return 0; }
float View::_computeFocusRatio( Vector3f& eye ) { eye = Vector3f::ZERO; const Observer* observer = getObserver(); const FocusMode mode = observer ? observer->getFocusMode() :FOCUSMODE_FIXED; if( mode == FOCUSMODE_FIXED ) return 1.f; const Channels& channels = getChannels(); if( channels.empty( )) return 1.f; Vector4f view4( Vector3f::FORWARD ); if( mode == FOCUSMODE_RELATIVE_TO_OBSERVER ) { view4 = observer->getHeadMatrix() * view4; eye = observer->getEyePosition( EYE_CYCLOP ); } Vector3f view = view4; view.normalize(); float distance = std::numeric_limits< float >::max(); if( getCurrentType() != Frustum::TYPE_NONE ) // frustum from view { const Wall& wall = getWall(); const Vector3f w = wall.getW(); const float denom = view.dot( w ); if( denom != 0.f ) // view parallel to wall { const float d = (wall.bottomLeft - eye).dot( w ) / denom; if( d > 0.f ) distance = d; } } else { // Find closest segment and its distance from cyclop eye for( ChannelsCIter i = channels.begin(); i != channels.end(); ++i ) { Segment* segment = (*i)->getSegment(); if( segment->getCurrentType() == Frustum::TYPE_NONE ) { segment->notifyFrustumChanged(); if( segment->getCurrentType() == Frustum::TYPE_NONE ) continue; } // http://en.wikipedia.org/wiki/Line-plane_intersection const Wall& wall = segment->getWall(); const Vector3f w = wall.getW(); const float denom = view.dot( w ); if( denom == 0.f ) // view parallel to wall continue; const float d = (wall.bottomLeft - eye).dot( w ) / denom; if( d > distance || d <= 0.f ) // further away or behind continue; distance = d; //LBINFO << "Eye " << eye << " is " << d << " from " << wall // << std::endl; } } float focusDistance = observer->getFocusDistance(); if( mode == FOCUSMODE_RELATIVE_TO_ORIGIN ) { eye = observer->getEyePosition( EYE_CYCLOP ); if( distance != std::numeric_limits< float >::max( )) { distance += eye.z(); focusDistance += eye.z(); if( fabsf( distance ) <= std::numeric_limits< float >::epsilon( )) distance = 2.f * std::numeric_limits< float >::epsilon(); } } if( distance == std::numeric_limits< float >::max( )) return 1.f; return focusDistance / distance; }
int main(int argc, char* argv[]) { // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("reactor.mesh", &mesh); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Solution variables. Solution sln1, sln2, sln3, sln4; Solution iter1, iter2, iter3, iter4; Hermes::Tuple<Solution*> solutions(&sln1, &sln2, &sln3, &sln4); // Define initial conditions. info("Setting initial conditions."); iter1.set_const(&mesh, 1.00); iter2.set_const(&mesh, 1.00); iter3.set_const(&mesh, 1.00); iter4.set_const(&mesh, 1.00); // Enter boundary markers. BCTypes bc_types; bc_types.add_bc_neumann(BDY_SYM); bc_types.add_bc_newton(BDY_VACUUM); // Create H1 spaces with default shapesets. H1Space space1(&mesh, &bc_types, P_INIT_1); H1Space space2(&mesh, &bc_types, P_INIT_2); H1Space space3(&mesh, &bc_types, P_INIT_3); H1Space space4(&mesh, &bc_types, P_INIT_4); Hermes::Tuple<Space*> spaces(&space1, &space2, &space3, &space4); int ndof = Space::get_num_dofs(Hermes::Tuple<Space*>(&space1, &space2, &space3, &space4)); info("ndof = %d.", ndof); // Initialize views. ScalarView view1("Neutron flux 1", new WinGeom(0, 0, 320, 600)); ScalarView view2("Neutron flux 2", new WinGeom(350, 0, 320, 600)); ScalarView view3("Neutron flux 3", new WinGeom(700, 0, 320, 600)); ScalarView view4("Neutron flux 4", new WinGeom(1050, 0, 320, 600)); // Do not show meshes. view1.show_mesh(false); view1.set_3d_mode(true); view2.show_mesh(false); view2.set_3d_mode(true); view3.show_mesh(false); view3.set_3d_mode(true); view4.show_mesh(false); view4.set_3d_mode(true); // Initialize the weak formulation. WeakForm wf(4); wf.add_matrix_form(0, 0, callback(biform_0_0), HERMES_SYM); wf.add_matrix_form(1, 1, callback(biform_1_1), HERMES_SYM); wf.add_matrix_form(1, 0, callback(biform_1_0)); wf.add_matrix_form(2, 2, callback(biform_2_2), HERMES_SYM); wf.add_matrix_form(2, 1, callback(biform_2_1)); wf.add_matrix_form(3, 3, callback(biform_3_3), HERMES_SYM); wf.add_matrix_form(3, 2, callback(biform_3_2)); wf.add_vector_form(0, callback(liform_0), marker_core, Hermes::Tuple<MeshFunction*>(&iter1, &iter2, &iter3, &iter4)); wf.add_vector_form(1, callback(liform_1), marker_core, Hermes::Tuple<MeshFunction*>(&iter1, &iter2, &iter3, &iter4)); wf.add_vector_form(2, callback(liform_2), marker_core, Hermes::Tuple<MeshFunction*>(&iter1, &iter2, &iter3, &iter4)); wf.add_vector_form(3, callback(liform_3), marker_core, Hermes::Tuple<MeshFunction*>(&iter1, &iter2, &iter3, &iter4)); wf.add_matrix_form_surf(0, 0, callback(biform_surf_0_0), BDY_VACUUM); wf.add_matrix_form_surf(1, 1, callback(biform_surf_1_1), BDY_VACUUM); wf.add_matrix_form_surf(2, 2, callback(biform_surf_2_2), BDY_VACUUM); wf.add_matrix_form_surf(3, 3, callback(biform_surf_3_3), BDY_VACUUM); // Initialize the FE problem. bool is_linear = true; DiscreteProblem dp(&wf, spaces, is_linear); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Time measurement. TimePeriod cpu_time, solver_time; // Main power iteration loop: int iter = 1; bool done = false; bool rhs_only = false; solver->set_factorization_scheme(HERMES_REUSE_FACTORIZATION_COMPLETELY); do { info("------------ Power iteration %d:", iter); info("Assembling the stiffness matrix and right-hand side vector."); dp.assemble(matrix, rhs, rhs_only); /* // Testing the factorization reuse schemes for direct solvers. if (iter == 10) solver->set_factorization_scheme(HERMES_REUSE_MATRIX_REORDERING); if (iter == 20) solver->set_factorization_scheme(HERMES_REUSE_MATRIX_REORDERING_AND_SCALING); if (iter == 30) solver->set_factorization_scheme(HERMES_REUSE_FACTORIZATION_COMPLETELY); */ info("Solving the matrix problem by %s.", MatrixSolverNames[matrix_solver].c_str()); solver_time.tick(HERMES_SKIP); bool solved = solver->solve(); solver_time.tick(); if(solved) Solution::vector_to_solutions(solver->get_solution(), spaces, solutions); else error ("Matrix solver failed.\n"); // Show intermediate solutions. // view1.show(&sln1); // view2.show(&sln2); // view3.show(&sln3); // view4.show(&sln4); SimpleFilter source(source_fn, Hermes::Tuple<MeshFunction*>(&sln1, &sln2, &sln3, &sln4)); SimpleFilter source_prev(source_fn, Hermes::Tuple<MeshFunction*>(&iter1, &iter2, &iter3, &iter4)); // Compute eigenvalue. double k_new = k_eff * (integrate(&source, marker_core) / integrate(&source_prev, marker_core)); info("Largest eigenvalue: %.8g, rel. difference from previous it.: %g", k_new, fabs((k_eff - k_new) / k_new)); // Stopping criterion. if (fabs((k_eff - k_new) / k_new) < ERROR_STOP) done = true; // Update eigenvalue. k_eff = k_new; if (!done) { // Save solutions for the next iteration. iter1.copy(&sln1); iter2.copy(&sln2); iter3.copy(&sln3); iter4.copy(&sln4); // Don't need to reassemble the system matrix in further iterations, // only the rhs changes to reflect the progressively updated source. rhs_only = true; iter++; } } while (!done); // Time measurement. cpu_time.tick(); solver_time.tick(HERMES_SKIP); // Print timing information. verbose("Average solver time for one power iteration: %g s", solver_time.accumulated() / iter); // Clean up. delete matrix; delete rhs; delete solver; // Show solutions. view1.show(&sln1); view2.show(&sln2); view3.show(&sln3); view4.show(&sln4); // Skip visualization time. cpu_time.tick(HERMES_SKIP); // Print timing information. verbose("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Time measurement. Hermes::Mixins::TimeMeasurable cpu_time; cpu_time.tick(); // Load physical data of the problem. MaterialPropertyMaps matprop(N_GROUPS); matprop.set_D(D); matprop.set_Sigma_r(Sr); matprop.set_Sigma_s(Ss); matprop.set_Sigma_a(Sa); matprop.set_Sigma_f(Sf); matprop.set_nu(nu); matprop.set_chi(chi); matprop.validate(); std::cout << matprop; // Use multimesh, i.e. create one mesh for each energy group. Hermes::vector<Mesh *> meshes; for (unsigned int g = 0; g < matprop.get_G(); g++) meshes.push_back(new Mesh()); // Load the mesh for the 1st group. MeshReaderH2D mloader; mloader.load(mesh_file.c_str(), meshes[0]); for (unsigned int g = 1; g < matprop.get_G(); g++) { // Obtain meshes for the 2nd to 4th group by cloning the mesh loaded for the 1st group. meshes[g]->copy(meshes[0]); // Initial uniform refinements. for (int i = 0; i < INIT_REF_NUM[g]; i++) meshes[g]->refine_all_elements(); } for (int i = 0; i < INIT_REF_NUM[0]; i++) meshes[0]->refine_all_elements(); // Create pointers to solutions on coarse and fine meshes and from the latest power iteration, respectively. Hermes::vector<Solution<double>*> coarse_solutions, fine_solutions; Hermes::vector<MeshFunction<double>*> power_iterates; // Initialize all the new solution variables. for (unsigned int g = 0; g < matprop.get_G(); g++) { coarse_solutions.push_back(new Solution<double>()); fine_solutions.push_back(new Solution<double>()); power_iterates.push_back(new ConstantSolution<double>(meshes[g], 1.0)); } // Create the approximation spaces with the default shapeset. H1Space<double> space1(meshes[0], P_INIT[0]); H1Space<double> space2(meshes[1], P_INIT[1]); H1Space<double> space3(meshes[2], P_INIT[2]); H1Space<double> space4(meshes[3], P_INIT[3]); Hermes::vector<const Space<double>*> const_spaces(&space1, &space2, &space3, &space4); Hermes::vector<Space<double>*> spaces(&space1, &space2, &space3, &space4); // Initialize the weak formulation. CustomWeakForm wf(matprop, power_iterates, k_eff, bdy_vacuum); // Initialize the discrete algebraic representation of the problem and its solver. // // Create the matrix and right-hand side vector for the solver. SparseMatrix<double>* mat = create_matrix<double>(); Vector<double>* rhs = create_vector<double>(); // Instantiate the solver itself. LinearMatrixSolver<double>* solver = create_linear_solver<double>( mat, rhs); // Initialize views. /* for 1280x800 display */ ScalarView view1("Neutron flux 1", new WinGeom(0, 0, 320, 400)); ScalarView view2("Neutron flux 2", new WinGeom(330, 0, 320, 400)); ScalarView view3("Neutron flux 3", new WinGeom(660, 0, 320, 400)); ScalarView view4("Neutron flux 4", new WinGeom(990, 0, 320, 400)); OrderView oview1("Mesh for group 1", new WinGeom(0, 450, 320, 500)); OrderView oview2("Mesh for group 2", new WinGeom(330, 450, 320, 500)); OrderView oview3("Mesh for group 3", new WinGeom(660, 450, 320, 500)); OrderView oview4("Mesh for group 4", new WinGeom(990, 450, 320, 500)); /* for adjacent 1280x800 and 1680x1050 displays ScalarView view1("Neutron flux 1", new WinGeom(0, 0, 640, 480)); ScalarView view2("Neutron flux 2", new WinGeom(650, 0, 640, 480)); ScalarView view3("Neutron flux 3", new WinGeom(1300, 0, 640, 480)); ScalarView view4("Neutron flux 4", new WinGeom(1950, 0, 640, 480)); OrderView oview1("Mesh for group 1", new WinGeom(1300, 500, 340, 500)); OrderView oview2("Mesh for group 2", new WinGeom(1650, 500, 340, 500)); OrderView oview3("Mesh for group 3", new WinGeom(2000, 500, 340, 500)); OrderView oview4("Mesh for group 4", new WinGeom(2350, 500, 340, 500)); */ Hermes::vector<ScalarView *> sviews(&view1, &view2, &view3, &view4); Hermes::vector<OrderView *> oviews(&oview1, &oview2, &oview3, &oview4); for (unsigned int g = 0; g < matprop.get_G(); g++) { sviews[g]->show_mesh(false); sviews[g]->set_3d_mode(true); } // DOF and CPU convergence graphs GnuplotGraph graph_dof("Error convergence", "NDOF", "log(error)"); graph_dof.add_row("H1 err. est. [%]", "r", "-", "o"); graph_dof.add_row("L2 err. est. [%]", "g", "-", "s"); graph_dof.add_row("Keff err. est. [milli-%]", "b", "-", "d"); graph_dof.set_log_y(); graph_dof.show_legend(); graph_dof.show_grid(); GnuplotGraph graph_dof_evol("Evolution of NDOF", "Adaptation step", "NDOF"); graph_dof_evol.add_row("group 1", "r", "-", "o"); graph_dof_evol.add_row("group 2", "g", "-", "x"); graph_dof_evol.add_row("group 3", "b", "-", "+"); graph_dof_evol.add_row("group 4", "m", "-", "*"); graph_dof_evol.set_log_y(); graph_dof_evol.set_legend_pos("bottom right"); graph_dof_evol.show_grid(); GnuplotGraph graph_cpu("Error convergence", "CPU time [s]", "log(error)"); graph_cpu.add_row("H1 err. est. [%]", "r", "-", "o"); graph_cpu.add_row("L2 err. est. [%]", "g", "-", "s"); graph_cpu.add_row("Keff err. est. [milli-%]", "b", "-", "d"); graph_cpu.set_log_y(); graph_cpu.show_legend(); graph_cpu.show_grid(); // Initialize the refinement selectors. H1ProjBasedSelector<double> selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER); Hermes::vector<RefinementSelectors::Selector<double>*> selectors; for (unsigned int g = 0; g < matprop.get_G(); g++) selectors.push_back(&selector); Hermes::vector<MatrixFormVol<double>*> projection_jacobian; Hermes::vector<VectorFormVol<double>*> projection_residual; for (unsigned int g = 0; g < matprop.get_G(); g++) { projection_jacobian.push_back(new H1AxisymProjectionJacobian(g)); projection_residual.push_back(new H1AxisymProjectionResidual(g, power_iterates[g])); } Hermes::vector<ProjNormType> proj_norms_h1, proj_norms_l2; for (unsigned int g = 0; g < matprop.get_G(); g++) { proj_norms_h1.push_back(HERMES_H1_NORM); proj_norms_l2.push_back(HERMES_L2_NORM); } // Initial power iteration to obtain a coarse estimate of the eigenvalue and the fission source. Hermes::Mixins::Loggable::Static::info("Coarse mesh power iteration, %d + %d + %d + %d = %d ndof:", report_num_dofs(spaces)); power_iteration(matprop, const_spaces, &wf, power_iterates, core, TOL_PIT_CM, matrix_solver); // Adaptivity loop: int as = 1; bool done = false; do { Hermes::Mixins::Loggable::Static::info("---- Adaptivity step %d:", as); // Construct globally refined meshes and setup reference spaces on them. Hermes::vector<const Space<double>*> ref_spaces_const; Hermes::vector<Mesh *> ref_meshes; for (unsigned int g = 0; g < matprop.get_G(); g++) { ref_meshes.push_back(new Mesh()); Mesh *ref_mesh = ref_meshes.back(); ref_mesh->copy(spaces[g]->get_mesh()); ref_mesh->refine_all_elements(); int order_increase = 1; ref_spaces_const.push_back(spaces[g]->dup(ref_mesh, order_increase)); } #ifdef WITH_PETSC // PETSc assembling is currently slow for larger matrices, so we switch to // UMFPACK when matrices of order >8000 start to appear. if (Space<double>::get_num_dofs(ref_spaces_const) > 8000 && matrix_solver == SOLVER_PETSC) { // Delete the old solver. delete mat; delete rhs; delete solver; // Create a new one. matrix_solver = SOLVER_UMFPACK; mat = create_matrix<double>(); rhs = create_vector<double>(); solver = create_linear_solver<double>( mat, rhs); } #endif // Solve the fine mesh problem. Hermes::Mixins::Loggable::Static::info("Fine mesh power iteration, %d + %d + %d + %d = %d ndof:", report_num_dofs(ref_spaces_const)); power_iteration(matprop, ref_spaces_const, &wf, power_iterates, core, TOL_PIT_RM, matrix_solver); // Store the results. for (unsigned int g = 0; g < matprop.get_G(); g++) fine_solutions[g]->copy((static_cast<Solution<double>*>(power_iterates[g]))); Hermes::Mixins::Loggable::Static::info("Projecting fine mesh solutions on coarse meshes."); // This is commented out as the appropriate method was deleted in the commit // "Cleaning global projections" (b282194946225014faa1de37f20112a5a5d7ab5a). //OGProjection<double> ogProjection; ogProjection.project_global(spaces, projection_jacobian, projection_residual, coarse_solutions); // Time measurement. cpu_time.tick(); // View the coarse mesh solution and meshes. for (unsigned int g = 0; g < matprop.get_G(); g++) { sviews[g]->show(coarse_solutions[g]); oviews[g]->show(spaces[g]); } // Skip visualization time. cpu_time.tick(Hermes::Mixins::TimeMeasurable::HERMES_SKIP); // Report the number of negative eigenfunction values. Hermes::Mixins::Loggable::Static::info("Num. of negative values: %d, %d, %d, %d", get_num_of_neg(coarse_solutions[0]), get_num_of_neg(coarse_solutions[1]), get_num_of_neg(coarse_solutions[2]), get_num_of_neg(coarse_solutions[3])); // Calculate element errors and total error estimate. Adapt<double> adapt_h1(spaces); Adapt<double> adapt_l2(spaces); for (unsigned int g = 0; g < matprop.get_G(); g++) { adapt_h1.set_error_form(g, g, new ErrorForm(proj_norms_h1[g])); adapt_l2.set_error_form(g, g, new ErrorForm(proj_norms_l2[g])); } // Calculate element errors and error estimates in H1 and L2 norms. Use the H1 estimate to drive adaptivity. Hermes::Mixins::Loggable::Static::info("Calculating errors."); Hermes::vector<double> h1_group_errors, l2_group_errors; double h1_err_est = adapt_h1.calc_err_est(coarse_solutions, fine_solutions, &h1_group_errors) * 100; double l2_err_est = adapt_l2.calc_err_est(coarse_solutions, fine_solutions, &l2_group_errors, false) * 100; // Time measurement. cpu_time.tick(); double cta = cpu_time.accumulated(); // Report results. Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d + %d + %d + %d = %d", report_num_dofs(spaces)); // Millipercent eigenvalue error w.r.t. the reference value (see physical_parameters.cpp). double keff_err = 1e5*fabs(wf.get_keff() - REF_K_EFF)/REF_K_EFF; Hermes::Mixins::Loggable::Static::info("per-group err_est_coarse (H1): %g%%, %g%%, %g%%, %g%%", report_errors(h1_group_errors)); Hermes::Mixins::Loggable::Static::info("per-group err_est_coarse (L2): %g%%, %g%%, %g%%, %g%%", report_errors(l2_group_errors)); Hermes::Mixins::Loggable::Static::info("total err_est_coarse (H1): %g%%", h1_err_est); Hermes::Mixins::Loggable::Static::info("total err_est_coarse (L2): %g%%", l2_err_est); Hermes::Mixins::Loggable::Static::info("k_eff err: %g milli-percent", keff_err); // Add entry to DOF convergence graph. int ndof_coarse = spaces[0]->get_num_dofs() + spaces[1]->get_num_dofs() + spaces[2]->get_num_dofs() + spaces[3]->get_num_dofs(); graph_dof.add_values(0, ndof_coarse, h1_err_est); graph_dof.add_values(1, ndof_coarse, l2_err_est); graph_dof.add_values(2, ndof_coarse, keff_err); // Add entry to CPU convergence graph. graph_cpu.add_values(0, cta, h1_err_est); graph_cpu.add_values(1, cta, l2_err_est); graph_cpu.add_values(2, cta, keff_err); for (unsigned int g = 0; g < matprop.get_G(); g++) graph_dof_evol.add_values(g, as, Space<double>::get_num_dofs(spaces[g])); cpu_time.tick(Hermes::Mixins::TimeMeasurable::HERMES_SKIP); // If err_est too large, adapt the mesh (L2 norm chosen since (weighted integrals of) solution values // are more important for further analyses than the derivatives. if (l2_err_est < ERR_STOP) done = true; else { Hermes::Mixins::Loggable::Static::info("Adapting the coarse mesh."); done = adapt_h1.adapt(selectors, THRESHOLD, STRATEGY, MESH_REGULARITY); if (spaces[0]->get_num_dofs() + spaces[1]->get_num_dofs() + spaces[2]->get_num_dofs() + spaces[3]->get_num_dofs() >= NDOF_STOP) done = true; } // Free reference meshes and spaces. for (unsigned int g = 0; g < matprop.get_G(); g++) { delete ref_spaces_const[g]; delete ref_meshes[g]; } as++; if (as >= MAX_ADAPT_NUM) done = true; } while(done == false); Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated()); for (unsigned int g = 0; g < matprop.get_G(); g++) { delete spaces[g]; delete meshes[g]; delete coarse_solutions[g], delete fine_solutions[g]; delete power_iterates[g]; } delete mat; delete rhs; delete solver; graph_dof.save("conv_dof.gp"); graph_cpu.save("conv_cpu.gp"); graph_dof_evol.save("dof_evol.gp"); // Wait for all views to be closed. View::wait(); return 0; }
int main(int argc, char* argv[]) { // Instantiate a class with global functions. Hermes2D hermes2d; // Load the mesh. Mesh mesh; H2DReader mloader; mloader.load("reactor.mesh", &mesh); // Perform initial mesh refinements. for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(); // Solution variables. Solution sln1, sln2, sln3, sln4; Hermes::vector<Solution*> solutions(&sln1, &sln2, &sln3, &sln4); // Define initial conditions. info("Setting initial conditions."); Solution iter1, iter2, iter3, iter4; iter1.set_const(&mesh, 1.00); iter2.set_const(&mesh, 1.00); iter3.set_const(&mesh, 1.00); iter4.set_const(&mesh, 1.00); Hermes::vector<MeshFunction*> iterates(&iter1, &iter2, &iter3, &iter4); // Create H1 spaces with default shapesets. H1Space space1(&mesh, P_INIT_1); H1Space space2(&mesh, P_INIT_2); H1Space space3(&mesh, P_INIT_3); H1Space space4(&mesh, P_INIT_4); Hermes::vector<Space*> spaces(&space1, &space2, &space3, &space4); int ndof = Space::get_num_dofs(spaces); info("ndof = %d.", ndof); // Initialize views. ScalarView view1("Neutron flux 1", new WinGeom(0, 0, 320, 600)); ScalarView view2("Neutron flux 2", new WinGeom(350, 0, 320, 600)); ScalarView view3("Neutron flux 3", new WinGeom(700, 0, 320, 600)); ScalarView view4("Neutron flux 4", new WinGeom(1050, 0, 320, 600)); // Do not show meshes. view1.show_mesh(false); view1.set_3d_mode(true); view2.show_mesh(false); view2.set_3d_mode(true); view3.show_mesh(false); view3.set_3d_mode(true); view4.show_mesh(false); view4.set_3d_mode(true); // Load physical data of the problem for the 4 energy groups. MaterialPropertyMaps matprop(4); matprop.set_D(D); matprop.set_Sigma_r(Sr); matprop.set_Sigma_s(Ss); matprop.set_Sigma_s_nnz_structure(Ss_nnz); matprop.set_Sigma_a(Sa); matprop.set_Sigma_f(Sf); matprop.set_nu(nu); matprop.set_chi(chi); matprop.validate(); std::cout << matprop; // Initialize the weak formulation. CustomWeakForm wf(matprop, iterates, k_eff, bdy_vacuum); // Initialize the FE problem. DiscreteProblem dp(&wf, spaces); SparseMatrix* matrix = create_matrix(matrix_solver); Vector* rhs = create_vector(matrix_solver); Solver* solver = create_linear_solver(matrix_solver, matrix, rhs); if (matrix_solver == SOLVER_AZTECOO) { ((AztecOOSolver*) solver)->set_solver(iterative_method); ((AztecOOSolver*) solver)->set_precond(preconditioner); // Using default iteration parameters (see solver/aztecoo.h). } // Time measurement. TimePeriod cpu_time, solver_time; // Initial coefficient vector for the Newton's method. scalar* coeff_vec = new scalar[ndof]; // Force the Jacobian assembling in the first iteration. bool Jacobian_changed = true; // In the following iterations, Jacobian will not be changing; its LU factorization // may be reused. solver->set_factorization_scheme(HERMES_REUSE_FACTORIZATION_COMPLETELY); // Main power iteration loop: int it = 1; bool done = false; do { info("------------ Power iteration %d:", it); info("Newton's method (matrix problem solved by %s).", MatrixSolverNames[matrix_solver].c_str()); memset(coeff_vec, 0.0, ndof*sizeof(scalar)); //TODO: Why it doesn't work without zeroing coeff_vec in each iteration? solver_time.tick(HERMES_SKIP); if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs, Jacobian_changed, 1e-8, 10, true)) error("Newton's iteration failed."); solver_time.tick(); Solution::vector_to_solutions(solver->get_solution(), spaces, solutions); // Show intermediate solutions. view1.show(&sln1); view2.show(&sln2); view3.show(&sln3); view4.show(&sln4); // Compute eigenvalue. SourceFilter source(solutions, matprop); SourceFilter source_prev(iterates, matprop); double k_new = k_eff * (integrate(&source, core) / integrate(&source_prev, core)); info("Largest eigenvalue: %.8g, rel. difference from previous it.: %g", k_new, fabs((k_eff - k_new) / k_new)); // Stopping criterion. if (fabs((k_eff - k_new) / k_new) < ERROR_STOP) done = true; // Update eigenvalue. k_eff = k_new; wf.update_keff(k_eff); if (!done) { // Save solutions for the next iteration. iter1.copy(&sln1); iter2.copy(&sln2); iter3.copy(&sln3); iter4.copy(&sln4); // Don't need to reassemble the system matrix in further iterations, // only the rhs changes to reflect the progressively updated source. Jacobian_changed = false; it++; } } while (!done); delete [] coeff_vec; // Time measurement. cpu_time.tick(); solver_time.tick(HERMES_SKIP); // Print timing information. verbose("Average solver time for one power iteration: %g s", solver_time.accumulated() / it); // Clean up. delete matrix; delete rhs; delete solver; // Show solutions. view1.show(&sln1); view2.show(&sln2); view3.show(&sln3); view4.show(&sln4); // Skip visualization time. cpu_time.tick(HERMES_SKIP); // Print timing information. verbose("Total running time: %g s", cpu_time.accumulated()); // Wait for all views to be closed. View::wait(); return 0; }