Exemple #1
0
int main(int argc, char* argv[])
{
  // Load the mesh.
  Mesh mesh;
  MeshReaderH2D mloader;
  mloader.load("motor.mesh", &mesh);

  // Initialize the weak formulation.
  CustomWeakFormPoisson wf("Motor", EPS_MOTOR, "Air", EPS_AIR, &mesh);
  
  // Initialize boundary conditions
  DefaultEssentialBCConst<double> bc_essential_out("Outer", 0.0);
  DefaultEssentialBCConst<double> bc_essential_stator("Stator", VOLTAGE);
  EssentialBCs<double> bcs(Hermes::vector<EssentialBoundaryCondition<double> *>(&bc_essential_out, &bc_essential_stator));

  // Create an H1 space with default shapeset.
  H1Space<double> space(&mesh, &bcs, P_INIT);

  // Initialize coarse and reference mesh solution.
  Solution<double> sln;

  // Initialize views.
  Views::ScalarView sview("Solution", new Views::WinGeom(0, 0, 410, 600));
  sview.fix_scale_width(50);
  sview.show_mesh(false);
  Views::OrderView  oview("Polynomial orders", new Views::WinGeom(420, 0, 400, 600));

  // DOF and CPU convergence graphs initialization.
  SimpleGraph graph_dof, graph_cpu;

  // Time measurement.
  Hermes::Mixins::TimeMeasurable cpu_time;

  // Adaptivity loop:
  int as = 1; bool done = false;
  do
  {
    Hermes::Mixins::Loggable::Static::info("---- Adaptivity step %d:", as);
    
    // Time measurement.
    cpu_time.tick();

    // Initialize reference problem.
    Hermes::Mixins::Loggable::Static::info("Solving.");
    DiscreteProblem<double> dp(&wf, &space);
    
    NewtonSolver<double> newton(&dp);
    newton.set_verbose_output(false);

    // Initial ndof.
    int ndof = space.get_num_dofs();

    // Perform Newton's iteration.
    try
    {
      newton.solve();
    }
    catch(std::exception& e)
    {
      std::cout << e.what();
      
    }
    // Translate the resulting coefficient vector into the instance of Solution.
    Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln);
    
    // Time measurement.
    cpu_time.tick();

    // VTK output.
    if (VTK_VISUALIZATION) 
    {
      // Output solution in VTK format.
      Views::Linearizer lin;
      char* title = new char[100];
      sprintf(title, "sln-%d.vtk", as);
      lin.save_solution_vtk(&sln, title, "Potential", false);
      Hermes::Mixins::Loggable::Static::info("Solution in VTK format saved to file %s.", title);

      // Output mesh and element orders in VTK format.
      Views::Orderizer ord;
      sprintf(title, "ord-%d.vtk", as);
      ord.save_orders_vtk(&space, title);
      Hermes::Mixins::Loggable::Static::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();
    
    // Calculate element errors and total error estimate.
    Hermes::Mixins::Loggable::Static::info("Calculating error estimate.");
    bool ignore_visited_segments = true;
    KellyTypeAdapt<double> adaptivity(&space, ignore_visited_segments, 
                                      USE_EPS_IN_INTERFACE_ESTIMATOR 
                                        ? 
                                          new CustomInterfaceEstimatorScalingFunction("Motor", EPS_MOTOR, "Air", EPS_AIR)
                                        :
                                          new CustomInterfaceEstimatorScalingFunction);
    
    adaptivity.add_error_estimator_surf(new Hermes::Hermes2D::BasicKellyAdapt<double>::ErrorEstimatorFormKelly());
    
    if (USE_RESIDUAL_ESTIMATOR) 
    {
      adaptivity.add_error_estimator_vol(new ResidualErrorFormMotor("Motor", EPS_MOTOR));
      adaptivity.add_error_estimator_vol(new ResidualErrorFormAir("Air", EPS_AIR));
    }
    
    if (USE_EPS_IN_INTERFACE_ESTIMATOR)
      // Use normalization by energy norm.
      adaptivity.set_error_form(new EnergyErrorForm(&wf));
    
    // Note that there is only one solution (the only one available) passed to BasicKellyAdapt::calc_err_est
    // and there is also no "solutions_for_adapt" parameter. The last parameter, "error_flags", is left 
    // intact and has the meaning explained in P04-adaptivity/01-intro. You may however still call
    // adaptivity.calc_err_est with a solution, an exact solution and solutions_for_adapt=false to calculate
    // error wrt. an exact solution (if provided). 
    double err_est_rel = adaptivity.calc_err_est(&sln, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100;

    // Report results.
    Hermes::Mixins::Loggable::Static::info("ndof: %d, err_est_rel: %g%%", space.get_num_dofs(), err_est_rel);

    // Add entry to DOF and CPU convergence graphs.
    cpu_time.tick();    
    graph_cpu.add_values(cpu_time.accumulated(), err_est_rel);
    graph_cpu.save("conv_cpu_est.dat");
    graph_dof.add_values(space.get_num_dofs(), err_est_rel);
    graph_dof.save("conv_dof_est.dat");
    
    // Skip the time spent to save the convergence graphs.
    cpu_time.tick();

    // If err_est too large, adapt the mesh.
    if (err_est_rel < ERR_STOP) 
      done = true;
    else
    {
      Hermes::Mixins::Loggable::Static::info("Adapting coarse mesh.");
      
      // h-refinement is automatically selected here, no need for parameter "selector".
      done = adaptivity.adapt(THRESHOLD, STRATEGY, MESH_REGULARITY);

      // Increase the counter of performed adaptivity steps.
      if (done == false)  
        as++;
    }
    if (space.get_num_dofs() >= NDOF_STOP) 
      done = true;
  }
  while (done == false);

  Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated());

  // The final result has already been shown in the final step of the adaptivity loop, so we only
  // adjust the title and hide the mesh here.
  sview.set_title("Fine mesh solution");
  sview.show_mesh(false);

  // Wait for all views to be closed.
  Views::View::wait();

  return 0;
}
int main(int argc, char* argv[])
{
  // Define problem parameters: (x_loc, y_loc) is the center of the circular wave front, R_ZERO is the distance from the 
  // wave front to the center of the circle, and alpha gives the steepness of the wave front.
  double alpha, x_loc, y_loc, r_zero;
  switch(PARAM) {
  case 0:
    alpha = 20;
    x_loc = -0.05;
    y_loc = -0.05;
    r_zero = 0.7;
    break;
  case 1:
    alpha = 1000;
    x_loc = -0.05;
    y_loc = -0.05;
    r_zero = 0.7;
    break;
  case 2:
    alpha = 1000;
    x_loc = 1.5;
    y_loc = 0.25;
    r_zero = 0.92;
    break;
  case 3:
    alpha = 50;
    x_loc = 0.5;
    y_loc = 0.5;
    r_zero = 0.25;
    break;
  default:   
    // The same as 0.
    alpha = 20;
    x_loc = -0.05;
    y_loc = -0.05;
    r_zero = 0.7;
    break;
  }
  
  // Set adaptivity options according to the command line argument.
  int refinement_mode;
  if (argc != 2)
    refinement_mode = 0;
  else
  {
    refinement_mode = atoi(argv[1]);
    if (refinement_mode < 1 || refinement_mode > 12)
      throw Hermes::Exceptions::Exception("Invalid run case: %d (valid range is [1,12])", refinement_mode);
  }
  
  double threshold = 0.3;                     
  // strategy = 0 ... Refine elements until sqrt(threshold) times total error is processed. 
  //                  If more elements have similar errors, refine all to keep the mesh symmetric.
  int strategy = 0;       
  // strategy = 1 ... Refine all elements whose error is larger than threshold times max. element error.
  // Add also the norm of the residual to the error estimate of each element.
  bool use_residual_estimator = false;        
  // Use energy norm for error estimate normalization and measuring of exact error.
  bool use_energy_norm_normalization = false; 
  
  switch (refinement_mode)
  {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    {
      strategy = 0;
      break;
    }
    
    case 7 :
    case 8 :
    case 9 :
    case 10:
    case 11:
    case 12:
    {
      strategy = 1;
      break;
    }
  }
  
  switch (refinement_mode)
  {
    case 1:
    case 2:
    case 3:
    case 7:
    case 8:
    case 9:
    {
      threshold = 0.3;
      break;
    }
    
    case 4:
    case 5:
    case 6:
    case 10:
    case 11:
    case 12:
    {
      threshold = 0.3*0.3;
      break;
    }
  }
  
  switch (refinement_mode)
  {
    case 2:
    case 3:
    case 5:
    case 6:
    case 8:
    case 9:
    case 11:
    case 12:
    {
      use_residual_estimator = true;
      break;
    }
  }
  
  switch (refinement_mode)
  {
    case 3:
    case 6:
    case 9:
    case 12:
    {
      use_energy_norm_normalization = true;
      break;
    }
  }
  
  double setup_time = 0, assemble_time = 0, solve_time = 0, adapt_time = 0;
  
  // Time measurement.
  Hermes::Mixins::TimeMeasurable wall_clock;
  // Stop counting time for adaptation.
  wall_clock.tick(); 

  // Load the mesh.
  Mesh mesh;
  MeshReaderH2D mloader;
  mloader.load("square_quad.mesh", &mesh);    

  // Perform initial mesh refinement.
  for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements();
  
  // Stop counting time for adaptation.
  wall_clock.tick(); 
  adapt_time += wall_clock.last();
  
  // Set exact solution.
  CustomExactSolution exact(&mesh, alpha, x_loc, y_loc, r_zero);

  // Define right-hand side.
  CustomRightHandSide rhs(alpha, x_loc, y_loc, r_zero);

  // Initialize the weak formulation.
  CustomWeakForm wf(&rhs);
  // Equivalent, but slower:
  // DefaultWeakFormPoisson<double> wf(Hermes::HERMES_ANY, HERMES_ONE, &rhs);

  // Initialize boundary conditions.
  DefaultEssentialBCNonConst<double> bc("Bdy", &exact);
  EssentialBCs<double> bcs(&bc);

  // Create an H1 space with default shapeset.
  H1Space<double> space(&mesh, &bcs, P_INIT);
  
  // Initialize approximate solution.
  Solution<double> sln;
  
  // Initialize views.
  Views::ScalarView sview("Solution", new Views::WinGeom(800, 0, 400, 400));
  sview.show_mesh(false);
  sview.set_3d_mode();
  sview.set_palette(Views::H2DV_PT_HUESCALE);
  sview.fix_scale_width(50);
  Views::OrderView  oview("Mesh", new Views::WinGeom(0, 0, 800, 800));
  oview.set_palette(Views::H2DV_PT_INVGRAYSCALE);

  // DOF and CPU convergence graphs.
  ConvergenceTable conv_table;
  conv_table.add_column(" cycle ", "%6d ");
  conv_table.add_column("  H1 error ", " %.4e ");
  conv_table.add_column("   ndof  ", " %6d ");
  conv_table.add_column(" total time ", " %8.3f  ");
  conv_table.add_column(" setup time ", "  %8.3f  ");
  conv_table.add_column(" assem time ", "  %8.3f  ");
  conv_table.add_column(" solve time ", "  %8.3f  ");
  conv_table.add_column(" adapt time ", "  %8.3f  ");
  
  wall_clock.tick(Hermes::Mixins::TimeMeasurable::HERMES_SKIP);

  // Adaptivity loop:
  int as = 0; bool done = false;
  do
  {
    // Start counting setup time.
    wall_clock.tick(); 
    
    // Assemble the discrete problem.    
    DiscreteProblem<double> dp(&wf, &space);

    // Actual ndof.
    int ndof = space.get_num_dofs();
    
    NewtonSolver<double> newton(&dp);
    newton.set_verbose_output(false);

    // Setup time continues in NewtonSolver::solve().
    try
    {
      newton.solve();
    }
    catch(Hermes::Exceptions::Exception e)
    {
      e.printMsg();
      throw Hermes::Exceptions::Exception("Newton's iteration failed.");
    };

    setup_time += newton.get_setup_time();
    assemble_time += newton.get_assemble_time();
    solve_time += newton.get_solve_time();
     
    // Start counting time for adaptation.
    wall_clock.tick();  
    Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln);
    
    double err_exact = Global<double>::calc_abs_error(&sln, &exact, HERMES_H1_NORM);
   
    // Report results.
    Hermes::Mixins::Loggable::Static::info(" Cycle %d:", as);
    Hermes::Mixins::Loggable::Static::info("    Number of degrees of freedom: %d", ndof);
    Hermes::Mixins::Loggable::Static::info("    H1 error w.r.t. exact soln.:  %g", err_exact);
    
    // Stop counting time for adaptation.
    wall_clock.tick(); 
    double accum_time = wall_clock.accumulated();
    adapt_time += wall_clock.last();
    
    // View the approximate solution and polynomial orders.
    //sview.show(&sln);
    //oview.show(&space);
    //Views::View::wait(Views::HERMES_WAIT_KEYPRESS);
    
    conv_table.add_value(0, as);
    conv_table.add_value(1, err_exact);
    conv_table.add_value(2, ndof);
    conv_table.add_value(3, accum_time);
    conv_table.add_value(4, setup_time);
    conv_table.add_value(5, assemble_time);
    conv_table.add_value(6, solve_time);
    conv_table.add_value(7, adapt_time);
    
    // Start counting time for adaptation.
    wall_clock.tick(); 
    
    if (err_exact < ERR_STOP) 
      done = true;
    else
    {
      // Calculate element errors and total error estimate.
      Hermes::Hermes2D::BasicKellyAdapt<double> adaptivity(&space);
      
      unsigned int error_flags = HERMES_TOTAL_ERROR_ABS;
      
      if (use_energy_norm_normalization)
      {
        error_flags |= HERMES_ELEMENT_ERROR_REL;
        adaptivity.set_error_form(new EnergyErrorForm(&wf));
      }
      else
        error_flags |= HERMES_ELEMENT_ERROR_ABS;
      
      if (use_residual_estimator) 
        adaptivity.add_error_estimator_vol(new ResidualErrorForm(&rhs));
      
      double err_est_rel = adaptivity.calc_err_est(&sln, error_flags);  
      
      done = adaptivity.adapt(threshold, strategy, MESH_REGULARITY);
      
      // Stop counting time for adaptation.
      wall_clock.tick(); 
      adapt_time += wall_clock.last();
    }
        
    // Increase the counter of performed adaptivity steps.
    if (done == false)  
      as++;
    else
    {
      Hermes::Mixins::Loggable::Static::info("Total running time:  %g s", wall_clock.accumulated());
      Hermes::Mixins::Loggable::Static::info("   Setup:            %g s", setup_time);
      Hermes::Mixins::Loggable::Static::info("   Assemble:         %g s", assemble_time);
      Hermes::Mixins::Loggable::Static::info("   Solve:            %g s", solve_time);
      Hermes::Mixins::Loggable::Static::info("   Adapt:            %g s", adapt_time);
      
      //sview.show(&sln);
      oview.show(&space);
      oview.save_screenshot(("final_mesh-"+itos(refinement_mode)+".bmp").c_str());
      oview.close();
      conv_table.save(("conv_table-"+itos(refinement_mode)+".dat").c_str());
    }
  }
  while (done == false);

  // Wait for all views to be closed.
  //Views::View::wait();
  return 0;
}
int main(int argc, char* argv[])
{
  // Define problem parameters: (x_loc, y_loc) is the center of the circular wave front, R_ZERO is the distance from the 
  // wave front to the center of the circle, and alpha gives the steepness of the wave front.
  double alpha, x_loc, y_loc, r_zero;
  switch(PARAM) {
  case 0:
    alpha = 20;
    x_loc = -0.05;
    y_loc = -0.05;
    r_zero = 0.7;
    break;
  case 1:
    alpha = 1000;
    x_loc = -0.05;
    y_loc = -0.05;
    r_zero = 0.7;
    break;
  case 2:
    alpha = 1000;
    x_loc = 1.5;
    y_loc = 0.25;
    r_zero = 0.92;
    break;
  case 3:
    alpha = 50;
    x_loc = 0.5;
    y_loc = 0.5;
    r_zero = 0.25;
    break;
  default:   // The same as 0.
    alpha = 20;
    x_loc = -0.05;
    y_loc = -0.05;
    r_zero = 0.7;
    break;
  }

  // Load the mesh.
  Mesh mesh;
  H2DReader mloader;
  mloader.load("square_quad.mesh", &mesh);     // quadrilaterals
  // mloader.load("square_tri.mesh", &mesh);   // triangles

  // Perform initial mesh refinement.
  for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements();
  
  // Set exact solution.
  CustomExactSolution exact(&mesh, alpha, x_loc, y_loc, r_zero);

  // Define right-hand side.
  CustomRightHandSide rhs(alpha, x_loc, y_loc, r_zero);

  // Initialize the weak formulation.
  CustomWeakForm wf(&rhs);
  // Equivalent, but slower:
  // DefaultWeakFormPoisson<double> wf(Hermes::HERMES_ANY, HERMES_ONE, &rhs);

  // Initialize boundary conditions.
  DefaultEssentialBCNonConst<double> bc("Bdy", &exact);
  EssentialBCs<double> bcs(&bc);

  // Create an H1 space with default shapeset.
  H1Space<double> space(&mesh, &bcs, P_INIT);
  
  // Initialize approximate solution.
  Solution<double> sln;

  // Initialize views.
  Views::ScalarView<double> sview("Solution", new Views::WinGeom(0, 0, 440, 350));
  sview.show_mesh(false);
  sview.fix_scale_width(50);
  Views::OrderView<double>  oview("Polynomial orders", new Views::WinGeom(450, 0, 420, 350));

  // DOF and CPU convergence graphs.
  SimpleGraph graph_dof, graph_cpu, graph_dof_exact, graph_cpu_exact;

  // Time measurement.
  Hermes::TimePeriod cpu_time;

  // Adaptivity loop:
  int as = 1; bool done = false;
  do
  {
    info("---- Adaptivity step %d (%d DOF):", as, space.get_num_dofs());
    cpu_time.tick();

    // Assemble the discrete problem.    
    DiscreteProblem<double> dp(&wf, &space);

    // Initial coefficient vector for the Newton's method.  
    int ndof = space.get_num_dofs();
    double* coeff_vec = new double[ndof];
    memset(coeff_vec, 0, ndof * sizeof(double));
    
    NewtonSolver<double> newton(&dp, matrix_solver_type);
    newton.set_verbose_output(false);

    if (!newton.solve(coeff_vec)) 
      error("Newton's iteration failed.");
    else
      Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln);
    
    cpu_time.tick();
    verbose("Solution: %g s", cpu_time.last());
    
    // Calculate element errors and total error estimate.
    BasicKellyAdapt<double> adaptivity(&space);
    
    if (USE_ENERGY_NORM_NORMALIZATION)
      adaptivity.set_error_form(new EnergyErrorForm(&wf));

    if (USE_RESIDUAL_ESTIMATOR) 
      adaptivity.add_error_estimator_vol(new ResidualErrorForm(&rhs));
    
    double err_est_rel = adaptivity.calc_err_est(&sln) * 100;  
    double err_exact_rel = Global<double>::calc_rel_error(&sln, &exact, HERMES_H1_NORM) * 100;
    
    cpu_time.tick();
    verbose("Error calculation: %g s", cpu_time.last());
    
    info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel);

    if (TEST_ELEMENT_BASED_KELLY)
    {
      cpu_time.tick();
      
      // Ensure that the two possible approaches to interface error estimators accumulation give same results.
      KellyTypeAdapt<double> adaptivity2(&space, false);
      adaptivity2.disable_aposteriori_interface_scaling();
      adaptivity2.add_error_estimator_surf(new InterfaceErrorForm);
      
      if (USE_ENERGY_NORM_NORMALIZATION)
        adaptivity2.set_error_form(new EnergyErrorForm(&wf));
      
      if (USE_RESIDUAL_ESTIMATOR) 
      {
        adaptivity2.add_error_estimator_vol(new ResidualErrorForm(&rhs));
        adaptivity2.set_volumetric_scaling_const(1./24.);
      }
      
      double err_est_rel2 = adaptivity2.calc_err_est(&sln) * 100;  
      double err_exact_rel2 = adaptivity2.calc_err_exact(&sln, &exact, false) * 100;
      
      info("err_est_rel_2: %g%%, err_exact_rel_2: %g%%", err_est_rel2, err_exact_rel2);
      
      if (fabs(err_est_rel2 - err_est_rel) >= 1e-13 || fabs(err_exact_rel2 - err_exact_rel) >= 1e-13)
      {
        info("err_est_rel diff: %1.15g, err_exact_rel diff: %1.15g", 
        std::abs(err_est_rel2 - err_est_rel), std::abs(err_exact_rel2 - err_exact_rel));
        err_est_rel = err_exact_rel = 0; // Exit the adaptivity loop.
      }
      
      cpu_time.tick(Hermes::HERMES_SKIP);
    }
    
    // Report results.
    
    cpu_time.tick();
    double accum_time = cpu_time.accumulated();
    
    // View the approximate solution and polynomial orders.
    sview.show(&sln);
    oview.show(&space);
       
    // Add entry to DOF and CPU convergence graphs.    
    graph_dof.add_values(space.get_num_dofs(), err_est_rel);
    graph_dof.save("conv_dof_est.dat");
    graph_cpu.add_values(accum_time, err_est_rel);
    graph_cpu.save("conv_cpu_est.dat");
    graph_dof_exact.add_values(space.get_num_dofs(), err_exact_rel);
    graph_dof_exact.save("conv_dof_exact.dat");
    graph_cpu_exact.add_values(accum_time, err_exact_rel);
    graph_cpu_exact.save("conv_cpu_exact.dat");

    cpu_time.tick(Hermes::HERMES_SKIP);
    
    // If err_est too large, adapt the mesh. The NDOF test must be here, so that the solution may be visualized
    // after ending due to this criterion.
    if (err_exact_rel < ERR_STOP || space.get_num_dofs() >= NDOF_STOP) 
      done = true;
    else
      done = adaptivity.adapt(THRESHOLD, STRATEGY, MESH_REGULARITY);
    
    cpu_time.tick();
    verbose("Adaptation: %g s", cpu_time.last());
    
    // Increase the counter of performed adaptivity steps.
    if (done == false)  
      as++;
