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; }
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; }