예제 #1
0
파일: main.cpp 프로젝트: LeiDai/hermes
int main(int argc, char* argv[])
{
  // Load the mesh.
  MeshSharedPtr mesh_coarse(new Mesh), mesh_fine(new Mesh);
  MeshReaderH2D mloader;
  mloader.load("square.mesh", mesh_coarse);

  mesh_fine->copy(mesh_coarse);
  mesh_fine->refine_all_elements();

  DefaultEssentialBCConst<double> bc_coarse("Bdy", 1.0);
  DefaultEssentialBCConst<double> bc_fine("Bdy", 2.0);

  EssentialBCs<double> bcs_coarse(&bc_coarse);
  EssentialBCs<double> bcs_fine(&bc_fine);

  // Create an H1 space with default shapeset.
  SpaceSharedPtr<double> space_coarse(new H1Space<double>(mesh_coarse, &bcs_coarse, 2));
  SpaceSharedPtr<double> space_fine(new H1Space<double>(mesh_fine, &bcs_fine, 3));

  // Translate the coefficient vector into a Solution.
  MeshFunctionSharedPtr<double> fn_coarse(new ConstantSolution<double>(mesh_coarse, 1.0));
  MeshFunctionSharedPtr<double> fn_fine_const(new ConstantSolution<double>(mesh_fine, 2.0));
  MeshFunctionSharedPtr<double> fn_fine_non_const(new CustomExactSolutionScalar(mesh_fine));

#ifdef CUSTOM_DEBUG
  // Visualise the solution and mesh.
  ScalarView s_view;
  s_view.show(fn_coarse);
  s_view.wait_for_keypress();
  s_view.show(fn_fine_const);
  s_view.wait_for_keypress();
  s_view.show(fn_fine_non_const);
  s_view.wait_for_keypress();
#endif

  ErrorCalculator<double> errorCalculator(AbsoluteError);
  errorCalculator.add_error_form(new CustomNormFormVol(0, 0));
  errorCalculator.add_error_form(new CustomNormFormSurf(0, 0));
  errorCalculator.add_error_form(new CustomNormFormDG(0, 0));

  errorCalculator.calculate_errors(fn_coarse, fn_fine_const);

#ifdef CUSTOM_DEBUG
  std::cout << "Total error const: " << errorCalculator.get_total_error_squared() << std::endl;
#endif

  if (std::abs(errorCalculator.get_total_error_squared() - 5.0) > 1e-10)
    return -1;

  errorCalculator.calculate_errors(fn_coarse, fn_fine_non_const);

#ifdef CUSTOM_DEBUG
  std::cout << "Total error nonconst: " << errorCalculator.get_total_error_squared() << std::endl;
#endif

  if (std::abs(errorCalculator.get_total_error_squared() - 13.0) > 1e-10)
  {
    std::cout << "Failure!";
    return -1;
  }

  std::cout << "Success!";
  return 0;
}
예제 #2
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;
}