/*    else
    {
      sview.show(&sln);
      oview.show(&space);
      info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_rel);
    }
*/
    // Clean up.
    delete [] coeff_vec;
  }
  while (done == false);

  cpu_time.tick();
  verbose("Total running time: %g s", cpu_time.accumulated());

  // Wait for all views to be closed.
  Views::View::wait();
  return 0;
}
Exemple #4
0
int main(int argc, char* argv[])
{
  // Initialize refinement selector.
  MySelector selector(hORpSelectionBasedOnDOFs);

  HermesCommonApi.set_integral_param_value(Hermes::showInternalWarnings, false);

  // Time measurement.
  Hermes::Mixins::TimeMeasurable cpu_time;
  cpu_time.tick();

  // Load the mesh.
  MeshSharedPtr mesh(new Mesh);
  MeshReaderH2D mloader;
  mloader.load("domain.mesh", mesh);

  // Error calculation & adaptivity.
  DefaultErrorCalculator<complex, HERMES_H1_NORM> errorCalculator(RelativeErrorToGlobalNorm, 1);
  // Stopping criterion for an adaptivity step.
  AdaptStoppingCriterionSingleElement<complex> stoppingCriterion(THRESHOLD);
  // Adaptivity processor class.
  Adapt<complex> adaptivity(&errorCalculator, &stoppingCriterion);

  // Perform initial mesh refinements.
  for (int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements();

  // Initialize boundary conditions.
  DefaultEssentialBCConst<complex> bc_essential("Source", P_SOURCE);
  EssentialBCs<complex> bcs(&bc_essential);

  // Create an H1 space with default shapeset.
  SpaceSharedPtr<complex> space(new H1Space<complex> (mesh, &bcs, P_INIT));
  int ndof = Space<complex>::get_num_dofs(space);
  //Hermes::Mixins::Loggable::Static::info("ndof = %d", ndof);

  // Initialize the weak formulation.
  CustomWeakFormAcoustics wf("Wall", RHO, SOUND_SPEED, OMEGA);

  // Initialize coarse and reference mesh solution.
  MeshFunctionSharedPtr<complex>  sln(new Solution<complex>), ref_sln(new Solution<complex>);

  // Initialize views.
  ScalarView sview("Acoustic pressure", new WinGeom(600, 0, 600, 350));
  sview.show_contours(.2);
  ScalarView eview("Error", new WinGeom(600, 377, 600, 350));
  sview.show_mesh(false);
  sview.fix_scale_width(50);
  OrderView  oview("Polynomial orders", new WinGeom(1208, 0, 600, 350));
  ScalarView ref_view("Refined elements", new WinGeom(1208, 377, 600, 350));
  ref_view.show_scale(false);
  ref_view.set_min_max_range(0, 2);

  // DOF and CPU convergence graphs initialization.
  SimpleGraph graph_dof, graph_cpu;

  //Hermes::Mixins::Loggable::Static::info("Solving on reference mesh.");
  // Time measurement.
  cpu_time.tick();

  // Perform Newton's iteration.
  Hermes::Hermes2D::NewtonSolver<complex> newton(&wf, space);
  newton.set_verbose_output(false);

  // Adaptivity loop:
  int as = 1;
  adaptivity.set_space(space);
  bool done = false;
  do
  {
    //Hermes::Mixins::Loggable::Static::info("---- Adaptivity step %d:", as);

    // Construct globally refined reference mesh and setup reference space.
    Mesh::ReferenceMeshCreator refMeshCreator(mesh);
    MeshSharedPtr ref_mesh = refMeshCreator.create_ref_mesh();

    Space<complex>::ReferenceSpaceCreator refSpaceCreator(space, ref_mesh);
    SpaceSharedPtr<complex> ref_space = refSpaceCreator.create_ref_space();

    int ndof_ref = Space<complex>::get_num_dofs(ref_space);
    wf.set_verbose_output(false);
    newton.set_space(ref_space);

    // Assemble the reference problem.
    try
    {
      newton.solve();
    }
    catch(Hermes::Exceptions::Exception e)
    {
      e.print_msg();
      throw Hermes::Exceptions::Exception("Newton's iteration failed.");
    };
    // Translate the resulting coefficient vector into the Solution<complex> sln->
    Hermes::Hermes2D::Solution<complex>::vector_to_solution(newton.get_sln_vector(), ref_space, ref_sln);

    // Project the fine mesh solution onto the coarse mesh.
    //Hermes::Mixins::Loggable::Static::info("Projecting reference solution on coarse mesh.");
    OGProjection<complex> ogProjection; ogProjection.project_global(space, ref_sln, sln);

    // Time measurement.
    cpu_time.tick();

    // View the coarse mesh solution and polynomial orders.
    MeshFunctionSharedPtr<double> acoustic_pressure(new RealFilter(sln));
    sview.show(acoustic_pressure);
    oview.show(space);

    // Calculate element errors and total error estimate.
    //Hermes::Mixins::Loggable::Static::info("Calculating error estimate.");
    errorCalculator.calculate_errors(sln, ref_sln);
    double err_est_rel = errorCalculator.get_total_error_squared() * 100;

    eview.show(errorCalculator.get_errorMeshFunction());

    // Report results.
    //Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", Space<complex>::get_num_dofs(space), Space<complex>::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<complex>::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
    {
      //Hermes::Mixins::Loggable::Static::info("Adapting coarse mesh.");
      done = adaptivity.adapt(&selector);
      ref_view.show(adaptivity.get_refinementInfoMeshFunction());
      cpu_time.tick();
      std::cout << "Adaptivity step: " << as << ", running CPU time: " << cpu_time.accumulated_str() << std::endl;
    }

    // Increase counter.
    as++;
  }
  while (done == false);

  //Hermes::Mixins::Loggable::Static::info("Total running time: %g s", cpu_time.accumulated());

  // Show the reference solution - the final result.
  sview.set_title("Fine mesh solution magnitude");

  MeshFunctionSharedPtr<double>  ref_mag(new RealFilter(ref_sln));
  sview.show(ref_mag);

  // Output solution in VTK format.
  Linearizer lin(FileExport);
  bool mode_3D = true;
  lin.save_solution_vtk(ref_mag, "sln.vtk", "Acoustic pressure", mode_3D);
  //Hermes::Mixins::Loggable::Static::info("Solution in VTK format saved to file %s.", "sln.vtk");

  // Wait for all views to be closed.
  View::wait();
  return 0;
}
Exemple #5
0
QList<SolutionArray *> SolutionAgros::solveSolutioArray(Hermes::vector<EssentialBCs> bcs)
{
    QTime time;

    // solution agros array
    QList<SolutionArray *> solutionArrayList;

    // load the mesh file
    mesh = readMeshFromFile(tempProblemFileName() + ".mesh");
    refineMesh(mesh, true, true);

    // create an H1 space
    Hermes::vector<Space *> space;
    // create hermes solution array
    Hermes::vector<Solution *> solution;
    // create reference solution
    Hermes::vector<Solution *> solutionReference;

    // projection norms
    Hermes::vector<ProjNormType> projNormType;

    // prepare selector
    Hermes::vector<RefinementSelectors::Selector *> selector;

    // error marker
    bool isError = false;

    RefinementSelectors::Selector *select = NULL;
    switch (adaptivityType)
    {
    case AdaptivityType_H:
        select = new RefinementSelectors::HOnlySelector();
        break;
    case AdaptivityType_P:
        select = new RefinementSelectors::H1ProjBasedSelector(RefinementSelectors::H2D_P_ANISO,
                                                              Util::config()->convExp,
                                                              H2DRS_DEFAULT_ORDER);
        break;
    case AdaptivityType_HP:
        select = new RefinementSelectors::H1ProjBasedSelector(RefinementSelectors::H2D_HP_ANISO,
                                                              Util::config()->convExp,
                                                              H2DRS_DEFAULT_ORDER);
        break;
    }

    for (int i = 0; i < numberOfSolution; i++)
    {
        space.push_back(new H1Space(mesh, &bcs[i], polynomialOrder));

        // set order by element
        for (int j = 0; j < Util::scene()->labels.count(); j++)
            if (Util::scene()->labels[j]->material != Util::scene()->materials[0])
                space.at(i)->set_uniform_order(Util::scene()->labels[j]->polynomialOrder > 0 ? Util::scene()->labels[j]->polynomialOrder : polynomialOrder,
                                               QString::number(j).toStdString());

        // solution agros array
        solution.push_back(new Solution());

        if (adaptivityType != AdaptivityType_None)
        {
            // add norm
            projNormType.push_back(Util::config()->projNormType);
            // add refinement selector
            selector.push_back(select);
            // reference solution
            solutionReference.push_back(new Solution());
        }
    }

    // check for DOFs
    if (Space::get_num_dofs(space) == 0)
    {
        m_progressItemSolve->emitMessage(QObject::tr("DOF is zero"), true);
    }
    else
    {
        for (int i = 0; i < numberOfSolution; i++)
        {
            // transient
            if (analysisType == AnalysisType_Transient)
            {
                // constant initial solution
                solution.at(i)->set_const(mesh, initialCondition);
                solutionArrayList.append(solutionArray(solution.at(i)));
            }

            // nonlinear
            if ((linearityType != LinearityType_Linear) && (analysisType != AnalysisType_Transient))
            {
                solution.at(i)->set_const(mesh, 0.0);
            }
        }

        actualTime = 0.0;

        // update time function
        Util::scene()->problemInfo()->hermes()->updateTimeFunctions(actualTime);

        m_wf->set_current_time(actualTime);
        m_wf->solution = solution;
        m_wf->delete_all();
        m_wf->registerForms();

        // emit message
        if (adaptivityType != AdaptivityType_None)
            m_progressItemSolve->emitMessage(QObject::tr("Adaptivity type: %1").arg(adaptivityTypeString(adaptivityType)), false);

        double error = 0.0;

        // solution
        int maxAdaptivitySteps = (adaptivityType == AdaptivityType_None) ? 1 : adaptivitySteps;
        int actualAdaptivitySteps = -1;
        for (int i = 0; i<maxAdaptivitySteps; i++)
        {
            // set up the solver, matrix, and rhs according to the solver selection.
            SparseMatrix *matrix = create_matrix(matrixSolver);
            Vector *rhs = create_vector(matrixSolver);
            Solver *solver = create_linear_solver(matrixSolver, matrix, rhs);

            if (adaptivityType == AdaptivityType_None)
            {
                if (analysisType != AnalysisType_Transient)
                    solve(space, solution, solver, matrix, rhs);
            }
            else
            {
                // construct globally refined reference mesh and setup reference space.
                Hermes::vector<Space *> spaceReference = *Space::construct_refined_spaces(space);

                // assemble reference problem.
                solve(spaceReference, solutionReference, solver, matrix, rhs);

                if (!isError)
                {
                    // project the fine mesh solution onto the coarse mesh.
                    OGProjection::project_global(space, solutionReference, solution, matrixSolver);

                    // Calculate element errors and total error estimate.
                    Adapt adaptivity(space, projNormType);

                    // Calculate error estimate for each solution component and the total error estimate.
                    error = adaptivity.calc_err_est(solution,
                                                    solutionReference) * 100;

                    // emit signal
                    m_progressItemSolve->emitMessage(QObject::tr("Adaptivity rel. error (step: %2/%3, DOFs: %4/%5): %1%").
                                                     arg(error, 0, 'f', 3).
                                                     arg(i + 1).
                                                     arg(maxAdaptivitySteps).
                                                     arg(Space::get_num_dofs(space)).
                                                     arg(Space::get_num_dofs(spaceReference)), false, 1);
                    // add error to the list
                    m_progressItemSolve->addAdaptivityError(error, Space::get_num_dofs(space));

                    if (error < adaptivityTolerance || Space::get_num_dofs(space) >= adaptivityMaxDOFs)
                    {
                        break;
                    }
                    if (i != maxAdaptivitySteps-1) adaptivity.adapt(selector,
                                                                    Util::config()->threshold,
                                                                    Util::config()->strategy,
                                                                    Util::config()->meshRegularity);
                    actualAdaptivitySteps = i+1;
                }

                if (m_progressItemSolve->isCanceled())
                {
                    isError = true;
                    break;
                }

                // delete reference space
                for (int i = 0; i < spaceReference.size(); i++)
                {
                    delete spaceReference.at(i)->get_mesh();
                    delete spaceReference.at(i);
                }
                spaceReference.clear();
            }

            // clean up.
            delete solver;
            delete matrix;
            delete rhs;
        }

        // delete reference solution
        for (int i = 0; i < solutionReference.size(); i++)
            delete solutionReference.at(i);
        solutionReference.clear();

        // delete selector
        if (select) delete select;
        selector.clear();

        // timesteps
        if (!isError)
        {
            SparseMatrix *matrix = NULL;
            Vector *rhs = NULL;
            Solver *solver = NULL;

            // allocate dp for transient solution
            DiscreteProblem *dpTran = NULL;
            if (analysisType == AnalysisType_Transient)
            {
                // set up the solver, matrix, and rhs according to the solver selection.
                matrix = create_matrix(matrixSolver);
                rhs = create_vector(matrixSolver);
                solver = create_linear_solver(matrixSolver, matrix, rhs);
                // solver->set_factorization_scheme(HERMES_REUSE_FACTORIZATION_COMPLETELY);

                dpTran = new DiscreteProblem(m_wf, space, true);
            }

            int timesteps = (analysisType == AnalysisType_Transient) ? floor(timeTotal/timeStep) : 1;
            for (int n = 0; n<timesteps; n++)
            {
                // set actual time
                actualTime = (n+1)*timeStep;

                // update essential bc values
                Space::update_essential_bc_values(space, actualTime);
                // update timedep values
                Util::scene()->problemInfo()->hermes()->updateTimeFunctions(actualTime);

                m_wf->set_current_time(actualTime);
                m_wf->delete_all();
                m_wf->registerForms();

                // transient
                if ((timesteps > 1) && (linearityType == LinearityType_Linear))
                    isError = !solveLinear(dpTran, space, solution,
                                           solver, matrix, rhs);
                if ((timesteps > 1) && (linearityType != LinearityType_Linear))
                    isError = !solve(space, solution,
                                     solver, matrix, rhs);

                // output
                for (int i = 0; i < numberOfSolution; i++)
                {
                    solutionArrayList.append(solutionArray(solution.at(i), space.at(i), error, actualAdaptivitySteps, (n+1)*timeStep));
                }

                if (analysisType == AnalysisType_Transient)
                    m_progressItemSolve->emitMessage(QObject::tr("Transient time step (%1/%2): %3 s").
                                                     arg(n+1).
                                                     arg(timesteps).
                                                     arg(actualTime, 0, 'e', 2), false, n+2);
                if (m_progressItemSolve->isCanceled())
                {
                    isError = true;
                    break;
                }
            }

            // clean up
            if (solver) delete solver;
            if (matrix) delete matrix;
            if (rhs) delete rhs;

            if (dpTran) delete dpTran;
        }
    }
    // delete mesh
    delete mesh;

    // delete space
    for (unsigned int i = 0; i < space.size(); i++)
    {
        // delete space.at(i)->get_mesh();
        delete space.at(i);
    }
    space.clear();

    // delete last solution
    for (unsigned int i = 0; i < solution.size(); i++)
        delete solution.at(i);
    solution.clear();

    if (isError)
    {
        for (int i = 0; i < solutionArrayList.count(); i++)
            delete solutionArrayList.at(i);
        solutionArrayList.clear();
    }
    return solutionArrayList;
}