Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
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;
}
main(int argc, char *argv[]) {
  char name[256];
  int i,j,k,squareSize,maxCZ;
  double radiusL,radiusC,num;
  double x1,y1,z1,xy1;
  double x2,y2,z2,xy2;
  double x3,y3,z3,xy3;
  
  GraphicsSpace space1("lightTest1.ppm");
  space1.createImage(301,301);

  space1.addSphere(100,100,0, 45, 255,0,0, 1,.5,.5,30);
  space1.addSphere(0,100,0, 45, 255,255,0, 1,1,1,30);
  space1.addSphere(-100,100,0, 45, 255,255,255, 1,.5,.5,30);
  space1.addSphere(-100,0,0, 45, 0,255,255, 1,1,1,30);
  space1.addSphere(-100,-100,0, 45, 0,255,0, 1,.5,.5,30);
  space1.addSphere(0,-100,0, 45, 255,0,255, 1,1,1,30);
  space1.addSphere(100,-100,0, 45, 0,0,255, 1,.5,.5,30);
  space1.addSphere(100,0,0, 45, 128,128,255, 1,1,1,30);
  
  //lighting
  space1.addLightAmbient(.5);
  //space1.addLightPoint(0,0,-100, 1, 255,255,255);

  space1.setCamera(0,0,-600);
  space1.setViewPlaneCenter(0,0,-30);
  space1.setViewPlaneNormal(1,1,1);//not important right now
  //render image
  space1.render();
  space1.writeImage();
  
  
  //image 2
  GraphicsSpace space2("lightTest2.ppm");
  space2.createImage(301,301);
  // space2.setBackground(255,255,255);

  space2.addSphere(100,100,0, 45, 255,0,0, 1,.5,.5,30);
  space2.addSphere(0,100,0, 45, 255,255,0, 1,1,1,30);
  space2.addSphere(-100,100,0, 45, 255,255,255, 1,.5,.5,30);
  space2.addSphere(-100,0,0, 45, 0,255,255, 1,1,1,30);
  space2.addSphere(-100,-100,0, 45, 0,255,0, 1,.5,.5,30);
  space2.addSphere(0,-100,0, 45, 255,0,255, 1,1,1,30);
  space2.addSphere(100,-100,0, 45, 0,0,255, 1,.5,.5,30);
  space2.addSphere(100,0,0, 45, 128,128,255, 1,1,1,30);
  
  //lighting
  //space2.addLightAmbient(.5);
  space2.addLightPoint(0,0,-100, 1, 255,255,255);

  space2.setCamera(0,0,-600);
  space2.setViewPlaneCenter(0,0,-30);
  space2.setViewPlaneNormal(1,1,1);//not important right now
  //render image
  space2.render();
  space2.writeImage();
  

  GraphicsSpace space4("lightTest4.ppm");
  space4.createImage(501,501);

  for (i=-250;i<=250;i+=100)
    for (j=-250;j<=250;j+=100){
      space4.addSphere(i,j,0, 30, 0,255,0, 1,1,.5,30);
    }
  
  space4.addPlane(0,0,50, 0,0,1, 0,0,255, 1,.8,1,30);
  //lighting
  space4.addLightAmbient(.1);
  space4.addLightPoint(50,50,-200, 1, 255,255,255);

  space4.setCamera(0,0,-600);
  space4.setViewPlaneCenter(0,0,-30);
  space4.setViewPlaneNormal(1,1,1);//not important right now
  //render image
  space4.render();
  space4.writeImage();


  GraphicsSpace space5("lightTest5.ppm");
  space5.createImage(501,501);

  space5.addPlane(0,0,-100, 0,0,1, 100,100,100, 1,.8,1,30);
  
  space5.addSphere(300,0,0, 100, 255,0,0, 1,1,1,30);
  //pyramid
  space5.addTriangle(-100,-100,-100, -100,100,-100, 0,0,100, 0,255,0, 1,1,1,30);
  space5.addTriangle(-100,-100,-100, 100,-100,-100, 0,0,100, 0,255,0, 1,1,1,30);
  space5.addTriangle(100,100,-100, -100,100,-100, 0,0,100, 0,255,0, 1,1,1,30);
  space5.addTriangle(100,100,-100, 100,-100,-100, 0,0,100, 0,255,0, 1,1,1,30);
  //cube
  ////base top
  space5.addTriangle(-200,-100,-100, -200,100,-100, -400,-100,-100, 0,0,255, 1,1,1,30);
  space5.addTriangle(-400,100,-100, -200,100,-100, -400,-100,-100, 0,0,255, 1,1,1,30);
  space5.addTriangle(-200,-100,100, -200,100,100, -400,-100,100, 0,0,255, 1,1,1,30);
  space5.addTriangle(-400,100,100, -200,100,100, -400,-100,100, 0,0,255, 1,1,1,30);
  
  ////left right
  space5.addTriangle(-400,100,-100, -400,100,100, -200,100,100, 0,0,255, 1,1,1,30);
  space5.addTriangle(-400,100,-100, -200,100,-100, -200,100,100, 0,0,255, 1,1,1,30);
  space5.addTriangle(-400,-100,-100, -400,-100,100, -200,-100,100, 0,0,255, 1,1,1,30);
  space5.addTriangle(-400,-100,-100, -200,-100,-100, -200,-100,100, 0,0,255, 1,1,1,30);
  
  ////other left right
  space5.addTriangle(-200,-100,-100, -200,100,100, -200,-100,100, 0,0,255, 1,1,1,30);
  space5.addTriangle(-200,-100,-100, -200,100,100, -200,100,-100, 0,0,255, 1,1,1,30);
  space5.addTriangle(-400,-100,-100, -400,100,100, -400,-100,100, 0,0,255, 1,1,1,30);
  space5.addTriangle(-400,-100,-100, -400,100,100, -400,100,-100, 0,0,255, 1,1,1,30);

  //lighting
  space5.addLightAmbient(.1);
  space5.addLightPoint(0,300,400, 1, 100,100,100);
  space5.addLightPoint(-500,300,400, 1, 50,50,50);


  space5.setCamera(0,0,900);
  space5.setViewPlaneCenter(0,0,300);
  space5.setViewPlaneNormal(1,1,1);//not important right now
  //render image
  space5.render();
  space5.writeImage();

//image 3
  GraphicsSpace space3("lightTest3.ppm");
     space3.createImage(501,501);
     
       // create edge planes
         
        space3.addPlane(300,0,0, 1,0,0, 255,255,255, 1,.8,1,30);
          space3.addPlane(-300,0,0, 1,0,0, 255,255,255, 1,.8,1,30);
          space3.addPlane(0,300,0, 0,1,0, 255,255,255, 1,.8,1,30);
          space3.addPlane(0,-300,0, 0,1,0, 255,255,255, 1,.8,1,30);
      radiusL=200;
     radiusC=50;
     num=12;
     
     // create outside circles
                            
                            for (i=0;i<360;i+=360/num){
                                x1=radiusL*cos((double)i*PI/180.0);
                                y1=radiusL*sin((double)i*PI/180.0);
                                space3.addSphere(x1,y1,60, radiusC, 255,0,0, 1,(double)i/360+1/num,(double)i/360+1/num,((double)i/360+1/num)*30);
                              }
                 
              //         // 
                      //   //create center circle with triangles
                        num=24;
                                 radiusC=100;
                                 for (k=0;k<num/2;k++){
                                   z1=radiusC*cos((double)k*PI*360/(num*180.0));
                                   xy1=radiusC*sin((double)k*PI*360/(num*180.0));
                                   
                                   z2=radiusC*cos((double)(k+1)*PI*360/(num*180.0));
                                   xy2=radiusC*sin((double)(k+1)*PI*360/(num*180.0));
                                   
                                   z3=radiusC*cos((double)(k+1)*PI*360/(num*180.0));
                                   xy3=radiusC*sin((double)(k+1)*PI*360/(num*180.0));
                                   if (k%2==1){
                                     for (i=0;i<num;i++){
                               x1=xy1*cos((double)i*PI*360/(num*180));
                               y1=xy1*sin((double)i*PI*360/(num*180));
                               
                               x2=xy2*cos(((double)i-.5)*PI*360/(num*180));
                               y2=xy2*sin(((double)i-.5)*PI*360/(num*180));
                               
                               x3=xy3*cos(((double)i+.5)*PI*360/(num*180));
                               y3=xy3*sin(((double)i+.5)*PI*360/(num*180));
                               
                               space3.addTriangle(z1,y1,x1,z2,y2,x2,z3,y3,x3, 0,0,255, 1,1,1,30);
                                     }
                                   } else {
                                     for (i=0;i<num;i++){
                               x1=xy1*cos(((double)i+.5)*PI*360/(num*180));
                               y1=xy1*sin(((double)i+.5)*PI*360/(num*180));
                               
                               x2=xy2*cos(((double)i)*PI*360/(num*180));
                               y2=xy2*sin(((double)i)*PI*360/(num*180));
                               
                               x3=xy3*cos(((double)i+1)*PI*360/(num*180));
                               y3=xy3*sin(((double)i+1)*PI*360/(num*180));
                               
                               space3.addTriangle(z1,y1,x1,z2,y2,x2,z3,y3,x3, 0,0,255, 1,1,1,30);
                                     }
                                   }
                                   
                                   if (k>0){
                                     z1=radiusC*cos((double)(k+1)*PI*360/(num*180.0));
                                     xy1=radiusC*sin((double)(k+1)*PI*360/(num*180.0));
                                     
                                     z2=radiusC*cos((double)(k)*PI*360/(num*180.0));
                                     xy2=radiusC*sin((double)(k)*PI*360/(num*180.0));
                                     
                                     z3=radiusC*cos((double)(k)*PI*360/(num*180.0));
                                     xy3=radiusC*sin((double)(k)*PI*360/(num*180.0));
                                    
                                     if (k%2==0){
                               for (i=0;i<num;i++){
                                 x1=xy1*cos((double)i*PI*360/(num*180));
                                 y1=xy1*sin((double)i*PI*360/(num*180));
                                 
                                 x2=xy2*cos(((double)i-.5)*PI*360/(num*180));
                                 y2=xy2*sin(((double)i-.5)*PI*360/(num*180));
                                 
                                 x3=xy3*cos(((double)i+.5)*PI*360/(num*180));
                                 y3=xy3*sin(((double)i+.5)*PI*360/(num*180));
                                 
                                 space3.addTriangle(z1,y1,x1,z2,y2,x2,z3,y3,x3, 0,0,255, 1,1,1,30);
                               }
                                     } else {
                               for (i=0;i<num;i++){
                                 x1=xy1*cos(((double)i+.5)*PI*360/(num*180));
                                 y1=xy1*sin(((double)i+.5)*PI*360/(num*180));
                                 
                                 x2=xy2*cos(((double)i)*PI*360/(num*180));
                                 y2=xy2*sin(((double)i)*PI*360/(num*180));
                                 
                                 x3=xy3*cos(((double)i+1)*PI*360/(num*180));
                                 y3=xy3*sin(((double)i+1)*PI*360/(num*180));
                                 
                                 space3.addTriangle(z1,y1,x1,z2,y2,x2,z3,y3,x3, 0,0,255, 1,1,1,30);
                               }
                                     } 
                                   }
                                 }
                                 
              //     
     //lighting
     space3.addLightPoint(0,0,-200, 1, 255,255,255);
     
     space3.setCamera(0,0,-600);
     space3.setViewPlaneCenter(0,0,-30);
     space3.setViewPlaneNormal(1,1,1);//not important right now
     //render image
     space3.render();
     space3.writeImage();
     
}
Beispiel #5
0
void X86_Stm_print (S s)
{
  Assert_ASSERT(s);
  switch (s->kind){
  case X86_STM_MOVERR:
    space4 ();
    print ("movl ");
    X86_Register_print (s->u.moverr.src);
    print (", ");
    X86_Register_print (s->u.moverr.dest);
    break;
  case X86_STM_MOVERI:
    space4 ();
    print ("movl $");
    print (Int_toString (s->u.moveri.src));
    print (", ");    
    X86_Register_print (s->u.moveri.dest);
    break;
  case X86_STM_LOAD:
    space4 ();
    print ("movl ");
    X86_Operand_print (s->u.load.src);
    print (", ");
    X86_Register_print (s->u.load.dest);
    break;
  case X86_STM_STORE:
    space4 ();
    print ("movl ");
    X86_Register_print (s->u.store.src);
    print (", ");
    X86_Operand_print (s->u.store.dest);
    break;
  case X86_STM_BOP:
    space4 ();
    X86_Operator_print (s->u.bop.op);
    X86_Register_print (s->u.bop.src);
    print (", ");
    X86_Register_print (s->u.bop.dest);
    break;
  case X86_STM_UOP:
    space4 ();
    X86_Operator_print (s->u.uop.op);
    X86_Register_print (s->u.uop.dest);
    break;
  case X86_STM_CALL:
    space4 ();
    print ("call ");
    print (Id_toString (s->u.call.name));
    break;
  case X86_STM_CMP:
    space4 ();
    print ("cmpl ");
    X86_Register_print (s->u.cmp.src);
    print (", ");
    X86_Register_print (s->u.cmp.dest);
    break;
  case X86_STM_LABEL:
    space2();
    print (Label_toString (s->u.label));
    print (":");
    break;
  case X86_STM_JE:
    space4 ();
    print ("je ");
    print (Label_toString (s->u.je));
    break;
  case X86_STM_JL:
    space4 ();
    print ("jl ");
    print (Label_toString (s->u.je));
    break;
  case X86_STM_JUMP:
    space4 ();
    print ("jmp ");
    print (Label_toString (s->u.jump));
    break;
  case X86_STM_PUSH:
    space4 ();
    print ("pushl ");
    X86_Register_print (s->u.push);
    break;
  case X86_STM_NEG:
    space4 ();
    print ("negl ");
    X86_Register_print (s->u.neg);
    break;
  case X86_STM_SETL:
    space4 ();
    print ("setl ");
    X86_Register_print (s->u.setAny);
    break;
  case X86_STM_SETLE:
    space4 ();
    print ("setle ");
    X86_Register_print (s->u.setAny);
    break;
  case X86_STM_SETG:
    space4 ();
    print ("setg ");
    X86_Register_print (s->u.setAny);
    break;
  case X86_STM_SETGE:
    space4 ();
    print ("setge ");
    X86_Register_print (s->u.setAny);
    break;
  case X86_STM_SETE:
    space4 ();
    print ("sete ");
    X86_Register_print (s->u.setAny);
    break;
  case X86_STM_SETNE:
    space4 ();
    print ("setne ");
    X86_Register_print (s->u.setAny);
    break;
  case X86_STM_XOR:
    space4 ();
    print ("xorl ");
    X86_Register_print (s->u.xor.src);
    print (", ");
    X86_Register_print (s->u.xor.dest);
    break;
  case X86_STM_EXTENDAL:
    space4 ();
    print ("cbtw\n");
    space4 ();
    print ("cwtl");
    break;
  case X86_STM_NOT:{
    space4 ();
    print ("notl ");
    X86_Register_print (s->u.not);
    break;
  }
  case X86_STM_RETURN:
    space4 ();
    print ("leave\n\tret");
    break;
  case X86_STM_CLTD:
    space4 ();
    print ("cltd");
    break;
  case X86_STM_INC:
    space4 ();
    print ("incl ");
    X86_Register_print (s->u.inc);
    break;
  default:
    Error_impossible();
    break;
  }
  print ("\n");
  return;
}
Beispiel #6
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;
}