Exemple #1
0
int main(int argc, char* argv[])
{
  // Load the mesh
  Mesh mesh;
  H2DReader mloader;
  mloader.load("domain.mesh", &mesh);
  for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements();

  // Initialize the shapeset and the cache
  H1Shapeset shapeset;
  PrecalcShapeset pss(&shapeset);

  // Create finite element space
  H1Space space(&mesh, &shapeset);
  space.set_bc_types(bc_types);
  space.set_bc_values(bc_values);
  space.set_uniform_order(P_INIT);

  // Enumerate basis functions
  space.assign_dofs();

  // Initialize the weak formulation
  WeakForm wf(1);
  wf.add_biform(0, 0, bilinear_form, bilinear_form_ord, SYM);
  wf.add_liform(0, linear_form, linear_form_ord);
  wf.add_liform_surf(0, linear_form_surf, linear_form_surf_ord, 2);

  // Visualize solution and mesh
  ScalarView sview("Coarse solution", 0, 100, 798, 700);
  OrderView  oview("Polynomial orders", 800, 100, 798, 700);

  // Matrix solver
  UmfpackSolver solver;

  // Time measurement
  double cpu = 0;
  begin_time();

  // Solve the problem
  Solution sln;
  LinSystem ls(&wf, &solver);
  ls.set_spaces(1, &space);
  ls.set_pss(1, &pss);
  ls.assemble();
  ls.solve(1, &sln);

  // Time measurement
  cpu += end_time();

  // View the solution and mesh
  sview.show(&sln);
  oview.show(&space);

  // Print timing information
  verbose("Total running time: %g sec", cpu);

  // wait for all views to be closed
  View::wait("Waiting for all views to be closed.");
  return 0;
}
Exemple #2
0
int main(int argc, char* argv[])
{
  // load the mesh file
  Mesh mesh;
  H2DReader mloader;
  mloader.load("square.mesh", &mesh);

  // initial mesh refinements
  for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements();
  mesh.refine_towards_boundary(1,INIT_BDY_REF_NUM);

  // initialize the shapeset and the cache
  H1Shapeset shapeset;
  PrecalcShapeset pss(&shapeset);

  // create an H1 space
  H1Space space(&mesh, &shapeset);
  space.set_bc_types(bc_types);
  space.set_uniform_order(P_INIT);
  space.assign_dofs();

  // previous solution for the Newton's iteration
  Solution u_prev;

  // initialize the weak formulation
  WeakForm wf(1);
  wf.add_biform(0, 0, callback(jac), UNSYM, ANY, 1, &u_prev);
  wf.add_liform(0, callback(res), ANY, 1, &u_prev);

  // initialize the nonlinear system and solver
  UmfpackSolver umfpack;
  NonlinSystem nls(&wf, &umfpack);
  nls.set_spaces(1, &space);
  nls.set_pss(1, &pss);

  // use a constant function as the initial guess
  u_prev.set_const(&mesh, 3.0);
  nls.set_ic(&u_prev, &u_prev, PROJ_TYPE);

  // Newton's loop
  if (!nls.solve_newton_1(&u_prev, NEWTON_TOL, NEWTON_MAX_ITER)) error("Newton's method did not converge.");

  // visualise the solution and mesh
  ScalarView sview("Solution", 0, 0, 800, 600);
  OrderView oview("Mesh", 820, 0, 800, 600);
  char title[100];
  sprintf(title, "Solution");
  sview.set_title(title);
  sview.show(&u_prev);
  sprintf(title, "Mesh");
  oview.set_title(title);
  oview.show(&space);

  // wait for keyboard or mouse input
  View::wait();
  return 0;
}
int main(int argc, char* argv[])
{
  // Time measurement.
  Hermes::Mixins::TimeMeasurable cpu_time;
  cpu_time.tick();

  // Load the mesh.
  Mesh mesh;
  if (USE_XML_FORMAT == true)
  {
    MeshReaderH2DXML mloader;  
    Hermes::Mixins::Loggable::Static::info("Reading mesh in XML format.");
    mloader.load("domain.xml", &mesh);
  }
  else 
  {
    MeshReaderH2D mloader;
    Hermes::Mixins::Loggable::Static::info("Reading mesh in original format.");
    mloader.load("domain.mesh", &mesh);
  }

  // Perform initial mesh refinements.
  for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements();
  
  // Initialize boundary conditions
  CustomEssentialBCNonConst bc_essential("Horizontal");
  EssentialBCs<double> bcs(&bc_essential);

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

  // Initialize the weak formulation.
  CustomWeakFormGeneral wf("Horizontal");

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

  // Initialize Newton solver.
  NewtonSolver<double> newton(&dp);

  // Perform Newton's iteration.
  try
  {
    newton.solve();
  }
  catch(std::exception& e)
  {
    std::cout << e.what();
    
  }

  // Translate the resulting coefficient vector into a Solution.
  Solution<double> sln;
  Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln);

  // Time measurement.
  cpu_time.tick();

  // View the solution and mesh.
  ScalarView sview("Solution", new WinGeom(0, 0, 440, 350));
  sview.show(&sln);
  OrderView oview("Polynomial orders", new WinGeom(450, 0, 405, 350));
  oview.show(&space);

  // 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;
}
Exemple #4
0
int main(int argc, char* argv[])
{
  // Instantiate a class with global functions.
  Hermes2D hermes2d;

  // Time measurement.
  TimePeriod cpu_time;
  cpu_time.tick();

  // Load the mesh.
  Mesh mesh;
  H2DReader mloader;
  mloader.load("domain.mesh", &mesh);

  // Perform initial mesh refinements.
  for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements();
  
  // Initialize boundary conditions
  CustomEssentialBCNonConst bc_essential("Boundary horizontal");
  EssentialBCs bcs(&bc_essential);

  // Create an H1 space with default shapeset.
  H1Space space(&mesh, &bcs, P_INIT);
  int ndof = space.get_num_dofs();
  info("ndof = %d", ndof);

  // Initialize the weak formulation.
  CustomWeakFormGeneral wf("Boundary horizontal");

  // Initialize the FE problem.
  DiscreteProblem dp(&wf, &space);

  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).
  }

  // Initial coefficient vector for the Newton's method.  
  scalar* coeff_vec = new scalar[ndof];
  memset(coeff_vec, 0, ndof*sizeof(scalar));

  // Perform Newton's iteration.
  if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs)) error("Newton's iteration failed.");

  // Translate the resulting coefficient vector into the Solution sln.
  Solution sln;
  Solution::vector_to_solution(coeff_vec, &space, &sln);

  // Time measurement.
  cpu_time.tick();

  // Clean up.
  delete solver;
  delete matrix;
  delete rhs;
  delete [] coeff_vec;

  // View the solution and mesh.
  ScalarView sview("Solution", new WinGeom(0, 0, 440, 350));
  sview.show(&sln);
  OrderView  oview("Polynomial orders", new WinGeom(450, 0, 400, 350));
  oview.show(&space);

  // 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;
}
Exemple #5
0
int main(int argc, char* argv[])
{
  // load the mesh
  Mesh mesh;
  H2DReader mloader;
  mloader.load("motor.mesh", &mesh);

  // initialize the shapeset and the cache
  H1Shapeset shapeset;
  PrecalcShapeset pss(&shapeset);

  // create finite element space
  H1Space space(&mesh, &shapeset);
  space.set_bc_types(bc_types);
  space.set_bc_values(bc_values);
  space.set_uniform_order(P_INIT);

  // enumerate basis functions
  space.assign_dofs();

  // initialize the weak formulation
  WeakForm wf(1);
  wf.add_biform(0, 0, callback(biform1), SYM, 1);
  wf.add_biform(0, 0, callback(biform2), SYM, 2);

  // visualize solution, gradient, and mesh
  ScalarView sview("Coarse solution", 0, 0, 600, 1000);
  VectorView gview("Gradient", 610, 0, 600, 1000);
  OrderView  oview("Polynomial orders", 1220, 0, 600, 1000);
  //gview.set_min_max_range(0.0, 400.0);

  // matrix solver
  UmfpackSolver solver;

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

  // adaptivity loop
  int it = 1, ndofs;
  bool done = false;
  double cpu = 0.0;
  Solution sln_coarse, sln_fine;
  do
  {
    info("\n---- Adaptivity step %d ---------------------------------------------\n", it++);

    // time measurement
    begin_time();

    // solve the coarse mesh problem
    LinSystem ls(&wf, &solver);
    ls.set_spaces(1, &space);
    ls.set_pss(1, &pss);
    ls.assemble();
    ls.solve(1, &sln_coarse);

    // time measurement
    cpu += end_time();

    // view the solution -- this can be slow; for illustration only
    sview.show(&sln_coarse);
    gview.show(&sln_coarse, &sln_coarse, EPS_NORMAL, FN_DX_0, FN_DY_0);
    oview.show(&space);

    // time measurement
    begin_time();

    // solve the fine mesh problem
    RefSystem rs(&ls);
    rs.assemble();
    rs.solve(1, &sln_fine);

    // calculate element errors and total error estimate
    H1OrthoHP hp(1, &space);
    double err_est = hp.calc_error(&sln_coarse, &sln_fine) * 100;
    info("Error estimate: %g%%", err_est);

    // time measurement
    cpu += end_time();

    // add entry to DOF convergence graph
    graph_dof.add_values(space.get_num_dofs(), err_est);
    graph_dof.save("conv_dof.dat");

    // add entry to CPU convergence graph
    graph_cpu.add_values(cpu, err_est);
    graph_cpu.save("conv_cpu.dat");

    // if err_est too large, adapt the mesh
    if (err_est < ERR_STOP) done = true;
    else {
      hp.adapt(THRESHOLD, STRATEGY, ADAPT_TYPE, ISO_ONLY, MESH_REGULARITY);
      ndofs = space.assign_dofs();
      if (ndofs >= NDOF_STOP) done = true;
    }
  }
  while (done == false);
  verbose("Total running time: %g sec", cpu);

  // show the fine solution - this is the final result
  sview.set_title("Final solution");
  sview.show(&sln_fine);
  gview.show(&sln_fine, &sln_fine, EPS_HIGH, FN_DX_0, FN_DY_0);

  // wait for all views to be closed
  View::wait();
  return 0;
}
Exemple #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("domain.mesh", &mesh);
  
  // Perform initial uniform mesh refinement.
  for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements();

  // Set essential boundary conditions.
  DefaultEssentialBCConst bc_essential(Hermes::vector<std::string>("right", "top"), 0.0);
  EssentialBCs bcs(&bc_essential);
  
  // Create an H1 space with default shapeset.
  H1Space space(&mesh, &bcs, P_INIT);

  // Associate element markers (corresponding to physical regions) 
  // with material properties (diffusion coefficient, absorption 
  // cross-section, external sources).
  Hermes::vector<std::string> regions("e1", "e2", "e3", "e4", "e5");
  Hermes::vector<double> D_map(D_1, D_2, D_3, D_4, D_5);
  Hermes::vector<double> Sigma_a_map(SIGMA_A_1, SIGMA_A_2, SIGMA_A_3, SIGMA_A_4, SIGMA_A_5);
  Hermes::vector<double> Sources_map(Q_EXT_1, 0.0, Q_EXT_3, 0.0, 0.0);
  
  // Initialize the weak formulation.
  WeakFormsNeutronics::Monoenergetic::Diffusion::DefaultWeakFormFixedSource
    wf(regions, D_map, Sigma_a_map, Sources_map);

  // Initialize coarse and reference mesh solution.
  Solution sln, ref_sln;
  
  // Initialize refinement selector.
  H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER);

  // Initialize views.
  ScalarView sview("Solution", new WinGeom(0, 0, 440, 350));
  sview.fix_scale_width(50);
  sview.show_mesh(false);
  OrderView  oview("Polynomial orders", new WinGeom(450, 0, 400, 350));
  
  // DOF and CPU convergence graphs initialization.
  SimpleGraph graph_dof, graph_cpu;
  
  // Time measurement.
  TimePeriod cpu_time;
  cpu_time.tick();

  // Adaptivity loop:
  int as = 1; bool done = false;
  do
  {
    info("---- Adaptivity step %d:", as);

    // Construct globally refined reference mesh and setup reference space.
    Space* ref_space = Space::construct_refined_space(&space);
    int ndof_ref = Space::get_num_dofs(ref_space);

    // Initialize the FE problem.
    DiscreteProblem dp(&wf, ref_space);

    // Initialize the FE problem.
    SparseMatrix* matrix = create_matrix(matrix_solver);
    Vector* rhs = create_vector(matrix_solver);
    Solver* solver = create_linear_solver(matrix_solver, matrix, rhs);

    // Initial coefficient vector for the Newton's method.  
    scalar* coeff_vec = new scalar[ndof_ref];
    memset(coeff_vec, 0, ndof_ref*sizeof(scalar));

    // Perform Newton's iteration on reference emesh.
    info("Solving on reference mesh.");
    if (!hermes2d.solve_newton(coeff_vec, &dp, solver, matrix, rhs)) error("Newton's iteration failed.");

    // Translate the resulting coefficient vector into the Solution sln.
    Solution::vector_to_solution(coeff_vec, ref_space, &ref_sln);

    // Project the fine mesh solution onto the coarse mesh.
    Solution sln;
    info("Projecting reference solution on coarse mesh.");
    OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver); 

    // Time measurement.
    cpu_time.tick();
   
    // View the coarse mesh solution and polynomial orders.
    sview.show(&sln);
    oview.show(&space);

    // Skip visualization time.
    cpu_time.tick(HERMES_SKIP);

    // Calculate element errors and total error estimate.
    info("Calculating error estimate."); 
    Adapt* adaptivity = new Adapt(&space);
    double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100;

    // Report results.
    info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%", 
      Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_est_rel);

    // Time measurement.
    cpu_time.tick();

    // Add entry to DOF and CPU convergence graphs.
    graph_dof.add_values(Space::get_num_dofs(&space), err_est_rel);
    graph_dof.save("conv_dof_est.dat");
    graph_cpu.add_values(cpu_time.accumulated(), err_est_rel);
    graph_cpu.save("conv_cpu_est.dat");

    // If err_est too large, adapt the mesh.
    if (err_est_rel < ERR_STOP) done = true;
    else 
    {
      info("Adapting coarse mesh.");
      done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY);
      
      // Increase the counter of performed adaptivity steps.
      if (done == false)  as++;
    }
    if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true;

    // Clean up.
    delete [] coeff_vec;
    delete solver;
    delete matrix;
    delete rhs;
    delete adaptivity;
    if(done == false) delete ref_space->get_mesh();
    delete ref_space;
  }
  while (done == false);
  
  verbose("Total running time: %g s", cpu_time.accumulated());

  // Show the reference solution - the final result.
  sview.set_title("Fine mesh solution");
  sview.show_mesh(false);
  sview.show(&ref_sln);

  // Wait for all views to be closed.
  View::wait();
  return 0;
}
int main(int argc, char* argv[])
{
  // 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;
}
Exemple #8
0
int main(int argc, char* argv[])
{
  // load the mesh
  Mesh xmesh, ymesh;
  H2DReader mloader;
  mloader.load("bracket.mesh", &xmesh);

  // create initial mesh for the vertical displacement component,
  // identical to the mesh for the horizontal displacement
  // (bracket.mesh becomes a master mesh)
  ymesh.copy(&xmesh);

  // initialize the shapeset and the cache
  H1Shapeset shapeset;
  PrecalcShapeset xpss(&shapeset);
  PrecalcShapeset ypss(&shapeset);

  // create the x displacement space
  H1Space xdisp(&xmesh, &shapeset);
  xdisp.set_bc_types(bc_types);
  xdisp.set_bc_values(bc_values);
  xdisp.set_uniform_order(P_INIT);

  // create the y displacement space
  H1Space ydisp(MULTI ? &ymesh : &xmesh, &shapeset);
  ydisp.set_bc_types(bc_types);
  ydisp.set_bc_values(bc_values);
  ydisp.set_uniform_order(P_INIT);

  // enumerate basis functions
  int ndofs = xdisp.assign_dofs();
  ndofs += ydisp.assign_dofs(ndofs);

  // initialize the weak formulation
  WeakForm wf(2);
  wf.add_biform(0, 0, callback(bilinear_form_0_0), SYM);  // note that only one symmetric part is
  wf.add_biform(0, 1, callback(bilinear_form_0_1), SYM);  // added in the case of symmetric bilinear
  wf.add_biform(1, 1, callback(bilinear_form_1_1), SYM);  // forms
  wf.add_liform_surf(1, callback(linear_form_surf_1), marker_top);

  // visualization of solution and meshes
  OrderView  xoview("X polynomial orders", 0, 0, 500, 500);
  OrderView  yoview("Y polynomial orders", 510, 0, 500, 500);
  ScalarView sview("Von Mises stress [Pa]", 1020, 0, 500, 500);

  // matrix solver
  UmfpackSolver umfpack;

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

  // adaptivity loop
  int it = 1;
  bool done = false;
  double cpu = 0.0;
  Solution x_sln_coarse, y_sln_coarse;
  Solution x_sln_fine, y_sln_fine;
  do
  {
    info("\n---- Adaptivity step %d ---------------------------------------------\n", it++);

    // time measurement
    begin_time();

    //calculating the number of degrees of freedom
    ndofs = xdisp.assign_dofs();
    ndofs += ydisp.assign_dofs(ndofs);
    printf("xdof=%d, ydof=%d\n", xdisp.get_num_dofs(), ydisp.get_num_dofs());

    // solve the coarse mesh problem
    LinSystem ls(&wf, &umfpack);
    ls.set_spaces(2, &xdisp, &ydisp);
    ls.set_pss(2, &xpss, &ypss);
    ls.assemble();
    ls.solve(2, &x_sln_coarse, &y_sln_coarse);

    // time measurement
    cpu += end_time();

    // view the solution -- this can be slow; for illustration only
    VonMisesFilter stress_coarse(&x_sln_coarse, &y_sln_coarse, mu, lambda);
    sview.set_min_max_range(0, 3e4);
    sview.show(&stress_coarse);
    xoview.show(&xdisp);
    yoview.show(&ydisp);

    // time measurement
    begin_time();

    // solve the fine mesh problem
    RefSystem rs(&ls);
    rs.assemble();
    rs.solve(2, &x_sln_fine, &y_sln_fine);

    // calculate element errors and total error estimate
    H1OrthoHP hp(2, &xdisp, &ydisp);
    hp.set_biform(0, 0, bilinear_form_0_0<scalar, scalar>, bilinear_form_0_0<Ord, Ord>);
    hp.set_biform(0, 1, bilinear_form_0_1<scalar, scalar>, bilinear_form_0_1<Ord, Ord>);
    hp.set_biform(1, 0, bilinear_form_1_0<scalar, scalar>, bilinear_form_1_0<Ord, Ord>);
    hp.set_biform(1, 1, bilinear_form_1_1<scalar, scalar>, bilinear_form_1_1<Ord, Ord>);
    double err_est = hp.calc_error_2(&x_sln_coarse, &y_sln_coarse, &x_sln_fine, &y_sln_fine) * 100;

    info("Estimate of error: %g%%", err_est);

    // time measurement
    cpu += end_time();

    // add entry to DOF convergence graph
    graph_dof.add_values(xdisp.get_num_dofs() + ydisp.get_num_dofs(), err_est);
    graph_dof.save("conv_dof.dat");

    // add entry to CPU convergence graph
    graph_cpu.add_values(cpu, err_est);
    graph_cpu.save("conv_cpu.dat");

    // if err_est too large, adapt the mesh
    if (err_est < ERR_STOP) done = true;
    else {
      hp.adapt(THRESHOLD, STRATEGY, ADAPT_TYPE, ISO_ONLY, MESH_REGULARITY, CONV_EXP, MAX_ORDER, SAME_ORDERS);
      ndofs = xdisp.assign_dofs();
      ndofs += ydisp.assign_dofs(ndofs);
      if (ndofs >= NDOF_STOP) done = true;
    }

  }
  while (!done);
  verbose("Total running time: %g sec", cpu);

  // show the fine solution - this is the final result
  VonMisesFilter stress_fine(&x_sln_fine, &y_sln_fine, mu, lambda);
  sview.set_title("Final solution");
  sview.set_min_max_range(0, 3e4);
  sview.show(&stress_fine);

  // wait for all views to be closed
  View::wait();
  return 0;
}
Exemple #9
0
int main(int argc, char* argv[])
{
  // load the mesh
  Mesh mesh;
  mesh.load("square_quad.mesh");
  if(P_INIT == 1) mesh.refine_all_elements();  // this is because there are no degrees of freedom
                                               // on the coarse mesh lshape.mesh if P_INIT == 1

  // initialize the shapeset and the cache
  H1ShapesetOrtho shapeset;
  PrecalcShapeset pss(&shapeset);

  // create finite element space
  H1Space space(&mesh, &shapeset);
  space.set_bc_values(bc_values);
  space.set_uniform_order(P_INIT);

  // enumerate basis functions
  space.assign_dofs();

  // initialize the weak formulation
  WeakForm wf(1);
  wf.add_biform(0, 0, bilinear_form, SYM);
  wf.add_liform(0, linear_form);

  // visualize solution and mesh
  ScalarView sview("Coarse solution", 0, 100, 798, 700);
  OrderView  oview("Polynomial orders", 800, 100, 798, 700);

  // matrix solver
  UmfpackSolver solver;

  // convergence graph wrt. the number of degrees of freedom
  GnuplotGraph graph;
  graph.set_log_y();
  graph.set_captions("Error Convergence for the Inner Layer Problem", "Degrees of Freedom", "Error [%]");
  graph.add_row("exact error", "k", "-", "o");
  graph.add_row("error estimate", "k", "--");

  // convergence graph wrt. CPU time
  GnuplotGraph graph_cpu;
  graph_cpu.set_captions("Error Convergence for the Inner Layer Problem", "CPU Time", "Error Estimate [%]");
  graph_cpu.add_row("exact error", "k", "-", "o");
  graph_cpu.add_row("error estimate", "k", "--");
  graph_cpu.set_log_y();

  // adaptivity loop
  int it = 1, ndofs;
  bool done = false;
  double cpu = 0.0;
  Solution sln_coarse, sln_fine;
  do
  {
    info("\n---- Adaptivity step %d ---------------------------------------------\n", it++);

    // time measurement
    begin_time();

    // solve the coarse mesh problem
    LinSystem ls(&wf, &solver);
    ls.set_spaces(1, &space);
    ls.set_pss(1, &pss);
    ls.assemble();
    ls.solve(1, &sln_coarse);

    // time measurement
    cpu += end_time();

    // calculate error wrt. exact solution
    ExactSolution exact(&mesh, fndd);
    double error = h1_error(&sln_coarse, &exact) * 100;
    info("\nExact solution error: %g%%", error);

    // view the solution and mesh
    sview.show(&sln_coarse);
    oview.show(&space);

    // time measurement
    begin_time();

    // solve the fine mesh problem
    RefSystem rs(&ls);
    rs.assemble();
    rs.solve(1, &sln_fine);

    // calculate error estimate wrt. fine mesh solution
    H1OrthoHP hp(1, &space);
    double err_est = hp.calc_error(&sln_coarse, &sln_fine) * 100;
    info("Estimate of error: %g%%", err_est);

    // add entry to DOF convergence graph
    graph.add_values(0, space.get_num_dofs(), error);
    graph.add_values(1, space.get_num_dofs(), err_est);
    graph.save("conv_dof.gp");

    // add entry to CPU convergence graph
    graph_cpu.add_values(0, cpu, error);
    graph_cpu.add_values(1, cpu, err_est);
    graph_cpu.save("conv_cpu.gp");

    // if err_est too large, adapt the mesh
    if (err_est < ERR_STOP) done = true;
    else {
      hp.adapt(THRESHOLD, STRATEGY, ADAPT_TYPE, ISO_ONLY, MESH_REGULARITY);
      ndofs = space.assign_dofs();
      if (ndofs >= NDOF_STOP) done = true;
    }

    // time measurement
    cpu += end_time();
  }
  while (done == false);
  verbose("Total running time: %g sec", cpu);

  // show the fine solution - this is the final result
  sview.set_title("Final solution");
  sview.show(&sln_fine);

  // wait for keyboard or mouse input
  printf("Waiting for keyboard or mouse input.\n");
  View::wait();
  return 0;
}
Exemple #10
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 #11
0
  int main(int argc, char* argv[])
  {
    // Load the mesh.
    MeshSharedPtr mesh(new Mesh);
    MeshReaderH2D mloader;
    mloader.load("domain.mesh", mesh);

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

    // Initialize boundary conditions.
    Hermes::Hermes2D::DefaultEssentialBCConst<complex> bc_essential("Dirichlet", complex(0.0, 0.0));
    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->get_num_dofs();

    // Initialize the weak formulation.
    CustomWeakForm wf("Air", MU_0, "Iron", MU_IRON, GAMMA_IRON,
      "Wire", MU_0, complex(J_EXT, 0.0), OMEGA);

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

    // Initialize refinement selector.
    H1ProjBasedSelector<complex> selector(CAND_LIST);

    // Initialize views.
#ifdef SHOW_OUTPUT
    Views::ScalarView sview("Solution", new Views::WinGeom(0, 0, 600, 350));
    Views::ScalarView sview2("Ref. Solution", new Views::WinGeom(0, 0, 600, 350));
    Views::OrderView oview("Polynomial orders", new Views::WinGeom(610, 0, 520, 350));
#endif

    DiscreteProblem<complex> dp(&wf, space);

    // Perform Newton's iteration and translate the resulting coefficient vector into a Solution.
    Hermes::Hermes2D::NewtonSolver<complex> newton(&dp);

    // Adaptivity loop:
    int as = 1; bool done = false;
    adaptivity.set_space(space);
    do
    {
      // Construct globally refined reference mesh and setup reference space->
      Mesh::ReferenceMeshCreator ref_mesh_creator(mesh);
      MeshSharedPtr ref_mesh = ref_mesh_creator.create_ref_mesh();
      Space<complex>::ReferenceSpaceCreator ref_space_creator(space, ref_mesh);
      SpaceSharedPtr<complex> ref_space = ref_space_creator.create_ref_space();

      newton.set_space(ref_space);
      ref_space->save("space-complex.xml");
      ref_space->free();
      ref_space->load("space-complex.xml");
#ifdef WITH_BSON
      ref_space->save_bson("space-complex.bson");
      ref_space->free();
      ref_space->load_bson("space-complex.bson");
#endif

      int ndof_ref = ref_space->get_num_dofs();

      // Initialize reference problem.

      // Initial coefficient vector for the Newton's method.
      complex* coeff_vec = new complex[ndof_ref];
      memset(coeff_vec, 0, ndof_ref * sizeof(complex));

      // Perform Newton's iteration and translate the resulting coefficient vector into a Solution.
      SpaceSharedPtr<complex> space_test = Space<complex>::load("space-complex.xml", ref_mesh, false, &bcs);
      newton.set_space(space_test);
      newton.solve(coeff_vec);

      Hermes::Hermes2D::Solution<complex>::vector_to_solution(newton.get_sln_vector(), ref_space, ref_sln);

      // Project the fine mesh solution onto the coarse mesh.
      OGProjection<complex> ogProjection;

#ifdef WITH_BSON
      space->save_bson("space-complex-coarse.bson");
      SpaceSharedPtr<complex> space_test2 = Space<complex>::load_bson("space-complex-coarse.bson", mesh, &bcs);
      ogProjection.project_global(space_test2, ref_sln, sln);
#else
      space->save("space-complex-coarse.xml2");
      SpaceSharedPtr<complex> space_test2 = Space<complex>::load("space-complex-coarse.xml2", mesh, false, &bcs);
      ogProjection.project_global(space_test2, ref_sln, sln);
#endif
      // View the coarse mesh solution and polynomial orders.
#ifdef SHOW_OUTPUT
      MeshFunctionSharedPtr<double> real_filter(new RealFilter(sln));
      MeshFunctionSharedPtr<double> rreal_filter(new RealFilter(ref_sln));
      sview2.show(rreal_filter);
      oview.show(space);
#endif

      // Calculate element errors and total error estimate.
      errorCalculator.calculate_errors(sln, ref_sln);

#ifdef SHOW_OUTPUT
      std::cout << "Relative error: " << errorCalculator.get_total_error_squared() * 100. << '%' << std::endl;
#endif

      // Add entry to DOF and CPU convergence graphs.
#ifdef SHOW_OUTPUT
      sview.show(errorCalculator.get_errorMeshFunction());
#endif

      // If err_est too large, adapt the mesh->
      if(errorCalculator.get_total_error_squared()  * 100. < ERR_STOP)
        done = true;
      else
      {
        std::cout << "Adapting..." << std::endl << std::endl;
        adaptivity.adapt(&selector);
      }

      // Clean up.
      delete [] coeff_vec;

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

#ifdef SHOW_OUTPUT
    // Show the reference solution - the final result.
    sview.set_title("Fine mesh solution");
    MeshFunctionSharedPtr<double> real_filter(new RealFilter(ref_sln));
    sview.show(real_filter);

    // Wait for all views to be closed.
    Views::View::wait();
#endif
    return as;
  }
Exemple #12
0
// Main function.
int main(int argc, char* argv[])
{
  ConstitutiveRelationsGenuchtenWithLayer constitutive_relations(CONSTITUTIVE_TABLE_METHOD, NUM_OF_INSIDE_PTS, LOW_LIMIT, TABLE_PRECISION, TABLE_LIMIT, K_S_vals, ALPHA_vals, N_vals, M_vals, THETA_R_vals, THETA_S_vals, STORATIVITY_vals);

  // Either use exact constitutive relations (slow) (method 0) or precalculate 
  // their linear approximations (faster) (method 1) or
  // precalculate their quintic polynomial approximations (method 2) -- managed by 
  // the following loop "Initializing polynomial approximation".
  if (CONSTITUTIVE_TABLE_METHOD == 1)
    constitutive_relations.constitutive_tables_ready = get_constitutive_tables(1, &constitutive_relations, MATERIAL_COUNT);  // 1 stands for the Newton's method.
  

  // The van Genuchten + Mualem K(h) function is approximated by polynomials close 
  // to zero in case of CONSTITUTIVE_TABLE_METHOD==1.
  // In case of CONSTITUTIVE_TABLE_METHOD==2, all constitutive functions are approximated by polynomials.
  info("Initializing polynomial approximations.");
  for (int i=0; i < MATERIAL_COUNT; i++)
  {
    // Points to be used for polynomial approximation of K(h).
    double* points = new double[NUM_OF_INSIDE_PTS];

    init_polynomials(6 + NUM_OF_INSIDE_PTS, LOW_LIMIT, points, NUM_OF_INSIDE_PTS, i, &constitutive_relations, MATERIAL_COUNT, NUM_OF_INTERVALS, INTERVALS_4_APPROX);
  }
  
  constitutive_relations.polynomials_ready = true;
  if (CONSTITUTIVE_TABLE_METHOD == 2)
  {
    constitutive_relations.constitutive_tables_ready = true;
    //Assign table limit to global definition.
    constitutive_relations.table_limit = INTERVALS_4_APPROX[NUM_OF_INTERVALS-1];
  }
  
  // Choose a Butcher's table or define your own.
  ButcherTable bt(butcher_table_type);
  if (bt.is_explicit()) info("Using a %d-stage explicit R-K method.", bt.get_size());
  if (bt.is_diagonally_implicit()) info("Using a %d-stage diagonally implicit R-K method.", bt.get_size());
  if (bt.is_fully_implicit()) info("Using a %d-stage fully implicit R-K method.", bt.get_size());

  // Load the mesh.
  Mesh mesh, basemesh;
  MeshReaderH2D mloader;
  mloader.load(mesh_file, &basemesh);
  
  // Perform initial mesh refinements.
  mesh.copy(&basemesh);
  for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements();
  mesh.refine_towards_boundary("Top", INIT_REF_NUM_BDY_TOP);

  // Initialize boundary conditions.
  RichardsEssentialBC bc_essential("Top", H_ELEVATION, PULSE_END_TIME, H_INIT, STARTUP_TIME);
  EssentialBCs<double> bcs(&bc_essential);

  // Create an H1 space with default shapeset.
  H1Space<double> space(&mesh, &bcs, P_INIT);
  int ndof = space.get_num_dofs();
  info("ndof = %d.", ndof);

  // Convert initial condition into a Solution.
  ZeroSolution h_time_prev(&mesh), h_time_new(&mesh), time_error_fn(&mesh);

  // Initialize views.
  ScalarView view("Initial condition", new WinGeom(0, 0, 600, 500));
  view.fix_scale_width(80);

  // Visualize the initial condition.
  view.show(&h_time_prev);

  // Initialize the weak formulation.
  CustomWeakFormRichardsRK wf(&constitutive_relations);

   // Visualize the projection and mesh.
  ScalarView sview("Initial condition", new WinGeom(0, 0, 400, 350));
  sview.fix_scale_width(50);
  sview.show(&h_time_prev, HERMES_EPS_VERYHIGH);
  ScalarView eview("Temporal error", new WinGeom(405, 0, 400, 350));
  eview.fix_scale_width(50);
  eview.show(&time_error_fn, HERMES_EPS_VERYHIGH);
  OrderView oview("Initial mesh", new WinGeom(810, 0, 350, 350));
  oview.show(&space);

  // Graph for time step history.
  SimpleGraph time_step_graph;
  info("Time step history will be saved to file time_step_history.dat.");

  // Initialize Runge-Kutta time stepping.
  RungeKutta<double> runge_kutta(&wf, &space, &bt, matrix_solver);

  // Time stepping:
  double current_time = 0;
  int ts = 1;
  do 
  {
    info("---- Time step %d, time %3.5f s", ts, current_time);

    Space<double>::update_essential_bc_values(&space, current_time);

    // Perform one Runge-Kutta time step according to the selected Butcher's table.
    info("Runge-Kutta time step (t = %g s, time step = %g s, stages: %d).", 
         current_time, time_step, bt.get_size());
    bool freeze_jacobian = false;
    bool block_diagonal_jacobian = false;
    bool verbose = true;
    double damping_coeff = 1.0;
    double max_allowed_residual_norm = 1e10;

    try
    {
      runge_kutta.rk_time_step_newton(current_time, time_step, &h_time_prev, 
          &h_time_new, &time_error_fn, freeze_jacobian, block_diagonal_jacobian, verbose,
          NEWTON_TOL, NEWTON_MAX_ITER, damping_coeff, max_allowed_residual_norm);
    }
    catch(Exceptions::Exception& e)
    {
      info("Runge-Kutta time step failed, decreasing time step size from %g to %g days.", 
           time_step, time_step * time_step_dec);
      time_step *= time_step_dec;
      if (time_step < time_step_min) 
        error("Time step became too small.");
      continue;
    }
    
    // Copy solution for the new time step.
    h_time_prev.copy(&h_time_new);

    // Show error function.
    char title[100];
    sprintf(title, "Temporal error, t = %g", current_time);
    eview.set_title(title);
    eview.show(&time_error_fn, HERMES_EPS_VERYHIGH);

    // Calculate relative time stepping error and decide whether the 
    // time step can be accepted. If not, then the time step size is 
    // reduced and the entire time step repeated. If yes, then another
    // check is run, and if the relative error is very low, time step 
    // is increased.
    double rel_err_time = Global<double>::calc_norm(&time_error_fn, HERMES_H1_NORM) / Global<double>::calc_norm(&h_time_new, HERMES_H1_NORM) * 100;
    info("rel_err_time = %g%%", rel_err_time);
    if (rel_err_time > time_tol_upper) {
      info("rel_err_time above upper limit %g%% -> decreasing time step from %g to %g days and repeating time step.", 
           time_tol_upper, time_step, time_step * time_step_dec);
      time_step *= time_step_dec;
      continue;
    }
    if (rel_err_time < time_tol_lower) {
      info("rel_err_time = below lower limit %g%% -> increasing time step from %g to %g days", 
           time_tol_lower, time_step, time_step * time_step_inc);
      time_step *= time_step_inc;
    }

    // Add entry to the timestep graph.
    time_step_graph.add_values(current_time, time_step);
    time_step_graph.save("time_step_history.dat");

    // Update time.
    current_time += time_step;

    // Show the new time level solution.
    sprintf(title, "Solution, t = %g", current_time);
    sview.set_title(title);
    sview.show(&h_time_new, HERMES_EPS_VERYHIGH);
    oview.show(&space);

    // Save complete Solution.
    char filename[100];
    sprintf(filename, "outputs/tsln_%f.dat", current_time);
    h_time_new.save(filename);
    info("Solution at time %g saved to file %s.", current_time, filename);

    // Save solution for the next time step.
    h_time_prev.copy(&h_time_new);

    // Increase time step counter.
    ts++;
  } 
  while (current_time < T_FINAL);

  // Wait for the view to be closed.
  View::wait();
  return 0;
}
Exemple #13
0
int main(int argc, char* argv[])
{
  // Load the mesh
  Mesh mesh;
  H2DReader mloader;
  mloader.load("domain.mesh", &mesh);
  mesh.refine_all_elements();

  // Initialize the shapeset and the cache
  H1Shapeset shapeset;
  PrecalcShapeset pss(&shapeset);

  // Create finite element space
  H1Space space(&mesh, &shapeset);
  space.set_bc_types(bc_types);
  space.set_bc_values(bc_values);
  space.set_uniform_order(P_INIT);

  // Enumerate basis functions
  space.assign_dofs();

  // initialize the weak formulation
  WeakForm wf(1);
  wf.add_biform(0, 0, bilinear_form, bilinear_form_ord, SYM);
  wf.add_liform(0, linear_form, linear_form_ord);
  wf.add_liform_surf(0, linear_form_surf, linear_form_surf_ord, 2);

  // Visualize solution and mesh
  ScalarView sview("Coarse solution", 0, 100, 798, 700);
  OrderView  oview("Polynomial orders", 800, 100, 798, 700);

  // Matrix solver
  UmfpackSolver solver;

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

  // Adaptivity loop
  int it = 1, ndofs;
  bool done = false;
  double cpu = 0.0;
  Solution sln_coarse, sln_fine;
  do
  {
    info("\n---- Adaptivity step %d ---------------------------------------------\n", it++);

    // Time measurement
    begin_time();

    // Solve the coarse mesh problem
    LinSystem ls(&wf, &solver);
    ls.set_spaces(1, &space);
    ls.set_pss(1, &pss);
    ls.assemble();
    ls.solve(1, &sln_coarse);

    // Time measurement
    cpu += end_time();

    // View the solution and mesh
    sview.show(&sln_coarse);
    oview.show(&space);

    // Time measurement
    begin_time();

    // Solve the fine mesh problem
    RefSystem rs(&ls);
    rs.assemble();
    rs.solve(1, &sln_fine);

    // Calculate error estimate wrt. fine mesh solution
    H1OrthoHP hp(1, &space);
    double err_est = hp.calc_error(&sln_coarse, &sln_fine) * 100;
    info("Estimate of error: %g%%", err_est);

    // add entry to DOF convergence graph
    graph_dof.add_values(space.get_num_dofs(), err_est);
    graph_dof.save("conv_dof.dat");

    // add entry to CPU convergence graph
    graph_cpu.add_values(cpu, err_est);
    graph_cpu.save("conv_cpu.dat");

    // If err_est too large, adapt the mesh
    if (err_est < ERR_STOP) done = true;
    else {
      hp.adapt(THRESHOLD, STRATEGY, ADAPT_TYPE, ISO_ONLY, MESH_REGULARITY);
      ndofs = space.assign_dofs();
      if (ndofs >= NDOF_STOP) done = true;
    }

    // Time measurement
    cpu += end_time();
  }
  while (done == false);
  verbose("Total running time: %g sec", cpu);

  // Show the fine solution - this is the final result
  sview.set_title("Final solution");
  sview.show(&sln_fine);

  // Wait for keyboard or mouse input
  View::wait("Waiting for all views to be closed.");
  return 0;
}
Exemple #14
0
int main(int argc, char* argv[])
{
  // load the mesh
  Mesh mesh;
  H2DReader mloader;
  mloader.load("square_quad.mesh", &mesh);
  // mloader.load("square_tri.mesh", &mesh);
  for (int i=0; i<INIT_REF_NUM; i++) mesh.refine_all_elements();
  mesh.refine_towards_boundary(2, INIT_REF_NUM_BDY);

  // initialize the shapeset and the cache
  H1Shapeset shapeset;
  PrecalcShapeset pss(&shapeset);

  // create finite element space
  H1Space space(&mesh, &shapeset);
  space.set_bc_types(bc_types);
  space.set_bc_values(bc_values);
  space.set_uniform_order(P_INIT);

  // enumerate basis functions
  space.assign_dofs();

  // initialize the weak formulation
  WeakForm wf(1);
  wf.add_biform(0, 0, callback(bilinear_form));
  if (STABILIZATION_ON == true) {
    wf.add_biform(0, 0, bilinear_form_stabilization,
            bilinear_form_stabilization_order);
  }
  if (SHOCK_CAPTURING_ON == true) {
    wf.add_biform(0, 0, bilinear_form_shock_capturing, bilinear_form_shock_capturing_order);
  }

  // visualize solution and mesh
  OrderView  oview("Coarse mesh", 0, 0, 500, 400);
  ScalarView sview("Coarse mesh solution", 510, 0, 500, 400);
  ScalarView sview2("Fine mesh solution", 1020, 0, 500, 400);

  // matrix solver
  UmfpackSolver solver;

  // DOF convergence graph
  SimpleGraph graph_dof_est, graph_cpu_est;

  // prepare selector
  RefinementSelectors::H1NonUniformHP selector(ISO_ONLY, ADAPT_TYPE, CONV_EXP, H2DRS_DEFAULT_ORDER, &shapeset);

  // adaptivity loop
  int it = 1, ndofs;
  bool done = false;
  double cpu = 0.0;
  Solution sln_coarse, sln_fine;
  do
  {
    info("\n---- Adaptivity step %d ---------------------------------------------\n", it++);

    // time measurement
    begin_time();

    // solve the coarse mesh problem
    LinSystem ls(&wf, &solver);
    ls.set_spaces(1, &space);
    ls.set_pss(1, &pss);
    ls.assemble();
    ls.solve(1, &sln_coarse);

    // solve the fine mesh problem
    int p_increase;
    if (ADAPT_TYPE == RefinementSelectors::H2DRS_CAND_HP) p_increase = 1;
    else p_increase = 0;
    RefSystem rs(&ls, p_increase, 1);  // the '1' is for one level of global refinement in space
    rs.assemble();
    rs.solve(1, &sln_fine);

    // time measurement
    cpu += end_time();

    // show fine mesh solution
    // view the solution and mesh
    oview.show(&space);
    sview.show(&sln_coarse);
    sview2.show(&sln_fine);
    //sview.wait_for_keypress();
 
    // time measurement
    begin_time();

    // calculate error estimate wrt. fine mesh solution
    H1AdaptHP hp(1, &space);
    double err_est = hp.calc_error(&sln_coarse, &sln_fine) * 100;
    info("Estimate of error: %g%%", err_est);

    // add entries to DOF and CPU convergence graphs
    graph_dof_est.add_values(space.get_num_dofs(), err_est);
    graph_dof_est.save("conv_dof_est.dat");
    graph_cpu_est.add_values(cpu, err_est);
    graph_cpu_est.save("conv_cpu_est.dat");

    // if err_est too large, adapt the mesh
    if (err_est < ERR_STOP) done = true;
    else {
      hp.adapt(THRESHOLD, STRATEGY, &selector, MESH_REGULARITY);
      ndofs = space.assign_dofs();
      if (ndofs >= NDOF_STOP) done = true;
    }

    // time measurement
    cpu += end_time();
  }
  while (done == false);
  verbose("Total running time: %g sec", cpu);

  // show the fine solution - this is the final result
  sview.set_title("Final solution");
  sview.show(&sln_fine);

  // wait for keyboard or mouse input
  View::wait();
  return 0;
}
Exemple #15
0
int main(int argc, char* argv[])
{
  // load the mesh
  Mesh mesh;
  H2DReader mloader;
  mloader.load("square_quad.mesh", &mesh);

  // initial mesh refinement
  for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements();

  // initialize the shapeset and the cache
  H1Shapeset shapeset;
  PrecalcShapeset pss(&shapeset);

  // create finite element space
  H1Space space(&mesh, &shapeset);
  space.set_bc_types(bc_types);
  space.set_bc_values(bc_values);
  space.set_uniform_order(P_INIT);

  // enumerate basis functions
  space.assign_dofs();

  // initialize the weak formulation
  WeakForm wf(1);
  wf.add_biform(0, 0, callback(bilinear_form), SYM);
  wf.add_liform(0, linear_form, linear_form_ord);

  // visualize solution and mesh
  ScalarView sview("Coarse solution", 0, 100, 798, 700);
  OrderView  oview("Polynomial orders", 800, 100, 798, 700);

  // matrix solver
  UmfpackSolver solver;

  // prepare selector
  RefinementSelectors::H1UniformHP selector(ISO_ONLY, ADAPT_TYPE, 1.0, H2DRS_DEFAULT_ORDER, &shapeset);

  // DOF and CPU convergence graphs
  SimpleGraph graph_dof_est, graph_dof_exact, graph_cpu_est, graph_cpu_exact;

  // adaptivity loop
  int it = 1, ndofs;
  bool done = false;
  double cpu = 0.0;
  Solution sln_coarse, sln_fine;
  do
  {
    info("\n---- Adaptivity step %d ---------------------------------------------\n", it++);

    // time measurement
    begin_time();

    // solve the coarse mesh problem
    LinSystem ls(&wf, &solver);
    ls.set_spaces(1, &space);
    ls.set_pss(1, &pss);
    ls.assemble();
    ls.solve(1, &sln_coarse);

    // time measurement
    cpu += end_time();

    // calculate error wrt. exact solution
    ExactSolution exact(&mesh, fndd);
    double error = h1_error(&sln_coarse, &exact) * 100;
    info("\nExact solution error: %g%%", error);

    // view the solution
    sview.show(&sln_coarse);
    oview.show(&space);

    // time measurement
    begin_time();

    // solve the fine mesh problem
    RefSystem rs(&ls);
    rs.assemble();
    rs.solve(1, &sln_fine);

    // calculate error estimate wrt. fine mesh solution
    H1AdaptHP hp(1, &space);
    double err_est = hp.calc_error(&sln_coarse, &sln_fine) * 100;
    info("Estimate of error: %g%%", err_est);

    // add entries to DOF convergence graphs
    graph_dof_exact.add_values(space.get_num_dofs(), error);
    graph_dof_exact.save("conv_dof_exact.dat");
    graph_dof_est.add_values(space.get_num_dofs(), err_est);
    graph_dof_est.save("conv_dof_est.dat");

    // add entries to CPU convergence graphs
    graph_cpu_exact.add_values(cpu, error);
    graph_cpu_exact.save("conv_cpu_exact.dat");
    graph_cpu_est.add_values(cpu, err_est);
    graph_cpu_est.save("conv_cpu_est.dat");

    // if err_est too large, adapt the mesh
    if (err_est < ERR_STOP) done = true;
    else {
      hp.adapt(THRESHOLD, STRATEGY, &selector, MESH_REGULARITY);
      ndofs = space.assign_dofs();
      if (ndofs >= NDOF_STOP) done = true;
    }

    // time measurement
    cpu += end_time();
    //sview.wait_for_keypress();
  }
  while (done == false);
  verbose("Total running time: %g sec", cpu);

  // show the fine solution - this is the final result
  sview.set_title("Final solution");
  sview.show(&sln_fine);

  // wait for keyboard or mouse input
  View::wait();
  return 0;
}
Exemple #16
0
int main(int argc, char* argv[])
{
  // Load the mesh.
  Mesh mesh;
  H2DReader mloader;
  mloader.load("domain.mesh", &mesh);

  // Perform initial mesh refinements.
  for(int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements();
  mesh.refine_towards_vertex(3, CORNER_REF_LEVEL);

  // Enter boundary markers.
  BCTypes bc_types;
  bc_types.add_bc_dirichlet(BDY_LEFT);
  bc_types.add_bc_neumann(Hermes::vector<int>(BDY_OUTER, BDY_INNER));
  bc_types.add_bc_newton(BDY_BOTTOM);

  // Enter Dirichlet boudnary values.
  BCValues bc_values;
  bc_values.add_const(BDY_LEFT, T1);

  // Create an H1 space with default shapeset.
  H1Space space(&mesh, &bc_types, &bc_values, P_INIT);
  int ndof = Space::get_num_dofs(&space);
  info("ndof = %d", ndof);

  // Initialize the weak formulation.
  WeakForm wf;
  wf.add_matrix_form(callback(bilinear_form_1), HERMES_SYM, MATERIAL_1);
  wf.add_matrix_form(callback(bilinear_form_2), HERMES_SYM, MATERIAL_2);
  wf.add_matrix_form_surf(callback(bilinear_form_surf_bottom), BDY_BOTTOM);
  wf.add_vector_form_surf(callback(linear_form_surf_bottom), BDY_BOTTOM);
  wf.add_vector_form_surf(callback(linear_form_surf_outer), BDY_OUTER);

  // Initialize coarse and reference mesh solution.
  Solution sln;
  
  // Initialize views.
  ScalarView sview("Solution", new WinGeom(0, 0, 410, 600));
  sview.fix_scale_width(50);
  sview.show_mesh(false);
  OrderView  oview("Polynomial orders", new WinGeom(420, 0, 400, 600));

  // DOF and CPU convergence graphs initialization.
  SimpleGraph graph_dof, graph_cpu;
  
  // Time measurement.
  TimePeriod cpu_time;
  cpu_time.tick();
  
  // Initialize matrix solver.
  SparseMatrix* matrix = create_matrix(matrix_solver);
  Vector* rhs = create_vector(matrix_solver);
  Solver* solver = create_linear_solver(matrix_solver, matrix, rhs);
  
  // Adaptivity loop:
  int as = 1; 
  bool done = false;
  do
  {
    info("---- Adaptivity step %d:", as);
       
    // Assemble reference problem.
    info("Solving on reference mesh.");
    bool is_linear = true;
    DiscreteProblem* dp = new DiscreteProblem(&wf, &space, is_linear);
    dp->assemble(matrix, rhs);
    
    // Time measurement.
    cpu_time.tick();
    
    // Solve the linear system of the reference problem. 
    // If successful, obtain the solution.
    if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), &space, &sln);
    else error ("Matrix solver failed.\n");
    
    // Time measurement.
    cpu_time.tick();
    
    // View the coarse mesh solution and polynomial orders.
    sview.show(&sln);
    oview.show(&space);
    
    // Skip visualization time.
    cpu_time.tick(HERMES_SKIP);
    
    // Calculate element errors and total error estimate.
    info("Calculating error estimate."); 
    KellyTypeAdapt* adaptivity = new KellyTypeAdapt(&space);
    adaptivity->add_error_estimator_surf(callback(kelly_interface_estimator));
    adaptivity->add_error_estimator_surf(callback(kelly_newton_boundary_estimator), BDY_BOTTOM);
    adaptivity->add_error_estimator_surf(callback(kelly_neumann_boundary_estimator), BDY_OUTER);
    adaptivity->add_error_estimator_surf(callback(kelly_zero_neumann_boundary_estimator), BDY_INNER);
    
    double err_est_rel = adaptivity->calc_err_est(&sln, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100;
                                                  
    // Report results.
    info("ndof: %d, err_est_rel: %g%%", Space::get_num_dofs(&space), err_est_rel);
    
    // Time measurement.
    cpu_time.tick();
    
    // Add entry to DOF and CPU convergence graphs.
    graph_dof.add_values(Space::get_num_dofs(&space), err_est_rel);
    graph_dof.save("conv_dof_est.dat");
    graph_cpu.add_values(cpu_time.accumulated(), err_est_rel);
    graph_cpu.save("conv_cpu_est.dat");
    
    // If err_est too large, adapt the mesh.
    if (err_est_rel < ERR_STOP) done = true;
    else 
    {
      info("Adapting coarse mesh.");
      done = adaptivity->adapt(THRESHOLD, STRATEGY, MESH_REGULARITY);
    }
    if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true;
    
    // Increase the counter of performed adaptivity steps.
    if (done == false)  as++;
    
    // Clean up.
    delete adaptivity;
    delete dp;                                    
  }
  while (done == false);
  
  // Clean up.
  delete solver;
  delete matrix;
  delete rhs;
  
  verbose("Total running time: %g s", cpu_time.accumulated());
  
  // Wait for all views to be closed.
  View::wait();
  
  return 0;
}
Exemple #17
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 #18
0
int main(int argc, char* argv[])
{
  // Load the mesh.
  Mesh mesh;
  H2DReader mloader;
  mloader.load("square.mesh", &mesh);

  // Initial mesh refinements.
  for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements();
  mesh.refine_towards_boundary(1, INIT_BDY_REF_NUM);

  // Create an H1 space with default shapeset.
  H1Space space(&mesh, bc_types, essential_bc_values, P_INIT);
  int ndof = Space::get_num_dofs(&space);
  info("ndof = %d.", ndof);

  // Solution for the previous time level.
  Solution u_prev_time;

  // Initialize the weak formulation.
  WeakForm wf;
  if (TIME_INTEGRATION == 1) {
    wf.add_matrix_form(jac_euler, jac_ord, HERMES_UNSYM, HERMES_ANY, &u_prev_time);
    wf.add_vector_form(res_euler, res_ord, HERMES_ANY, &u_prev_time);
  }
  else {
    wf.add_matrix_form(jac_cranic, jac_ord, HERMES_UNSYM, HERMES_ANY, &u_prev_time);
    wf.add_vector_form(res_cranic, res_ord, HERMES_ANY, &u_prev_time);
  }

  // Project the function init_cond() on the FE space
  // to obtain initial coefficient vector for the Newton's method.
  scalar* coeff_vec = new scalar[Space::get_num_dofs(&space)];
  info("Projecting initial condition to obtain initial vector for the Newton's method.");
  OGProjection::project_global(&space, init_cond, coeff_vec, matrix_solver);
  Solution::vector_to_solution(coeff_vec, &space, &u_prev_time);

  // Initialize views.
  ScalarView sview("Solution", 0, 0, 500, 400);
  OrderView oview("Mesh", 520, 0, 450, 400);
  oview.show(&space);
  sview.show(&u_prev_time);
  
  // Time stepping loop:
  double current_time = 0.0;
  int t_step = 1;
  do {
    info("---- Time step %d, t = %g s.", t_step, current_time); t_step++;

    // Initialize the FE problem.
    bool is_linear = false;
    DiscreteProblem dp(&wf, &space, is_linear);

    // Set up the solver, matrix, and rhs according to the solver selection.
    SparseMatrix* matrix = create_matrix(matrix_solver);
    Vector* rhs = create_vector(matrix_solver);
    Solver* solver = create_linear_solver(matrix_solver, matrix, rhs);

    // Perform Newton's iteration.
    int it = 1;
    while (1)
    {
      // Obtain the number of degrees of freedom.
      int ndof = Space::get_num_dofs(&space);

      // Assemble the Jacobian matrix and residual vector.
      dp.assemble(coeff_vec, matrix, rhs, false);

      // Multiply the residual vector with -1 since the matrix 
      // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n).
      for (int i = 0; i < ndof; i++) rhs->set(i, -rhs->get(i));
      
      // Calculate the l2-norm of residual vector.
      double res_l2_norm = get_l2_norm(rhs);

      // Info for user.
      info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(&space), res_l2_norm);

      // If l2 norm of the residual vector is within tolerance, or the maximum number 
      // of iteration has been reached, then quit.
      if (res_l2_norm < NEWTON_TOL || it > NEWTON_MAX_ITER) break;

      // Solve the linear system.
      if(!solver->solve())
        error ("Matrix solver failed.\n");

      // Add \deltaY^{n+1} to Y^n.
      for (int i = 0; i < ndof; i++) coeff_vec[i] += solver->get_solution()[i];
      
      if (it >= NEWTON_MAX_ITER)
        error ("Newton method did not converge.");

      it++;
    }

    // Translate the resulting coefficient vector into the Solution sln.
    Solution::vector_to_solution(coeff_vec, &space, &u_prev_time);

    // Cleanup.
    delete matrix;
    delete rhs;
    delete solver;

    // Update time.
    current_time += TAU;

    // Show the new time level solution.
    char title[100];
    sprintf(title, "Solution, t = %g", current_time);
    sview.set_title(title);
    sview.show(&u_prev_time);
  } while (current_time < T_FINAL);
  
  delete [] coeff_vec;

  // Wait for all views to be closed.
  View::wait();
  return 0;
}
Exemple #19
0
int main(int argc, char* argv[])
{
  // Load the mesh.
  Mesh mesh;
  H2DReader mloader;
  mloader.load("square.mesh", &mesh);

  // Initial mesh refinements.
  for(int i = 0; i < INIT_GLOB_REF_NUM; i++) mesh.refine_all_elements();
  mesh.refine_towards_boundary(BDY_DIRICHLET, INIT_BDY_REF_NUM);

  // Enter boundary markers.
  BCTypes bc_types;
  bc_types.add_bc_dirichlet(BDY_DIRICHLET);

  // Enter Dirichlet boundary values.
  BCValues bc_values;
  bc_values.add_function(BDY_DIRICHLET, essential_bc_values);

  // Create an H1 space with default shapeset.
  H1Space space(&mesh, &bc_types, &bc_values, P_INIT);
  int ndof = Space::get_num_dofs(&space);
  info("ndof = %d.", ndof);

  // Solution for the previous time level.
  Solution u_prev_time;

  // Initialize the weak formulation.
  WeakForm wf;
  if (TIME_INTEGRATION == 1) {
    wf.add_matrix_form(jac_euler, jac_ord, HERMES_NONSYM, HERMES_ANY, &u_prev_time);
    wf.add_vector_form(res_euler, res_ord, HERMES_ANY, &u_prev_time);
  }
  else {
    wf.add_matrix_form(jac_cranic, jac_ord, HERMES_NONSYM, HERMES_ANY, &u_prev_time);
    wf.add_vector_form(res_cranic, res_ord, HERMES_ANY, &u_prev_time);
  }

  // Project the function init_cond() on the FE space
  // to obtain initial coefficient vector for the Newton's method.
  scalar* coeff_vec = new scalar[Space::get_num_dofs(&space)];
  info("Projecting initial condition to obtain initial vector for the Newton's method.");
  OGProjection::project_global(&space, init_cond, coeff_vec, matrix_solver);
  Solution::vector_to_solution(coeff_vec, &space, &u_prev_time);

  // Initialize views.
  ScalarView sview("Solution", new WinGeom(0, 0, 500, 400));
  OrderView oview("Mesh", new WinGeom(520, 0, 450, 400));
  oview.show(&space);
  sview.show(&u_prev_time);
  
  // Time stepping loop:
  double current_time = 0.0;
  int t_step = 1;
  do {
    info("---- Time step %d, t = %g s.", t_step, current_time); t_step++;

    // Initialize the FE problem.
    bool is_linear = false;
    DiscreteProblem dp(&wf, &space, is_linear);

    // Set up the solver, matrix, and rhs according to the solver selection.
    SparseMatrix* matrix = create_matrix(matrix_solver);
    Vector* rhs = create_vector(matrix_solver);
    Solver* solver = create_linear_solver(matrix_solver, matrix, rhs);

    // Perform Newton's iteration.
    bool verbose = true;
    if (!solve_newton(coeff_vec, &dp, solver, matrix, rhs, 
        NEWTON_TOL, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed.");

    // Translate the resulting coefficient vector into the Solution sln.
    Solution::vector_to_solution(coeff_vec, &space, &u_prev_time);

    // Cleanup.
    delete matrix;
    delete rhs;
    delete solver;

    // Update time.
    current_time += TAU;

    // Show the new time level solution.
    char title[100];
    sprintf(title, "Solution, t = %g", current_time);
    sview.set_title(title);
    sview.show(&u_prev_time);
  } while (current_time < T_FINAL);
  
  delete [] coeff_vec;

  // Wait for all views to be closed.
  View::wait();
  return 0;
}
Exemple #20
0
int main(int argc, char* argv[])
{
    // Time measurement.
    TimePeriod cpu_time;
    cpu_time.tick();

    // Load the mesh.
    Mesh mesh;
    H2DReader mloader;
    mloader.load("domain.mesh", &mesh);

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

    // Create an H1 space with default shapeset.
    H1Space space(&mesh, bc_types, essential_bc_values, P_INIT);
    int ndof = Space::get_num_dofs(&space);
    info("ndof = %d", ndof);

    // Initialize the weak formulation.
    WeakForm wf;
    wf.add_matrix_form(bilinear_form, bilinear_form_ord, HERMES_SYM);
    wf.add_vector_form(linear_form, linear_form_ord);
    wf.add_vector_form_surf(linear_form_surf, linear_form_surf_ord, BDY_VERTICAL);

    // Initialize the FE problem.
    bool is_linear = true;
    DiscreteProblem dp(&wf, &space, is_linear);

    initialize_solution_environment(matrix_solver, argc, argv);

    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).
    }

    // Initialize the solution.
    Solution sln;

    // Assemble the stiffness matrix and right-hand side vector.
    info("Assembling the stiffness matrix and right-hand side vector.");
    dp.assemble(matrix, rhs);

    // Solve the linear system and if successful, obtain the solution.
    info("Solving the matrix problem.");
    if(solver->solve())
        Solution::vector_to_solution(solver->get_solution(), &space, &sln);
    else
        error ("Matrix solver failed.\n");

    // Time measurement.
    cpu_time.tick();

    // Clean up.
    delete solver;
    delete matrix;
    delete rhs;

    finalize_solution_environment(matrix_solver);

    // View the solution and mesh.
    ScalarView sview("Solution", new WinGeom(0, 0, 440, 350));
    sview.show(&sln);
    OrderView  oview("Polynomial orders", new WinGeom(450, 0, 400, 350));
    oview.show(&space);

    // 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;
}
Exemple #21
0
int main(int argc, char **argv)
{
  // Time measurement.
  TimePeriod cpu_time;
  cpu_time.tick();

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

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

  // Set exact solution.
  CustomExactSolution exact(&mesh);

  // Initialize boundary conditions
  DefaultEssentialBCNonConst<double> bc_essential("Bdy", &exact);
  EssentialBCs<double> bcs(&bc_essential);
  
  // Initialize the weak formulation.
  CustomWeakFormPoisson wf1;
 
  // Create an H1 space with default shapeset.
  H1Space<double> space(&mesh, &bcs, P_INIT);
  int ndof = Space<double>::get_num_dofs(&space);
  info("ndof: %d", ndof);

  info("---- Assembling by DiscreteProblem, solving by %s:", 
       MatrixSolverNames[matrix_solver].c_str());

  // Initialize the linear discrete problem.
  DiscreteProblem<double> dp1(&wf1, &space);
    
  // Set up the solver, matrix, and rhs according to the solver selection.
  SparseMatrix<double>* matrix = create_matrix<double>(matrix_solver);
  Vector<double>* rhs = create_vector<double>(matrix_solver);
  LinearSolver<double>* solver = create_linear_solver<double>(matrix_solver, matrix, rhs);
  
#ifdef HAVE_AZTECOO
    if (matrix_solver == SOLVER_AZTECOO) 
    {
      (dynamic_cast<AztecOOSolver<double>*>(solver))->set_solver(iterative_method);
      (dynamic_cast<AztecOOSolver<double>*>(solver))->set_precond(preconditioner);
      // Using default iteration parameters (see solver/aztecoo.h).
    }    
#endif
  
  // Begin time measurement of assembly.
  cpu_time.tick(HERMES_SKIP);

  // Initial coefficient vector for the Newton's method.  
  double* coeff_vec = new double[ndof];
  memset(coeff_vec, 0, ndof*sizeof(double));

  // Initialize the Newton solver.
  Hermes::Hermes2D::NewtonSolver<double> newton(&dp1, matrix_solver);

  // Perform Newton's iteration and translate the resulting coefficient vector into a Solution.
  Hermes::Hermes2D::Solution<double> sln1;
  try
  {
    newton.solve(coeff_vec);
  }
  catch(Hermes::Exceptions::Exception e)
  {
    e.printMsg();
    error("Newton's iteration failed.");
  }

  Hermes::Hermes2D::Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln1);

  // CPU time measurement.
  double time = cpu_time.tick().last();

  // Calculate errors.
  double rel_err_1 = Global<double>::calc_rel_error(&sln1, &exact, HERMES_H1_NORM) * 100;
  info("CPU time: %g s.", time);
  info("Exact H1 error: %g%%.", rel_err_1);

  delete(matrix);
  delete(rhs);
  delete(solver);
    
  // View the solution and mesh.
  ScalarView sview("Solution", new WinGeom(0, 0, 440, 350));
  sview.show(&sln1);
  //OrderView  oview("Polynomial orders", new WinGeom(450, 0, 400, 350));
  //oview.show(&space);
  
  // TRILINOS PART:

  info("---- Assembling by DiscreteProblem, solving by NOX:");

  // Initialize the weak formulation for Trilinos.
  CustomWeakFormPoisson wf2(TRILINOS_JFNK);
  
  // Initialize DiscreteProblem.
  DiscreteProblem<double> dp2(&wf2, &space);
  
  // Time measurement.
  cpu_time.tick(HERMES_SKIP);

  // Set initial vector for NOX.
  // NOTE: Using zero vector was causing convergence problems.
  info("Projecting to obtain initial vector for the Newton's method.");
  ZeroSolution init_sln(&mesh);

  // Initialize the NOX solver with the vector "coeff_vec".
  info("Initializing NOX.");
  NewtonSolverNOX<double> nox_solver(&dp2);
  nox_solver.set_output_flags(message_type);

  nox_solver.set_ls_type(iterative_method);
  nox_solver.set_ls_tolerance(ls_tolerance);

  nox_solver.set_conv_iters(max_iters);
  if (flag_absresid)
    nox_solver.set_conv_abs_resid(abs_resid);
  if (flag_relresid)
    nox_solver.set_conv_rel_resid(rel_resid);

  // Choose preconditioning.
  MlPrecond<double> pc("sa");
  if (PRECOND)
  {
    if (TRILINOS_JFNK) nox_solver.set_precond(pc);
    else nox_solver.set_precond(preconditioner);
  }

  // Assemble and solve using NOX.
  Solution<double> sln2;
  OGProjection<double>::project_global(&space, &init_sln, coeff_vec);
  try
  {
    nox_solver.solve(coeff_vec);
  }
  catch(Hermes::Exceptions::Exception e)
  {
    e.printMsg();
    error("NOX failed.");
  }

  Solution<double>::vector_to_solution(nox_solver.get_sln_vector(), &space, &sln2);

  info("Number of nonlin iterations: %d (norm of residual: %g)", 
    nox_solver.get_num_iters(), nox_solver.get_residual());
  info("Total number of iterations in linsolver: %d (achieved tolerance in the last step: %g)", 
    nox_solver.get_num_lin_iters(), nox_solver.get_achieved_tol());

  // CPU time needed by NOX.
  time = cpu_time.tick().last();

  // Show the NOX solution.
  ScalarView view2("Solution<double> 2", new WinGeom(450, 0, 460, 350));
  view2.show(&sln2);
  //view2.show(&exact);

  // Calculate errors.
  double rel_err_2 = Global<double>::calc_rel_error(&sln2, &exact, HERMES_H1_NORM) * 100;
  info("CPU time: %g s.", time);
  info("Exact H1 error: %g%%.", rel_err_2);
 
  // Wait for all views to be closed.
  View::wait();
  
  return 0;
}
Exemple #22
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;
}
Exemple #23
0
int main(int argc, char* argv[])
{
  // Load the mesh.
  MeshSharedPtr mesh(new Mesh);
  MeshReaderH2D mloader;
  mloader.load("square_quad.mesh", mesh);
  // mloader.load("square_tri.mesh", mesh);

  // Perform initial mesh refinement.
  for (int i = 0; i < INIT_REF_NUM; i++) mesh->refine_all_elements();
  mesh->refine_towards_boundary("Layer", INIT_REF_NUM_BDY);

  // Initialize the weak formulation.
  WeakFormSharedPtr<double> wf(new WeakFormLinearAdvectionDiffusion(STABILIZATION_ON, SHOCK_CAPTURING_ON, B1, B2, EPSILON));

  // Initialize boundary conditions
  DefaultEssentialBCConst<double> bc_rest("Rest", 1.0);
  EssentialBCNonConst bc_layer("Layer");

  EssentialBCs<double> bcs({ &bc_rest, &bc_layer });

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

  WinGeom* sln_win_geom = new WinGeom(0, 0, 440, 350);
  WinGeom* mesh_win_geom = new WinGeom(450, 0, 400, 350);

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

  // Initialize refinement selector.
  H1ProjBasedSelector<double> selector(CAND_LIST);

  // Initialize views.
  ScalarView sview("Solution", new WinGeom(0, 0, 440, 350));
  sview.fix_scale_width(50);
  sview.show_mesh(false);
  OrderView  oview("Polynomial orders", new WinGeom(450, 0, 400, 350));

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

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

  // Adaptivity loop:
  int as = 1;
  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<double>::ReferenceSpaceCreator refSpaceCreator(space, ref_mesh);
    SpaceSharedPtr<double> ref_space = refSpaceCreator.create_ref_space();

    // Assemble the reference problem.
    Hermes::Mixins::Loggable::Static::info("Solving on reference mesh.");
    LinearSolver<double> solver(wf, ref_space);

    // Time measurement.
    cpu_time.tick();

    // Solve the linear system of the reference problem.
    // If successful, obtain the solution.
    solver.solve();
    Solution<double>::vector_to_solution(solver.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<double>::project_global(space, ref_sln, sln);

    // Time measurement.
    cpu_time.tick();

    // View the coarse mesh solution and polynomial orders.
    sview.show(sln);
    oview.show(space);

    // Skip visualization time.
    cpu_time.tick(Hermes::Mixins::TimeMeasurable::HERMES_SKIP);

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

    // Report results.
    Hermes::Mixins::Loggable::Static::info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%",
      Space<double>::get_num_dofs(space), Space<double>::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<double>::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);

      // Increase the counter of performed adaptivity steps.
      if (done == false)  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");
  sview.show_mesh(false);
  sview.show(ref_sln);

  // Wait for all views to be closed.
  View::wait();
  return 0;
}