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

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

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

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

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

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

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

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

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

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

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

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

      // Output mesh and element orders in VTK format.
      Views::Orderizer ord;
      sprintf(title, "ord-%d.vtk", as);
      ord.save_orders_vtk(&space, title);
      Hermes::Mixins::Loggable::Static::info("Element orders in VTK format saved to file %s.", title);
    }

    // View the coarse mesh solution and polynomial orders.
    if (HERMES_VISUALIZATION) 
    {
      sview.show(&sln);
      oview.show(&space);
    }

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

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

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

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

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

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

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

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

  return 0;
}
Beispiel #2
0
int main(int argc, char* argv[])
{
  // Load the mesh.
  Mesh mesh;
  MeshReaderH1DXML mloader;
  mloader.load("domain.xml", &mesh);

  // Perform initial mesh refinements (optional).
  // Split elements vertically.
  int refinement_type = 2;            
  for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(refinement_type);

  // Initialize the weak formulation.
  CustomWeakFormPoisson wf("Al", new Hermes::Hermes1DFunction<double>(LAMBDA_AL), "Cu", 
      new Hermes::Hermes1DFunction<double>(LAMBDA_CU), 
      new Hermes::Hermes2DFunction<double>(-VOLUME_HEAT_SRC));

  // Initialize essential boundary conditions.
  DefaultEssentialBCConst<double> bc_essential(Hermes::vector<std::string>("Left", "Right"), 
      FIXED_BDY_TEMP);
  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);
  
  // Show the mesh and poly degrees.
  Views::OrderView oview("Mesh", new Views::WinGeom(0, 0, 900, 250));
  if (HERMES_VISUALIZATION) oview.show(&space);

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

  // Perform Newton's iteration and translate the resulting coefficient vector into a Solution.
  Solution<double> sln;
  NewtonSolver<double> newton(&dp);
  try
  {
    newton.solve();
  }
  catch(Hermes::Exceptions::Exception e)
  {
    e.printMsg();
    throw Hermes::Exceptions::Exception("Newton's iteration failed.");
  };
  Solution<double>::vector_to_solution(newton.get_sln_vector(), &space, &sln);

  // Get info about time spent during assembling in its respective parts.
  //dp.get_all_profiling_output(std::cout);

  // VTK output.
  if (VTK_VISUALIZATION)
  {
    // Output solution in VTK format.
    Views::Linearizer lin;
    bool mode_3D = true;
    lin.save_solution_vtk(&sln, "sln.vtk", "Temperature", mode_3D);
    Hermes::Mixins::Loggable::Static::info("Solution in VTK format saved to file %s.", "sln.vtk");

    // Output mesh and element orders in VTK format.
    Views::Orderizer ord;
    ord.save_orders_vtk(&space, "ord.vtk");
    Hermes::Mixins::Loggable::Static::info("Element orders in VTK format saved to file %s.", "ord.vtk");
  }

  // Visualize the solution.
  if (HERMES_VISUALIZATION)
  {
    Views::ScalarView view("Solution", new Views::WinGeom(0, 300, 900, 350));
    // Hermes uses adaptive FEM to approximate higher-order FE solutions with linear
    // triangles for OpenGL. The second parameter of View::show() sets the error 
    // tolerance for that. Options are HERMES_EPS_LOW, HERMES_EPS_NORMAL (default), 
    // HERMES_EPS_HIGH and HERMES_EPS_VERYHIGH. The size of the graphics file grows 
    // considerably with more accurate representation, so use it wisely.
    view.show(&sln, Views::HERMES_EPS_HIGH);
    Views::View::wait();
  }

  return 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);
  
  // 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, ref_sln;

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

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

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

  // Time measurement.
  TimePeriod cpu_time;

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

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

    // Initialize reference problem.
    info("Solving on reference mesh.");
    DiscreteProblem<double> dp(&wf, ref_space);
    
    NewtonSolver<double> newton(&dp, matrix_solver_type);
    newton.set_verbose_output(false);

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

    // Perform Newton's iteration.
    if (!newton.solve(coeff_vec)) 
      error("Newton's iteration failed.");
    else
      // Translate the resulting coefficient vector into the instance of Solution.
      Solution<double>::vector_to_solution(newton.get_sln_vector(), ref_space, &ref_sln);
    
    // Project the fine mesh solution onto the coarse mesh.
    info("Projecting reference solution on coarse mesh.");
    OGProjection<double>::project_global(&space, &ref_sln, &sln, matrix_solver_type);

    // Time measurement.
    cpu_time.tick();

    // VTK output.
    if (VTK_VISUALIZATION) 
    {
      // Output solution in VTK format.
      Views::Linearizer lin(&sln);
      char* title = new char[100];
      sprintf(title, "sln-%d.vtk", as);
      lin.save_solution_vtk(title, "Potential", false);
      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);
      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(HERMES_SKIP);

    // Calculate element errors and total error estimate.
    info("Calculating error estimate.");
    Adapt<double> adaptivity(&space);
    bool solutions_for_adapt = true;
    // In the following function, the Boolean parameter "solutions_for_adapt" determines whether
    // the calculated errors are intended for use with adaptivity (this may not be the case, for example,
    // when error wrt. an exact solution is calculated). The default value is solutions_for_adapt = true,
    // The last parameter "error_flags" determine whether the total and element errors are treated as
    // absolute or relative. Its default value is error_flags = HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL.
    // In subsequent examples and benchmarks, these two parameters will be often used with
    // their default values, and thus they will not be present in the code explicitly.
    double err_est_rel = adaptivity.calc_err_est(&sln, &ref_sln, solutions_for_adapt,
                         HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100;

    // Report results.
    info("ndof_coarse: %d, ndof_fine: %d, err_est_rel: %g%%",
      space.get_num_dofs(), ref_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(HERMES_SKIP);

    // 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() >= NDOF_STOP) 
      done = true;

    // Clean up.
    delete [] coeff_vec;
    // Keep the mesh from final step to allow further working with the final reference solution.
    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.
  Views::View::wait();

  return 0;
}
Beispiel #4
0
int main(int argc, char* argv[])
{
    // Load the mesh.
    MeshSharedPtr mesh(new Mesh);
    MeshReaderH2D mloader;
    mloader.load("domain.mesh", mesh);

    // Initialize the weak formulation.
    CustomWeakFormPoisson wf("Motor", EPS_MOTOR, "Air", EPS_AIR);

    // 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.
    SpaceSharedPtr<double> space(new H1Space<double>(mesh, &bcs, P_INIT));

    // Set the space to adaptivity.
    adaptivity.set_space(space);

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

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

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

    DiscreteProblem<double> dp(&wf, space);
    NewtonSolver<double> newton(&dp);
    newton.set_verbose_output(true);

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

        // Time measurement.
        cpu_time.tick();

        // Construct globally refined mesh and setup fine mesh space.
        Mesh::ReferenceMeshCreator ref_mesh_creator(mesh);
        MeshSharedPtr ref_mesh = ref_mesh_creator.create_ref_mesh();
        Space<double>::ReferenceSpaceCreator ref_space_creator(space, ref_mesh);
        SpaceSharedPtr<double> ref_space = ref_space_creator.create_ref_space();
        int ndof_ref = ref_space->get_num_dofs();

        // Initialize fine mesh problem.
        Hermes::Mixins::Loggable::Static::info("Solving on fine mesh.");

        newton.set_space(ref_space);

        // 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(), ref_space, ref_sln);

        // Project the fine mesh solution onto the coarse mesh.
        Hermes::Mixins::Loggable::Static::info("Projecting fine mesh solution on coarse mesh.");
        OGProjection<double>::project_global(space, ref_sln, 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(ref_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.");
        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->get_num_dofs(), ref_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.");
            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 fine mesh solution - final result.
    sview.set_title("Fine mesh solution");
    sview.show_mesh(false);
    sview.show(ref_sln);

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

    return 0;
}