示例#1
0
int main(int argc, char* argv[])
{
  try
  {
    // Sanity check for omega.
    double K_squared = Hermes::sqr(OMEGA / M_PI) * (OMEGA - 2) / (1 - OMEGA);
    if (K_squared <= 0) throw Hermes::Exceptions::Exception("Wrong choice of omega, K_squared < 0!");
    double K_norm_coeff = std::sqrt(K_squared) / std::sqrt(Hermes::sqr(K_x) + Hermes::sqr(K_y));
    Hermes::Mixins::Loggable::Static::info("Wave number K = %g", std::sqrt(K_squared));
    K_x *= K_norm_coeff;
    K_y *= K_norm_coeff;

    // Wave number.
    double K = std::sqrt(Hermes::sqr(K_x) + Hermes::sqr(K_y));

    // Choose a Butcher's table or define your own.
    ButcherTable bt(butcher_table);
    if (bt.is_explicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage explicit R-K method.", bt.get_size());
    if (bt.is_diagonally_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage diagonally implicit R-K method.", bt.get_size());
    if (bt.is_fully_implicit()) Hermes::Mixins::Loggable::Static::info("Using a %d-stage fully implicit R-K method.", bt.get_size());

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

    // Perform initial mesh refinemets.
    for (int i = 0; i < INIT_REF_NUM; i++)
    {
      E_mesh->refine_all_elements();
      H_mesh->refine_all_elements();
      P_mesh->refine_all_elements();
    }

    // Initialize solutions.
    double current_time = 0;
    MeshFunctionSharedPtr<double> E_time_prev(new CustomInitialConditionE(E_mesh, current_time, OMEGA, K_x, K_y));
    MeshFunctionSharedPtr<double> H_time_prev(new CustomInitialConditionH(H_mesh, current_time, OMEGA, K_x, K_y));
    MeshFunctionSharedPtr<double> P_time_prev(new CustomInitialConditionP(P_mesh, current_time, OMEGA, K_x, K_y));
    std::vector<MeshFunctionSharedPtr<double> > slns_time_prev({ E_time_prev, H_time_prev, P_time_prev });
    MeshFunctionSharedPtr<double> E_time_new(new Solution<double>(E_mesh)), H_time_new(new Solution<double>(H_mesh)), P_time_new(new Solution<double>(P_mesh));
    MeshFunctionSharedPtr<double> E_time_new_coarse(new Solution<double>(E_mesh)), H_time_new_coarse(new Solution<double>(H_mesh)), P_time_new_coarse(new Solution<double>(P_mesh));
    std::vector<MeshFunctionSharedPtr<double> > slns_time_new({ E_time_new, H_time_new, P_time_new });

    // Initialize the weak formulation.
    WeakFormSharedPtr<double> wf(new CustomWeakFormMD(OMEGA, K_x, K_y, MU_0, EPS_0, EPS_INF, EPS_Q, TAU));

    // Initialize boundary conditions
    DefaultEssentialBCConst<double> bc_essential("Bdy", 0.0);
    EssentialBCs<double> bcs(&bc_essential);

    SpaceSharedPtr<double> E_space(new HcurlSpace<double>(E_mesh, &bcs, P_INIT));
    SpaceSharedPtr<double> H_space(new H1Space<double>(H_mesh, NULL, P_INIT));
    //L2Space<double> H_space(mesh, P_INIT));
    SpaceSharedPtr<double> P_space(new HcurlSpace<double>(P_mesh, &bcs, P_INIT));

    std::vector<SpaceSharedPtr<double> > spaces = std::vector<SpaceSharedPtr<double> >({ E_space, H_space, P_space });

    // Initialize views.
    ScalarView E1_view("Solution E1", new WinGeom(0, 0, 400, 350));
    E1_view.fix_scale_width(50);
    ScalarView E2_view("Solution E2", new WinGeom(410, 0, 400, 350));
    E2_view.fix_scale_width(50);
    ScalarView H_view("Solution H", new WinGeom(0, 410, 400, 350));
    H_view.fix_scale_width(50);
    ScalarView P1_view("Solution P1", new WinGeom(410, 410, 400, 350));
    P1_view.fix_scale_width(50);
    ScalarView P2_view("Solution P2", new WinGeom(820, 410, 400, 350));
    P2_view.fix_scale_width(50);

    // Visualize initial conditions.
    char title[100];
    sprintf(title, "E1 - Initial Condition");
    E1_view.set_title(title);
    E1_view.show(E_time_prev, H2D_FN_VAL_0);
    sprintf(title, "E2 - Initial Condition");
    E2_view.set_title(title);
    E2_view.show(E_time_prev, H2D_FN_VAL_1);

    sprintf(title, "H - Initial Condition");
    H_view.set_title(title);
    H_view.show(H_time_prev);

    sprintf(title, "P1 - Initial Condition");
    P1_view.set_title(title);
    P1_view.show(P_time_prev, H2D_FN_VAL_0);
    sprintf(title, "P2 - Initial Condition");
    P2_view.set_title(title);
    P2_view.show(P_time_prev, H2D_FN_VAL_1);

    // Initialize Runge-Kutta time stepping.
    RungeKutta<double> runge_kutta(wf, spaces, &bt);
    runge_kutta.set_newton_max_allowed_iterations(NEWTON_MAX_ITER);
    runge_kutta.set_newton_tolerance(NEWTON_TOL);
    runge_kutta.set_verbose_output(true);

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

    // Time stepping loop.
    int ts = 1;
    do
    {
      // Perform one Runge-Kutta time step according to the selected Butcher's table.
      Hermes::Mixins::Loggable::Static::info("\nRunge-Kutta time step (t = %g s, time_step = %g s, stages: %d).",
        current_time, time_step, bt.get_size());

      // Periodic global derefinements.
      if (ts > 1 && ts % UNREF_FREQ == 0 && REFINEMENT_COUNT > 0)
      {
        Hermes::Mixins::Loggable::Static::info("Global mesh derefinement.");
        REFINEMENT_COUNT = 0;

        E_space->unrefine_all_mesh_elements(true);
        H_space->unrefine_all_mesh_elements(true);
        P_space->unrefine_all_mesh_elements(true);

        E_space->adjust_element_order(-1, P_INIT);
        H_space->adjust_element_order(-1, P_INIT);
        P_space->adjust_element_order(-1, P_INIT);

        E_space->assign_dofs();
        H_space->assign_dofs();
        P_space->assign_dofs();
      }

      // 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.
        int order_increase = 1;

        Mesh::ReferenceMeshCreator refMeshCreatorE(E_mesh);
        Mesh::ReferenceMeshCreator refMeshCreatorH(H_mesh);
        Mesh::ReferenceMeshCreator refMeshCreatorP(P_mesh);
        MeshSharedPtr ref_mesh_E = refMeshCreatorE.create_ref_mesh();
        MeshSharedPtr ref_mesh_H = refMeshCreatorH.create_ref_mesh();
        MeshSharedPtr ref_mesh_P = refMeshCreatorP.create_ref_mesh();

        Space<double>::ReferenceSpaceCreator refSpaceCreatorE(E_space, ref_mesh_E, order_increase);
        SpaceSharedPtr<double> ref_space_E = refSpaceCreatorE.create_ref_space();
        Space<double>::ReferenceSpaceCreator refSpaceCreatorH(H_space, ref_mesh_H, order_increase);
        SpaceSharedPtr<double> ref_space_H = refSpaceCreatorH.create_ref_space();
        Space<double>::ReferenceSpaceCreator refSpaceCreatorP(P_space, ref_mesh_P, order_increase);
        SpaceSharedPtr<double> ref_space_P = refSpaceCreatorP.create_ref_space();
        std::vector<SpaceSharedPtr<double> > ref_spaces({ ref_space_E, ref_space_H, ref_space_P });

        int ndof = Space<double>::get_num_dofs(ref_spaces);
        Hermes::Mixins::Loggable::Static::info("ndof = %d.", ndof);

        try
        {
          runge_kutta.set_spaces(ref_spaces);
          runge_kutta.set_time(current_time);
          runge_kutta.set_time_step(time_step);
          runge_kutta.rk_time_step_newton(slns_time_prev, slns_time_new);
        }
        catch (Exceptions::Exception& e)
        {
          e.print_msg();
          throw Hermes::Exceptions::Exception("Runge-Kutta time step failed");
        }

        // Visualize the solutions.
        char title[100];
        sprintf(title, "E1, t = %g", current_time + time_step);
        E1_view.set_title(title);
        E1_view.show(E_time_new, H2D_FN_VAL_0);
        sprintf(title, "E2, t = %g", current_time + time_step);
        E2_view.set_title(title);
        E2_view.show(E_time_new, H2D_FN_VAL_1);

        sprintf(title, "H, t = %g", current_time + time_step);
        H_view.set_title(title);
        H_view.show(H_time_new);

        sprintf(title, "P1, t = %g", current_time + time_step);
        P1_view.set_title(title);
        P1_view.show(P_time_new, H2D_FN_VAL_0);
        sprintf(title, "P2, t = %g", current_time + time_step);
        P2_view.set_title(title);
        P2_view.show(P_time_new, H2D_FN_VAL_1);

        // Project the fine mesh solution onto the coarse mesh.
        Hermes::Mixins::Loggable::Static::info("Projecting reference solution on coarse mesh.");
        OGProjection<double>::project_global({ E_space, H_space, P_space }, { E_time_new, H_time_new, P_time_new }, { E_time_new_coarse, H_time_new_coarse, P_time_new_coarse });

        // Calculate element errors and total error estimate.
        Hermes::Mixins::Loggable::Static::info("Calculating error estimate.");
        adaptivity.set_spaces({ E_space, H_space, P_space });
        errorCalculator.calculate_errors({ E_time_new_coarse, H_time_new_coarse, P_time_new_coarse }, { E_time_new, H_time_new, P_time_new });

        double err_est_rel_total = errorCalculator.get_total_error_squared() * 100.;

        // Report results.
        Hermes::Mixins::Loggable::Static::info("Error estimate: %g%%", err_est_rel_total);

        // If err_est too large, adapt the mesh.
        if (err_est_rel_total < ERR_STOP)
        {
          Hermes::Mixins::Loggable::Static::info("Error estimate under the specified threshold -> moving to next time step.");
          done = true;
        }
        else
        {
          Hermes::Mixins::Loggable::Static::info("Adapting coarse mesh.");
          REFINEMENT_COUNT++;
          done = adaptivity.adapt({ &HcurlSelector, &H1selector, &HcurlSelector });

          if (!done)
            as++;
        }
      } while (!done);

      //View::wait();
      E_time_prev->copy(E_time_new);
      H_time_prev->copy(H_time_new);
      P_time_prev->copy(P_time_new);

      // Update time.
      current_time += time_step;
      ts++;
    } while (current_time < T_FINAL);

    // Wait for the view to be closed.
    View::wait();
  }
  catch (std::exception& e)
  {
    std::cout << e.what();
  }

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

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

  // Initialize solutions.
  CustomInitialConditionWave E_sln(&mesh);
  ZeroSolutionVector F_sln(&mesh);
  Hermes::vector<Solution<double>*> slns(&E_sln, &F_sln);

  // Initialize the weak formulation.
  CustomWeakFormWave wf(time_step, C_SQUARED, &E_sln, &F_sln);
  
  // Initialize boundary conditions
  DefaultEssentialBCConst<double> bc_essential("Perfect conductor", 0.0);
  EssentialBCs<double> bcs(&bc_essential);

  // Create x- and y- displacement space using the default H1 shapeset.
  HcurlSpace<double> E_space(&mesh, &bcs, P_INIT);
  HcurlSpace<double> F_space(&mesh, &bcs, P_INIT);
  Hermes::vector<Space<double> *> spaces = Hermes::vector<Space<double> *>(&E_space, &F_space);

  info("ndof = %d.", Space<double>::get_num_dofs(spaces));

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

  // Set up the solver, matrix, and rhs according to the solver selection.
  SparseMatrix<double>* matrix = create_matrix<double>(matrix_solver_type);
  Vector<double>* rhs = create_vector<double>(matrix_solver_type);
  LinearSolver<double>* solver = create_linear_solver<double>(matrix_solver_type, matrix, rhs);
  solver->set_factorization_scheme(HERMES_REUSE_FACTORIZATION_COMPLETELY);

  // Initialize views.
  ScalarView E1_view("Solution E1", new WinGeom(0, 0, 400, 350));
  E1_view.fix_scale_width(50);
  ScalarView E2_view("Solution E2", new WinGeom(410, 0, 400, 350));
  E2_view.fix_scale_width(50);

  // Time stepping loop.
  double current_time = 0; int ts = 1;
  do
  {
    // Perform one implicit Euler time step.
    info("Implicit Euler time step (t = %g s, time_step = %g s).", current_time, time_step);

    // First time assemble both the stiffness matrix and right-hand side vector,
    // then just the right-hand side vector.
    if (ts == 1) {
      info("Assembling the stiffness matrix and right-hand side vector.");
      dp.assemble(matrix, rhs);
      static char file_name[1024];
      sprintf(file_name, "matrix.m");
      FILE *f = fopen(file_name, "w");
      matrix->dump(f, "A");
      fclose(f);
    }
    else {
      info("Assembling the right-hand side vector (only).");
      dp.assemble(rhs);
    }

    // Solve the linear system and if successful, obtain the solution.
    info("Solving the matrix problem.");
    if(solver->solve()) Solution<double>::vector_to_solutions(solver->get_sln_vector(), spaces, slns);
    else error ("Matrix solver failed.\n");

    // Visualize the solutions.
    char title[100];
    sprintf(title, "E1, t = %g", current_time);
    E1_view.set_title(title);
    E1_view.show(&E_sln, HERMES_EPS_NORMAL, H2D_FN_VAL_0);
    sprintf(title, "E2, t = %g", current_time);
    E2_view.set_title(title);
    E2_view.show(&E_sln, HERMES_EPS_NORMAL, H2D_FN_VAL_1);

    // Update time.
    current_time += time_step;
  } while (current_time < T_FINAL);

  // Wait for the view to be closed.
  View::wait();

  return 0;
}
示例#3
0
int main(int argc, char* argv[])
{
  // 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;
  MeshReaderH2D mloader;
  mloader.load("domain.mesh", &mesh);

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

  // Initialize solutions.
  CustomInitialConditionWave E_sln(&mesh);
  ZeroSolution B_sln(&mesh);
  Hermes::vector<Solution<double>*> slns(&E_sln, &B_sln);

  // Initialize the weak formulation.
  CustomWeakFormWave wf(C_SQUARED);
  
  // Initialize boundary conditions
  DefaultEssentialBCConst<double> bc_essential("Perfect conductor", 0.0);
  EssentialBCs<double> bcs_E(&bc_essential);
  EssentialBCs<double> bcs_B;

  // Create x- and y- displacement space using the default H1 shapeset.
  HcurlSpace<double> E_space(&mesh, &bcs_E, P_INIT);
  H1Space<double> B_space(&mesh, &bcs_B, P_INIT);
  //L2Space<double> B_space(&mesh, P_INIT);
  Hermes::vector<Space<double> *> spaces = Hermes::vector<Space<double> *>(&E_space, &B_space);
  info("ndof = %d.", Space<double>::get_num_dofs(spaces));

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

  // Initialize views.
  ScalarView E1_view("Solution E1", new WinGeom(0, 0, 400, 350));
  E1_view.fix_scale_width(50);
  ScalarView E2_view("Solution E2", new WinGeom(410, 0, 400, 350));
  E2_view.fix_scale_width(50);
  ScalarView B_view("Solution B", new WinGeom(0, 405, 400, 350));
  B_view.fix_scale_width(50);

  // Initialize Runge-Kutta time stepping.
  RungeKutta<double> runge_kutta(&dp, &bt, matrix_solver_type);

  // Time stepping loop.
  double current_time = time_step; int ts = 1;
  do
  {
    // 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 jacobian_changed = false;
    bool verbose = true;
    
    try
    {
      runge_kutta.rk_time_step_newton(current_time, time_step, slns, slns, jacobian_changed, verbose);
    }
    catch(Exceptions::Exception& e)
    {
      e.printMsg();
      error("Runge-Kutta time step failed");
    }

    // Visualize the solutions.
    char title[100];
    sprintf(title, "E1, t = %g", current_time);
    E1_view.set_title(title);
    E1_view.show(&E_sln, HERMES_EPS_NORMAL, H2D_FN_VAL_0);
    sprintf(title, "E2, t = %g", current_time);
    E2_view.set_title(title);
    E2_view.show(&E_sln, HERMES_EPS_NORMAL, H2D_FN_VAL_1);
    sprintf(title, "B, t = %g", current_time);
    B_view.set_title(title);
    B_view.show(&B_sln, HERMES_EPS_NORMAL, H2D_FN_VAL_0);

    // Update time.
    current_time += time_step;
  
  } while (current_time < T_FINAL);

  // Wait for the view to be closed.
  View::wait();

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

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

  // Initialize solutions.
  MeshFunctionSharedPtr<double> E_sln(new CustomInitialConditionWave(mesh));
  MeshFunctionSharedPtr<double>  F_sln(new ZeroSolutionVector<double>(mesh));
  Hermes::vector<MeshFunctionSharedPtr<double> > slns(E_sln, F_sln);

  // Initialize the weak formulation.
  CustomWeakFormWaveIE wf(time_step, C_SQUARED, E_sln, F_sln);

  // Initialize boundary conditions
  DefaultEssentialBCConst<double> bc_essential("Perfect conductor", 0.0);
  EssentialBCs<double> bcs(&bc_essential);

  SpaceSharedPtr<double> E_space(new HcurlSpace<double>(mesh, &bcs, P_INIT));
  SpaceSharedPtr<double> F_space(new HcurlSpace<double>(mesh, &bcs, P_INIT));

  Hermes::vector<SpaceSharedPtr<double> > spaces = Hermes::vector<SpaceSharedPtr<double> >(E_space, F_space);
  int ndof = HcurlSpace<double>::get_num_dofs(spaces);
  Hermes::Mixins::Loggable::Static::info("ndof = %d.", ndof);

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

  // Project the initial condition on the FE space to obtain initial 
  // coefficient vector for the Newton's method.
  // NOTE: If you want to start from the zero vector, just define 
  // coeff_vec to be a vector of ndof zeros (no projection is needed).
  Hermes::Mixins::Loggable::Static::info("Projecting to obtain initial vector for the Newton's method.");
  double* coeff_vec = new double[ndof];
  OGProjection<double> ogProjection; ogProjection.project_global(spaces, slns, coeff_vec); 

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

  // Initialize views.
  ScalarView E1_view("Solution E1", new WinGeom(0, 0, 400, 350));
  E1_view.fix_scale_width(50);
  ScalarView E2_view("Solution E2", new WinGeom(410, 0, 400, 350));
  E2_view.fix_scale_width(50);
  ScalarView F1_view("Solution F1", new WinGeom(0, 410, 400, 350));
  F1_view.fix_scale_width(50);
  ScalarView F2_view("Solution F2", new WinGeom(410, 410, 400, 350));
  F2_view.fix_scale_width(50);

  // Time stepping loop.
  double current_time = 0; int ts = 1;
  do
  {
    // Perform one implicit Euler time step.
    Hermes::Mixins::Loggable::Static::info("Implicit Euler time step (t = %g s, time_step = %g s).", current_time, time_step);

    // Perform Newton's iteration.
    try
    {
      newton.set_max_allowed_iterations(NEWTON_MAX_ITER);
      newton.set_tolerance(NEWTON_TOL, Hermes::Solvers::ResidualNormAbsolute);
      newton.solve(coeff_vec);
    }
    catch(Hermes::Exceptions::Exception e)
    {
      e.print_msg();
      throw Hermes::Exceptions::Exception("Newton's iteration failed.");
    }

    // Translate the resulting coefficient vector into Solutions.
    Solution<double>::vector_to_solutions(newton.get_sln_vector(), spaces, slns);

    // Visualize the solutions.
    char title[100];
    sprintf(title, "E1, t = %g", current_time + time_step);
    E1_view.set_title(title);
    E1_view.show(E_sln, H2D_FN_VAL_0);
    sprintf(title, "E2, t = %g", current_time + time_step);
    E2_view.set_title(title);
    E2_view.show(E_sln, H2D_FN_VAL_1);

    sprintf(title, "F1, t = %g", current_time + time_step);
    F1_view.set_title(title);
    F1_view.show(F_sln, H2D_FN_VAL_0);
    sprintf(title, "F2, t = %g", current_time + time_step);
    F2_view.set_title(title);
    F2_view.show(F_sln, H2D_FN_VAL_1);

    //View::wait();

    // Update time.
    current_time += time_step;

  } while (current_time < T_FINAL);

  // Wait for the view to be closed.
  View::wait();

  return 0;
}