Пример #1
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);

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

  // Previous time level solution (initialized by the initial condition).
  Solution u_prev_time(&mesh, init_cond);

  // Initialize the weak formulation.
  WeakForm wf;
  wf.add_matrix_form(callback(jac), HERMES_NONSYM, HERMES_ANY);
  wf.add_vector_form(callback(res), HERMES_ANY, &u_prev_time);

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

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

  // Initialize views.
  ScalarView sview("Solution", new WinGeom(0, 0, 500, 400));
  OrderView oview("Mesh", new WinGeom(510, 0, 460, 400));
  oview.show(&space);

  // Time stepping loop:
  double current_time = 0.0; int ts = 1;
  do 
  {
    info("---- Time step %d, t = %g s.", ts, current_time); ts++;

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

    // Update previous time level solution.
    Solution::vector_to_solution(coeff_vec, &space, &u_prev_time);

    // 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);
    oview.show(&space);
  } 
  while (current_time < T_FINAL);

  // Cleanup.
  delete [] coeff_vec;
  delete matrix;
  delete rhs;
  delete solver;

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

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

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

    // Enter boundary markers.
    BCTypes bc_types;
    bc_types.add_bc_dirichlet(Hermes::Tuple<int>(BDY_1, BDY_6));
    bc_types.add_bc_newton(Hermes::Tuple<int>(BDY_2, BDY_3, BDY_4, BDY_5));

    // Enter Dirichlet boundary values.
    BCValues bc_values;
    bc_values.add_zero(Hermes::Tuple<int>(BDY_1, BDY_6));

    // Create an Hcurl space with default shapeset.
    HcurlSpace space(&mesh, &bc_types, &bc_values, P_INIT);

    // Initialize the weak formulation.
    WeakForm wf;
    wf.add_matrix_form(callback(bilinear_form), HERMES_SYM);
    wf.add_matrix_form_surf(callback(bilinear_form_surf));
    wf.add_vector_form_surf(linear_form_surf, linear_form_surf_ord);

    // Initialize coarse and reference mesh solutions.
    Solution sln, ref_sln;

    // Initialize exact solution.
    ExactSolution sln_exact(&mesh, exact);

    // Initialize refinement selector.
    HcurlProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER);

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

    // 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 = construct_refined_space(&space);

        // Assemble the reference problem.
        info("Solving on reference mesh.");
        bool is_linear = true;
        DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear);
        SparseMatrix* matrix = create_matrix(matrix_solver);
        Vector* rhs = create_vector(matrix_solver);
        Solver* solver = create_linear_solver(matrix_solver, matrix, rhs);
        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(), ref_space, &ref_sln);
        else error ("Matrix solver failed.\n");

        // Time measurement.
        cpu_time.tick();

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

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

        // Calculate exact error,
        bool solutions_for_adapt = false;
        double err_exact_rel = adaptivity->calc_err_exact(&sln, &sln_exact, solutions_for_adapt) * 100;

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

        // Time measurement.
        cpu_time.tick();

        // Add entry to DOF and CPU convergence graphs.
        graph_dof_est.add_values(Space::get_num_dofs(&space), err_est_rel);
        graph_dof_est.save("conv_dof_est.dat");
        graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel);
        graph_cpu_est.save("conv_cpu_est.dat");
        graph_dof_exact.add_values(Space::get_num_dofs(&space), err_exact_rel);
        graph_dof_exact.save("conv_dof_exact.dat");
        graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel);
        graph_cpu_exact.save("conv_cpu_exact.dat");

        // If err_est_rel 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 solver;
        delete matrix;
        delete rhs;
        delete adaptivity;
        if(done == false) delete ref_space->get_mesh();
        delete ref_space;
        delete dp;

    }
    while (done == false);

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

    int ndof = Space::get_num_dofs(&space);

    printf("ndof allowed = %d\n", 1400);
    printf("ndof actual = %d\n", ndof);
    if (ndof < 1400) {      // ndofs was 1384 atthe time this test was created
        printf("Success!\n");
        return ERR_SUCCESS;
    }
    else {
        printf("Failure!\n");
        return ERR_FAILURE;
    }
}
Пример #3
0
int main(int argc, char* argv[]) 
{
  // This is a hack I used to run the code a dozen of times when plotting convergence graphs.
  if (argc > 1) {
    if (argv[1][0] == 'e') method = IE;
    else if (argv[1][0] == 's') method = SDIRK;
    else error("what are you doing?");
  }
  if (argc > 2) {
    TAU = std::atof(argv[2]);
  }

  // This is important to make sure we compare solution at exact same point in time when studying convergence.
  int N_STEP = std::ceil(T_FINAL / TAU);
  if (fabs(T_FINAL - N_STEP * TAU) > 1e-10) {
    error("bad choice of TAU");
  }

  info("t_final = %g, tau = %g, n = %i", T_FINAL, TAU, N_STEP);

  // 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 boudnary values.
  BCValues bc_values;
  bc_values.add_zero(BDY_DIRICHLET);

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

  // Previous time level solution (initialized by the initial condition).
  Solution u_prev_time(&mesh, exact_solution);

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

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

  // Initialize views.
  ScalarView sview("Solution", new WinGeom(0, 0, 500, 400));
  OrderView oview("Mesh", new WinGeom(520, 0, 450, 400));
  oview.show(&space);

  if (method == IE) {
    info("IMPLICIT EULER METHOD");
    // Initialize the weak formulation.
    WeakForm wf;
    wf.add_matrix_form(callback(jac), HERMES_NONSYM, HERMES_ANY);
    wf.add_vector_form(callback(res), HERMES_ANY, &u_prev_time);

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

    // Time stepping loop:
    int ts = 0;
    do {
      info("---- Time step %d, t = %g s.", ++ts, TIME);

      info("We are computing solution at next time step TIME+TAU = %g s.", TIME+TAU);

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

      // Update previous time level solution.
      Solution::vector_to_solution(coeff_vec, &space, &u_prev_time);

      // Update time.
      TIME = TIME + TAU;

      // Compute exact error.
      Solution exact_sln(&mesh, exact_solution);
      double exact_l2_error = calc_abs_error(&u_prev_time, &exact_sln, HERMES_L2_NORM);
      info("TIME: %g s.", TIME);
      info("Exact error in l2-norm: %g.", exact_l2_error);

      // Show the new time level solution.
      char title[100];
      sprintf(title, "Solution, t = %g", TIME);
      sview.set_title(title);
      sview.show(&u_prev_time);
      oview.show(&space);
    } 
    while (ts < N_STEP);

    // Cleanup.
    delete [] coeff_vec;
    delete matrix;
    delete rhs;
    delete solver;

    // Hack to extract error at final time for convergence graph.
    Solution citrouille(&mesh, exact_solution);
    info("IE: tau %g, abs_error %g.", TAU, calc_abs_error(&u_prev_time, &citrouille, HERMES_L2_NORM));
  }
  else if (method == SDIRK) {
    info("SDIRK22");

    Solution Y1(&mesh, init_cond);
    Solution Y2(&mesh, init_cond);

    scalar* coeff_vec1 = new scalar[ndof];
    OGProjection::project_global(&space, &u_prev_time, coeff_vec1, matrix_solver);
    scalar* coeff_vec2 = new scalar[ndof];
    OGProjection::project_global(&space, &u_prev_time, coeff_vec2, matrix_solver);

    WeakForm wf1;
    wf1.add_matrix_form(callback(jac_Y), HERMES_NONSYM, HERMES_ANY);
    wf1.add_vector_form(callback(res_Y1), HERMES_ANY, Hermes::vector<MeshFunction*>(&u_prev_time));
    WeakForm wf2;
    wf2.add_matrix_form(callback(jac_Y), HERMES_NONSYM, HERMES_ANY);
    wf2.add_vector_form(callback(res_Y2), HERMES_ANY, Hermes::vector<MeshFunction*>(&u_prev_time, &Y1));

    // Initialize the FE problem. 
    bool is_linear = false;
    DiscreteProblem dp1(&wf1, &space, is_linear);
    DiscreteProblem dp2(&wf2, &space, is_linear);

    double current_time = 0.0; int ts = 0;
    do {
      info("---- Time step %d, t = %g s.", ++ts, current_time);

      // Compute Y1.
      info("Compute Y1 at t = %g s.", TIME+GAMMA*TAU);

      // Perform Newton's iteration for Y1.
      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.
        dp1.assemble(coeff_vec1, matrix, rhs, false);

        // Multiply the residual vector with -1 since the matrix 
        // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n).
        rhs->change_sign();

        // 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_vec1[i] += solver->get_solution()[i];

        if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge.");

        it++;
      }

      // Store Y1.
      Solution::vector_to_solution(coeff_vec1, &space, &Y1);

      // Compute Y2.
      info("Compute Y2 at t = %g s.", TIME+TAU);

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

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

        // Multiply the residual vector with -1 since the matrix 
        // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n).
        rhs->change_sign();

        // 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_vec2[i] += solver->get_solution()[i];

        if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge.");

        it++;
      }

      // Store Y2.
      Solution::vector_to_solution(coeff_vec2, &space, &Y2);

      // Update previous time level solution.
      u_prev_time = Y2;

      // Update time.
      TIME = TIME + TAU;

      // Compute exact error.
      Solution exact_sln(&mesh, exact_solution);
      double exact_l2_error = calc_abs_error(&u_prev_time, &exact_sln, HERMES_L2_NORM);
      info("TIME: %g s.", TIME);
      info("Exact error in l2-norm: %g.", exact_l2_error);

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

    // Hack to extract error at final time for convergence graph.
    Solution citrouille(&mesh, exact_solution);
    info("SDIRK: tau %g, abs_error %g.", TAU, calc_abs_error(&u_prev_time, &citrouille, HERMES_L2_NORM));
  }

  // Wait for all views to be closed.
  View::wait();
  return 0;
}
Пример #4
0
int main(int argc, char* argv[])
{
  // Choose a Butcher's table or define your own.
  ButcherTable* bt = new ButcherTable(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());

  // Turn off adaptive time stepping if R-K method is not embedded.
  if (bt->is_embedded() == false && ADAPTIVE_TIME_STEP_ON == true) {
    warn("R-K method not embedded, turning off adaptive time stepping.");
    ADAPTIVE_TIME_STEP_ON = false;
  }

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

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

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

  // Convert initial condition into a Solution.
  Solution* sln_prev_time = new Solution(&mesh, init_cond);

  // Initialize the weak formulation.
  WeakForm wf;
  wf.add_matrix_form(callback(stac_jacobian), HERMES_NONSYM, HERMES_ANY, sln_prev_time);
  wf.add_vector_form(callback(stac_residual), HERMES_ANY, sln_prev_time);

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

  // Create a refinement selector.
  H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER);

  // Graph for time step history.
  SimpleGraph time_step_graph;
  if (ADAPTIVE_TIME_STEP_ON) info("Time step history will be saved to file time_step_history.dat.");
  
  // Time stepping loop.
  double current_time = time_step; int ts = 1;
  do 
  {
    info("Begin time step %d.", ts);
    // Periodic global derefinement.
    if (ts > 1 && ts % UNREF_FREQ == 0) 
    {
      info("Global mesh derefinement.");
      if (UNREF_LEVEL == 1) mesh.unrefine_all_elements();
      else mesh.copy(&basemesh);
      space.set_uniform_order(P_INIT);
      ndof = Space::get_num_dofs(&space);
    }

    // Spatial adaptivity loop. Note: sln_prev_time must not be 
    // changed during spatial adaptivity. 
    Solution ref_sln;
    Solution* time_error_fn;
    if (bt->is_embedded() == true) time_error_fn = new Solution(&mesh);
    else time_error_fn = NULL;
    bool done = false; int as = 1;
    double err_est;
    do {
      // Construct globally refined reference mesh and setup reference space.
      Space* ref_space = construct_refined_space(&space);

      // Initialize discrete problem on reference mesh.
      DiscreteProblem* ref_dp = new DiscreteProblem(&wf, ref_space);

      // Runge-Kutta step on the fine mesh.
      info("Runge-Kutta time step on fine mesh (t = %g s, tau = %g s, stages: %d).", 
         current_time, time_step, bt->get_size());
      bool verbose = true;
      bool is_linear = false;
      if (!rk_time_step(current_time, time_step, bt, sln_prev_time, &ref_sln, time_error_fn,
                        ref_dp, matrix_solver, verbose, is_linear, NEWTON_TOL_FINE, NEWTON_MAX_ITER)) {
        error("Runge-Kutta time step failed, try to decrease time step size.");
      }

      /* If ADAPTIVE_TIME_STEP_ON == true, estimate temporal error. 
         If too large or too small, then adjust it and restart the time step. */

      double rel_err_time;
      if (bt->is_embedded() == true) {
        info("Calculating temporal error estimate.");

        rel_err_time = calc_norm(time_error_fn, HERMES_H1_NORM) / calc_norm(&ref_sln, HERMES_H1_NORM) * 100;
        if (ADAPTIVE_TIME_STEP_ON == false) info("rel_err_time: %g%%", rel_err_time);
      }

      if (ADAPTIVE_TIME_STEP_ON) {
        if (rel_err_time > TIME_ERR_TOL_UPPER) {
          info("rel_err_time %g%% is above upper limit %g%%", rel_err_time, TIME_ERR_TOL_UPPER);
          info("Decreasing tau from %g to %g s and restarting time step.", 
               time_step, time_step * TIME_STEP_DEC_RATIO);
          time_step *= TIME_STEP_DEC_RATIO;
          delete ref_space;
          delete ref_dp;
          continue;
        }
        else if (rel_err_time < TIME_ERR_TOL_LOWER) {
          info("rel_err_time = %g%% is below lower limit %g%%", rel_err_time, TIME_ERR_TOL_UPPER);
          info("Increasing tau from %g to %g s and restarting time step.", 
               time_step, time_step * TIME_STEP_INC_RATIO);
          time_step *= TIME_STEP_INC_RATIO;
          delete ref_space;
          delete ref_dp;
          continue;
        }
        else {
          info("rel_err_time = %g%% is in acceptable interval (%g%%, %g%%)", 
            rel_err_time, TIME_ERR_TOL_LOWER, TIME_ERR_TOL_UPPER);
        }

        // Add entry to time step history graph.
        time_step_graph.add_values(current_time, time_step);
        time_step_graph.save("time_step_history.dat");
      }

      /* Estimate spatial errors and perform mesh refinement */

      info("Spatial adaptivity step %d.", as);

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

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

      // Report results.
      info("ndof: %d, ref_ndof: %d, err_rel_space: %g%%", 
           Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_rel_space);

      // If err_est too large, adapt the mesh.
      if (err_rel_space < SPACE_ERR_TOL) done = true;
      else 
      {
        info("Adapting the coarse mesh.");
        done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY);

        if (Space::get_num_dofs(&space) >= NDOF_STOP) 
          done = true;
        else
          // Increase the counter of performed adaptivity steps.
          as++;
      }
      
      // Clean up.
      delete adaptivity;
      delete ref_space;
      delete ref_dp;
    }
    while (done == false);

    // Clean up.
    if (time_error_fn != NULL) delete time_error_fn;


    // Copy last reference solution into sln_prev_time.
    sln_prev_time->copy(&ref_sln);

    // Increase current time and counter of time steps.
    current_time += time_step;
    ts++;
  }
  while (current_time < T_FINAL);

  // Clean up.
  delete sln_prev_time;
  delete bt;

  ndof = Space::get_num_dofs(&space);

  printf("ndof allowed = %d\n", 130);
  printf("ndof actual = %d\n", ndof);
  if (ndof < 130) {      // ndofs was 121 at the time this test was created.
    printf("Success!\n");
    return ERR_SUCCESS;
  }
  else {
    printf("Failure!\n");
    return ERR_FAILURE;
  }
}
Пример #5
0
int main(int argc, char **argv) {
	int res = ERR_SUCCESS;

#ifdef WITH_PETSC
	PetscInitialize(&argc, &argv, (char *) PETSC_NULL, PETSC_NULL);
#endif
	set_verbose(false);

	if (argc < 3) error("Not enough parameters");

	HcurlShapesetLobattoHex shapeset;

	printf("* Loading mesh '%s'\n", argv[1]);
	Mesh mesh;
	Mesh3DReader mesh_loader;
	if (!mesh_loader.load(argv[1], &mesh)) error("Loading mesh file '%s'\n", argv[1]);

	printf("* Setting the space up\n");
	HcurlSpace space(&mesh, &shapeset);
	space.set_bc_types(bc_types);

	int order;
	sscanf(argv[2], "%d", &order);
	int dir_x = order, dir_y = order, dir_z = order;
	order3_t o(dir_x, dir_y, dir_z);
	printf("  - Setting uniform order to (%d, %d, %d)\n", o.x, o.y ,o.z);
	space.set_uniform_order(o);

	int ndofs = space.assign_dofs();
	printf("  - Number of DOFs: %d\n", ndofs);

	printf("* Calculating a solution\n");

#if defined WITH_UMFPACK
	UMFPackMatrix mat;
	UMFPackVector rhs;
	UMFPackLinearSolver solver(&mat, &rhs);
#elif defined WITH_PARDISO
	PardisoMatrix mat;
	PardisoVector rhs;
	PardisoSolver solver(&mat, &rhs);
#elif defined WITH_PETSC
	PetscMatrix mat;
	PetscVector rhs;
	PetscLinearSolver solver(&mat, &rhs);
#elif defined WITH_MUMPS
	MumpsMatrix mat;
	MumpsVector rhs;
	MumpsSolver solver(&mat, &rhs);
#endif

	WeakForm wf;
	wf.add_matrix_form(bilinear_form<double, scalar>, bilinear_form<ord_t, ord_t>, SYM);
	wf.add_matrix_form_surf(bilinear_form_surf<double, scalar>, bilinear_form_surf<ord_t, ord_t>);
	wf.add_vector_form(linear_form<double, scalar>, linear_form<ord_t, ord_t>);
	wf.add_vector_form_surf(linear_form_surf<double, scalar>, linear_form_surf<ord_t, ord_t>);

	LinearProblem lp(&wf, &space);

	// assemble stiffness matrix
	Timer assemble_timer("Assembling stiffness matrix");
	assemble_timer.start();
	lp.assemble(&mat, &rhs);
	assemble_timer.stop();

	// solve the stiffness matrix
	Timer solve_timer("Solving stiffness matrix");
	solve_timer.start();
	bool solved = solver.solve();
	solve_timer.stop();

//#ifdef OUTPUT_DIR
	mat.dump(stdout, "a");
	rhs.dump(stdout, "b");
//#endif

	if (solved) {
		scalar *s = solver.get_solution();

		Solution sln(&mesh);
		sln.set_coeff_vector(&space, s);

		printf("* Solution:\n");
		for (int i = 1; i <= ndofs; i++) {
			printf(" x[% 3d] = " SCALAR_FMT "\n", i, SCALAR(s[i]));
		}

		// output the measured values
		printf("%s: %s (%lf secs)\n", assemble_timer.get_name(), assemble_timer.get_human_time(), assemble_timer.get_seconds());
		printf("%s: %s (%lf secs)\n", solve_timer.get_name(), solve_timer.get_human_time(), solve_timer.get_seconds());

		// norm
		ExactSolution ex_sln(&mesh, exact_solution);
		double hcurl_sln_norm = hcurl_norm(&sln);
		double hcurl_err_norm = hcurl_error(&sln, &ex_sln);
		printf(" - Hcurl solution norm: % le\n", hcurl_sln_norm);
		printf(" - Hcurl error norm:    % le\n", hcurl_err_norm);

		double l2_sln_norm = l2_norm_hcurl(&sln);
		double l2_err_norm = l2_error_hcurl(&sln, &ex_sln);
		printf(" - L2 solution norm:    % le\n", l2_sln_norm);
		printf(" - L2 error norm:       % le\n", l2_err_norm);

		if (hcurl_err_norm > EPS || l2_err_norm > EPS) {
			// calculated solution is not enough precise
			res = ERR_FAILURE;
		}


#if 0 //def OUTPUT_DIR
		// output
		printf("starting output\n");
		const char *of_name = OUTPUT_DIR "/solution.vtk";
		FILE *ofile = fopen(of_name, "w");
		if (ofile != NULL) {
			ExactSolution ex_sln(&mesh, exact_solution_0, exact_solution_1, exact_solution_2);

			RealPartFilter real_sln(&mesh, &sln, FN_VAL);
			ImagPartFilter imag_sln(&mesh, &sln, FN_VAL);

			DiffFilter eh(&mesh, &sln, &ex_sln);
			DiffFilter eh_dx(&mesh, &sln, &ex_sln, FN_DX, FN_DX);
//			DiffFilter eh_dy(&mesh, &sln, &ex_sln, FN_DY, FN_DY);
//			DiffFilter eh_dz(&mesh, &sln, &ex_sln, FN_DZ, FN_DZ);

//			GmshOutputEngine output(ofile);
			VtkOutputEngine output(ofile);

			output.out(&real_sln, "real_Uh", FN_VAL);
			output.out(&imag_sln, "imag_Uh", FN_VAL);

			output.out(&real_sln, "real_Uh_0", FN_VAL_0);
			output.out(&real_sln, "real_Uh_1", FN_VAL_1);
			output.out(&real_sln, "real_Uh_2", FN_VAL_2);

			output.out(&imag_sln, "imag_Uh_0", FN_VAL_0);
			output.out(&imag_sln, "imag_Uh_1", FN_VAL_1);
			output.out(&imag_sln, "imag_Uh_2", FN_VAL_2);

			fclose(ofile);
		}
		else {
			warning("Can not open '%s' for writing.", of_name);
		}
#endif
	}

#ifdef WITH_PETSC
	mat.free();
	rhs.free();
	PetscFinalize();
#endif

	return res;
}
Пример #6
0
int main(int argc, char* argv[])
{
  // Load the mesh.
  Mesh mesh;
  ExodusIIReader mloader;
  if (!mloader.load("iron-water.e", &mesh)) error("ExodusII mesh load failed.");

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

  // Enter boundary markers.
  BCTypes bc_types;
  bc_types.add_bc_dirichlet(Hermes::vector<int>(WATER_2, IRON));
  bc_types.add_bc_neumann(WATER_1); 

  // Enter Dirichlet boundary values.
  BCValues bc_values;
  bc_values.add_zero(Hermes::vector<int>(WATER_2, IRON));

  // Create an H1 space with default shapeset.
  H1Space space(&mesh, &bc_types, &bc_values, P_INIT);

  // Initialize the weak formulation
  WeakForm wf;
  wf.add_matrix_form(bilinear_form_water, bilinear_form_ord, HERMES_SYM, WATER_1);
  wf.add_matrix_form(bilinear_form_water, bilinear_form_ord, HERMES_SYM, WATER_2);
  wf.add_matrix_form(bilinear_form_iron, bilinear_form_ord, HERMES_SYM, IRON);
  wf.add_vector_form(linear_form_source, linear_form_ord, WATER_1);

  // Initialize coarse and reference mesh solution.
  Solution sln, ref_sln;
  
  // Initialize refinement selector.
  H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER);
  
  // 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 = construct_refined_space(&space);

    // Assemble the reference problem.
    info("Solving on reference mesh.");
    bool is_linear = true;
    DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear);
    SparseMatrix* matrix = create_matrix(matrix_solver);
    Vector* rhs = create_vector(matrix_solver);
    Solver* solver = create_linear_solver(matrix_solver, matrix, rhs);
    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(), ref_space, &ref_sln);
    else error ("Matrix solver failed.\n");

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

    // 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 solver;
    delete matrix;
    delete rhs;
    delete adaptivity;
    if(done == false) delete ref_space->get_mesh();
    delete ref_space;
    delete dp;
    
  }
  while (done == false);
  
  verbose("Total running time: %g s", cpu_time.accumulated());

  int ndof = Space::get_num_dofs(&space);

#define ERROR_SUCCESS                               0
#define ERROR_FAILURE                               -1
  int n_dof_allowed = 170;
  printf("n_dof_actual = %d\n", ndof);
  printf("n_dof_allowed = %d\n", n_dof_allowed);// ndofs was 158 at the time this test was created
  if (ndof <= n_dof_allowed) {
    printf("Success!\n");
    return ERROR_SUCCESS;
  }
  else {
    printf("Failure!\n");
    return ERROR_FAILURE;
  }
}
Пример #7
0
int main(int argc, char **args)
{
    // Test variable.
    int success_test = 1;

    // Load the initial mesh.
    Mesh mesh;
    H3DReader mesh_loader;
    mesh_loader.load("../hexahedron.mesh3d", &mesh);

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

    // Create H1 space with default shapeset.
    H1Space space(&mesh, bc_types, essential_bc_values, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z));

    // Construct initial solution and set it to zero.
    Solution sln_prev(&mesh);
    sln_prev.set_zero();

    // Initialize weak formulation.
    WeakForm wf;
    wf.add_matrix_form(bilinear_form<double, scalar>, bilinear_form<Ord, Ord>, HERMES_SYM);
    wf.add_vector_form(linear_form<double, scalar>, linear_form<Ord, Ord>, HERMES_ANY_INT, &sln_prev);

    // Initialize discrete problem.
    bool is_linear = true;
    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);

    // Initialize the preconditioner in the case of SOLVER_AZTECOO.
    if (matrix_solver == SOLVER_AZTECOO)
    {
        ((AztecOOSolver*) solver)->set_solver(iterative_method);
        ((AztecOOSolver*) solver)->set_precond(preconditioner);
        // Using default iteration parameters (see solver/aztecoo.h).
    }

    // Exact error for testing purposes.
    double err_exact;

    // Time stepping.
    int nsteps = (int) (FINAL_TIME/TAU + 0.5);
    for (int ts = 0; ts < nsteps;  ts++)
    {
        info("---- Time step %d, time %3.5f.", ts, TIME);

        // Assemble the linear problem.
        info("Assembling the linear problem (ndof: %d).", Space::get_num_dofs(&space));

        if (ts == 0) dp.assemble(matrix, rhs);
        else dp.assemble(NULL, rhs);

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

        // Output solution.
        if (solution_output)
            out_fn_vtk(&sln, "sln", ts);


        // Calculate exact error.
        ExactSolution esln(&mesh, fndd);

        info("Calculating exact error.");
        Adapt *adaptivity = new Adapt(&space, HERMES_H1_NORM);
        bool solutions_for_adapt = false;
        err_exact = adaptivity->calc_err_exact(&sln, &esln, solutions_for_adapt, HERMES_TOTAL_ERROR_ABS) * 100;
        info("Err. exact: %g%%.", err_exact);

        // Next time step.
        sln_prev = sln;
        TIME += TAU;

        // Cleanup.
        delete adaptivity;
    }

    if(err_exact > 3.00)
        success_test = 0;

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

    if (success_test) {
        info("Success!");
        return ERR_SUCCESS;
    }
    else {
        info("Failure!");
        return ERR_FAILURE;
    }
}
Пример #8
0
int main(int argc, char **args)
{
  // Test variable.
  int success_test = 1;

  // Check the number of command-line parameters.
  if (argc < 2) {
    info("Use x, y, z, xy, xz, yz, or xyz as a command-line parameter.");
    error("Not enough command-line parameters.");
  }

  // Determine anisotropy type from the command-line parameter.
  ANISO_TYPE = parse_aniso_type(args[1]);

  // Load the mesh.
  Mesh mesh;
  H3DReader mloader;
  mloader.load("hex-0-1.mesh3d", &mesh);

  // Assign the lowest possible directional polynomial degrees so that the problem's NDOF >= 1.
  assign_poly_degrees();

  // Create an H1 space with default shapeset.
  info("Setting directional polynomial degrees %d, %d, %d.", P_INIT_X, P_INIT_Y, P_INIT_Z);
  H1Space space(&mesh, bc_types, essential_bc_values, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z));

  // Initialize weak formulation.
  WeakForm wf;
  wf.add_matrix_form(bilinear_form<double, scalar>, bilinear_form<Ord, Ord>, HERMES_SYM, HERMES_ANY);
  wf.add_vector_form(linear_form<double, scalar>, linear_form<Ord, Ord>, HERMES_ANY);

  // Set exact solution.
  ExactSolution exact(&mesh, fndd);

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

  // Initialize the solver in the case of SOLVER_PETSC or SOLVER_MUMPS.
  initialize_solution_environment(matrix_solver, argc, args);

  // 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 = construct_refined_space(&space,1 , H3D_H3D_H3D_REFT_HEX_XYZ);

    // Initialize the FE problem.
    bool is_linear = true;
    DiscreteProblem dp(&wf, ref_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);
    
    // Initialize the preconditioner in the case of SOLVER_AZTECOO.
    if (matrix_solver == SOLVER_AZTECOO) 
    {
      ((AztecOOSolver*) solver)->set_solver(iterative_method);
      ((AztecOOSolver*) solver)->set_precond(preconditioner);
      // Using default iteration parameters (see solver/aztecoo.h).
    }
  
    // Assemble the reference problem.
    info("Assembling on reference mesh (ndof: %d).", Space::get_num_dofs(ref_space));
    dp.assemble(matrix, rhs);

    // Time measurement.
    cpu_time.tick();

    // Solve the linear system on reference mesh. If successful, obtain the solution.
    info("Solving on reference mesh.");
    Solution ref_sln(ref_space->get_mesh());
    if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln);
    else {
		  printf("Matrix solver failed.\n");
		  success_test = 0;
	  }

    // Time measurement.
    cpu_time.tick();

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

    // Time measurement.
    cpu_time.tick();

    // Output solution and mesh with polynomial orders.
    if (solution_output) 
    {
      out_fn_vtk(&sln, "sln", as);
      out_orders_vtk(&space, "order", as);
    }

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

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

    // Calculate exact error.
    solutions_for_adapt = false;
    double err_exact_rel = adaptivity->calc_err_exact(&sln, &exact, solutions_for_adapt) * 100;

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

    // If err_est_rel is too large, adapt the mesh. 
    if (err_est_rel < ERR_STOP) done = true;
    else 
    {
      info("Adapting coarse mesh.");
      adaptivity->adapt(THRESHOLD);
    }
    if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true;

    // Clean up.
    delete ref_space->get_mesh();
    delete ref_space;
    delete matrix;
    delete rhs;
    delete solver;
    delete adaptivity;

    // Increase the counter of performed adaptivity steps.
    as++;
  } while (!done);

  // Properly terminate the solver in the case of SOLVER_PETSC or SOLVER_MUMPS.
  finalize_solution_environment(matrix_solver);

  // This is the actual test.
#define ERROR_SUCCESS                               0
#define ERROR_FAILURE                               -1
  int ndof_allowed;
  switch (ANISO_TYPE) {
  case ANISO_X: ndof_allowed = 28; break;
    case ANISO_Y: ndof_allowed = 28; break;
    case ANISO_Z: ndof_allowed = 28; break;
    case ANISO_X | ANISO_Y: ndof_allowed = 98; break;
    case ANISO_X | ANISO_Z: ndof_allowed = 98; break;
    case ANISO_Y | ANISO_Z: ndof_allowed = 98; break;
  case ANISO_X | ANISO_Y | ANISO_Z: ndof_allowed = 343; break; 
    default: error("Admissible command-line options are x, y, x, xy, xz, yz, xyz.");
  }

  int ndof = Space::get_num_dofs(&space);

  info("ndof_actual = %d", ndof);
  info("ndof_allowed = %d", ndof_allowed); 
  if (ndof > ndof_allowed)
    success_test = 0;
  
  if (success_test) {
    info("Success!");
    return ERR_SUCCESS;
  }
  else {
    info("Failure!");
    return ERR_FAILURE;
  }
}
Пример #9
0
int main(int argc, char* argv[])
{
  // 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();

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

  // Enter Dirichlet boudnary 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);

  // Initialize the weak formulation.
  WeakForm wf;
  wf.add_matrix_form(callback(bilinear_form), HERMES_SYM);
  wf.add_vector_form(callback(linear_form));

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

  // Set exact solution.
  ExactSolution exact(&mesh, fndd);

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

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

  // 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 = construct_refined_space(&space);

    // Assemble the reference problem.
    info("Solving on reference mesh.");
    bool is_linear = true;
    DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear);
    SparseMatrix* matrix = create_matrix(matrix_solver);
    Vector* rhs = create_vector(matrix_solver);
    Solver* solver = create_linear_solver(matrix_solver, matrix, rhs);
    dp->assemble(matrix, rhs);

    // Time measurement.
    cpu_time.tick();

    // Solve the linear system of the reference problem. If successful, obtain the solution.
    Solution ref_sln;
    if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln);
    else error ("Matrix solver failed.\n");

    // Time measurement.
    cpu_time.tick();

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

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

    // Calculate element errors and total error estimate.
    info("Calculating error estimate and exact error.");
    Adapt* adaptivity = new Adapt(&space, HERMES_H1_NORM);
    bool solutions_for_adapt = true;
    double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100;

    // Calculate exact error.   
    solutions_for_adapt = false;
    double err_exact_rel = adaptivity->calc_err_exact(&sln, &exact, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100;

    // Report results.
    info("ndof_coarse: %d, ndof_fine: %d", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space));
    info("err_est_rel: %g%%, err_exact_rel: %g%%", err_est_rel, err_exact_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");
    graph_dof_exact.add_values(Space::get_num_dofs(&space), err_exact_rel);
    graph_dof_exact.save("conv_dof_exact.dat");
    graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel);
    graph_cpu_exact.save("conv_cpu_exact.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 solver;
    delete matrix;
    delete rhs;
    delete adaptivity;
    if(done == false) delete ref_space->get_mesh();
    delete ref_space;
    delete dp;

  }
  while (done == false);

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

  // Wait for all views to be closed.
  View::wait();
  return 0;
}
Пример #10
0
int main(int argc, char **args) 
{
  // Test variable.
  int success_test = 1;

	if (argc < 3) error("Not enough parameters.");

  // Load the mesh.
	Mesh mesh;
  H3DReader mloader;
  if (!mloader.load(args[1], &mesh)) error("Loading mesh file '%s'.", args[1]);

  // Initialize the space according to the
  // command-line parameters passed.
	int o;
	sscanf(args[2], "%d", &o);
	Ord3 order(o, o, o);
	HcurlSpace space(&mesh, bc_types, NULL, order);

  // Initialize the weak formulation.
	WeakForm wf;
	wf.add_matrix_form(callback(bilinear_form), HERMES_SYM);
	wf.add_vector_form(callback(linear_form));

  // Initialize the FE problem.
  bool is_linear = true;
  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);

  // Initialize the preconditioner in the case of SOLVER_AZTECOO.
  if (matrix_solver == SOLVER_AZTECOO) 
  {
    ((AztecOOSolver*) solver)->set_solver(iterative_method);
    ((AztecOOSolver*) solver)->set_precond(preconditioner);
    // Using default iteration parameters (see solver/aztecoo.h).
  }

  // Assemble the linear problem.
  info("Assembling (ndof: %d).", Space::get_num_dofs(&space));
  dp.assemble(matrix, rhs);

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

  ExactSolution ex_sln(&mesh, exact_solution);

  // Calculate exact error.
  info("Calculating exact error.");
  Adapt *adaptivity = new Adapt(&space, HERMES_HCURL_NORM);
  bool solutions_for_adapt = false;
  double err_exact = adaptivity->calc_err_exact(&sln, &ex_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_ABS);

  if (err_exact > EPS)
		// Calculated solution is not precise enough.
		success_test = 0;

  // Clean up.
  delete matrix;
  delete rhs;
  delete solver;
  delete adaptivity;
  
  if (success_test) {
    info("Success!");
    return ERR_SUCCESS;
	}
	else {
    info("Failure!");
    return ERR_FAILURE;
	}
}
Пример #11
0
int main(int argc, char* argv[])
{
  // Choose a Butcher's table or define your own.
  ButcherTable* bt = new ButcherTable(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());

  // Turn off adaptive time stepping if R-K method is not embedded.
  if (bt->is_embedded() == false && ADAPTIVE_TIME_STEP_ON == true) {
    warn("R-K method not embedded, turning off adaptive time stepping.");
    ADAPTIVE_TIME_STEP_ON = false;
  }

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

  // Perform initial mesh refinements.
  for(int i = 0; i < INIT_REF_NUM; i++) basemesh.refine_all_elements();
  basemesh.refine_towards_boundary(BDY_BOTTOM, INIT_REF_NUM_BDY);
  mesh.copy(&basemesh);

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

  // Initialize an H1 space with default shapeset.
  H1Space space(&mesh, &bc_types, NULL, P_INIT);
  int ndof = Space::get_num_dofs(&space);
  info("ndof = %d.", ndof);
 
  // Convert initial condition into a Solution.
  Solution* sln_prev_time = new Solution(&mesh, TEMP_INIT);

  // Initialize weak formulation.
  WeakForm wf;
  wf.add_matrix_form(stac_jacobian_vol, stac_jacobian_vol_ord, HERMES_NONSYM, HERMES_ANY, sln_prev_time);
  wf.add_vector_form(stac_residual_vol, stac_residual_vol_ord, HERMES_ANY, sln_prev_time);
  wf.add_matrix_form_surf(stac_jacobian_bottom, stac_jacobian_bottom_ord, BDY_BOTTOM, sln_prev_time);
  wf.add_vector_form_surf(stac_residual_bottom, stac_residual_bottom_ord, BDY_BOTTOM, sln_prev_time);
  wf.add_matrix_form_surf(stac_jacobian_top, stac_jacobian_top_ord, BDY_TOP, sln_prev_time);
  wf.add_vector_form_surf(stac_residual_top, stac_residual_top_ord, BDY_TOP, sln_prev_time);

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

  // Create a refinement selector.
  H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER);

  // Visualize initial condition.
  char title[100];
  ScalarView sln_view("Initial condition", new WinGeom(0, 0, 1500, 360));
  OrderView ordview("Initial mesh", new WinGeom(0, 410, 1500, 360));
  ScalarView time_error_view("Temporal error", new WinGeom(0, 800, 1500, 360));
  time_error_view.fix_scale_width(40);
  ScalarView space_error_view("Spatial error", new WinGeom(0, 1220, 1500, 360));
  space_error_view.fix_scale_width(40);
  sln_view.show(sln_prev_time, HERMES_EPS_VERYHIGH);
  ordview.show(&space);

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

  // Time stepping loop:
  double current_time = 0; int ts = 1;
  do 
  {
    info("Begin time step %d.", ts);
    // Periodic global derefinement.
    if (ts > 1 && ts % UNREF_FREQ == 0) 
    {
      info("Global mesh derefinement.");
      if (UNREF_LEVEL == 1) mesh.unrefine_all_elements();
      else mesh.copy(&basemesh);
      space.set_uniform_order(P_INIT);
      ndof = Space::get_num_dofs(&space);
    }

    // Spatial adaptivity loop. Note: sln_prev_time must not be 
    // changed during spatial adaptivity. 
    Solution ref_sln;
    Solution* time_error_fn;
    if (bt->is_embedded() == true) time_error_fn = new Solution(&mesh);
    else time_error_fn = NULL;
    bool done = false; int as = 1;
    double err_est;
    do {
      // Construct globally refined reference mesh and setup reference space.
      Space* ref_space = construct_refined_space(&space);

      // Initialize discrete problem on reference mesh.
      DiscreteProblem* ref_dp = new DiscreteProblem(&wf, ref_space);

      // Runge-Kutta step on the fine mesh.
      info("Runge-Kutta time step on fine mesh (t = %g s, tau = %g s, stages: %d).", 
         current_time, time_step, bt->get_size());
      bool verbose = true;
      bool is_linear = false;
      if (!rk_time_step(current_time, time_step, bt, sln_prev_time, &ref_sln, time_error_fn,
                        ref_dp, matrix_solver, verbose, is_linear, NEWTON_TOL_FINE, NEWTON_MAX_ITER)) {
        error("Runge-Kutta time step failed, try to decrease time step size.");
      }

      /* If ADAPTIVE_TIME_STEP_ON == true, estimate temporal error. 
         If too large or too small, then adjust it and restart the time step. */

      double rel_err_time;
      if (bt->is_embedded() == true) {
        info("Calculating temporal error estimate.");

        // Show temporal error.
        char title[100];
        sprintf(title, "Temporal error est, spatial adaptivity step %d", as);     
        time_error_view.set_title(title);
        time_error_view.show_mesh(false);
        time_error_view.show(time_error_fn, HERMES_EPS_VERYHIGH);

        rel_err_time = calc_norm(time_error_fn, HERMES_H1_NORM) / calc_norm(&ref_sln, HERMES_H1_NORM) * 100;
        if (ADAPTIVE_TIME_STEP_ON == false) info("rel_err_time: %g%%", rel_err_time);
      }

      if (ADAPTIVE_TIME_STEP_ON) {
        if (rel_err_time > TIME_ERR_TOL_UPPER) {
          info("rel_err_time %g%% is above upper limit %g%%", rel_err_time, TIME_ERR_TOL_UPPER);
          info("Decreasing tau from %g to %g s and restarting time step.", 
               time_step, time_step * TIME_STEP_DEC_RATIO);
          time_step *= TIME_STEP_DEC_RATIO;
          delete ref_space;
          delete ref_dp;
          continue;
        }
        else if (rel_err_time < TIME_ERR_TOL_LOWER) {
          info("rel_err_time = %g%% is below lower limit %g%%", rel_err_time, TIME_ERR_TOL_UPPER);
          info("Increasing tau from %g to %g s.", time_step, time_step * TIME_STEP_INC_RATIO);
          time_step *= TIME_STEP_INC_RATIO;
        }
        else {
          info("rel_err_time = %g%% is in acceptable interval (%g%%, %g%%)", 
            rel_err_time, TIME_ERR_TOL_LOWER, TIME_ERR_TOL_UPPER);
        }

        // Add entry to time step history graph.
        time_step_graph.add_values(current_time, time_step);
        time_step_graph.save("time_step_history.dat");
      }

      /* Estimate spatial errors and perform mesh refinement */

      info("Spatial adaptivity step %d.", as);

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

      // Show spatial error.
      sprintf(title, "Spatial error est, spatial adaptivity step %d", as);  
      DiffFilter* space_error_fn = new DiffFilter(Hermes::vector<MeshFunction*>(&ref_sln, &sln));   
      space_error_view.set_title(title);
      space_error_view.show_mesh(false);
      AbsFilter abs_sef(space_error_fn);
      space_error_view.show(&abs_sef, HERMES_EPS_VERYHIGH);

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

      // Report results.
      info("ndof: %d, ref_ndof: %d, err_rel_space: %g%%", 
           Space::get_num_dofs(&space), Space::get_num_dofs(ref_space), err_rel_space);

      // If err_est too large, adapt the mesh.
      if (err_rel_space < SPACE_ERR_TOL) done = true;
      else 
      {
        info("Adapting the coarse mesh.");
        done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY);

        if (Space::get_num_dofs(&space) >= NDOF_STOP) 
          done = true;
        else
          // Increase the counter of performed adaptivity steps.
          as++;
      }
      
      // Clean up.
      delete adaptivity; 
      delete ref_space;
      delete ref_dp;
      delete space_error_fn;
    }
    while (done == false);

    // Clean up.
    if (time_error_fn != NULL) delete time_error_fn;

    // Visualize the solution and mesh.
    char title[100];
    sprintf(title, "Solution, time %g s", current_time);
    sln_view.set_title(title);
    sln_view.show_mesh(false);
    sln_view.show(&ref_sln, HERMES_EPS_VERYHIGH);
    sprintf(title, "Mesh, time %g s", current_time);
    ordview.set_title(title);
    ordview.show(&space);

    // Copy last reference solution into sln_prev_time.
    sln_prev_time->copy(&ref_sln);

    // Increase current time and counter of time steps.
    current_time += time_step;
    ts++;
  }
  while (current_time < T_FINAL);

  // Clean up.
  delete sln_prev_time;
  delete bt;

  // Wait for all views to be closed.
  View::wait();
  return 0;
}
Пример #12
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;
  H2DReader mloader;
  mloader.load("cathedral.mesh", &mesh);

  // Perform initial mesh refinements.
  for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements();
  mesh.refine_towards_boundary(BDY_AIR, INIT_REF_NUM_BDY);
  mesh.refine_towards_boundary(BDY_GROUND, INIT_REF_NUM_BDY);

  // Enter boundary markers.
  BCTypes bc_types;
  bc_types.add_bc_dirichlet(Hermes::vector<std::string>(BDY_GROUND));
  bc_types.add_bc_newton(BDY_AIR);

  // Enter Dirichlet boundary values.
  BCValues bc_values;
  bc_values.add_const(BDY_GROUND, TEMP_INIT);

  // Initialize 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);
 
  // Previous time level solution (initialized by the external temperature).
  Solution u_prev_time(&mesh, TEMP_INIT);

  // Initialize weak formulation.
  WeakForm wf;
  wf.add_matrix_form(callback(stac_jacobian_vol));
  wf.add_vector_form(callback(stac_residual_vol));
  wf.add_matrix_form_surf(callback(stac_jacobian_surf), BDY_AIR);
  wf.add_vector_form_surf(callback(stac_residual_surf), BDY_AIR);

  // Project the initial condition on the FE space to obtain initial solution coefficient vector.
  info("Projecting initial condition to translate initial condition into a vector.");
  scalar* coeff_vec = new scalar[ndof];
  OGProjection::project_global(&space, &u_prev_time, coeff_vec, matrix_solver);

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

  // Initialize views.
  ScalarView Tview("Temperature", new WinGeom(0, 0, 450, 600));
  Tview.set_min_max_range(0,20);
  Tview.fix_scale_width(30);

  // Time stepping loop:
  double current_time = 0.0; int ts = 1;
  do 
  {
    // Perform one Runge-Kutta time step according to the selected Butcher's table.
    info("Runge-Kutta time step (t = %g, tau = %g, stages: %d).", 
         current_time, time_step, bt.get_size());
    bool verbose = true;
    bool is_linear = true;
    if (!rk_time_step(current_time, time_step, &bt, coeff_vec, &dp, matrix_solver,
		      verbose, is_linear)) {
      error("Runge-Kutta time step failed, try to decrease time step size.");
    }

    // Convert coeff_vec into a new time level solution.
    Solution::vector_to_solution(coeff_vec, &space, &u_prev_time);

    // Update time.
    current_time += time_step;

    // Show the new time level solution.
    char title[100];
    sprintf(title, "Time %3.2f, exterior temperature %3.5f", current_time, temp_ext(current_time));
    Tview.set_title(title);
    Tview.show(&u_prev_time);

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

  // Cleanup.
  delete [] coeff_vec;

  // Wait for the view to be closed.
  View::wait();
  return 0;
}
Пример #13
0
int main(int argc, char* argv[])
{
  // Time measurement.
  TimePeriod cpu_time;
  cpu_time.tick();

  // Load the mesh.
  Mesh mesh, basemesh;
  H2DReader mloader;
  mloader.load("square.mesh", &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(BDY_TOP, INIT_REF_NUM_BDY);

  // Enter boundary markers.
  BCTypes bc_types;
  bc_types.add_bc_dirichlet(Hermes::Tuple<int>(BDY_TOP, BDY_REST));

  // Enter Dirichlet boundary values.
  BCValues bc_values;
  bc_values.add_function(Hermes::Tuple<int>(BDY_TOP, BDY_REST), 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);

  // Create an H1 space for the initial coarse mesh solution.
  H1Space init_space(&basemesh, &bc_types, &bc_values, P_INIT);

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

  // Solutions for the time stepping and adaptivity.
  Solution u_prev_time, sln, ref_sln;

  // Initialize views.
  char title_init[200];
  sprintf(title_init, "Projection of initial condition");
  ScalarView* view_init = new ScalarView(title_init, new WinGeom(0, 0, 410, 300));
  sprintf(title_init, "Initial mesh");
  OrderView* ordview_init = new OrderView(title_init, new WinGeom(420, 0, 350, 300));
  view_init->fix_scale_width(80);

  // Initialize u_prev_time.
  // Note: only if adaptivity to initial condition is not done.
  u_prev_time.set_exact(&basemesh, init_cond);

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

  // Error estimate and discrete problem size as a function of physical time.
  SimpleGraph graph_time_err_est, graph_time_err_exact, graph_time_dof, graph_time_cpu;

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

  ScalarView view("Projection of initial condition", new WinGeom(0, 0, 410, 300));
  OrderView ordview("Initial mesh", new WinGeom(420, 0, 350, 300));
  view.fix_scale_width(80);

  // Newton's loop on the coarse mesh.
  info("Solving on coarse mesh.");

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

  // Set up the solver_coarse, matrix_coarse, and rhs_coarse according to the solver_coarse selection.
  SparseMatrix* matrix_coarse = create_matrix(matrix_solver);
  Vector* rhs_coarse = create_vector(matrix_solver);
  Solver* solver_coarse = create_linear_solver(matrix_solver, matrix_coarse, rhs_coarse);

  // Perform Newton's iteration.
  info("Solving on coarse mesh.");
  bool verbose = true;
  if (!solve_newton(coeff_vec_coarse, &dp_coarse, solver_coarse, matrix_coarse, rhs_coarse, 
      NEWTON_TOL_COARSE, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed.");

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

  // Clean up.
  delete [] coeff_vec_coarse;
  delete rhs_coarse;
  delete matrix_coarse;
  delete solver_coarse;

  // Time stepping loop.
  int num_time_steps = (int)(T_FINAL/TAU + 0.5);
  for(int ts = 1; ts <= num_time_steps; ts++)
  {
    // Time measurement.
    cpu_time.tick();

    // Updating current time.
    TIME = ts*TAU;

    // Periodic global derefinements.
    if (ts > 1 && ts % UNREF_FREQ == 0) {
      info("Global mesh derefinement.");
      mesh.copy(&basemesh);
      space.set_uniform_order(P_INIT);
    }

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

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

      scalar* coeff_vec = new scalar[Space::get_num_dofs(ref_space)];
     
      // Calculate initial coefficient vector for Newton on the fine mesh.
      if (as == 1 && ts == 1) {
        info("Projecting coarse mesh solution to obtain initial vector on new fine mesh.");
        OGProjection::project_global(ref_space, &sln, coeff_vec, matrix_solver);
      }
      else {
        info("Projecting previous fine mesh solution to obtain initial vector on new fine mesh.");
        OGProjection::project_global(ref_space, &ref_sln, coeff_vec, matrix_solver);
        delete ref_sln.get_mesh();
      }

      // Initialize the FE problem.
      bool is_linear = false;
      DiscreteProblem dp(&wf, ref_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.
      info("Solving on fine mesh.");
      if (!solve_newton(coeff_vec, &dp, solver, matrix, rhs, 
          NEWTON_TOL_FINE, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed.");

      // Translate the resulting coefficient vector into the actual solutions. 
      Solution::vector_to_solutions(coeff_vec, ref_space, &ref_sln);

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

      // Calculate element errors.
      info("Calculating error estimate and exact error."); 
      Adapt* adaptivity = new Adapt(&space, HERMES_H1_NORM);
      bool solutions_for_adapt = true;
      
      // Calculate error estimate wrt. fine mesh solution.
      double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt, 
                           HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_ABS) * 100;

      // Calculate error wrt. exact solution.
      ExactSolution exact(&mesh, exact_sol);
      solutions_for_adapt = false;
      double err_exact_rel = adaptivity->calc_err_exact(&sln, &exact, solutions_for_adapt, 
                             HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100;

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

      // Add entries to convergence graphs.
      graph_time_err_est.add_values(ts*TAU, err_est_rel);
      graph_time_err_est.save("time_error_est.dat");
      graph_time_err_exact.add_values(ts*TAU, err_exact_rel);
      graph_time_err_exact.save("time_error_exact.dat");
      graph_time_dof.add_values(ts*TAU, Space::get_num_dofs(&space));
      graph_time_dof.save("time_dof.dat");
      graph_time_cpu.add_values(ts*TAU, cpu_time.accumulated());
      graph_time_cpu.save("time_cpu.dat");

      // If space_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);
        if (Space::get_num_dofs(&space) >= NDOF_STOP) {
          done = true;
          break;
        }

        as++;
      }

      // Clean up.
      delete [] coeff_vec;
      delete solver;
      delete matrix;
      delete rhs;
      delete adaptivity;
      delete ref_space;
    }
    while (!done);

    // Visualize the solution and mesh.
    char title[100];
    sprintf(title, "Solution, time level %d", ts);
    view.set_title(title);
    view.show(&sln);
    sprintf(title, "Mesh, time level %d", ts);
    ordview.set_title(title);
    ordview.show(&space);

    // Copy new time level solution into u_prev_time.
    u_prev_time.copy(&ref_sln);
  }

  // Wait for all views to be closed.
  View::wait();
  return 0;
}
Пример #14
0
int main(int argc, char* argv[])
{
  // Load the mesh.
  Mesh mesh;
  H2DReader mloader;
  mloader.load("cathedral.mesh", &mesh);

  // Perform initial mesh refinements.
  for(int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements();
  mesh.refine_towards_boundary(BDY_AIR, INIT_REF_NUM_BDY);
  mesh.refine_towards_boundary(BDY_GROUND, INIT_REF_NUM_BDY);

  // Enter boundary markers.
  BCTypes bc_types;
  bc_types.add_bc_dirichlet(Hermes::vector<std::string>(BDY_GROUND));
  bc_types.add_bc_newton(BDY_AIR);

  // Enter Dirichlet boundary values.
  BCValues bc_values;
  bc_values.add_const(BDY_GROUND, TEMP_INIT);

  // Initialize 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);
 
  // Previous time level solution (initialized by the external temperature).
  Solution tsln(&mesh, TEMP_INIT);

  // Initialize weak formulation.
  WeakForm wf;
  wf.add_matrix_form(callback(bilinear_form));
  wf.add_matrix_form_surf(callback(bilinear_form_surf), BDY_AIR);
  wf.add_vector_form(callback(linear_form), HERMES_ANY, &tsln);
  wf.add_vector_form_surf(callback(linear_form_surf), BDY_AIR);

  // Initialize the FE problem.
  bool is_linear = true;
  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);
  solver->set_factorization_scheme(HERMES_REUSE_FACTORIZATION_COMPLETELY);

  // Initialize views.
  ScalarView Tview("Temperature", new WinGeom(0, 0, 450, 600));
  Tview.set_min_max_range(0,20);
  Tview.fix_scale_width(30);

  // Time stepping:
  int ts = 1; bool rhs_only = false;
  do 
  {
    info("---- Time step %d, time %3.5f s, ext_temp %g C", ts, current_time, temp_ext(current_time));

    // First time assemble both the stiffness matrix and right-hand side vector,
    // then just the right-hand side vector.
    if (rhs_only == false) info("Assembling the stiffness matrix and right-hand side vector.");
    else info("Assembling the right-hand side vector (only).");
    dp.assemble(matrix, rhs, rhs_only);
    rhs_only = true;

    // 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, &tsln);
    else error ("Matrix solver failed.\n");

    // Visualize the solution.
    char title[100];
    sprintf(title, "Time %3.2f s, exterior temperature %3.5f C", current_time, temp_ext(current_time));
    Tview.set_title(title);
    Tview.show(&tsln);

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

  // Wait for the view to be closed.
  View::wait();
  return 0;
}
Пример #15
0
// Main function.
int main(int argc, char* argv[])
{
  
  // 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 following loop "Initializing polynomial approximation".
  if (CONSTITUTIVE_TABLE_METHOD == 1)
    CONSTITUTIVE_TABLES_READY = get_constitutive_tables(ITERATIVE_METHOD);
  // Points to be used for polynomial approximation of K(h).
  double* points = new double[NUM_OF_INSIDE_PTS];

  // 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++) {
    info("Processing layer %d", i);
    init_polynomials(6 + NUM_OF_INSIDE_PTS, LOW_LIMIT, points, NUM_OF_INSIDE_PTS, i);
  }
  POLYNOMIALS_READY = true;
  if (CONSTITUTIVE_TABLE_METHOD == 2) {
    CONSTITUTIVE_TABLES_READY = true ;
    //Assign table limit to global definition.
    TABLE_LIMIT = INTERVALS_4_APPROX[NUM_OF_INTERVALS-1];
  }
  

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

  // Load the mesh.
  Mesh mesh, basemesh;
  H2DReader mloader;
  mloader.load(mesh_file, &basemesh);
  
  // Initial refinements.
  //basemesh.refine_towards_boundary(1, 1);
  //basemesh.refine_towards_boundary(3, 1);
  //basemesh.refine_towards_boundary(4, 1);

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

  // Enter boundary markers.
  BCTypes bc_types;
  bc_types.add_bc_dirichlet(BDY_1);
  bc_types.add_bc_neumann(Hermes::Tuple<int>(BDY_2, BDY_3, BDY_4));

  // Enter Dirichlet boundary values.
  BCValues bc_values(&TIME);
  bc_values.add_timedep_function(BDY_1, 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);

  // Create a selector which will select optimal candidate.
  H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER);

  // Solutions for the time stepping and the Newton's method.
  Solution sln, ref_sln, sln_prev_time, sln_prev_iter;
  
  // Assign the function f() to the fine mesh.
  sln_prev_time.set_exact(&mesh, init_cond);
  sln_prev_iter.set_exact(&mesh, init_cond);

  // Initialize the weak formulation.
  WeakForm wf;
  if (ITERATIVE_METHOD == 1) {
    if (TIME_INTEGRATION == 1) {
      info("Registering forms for the Newton's method (implicit Euler in time).");
      wf.add_matrix_form(jac_form_vol_euler, jac_form_vol_ord, HERMES_NONSYM, HERMES_ANY, 
	                 &sln_prev_time);
      wf.add_vector_form(res_form_vol_euler, res_form_vol_ord, HERMES_ANY, 
			 &sln_prev_time);
    }
    else {
      info("Registering forms for the Newton's method (Crank-Nicolson in time).");
      wf.add_matrix_form(jac_form_vol_cranic, jac_form_vol_ord, HERMES_NONSYM, HERMES_ANY, 
      		         &sln_prev_time);
      wf.add_vector_form(res_form_vol_cranic, res_form_vol_ord, HERMES_ANY, 
			 &sln_prev_time);
    }
  }
  else {
    if (TIME_INTEGRATION == 1) {
      info("Registering forms for the Picard's method (implicit Euler in time).");
      wf.add_matrix_form(bilinear_form_picard_euler, bilinear_form_picard_euler_ord, HERMES_NONSYM, HERMES_ANY, 
	                 &sln_prev_iter);
      wf.add_vector_form(linear_form_picard_euler, linear_form_picard_euler_ord, HERMES_ANY, 
			 Hermes::Tuple<MeshFunction*>(&sln_prev_iter, &sln_prev_time));
    }
    else {
      info("Registering forms for the Picard's method (Crank-Nicolson in time).");
      error("Not implemented yet.");
      wf.add_matrix_form(bilinear_form_picard_euler, bilinear_form_picard_euler_ord, HERMES_NONSYM, HERMES_ANY, 
	                 &sln_prev_iter);
      wf.add_vector_form(linear_form_picard_euler, linear_form_picard_euler_ord, HERMES_ANY, 
			 Hermes::Tuple<MeshFunction*>(&sln_prev_iter, &sln_prev_time));
    }
  }

  // Error estimate and discrete problem size as a function of physical time.
  SimpleGraph graph_time_err_est, graph_time_err_exact, 
    graph_time_dof, graph_time_cpu, graph_time_step;
 
  // Visualize the projection and mesh.
  ScalarView view("Initial condition", new WinGeom(0, 0, 630, 350));
  view.fix_scale_width(50);
  OrderView ordview("Initial mesh", new WinGeom(640, 0, 600, 350));
  view.show(&sln_prev_time, HERMES_EPS_HIGH);
  ordview.show(&space);
  //MeshView mview("Mesh", new WinGeom(840, 0, 600, 350));
  //mview.show(&mesh);
  //View::wait();

  // Time stepping loop.
  int num_time_steps = (int)(T_FINAL/TAU + 0.5);
  for(int ts = 1; ts <= num_time_steps; ts++)
  {
    info("---- Time step %d:", ts);

    // Time measurement.
    cpu_time.tick();

    // Periodic global derefinements.
    if (ts > 1 && ts % UNREF_FREQ == 0) {
      info("Global mesh derefinement.");
      //mesh.copy(&basemesh);            // Brings the mesh back to the basemesh.
      mesh.unrefine_all_elements();      // Shaves off one layer of refinement for all elements.
      space.set_uniform_order(P_INIT);   // Resets poly degree to the initial one.
    }

    // Spatial adaptivity loop. Note: sln_prev_time must not be touched during adaptivity.
    bool done = false;
    int as = 1;
    double err_est_rel;
    do
    {
      info("---- Time step %d, time step lenght %g, time %g (days), adaptivity step %d:", ts, TAU, TIME, as);

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

      // debug 
      //BaseView bview("FE basis", new WinGeom(0, 360, 600, 350));
      //H1Space *temp = (H1Space*)space.dup(&mesh);
      //temp->copy_orders((Space*)&space, 0);
      //bview.show(temp);

      // Next we need to calculate the reference solution.
      // Newton's method:
      if(ITERATIVE_METHOD == 1) {
        scalar* coeff_vec = new scalar[Space::get_num_dofs(ref_space)];
     
        // Calculate initial coefficient vector for Newton on the fine mesh.
        if (as == 1 && ts == 1) {
          info("Projecting coarse mesh solution to obtain initial vector on new fine mesh.");
          OGProjection::project_global(ref_space, &sln_prev_time, coeff_vec, matrix_solver);
        }
        else {
          info("Projecting previous fine mesh solution to obtain initial vector on new fine mesh.");
          OGProjection::project_global(ref_space, &ref_sln, coeff_vec, matrix_solver);
          delete ref_sln.get_mesh();
        }

        // Initialize the FE problem.
        bool is_linear = false;
        DiscreteProblem dp(&wf, ref_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 on the reference mesh. If necessary, 
        // reduce time step to make it converge, but then restore time step 
        // size to its original value.
        info("Performing Newton's iteration (tau = %g days):", TAU);
        bool success, verbose = true;
        double* save_coeff_vec = new double[ndof];
        // Save coefficient vector.
        for (int i=0; i < ndof; i++) save_coeff_vec[i] = coeff_vec[i];
        double damping_coeff = 1.0;
        while (!solve_newton(coeff_vec, &dp, solver, matrix, rhs, 
                             NEWTON_TOL, NEWTON_MAX_ITER, verbose, damping_coeff)) {
          // Restore solution from the beginning of time step.
          for (int i=0; i < ndof; i++) coeff_vec[i] = save_coeff_vec[i];
          // Reducing time step to 50%.
          info("Reducing time step size from %g to %g days for the rest of this time step.", 
               TAU, TAU * TIMESTEP_DEC);
          TAU *= TIMESTEP_DEC;
          // If TAU less than the prescribed minimum, stop.
          if (TAU < TAU_MIN) error("Time step dropped below prescribed minimum value.");
        }  
        // Delete the saved coefficient vector.
        delete [] save_coeff_vec;

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

        // Cleanup.
        delete [] coeff_vec;
        delete solver;
        delete matrix;
        delete rhs;
      }
      else {
        // Calculate initial condition for Picard on the fine mesh.
        if (as == 1 && ts == 1) {
          info("Projecting coarse mesh solution to obtain initial vector on new fine mesh.");
          OGProjection::project_global(ref_space, &sln_prev_time, &sln_prev_iter, matrix_solver);
        }
        else {
          info("Projecting previous fine mesh solution to obtain initial vector on new fine mesh.");
          OGProjection::project_global(ref_space, &ref_sln, &sln_prev_iter, matrix_solver);
        }

        // Perform Picard iteration on the reference mesh. If necessary, 
        // reduce time step to make it converge, but then restore time step 
        // size to its original value.
        info("Performing Picard's iteration (tau = %g days):", TAU);
        bool success, verbose = true;
        while(!solve_picard(&wf, ref_space, &sln_prev_iter, matrix_solver, PICARD_TOL, 
                            PICARD_MAX_ITER, verbose)) {
          // Restore solution from the beginning of time step.
          sln_prev_iter.copy(&sln_prev_time);
          // Reducing time step to 50%.
          info("Reducing time step size from %g to %g days for the rest of this time step", TAU, TAU * TIMESTEP_DEC);
          TAU *= TIMESTEP_DEC;
          // If TAU less than the prescribed minimum, stop.
          if (TAU < TAU_MIN) error("Time step dropped below prescribed minimum value.");
        }	

        ref_sln.copy(&sln_prev_iter);
      }


      /*** ADAPTIVITY ***/

      // Project the fine mesh solution on the coarse mesh.
      info("Projecting fine mesh solution on coarse mesh for error calculation.");
      if(space.get_mesh() == NULL) error("it is NULL");
      OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver);

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

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

      // If space_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);
        if (Space::get_num_dofs(&space) >= NDOF_STOP) {
          done = true;
          break;
        }
        as++;
      }

      delete adaptivity;
      delete ref_space;
    }
    while (!done);

    // Add entries to graphs.
    graph_time_err_est.add_values(TIME, err_est_rel);
    graph_time_err_est.save("time_error_est.dat");
    graph_time_dof.add_values(TIME, Space::get_num_dofs(&space));
    graph_time_dof.save("time_dof.dat");
    graph_time_cpu.add_values(TIME, cpu_time.accumulated());
    graph_time_cpu.save("time_cpu.dat");
    graph_time_step.add_values(TIME, TAU);
    graph_time_step.save("time_step_history.dat");

    // Visualize the solution and mesh.
    char title[100];
    sprintf(title, "Solution, time %g days", TIME);
    view.set_title(title);
    view.show(&sln, HERMES_EPS_HIGH);
    sprintf(title, "Mesh, time %g days", TIME);
    ordview.set_title(title);
    ordview.show(&space);
    
    // Save complete Solution.
    char* filename = new char[100];
    sprintf(filename, "outputs/tsln_%f.dat", TIME);
    bool compress = false;   // Gzip compression not used as it only works on Linux.
    sln.save(filename, compress);
    info("Solution at time %g saved to file %s.", TIME, filename);

    // Copy new reference level solution into sln_prev_time.
    // This starts new time step.
    sln_prev_time.copy(&ref_sln);

    // Updating time step. Note that TAU might have been reduced during adaptivity.
    TIME += TAU;

    // Increase time step.
    if (TAU < TAU_MAX) {
      info("Increasing time step from %g to %g days.", TAU, TAU * TIMESTEP_INC);
      TAU *= TIMESTEP_INC;
    }
  }

  // Wait for all views to be closed.
  View::wait();
  return 0;
}
Пример #16
0
int main(int argc, char **args)
{
    // Load the mesh.
    Mesh mesh;
    H3DReader mloader;
    mloader.load("fichera-corner.mesh3d", &mesh);

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

    // Create an H1 space with default shapeset.
    H1Space space(&mesh, bc_types, essential_bc_values, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z));

    // Initialize weak formulation.
    WeakForm wf;
    wf.add_matrix_form(bilinear_form<double, double>, bilinear_form<Ord, Ord>, HERMES_SYM, HERMES_ANY);
    wf.add_vector_form(linear_form<double, double>, linear_form<Ord, Ord>, HERMES_ANY);

    // Set exact solution.
    ExactSolution exact(&mesh, fndd);

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

    // 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 = construct_refined_space(&space,1 , H3D_H3D_H3D_REFT_HEX_XYZ);

        // Initialize discrete problem.
        bool is_linear = true;
        DiscreteProblem dp(&wf, ref_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);

        // Initialize the preconditioner in the case of SOLVER_AZTECOO.
        if (matrix_solver == SOLVER_AZTECOO)
        {
            ((AztecOOSolver*) solver)->set_solver(iterative_method);
            ((AztecOOSolver*) solver)->set_precond(preconditioner);
            // Using default iteration parameters (see solver/aztecoo.h).
        }

        // Assemble the reference problem.
        info("Assembling on reference mesh (ndof: %d).", Space::get_num_dofs(ref_space));
        dp.assemble(matrix, rhs);

        // Time measurement.
        cpu_time.tick();

        // Solve the linear system on reference mesh. If successful, obtain the solution.
        info("Solving on reference mesh.");
        Solution ref_sln(ref_space->get_mesh());
        if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln);
        else error ("Matrix solver failed.\n");

        // Time measurement.
        cpu_time.tick();

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

        // Time measurement.
        cpu_time.tick();

        // Output solution and mesh with polynomial orders.
        if (solution_output)
        {
            out_fn_vtk(&sln, "sln", as);
            out_orders_vtk(&space, "order", as);
        }

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

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

        // Calculate exact error.
        solutions_for_adapt = false;
        double err_exact_rel = adaptivity->calc_err_exact(&sln, &exact, solutions_for_adapt) * 100;

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

        // Add entry to DOF and CPU convergence graphs.
        graph_dof_est.add_values(Space::get_num_dofs(&space), err_est_rel);
        graph_dof_est.save("conv_dof_est.dat");
        graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel);
        graph_cpu_est.save("conv_cpu_est.dat");
        graph_dof_exact.add_values(Space::get_num_dofs(&space), err_exact_rel);
        graph_dof_exact.save("conv_dof_exact.dat");
        graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel);
        graph_cpu_exact.save("conv_cpu_exact.dat");

        // If err_est_rel is too large, adapt the mesh.
        if (err_est_rel < ERR_STOP) done = true;
        else
        {
            info("Adapting coarse mesh.");
            adaptivity->adapt(THRESHOLD);
        }
        if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true;

        // Clean up.
        delete ref_space->get_mesh();
        delete ref_space;
        delete matrix;
        delete rhs;
        delete solver;
        delete adaptivity;

        // Increase the counter of performed adaptivity steps.
        as++;
    } while (!done);

    return 0;
}
Пример #17
0
int main()
{
    // Create space, set Dirichlet BC, enumerate basis functions.
    Space* space = new Space(A, B, NELEM, DIR_BC_LEFT, DIR_BC_RIGHT, P_INIT, NEQ);
    int ndof = Space::get_num_dofs(space);
    info("ndof: %d", ndof);

    // Initialize the weak formulation.
    WeakForm wf;
    wf.add_matrix_form(jacobian_vol);
    wf.add_vector_form(residual_vol);
    wf.add_vector_form_surf(0, residual_surf_right, BOUNDARY_RIGHT);

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

    // Newton's loop.
    // Fill vector coeff_vec using dof and coeffs arrays in elements.
    double *coeff_vec = new double[Space::get_num_dofs(space)];
    get_coeff_vector(space, coeff_vec);

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

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

        // 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, then quit.
        // NOTE: at least one full iteration forced
        //       here because sometimes the initial
        //       residual on fine mesh is too small.
        if(res_l2_norm < NEWTON_TOL && it > 1) break;

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

        // 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 the maximum number of iteration has been reached, then quit.
        if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge.");

        // Copy coefficients from vector y to elements.
        set_coeff_vector(coeff_vec, space);

        it++;
    }

    // Plot the solution.
    Linearizer l(space);
    l.plot_solution("solution.gp");

    // Plot the resulting space.
    space->plot("space.gp");

    // Cleaning
    delete dp;
    delete rhs;
    delete solver;
    delete[] coeff_vec;
    delete space;
    delete bc;
    delete matrix;

    info("Done.");
    return 0;
}
Пример #18
0
int main(int argc, char* argv[])
{
  // Load the mesh.
  Mesh mesh;
  H2DReader mloader;
  mloader.load("cathedral.mesh", &mesh);

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

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

  // Set initial condition.
  Solution tsln;
  tsln.set_const(&mesh, T_INIT);

  // Initialize weak formulation.
  WeakForm wf;
  wf.add_matrix_form(bilinear_form<double, double>, bilinear_form<Ord, Ord>);
  wf.add_matrix_form_surf(bilinear_form_surf<double, double>, bilinear_form_surf<Ord, Ord>, bdy_air);
  wf.add_vector_form(linear_form<double, double>, linear_form<Ord, Ord>, H2D_ANY, &tsln);
  wf.add_vector_form_surf(linear_form_surf<double, double>, linear_form_surf<Ord, Ord>, bdy_air);

  // Initialize the linear problem.
  LinearProblem lp(&wf, &space);

  // Initialize matrix solver.
  Matrix* mat; Vector* rhs; CommonSolver* solver;  
  init_matrix_solver(matrix_solver, ndof, mat, rhs, solver);

  // Initialize views.
  ScalarView Tview("Temperature", new WinGeom(0, 0, 450, 600));
  char title[100];
  sprintf(title, "Time %3.5f, exterior temperature %3.5f", TIME, temp_ext(TIME));
  Tview.set_min_max_range(0,20);
  Tview.set_title(title);
  Tview.fix_scale_width(3);

  // Time stepping:
  int nsteps = (int)(FINAL_TIME/TAU + 0.5);
  bool rhsonly = false;
  for(int ts = 1; ts <= nsteps; ts++)
  {
    info("---- Time step %d, time %3.5f, ext_temp %g", ts, TIME, temp_ext(TIME));

    // Assemble stiffness matrix and rhs.
    lp.assemble(mat, rhs, rhsonly);
    rhsonly = true;

    // Solve the matrix problem.
    if (!solver->solve(mat, rhs)) error ("Matrix solver failed.\n");

    // Update tsln.
    tsln.set_fe_solution(&space, rhs);

    // Update the time variable.
    TIME += TAU;

    // Visualize the solution.
    sprintf(title, "Time %3.2f, exterior temperature %3.5f", TIME, temp_ext(TIME));
    Tview.set_title(title);
    Tview.show(&tsln);
  }

  // Wait for the view to be closed.
  View::wait();
  return 0;
}
Пример #19
0
// Main function.
int main(int argc, char* argv[])
{
  // 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_TABLES_READY = get_constitutive_tables(1);  // 1 stands for the Newton's method.
  // Points to be used for polynomial approximation of K(h).
  double* points = new double[NUM_OF_INSIDE_PTS];

  // 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++) {
    init_polynomials(6 + NUM_OF_INSIDE_PTS, LOW_LIMIT, points, NUM_OF_INSIDE_PTS, i);
  }
  POLYNOMIALS_READY = true;
  if (CONSTITUTIVE_TABLE_METHOD == 2) {
    CONSTITUTIVE_TABLES_READY = true ;
    //Assign table limit to global definition.
    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;
  H2DReader 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(BDY_TOP, INIT_REF_NUM_BDY_TOP);

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

  // Enter Dirichlet boundary values.
  BCValues bc_values(&current_time);
  bc_values.add_timedep_function(BDY_TOP, essential_bc_values);

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

  // Solution (initialized by the initial condition) and error function.
  Solution* sln_time_prev = new Solution(&mesh, init_cond);
  Solution* sln_time_new = new Solution(&mesh);
  Solution* time_error_fn = new Solution(&mesh, 0.0);
  
  // Initialize the weak formulation.
  WeakForm wf;
  info("Registering forms for the Newton's method.");
  wf.add_matrix_form(jac_form_vol, jac_form_vol_ord, HERMES_NONSYM, HERMES_ANY, sln_time_prev);
  wf.add_vector_form(res_form_vol, res_form_vol_ord, HERMES_ANY, sln_time_prev);

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

  // Visualize the projection and mesh.
  ScalarView sview("Initial condition", new WinGeom(0, 0, 400, 350));
  sview.fix_scale_width(50);
  sview.show(sln_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.");

  // Time stepping loop:
  int ts = 1;
  do 
  {
    // Perform one Runge-Kutta time step according to the selected Butcher's table.
    info("Runge-Kutta time step (t = %g, tau = %g, stages: %d).", 
         current_time, time_step, bt.get_size());
    bool verbose = true;
    bool is_linear = false;
    if (!rk_time_step(current_time, time_step, &bt, sln_time_prev, sln_time_new, time_error_fn, &dp, matrix_solver,
		      verbose, is_linear, NEWTON_TOL, NEWTON_MAX_ITER)) {
      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;
    }

    // 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 = calc_norm(time_error_fn, HERMES_H1_NORM) / calc_norm(sln_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(sln_time_new, HERMES_EPS_VERYHIGH);
    oview.show(space);

    // Save complete Solution.
    char filename[100];
    sprintf(filename, "outputs/tsln_%f.dat", current_time);
    bool compress = false;   // Gzip compression not used as it only works on Linux.
    sln_time_new->save(filename, compress);
    info("Solution at time %g saved to file %s.", current_time, filename);

    // Save solution for the next time step.
    sln_time_prev->copy(sln_time_new);

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

  // Cleanup.
  delete space;
  delete sln_time_prev;
  delete sln_time_new;
  delete time_error_fn;

  // Wait for all views to be closed.
  View::wait();
  return 0;
}
Пример #20
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_REF_NUM; i++) mesh.refine_all_elements();

  // Enter boundary markers.
  BCTypes bc_types;
  bc_types.add_bc_dirichlet(Hermes::Tuple<int>(BDY_DIRICHLET_1, BDY_DIRICHLET_2, BDY_DIRICHLET_3, BDY_DIRICHLET_4));

  // Enter Dirichlet boundary values.
  BCValues bc_values;
  bc_values.add_zero(Hermes::Tuple<int>(BDY_DIRICHLET_1, BDY_DIRICHLET_2, BDY_DIRICHLET_3, BDY_DIRICHLET_4));

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

  // Previous time level solution.
  Solution psi_prev_time(&mesh, init_cond);

  // Initialize the weak formulation.
  WeakForm wf;
  if(TIME_DISCR == 1) {
    wf.add_matrix_form(callback(J_euler), HERMES_UNSYM, HERMES_ANY);
    wf.add_vector_form(callback(F_euler), HERMES_ANY, &psi_prev_time);
  }
  else {
    wf.add_matrix_form(callback(J_cranic), HERMES_UNSYM, HERMES_ANY);
    wf.add_vector_form(callback(F_cranic), HERMES_ANY, &psi_prev_time);
  }

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

  // Project the initial condition on the FE space to obtain initial
  // coefficient vector for the Newton's method.
  info("Projecting initial condition to obtain initial vector for the Newton's method.");
  scalar* coeff_vec = new scalar[ndof];
  OGProjection::project_global(&space, &psi_prev_time, coeff_vec, matrix_solver);
  
  // Time stepping loop:
  int nstep = (int)(T_FINAL/TAU + 0.5);
  for(int ts = 1; ts <= nstep; ts++)
  {
    info("Time step %d:", ts);

    // Perform Newton's iteration.
    info("Solving nonlinear problem:");
    bool verbose = true;
    if (!solve_newton(coeff_vec, &dp, solver, matrix, rhs, 
        NEWTON_TOL, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed.");
    
    // Update previous time level solution.
    Solution::vector_to_solution(coeff_vec, &space, &psi_prev_time);
  }

  delete coeff_vec;
  delete matrix;
  delete rhs;
  delete solver;

  AbsFilter mag2(&psi_prev_time);
  int success = 1;
  double eps = 1e-5;
  double val = std::abs(mag2.get_pt_value(0.1, 0.1));
  info("Coordinate ( 0.1, 0.1) psi value = %lf", val);
  if (fabs(val - (0.804900)) > eps) {
    printf("Coordinate ( 0.1, 0.1) psi value = %lf\n", val);
    success = 0;
  }

  val = std::abs(mag2.get_pt_value(0.1, -0.1));
  info("Coordinate ( 0.1, -0.1) psi value = %lf", val);
  if (fabs(val - (0.804900)) > eps) {
    printf("Coordinate ( 0.1, -0.1) psi value = %lf\n", val);
    success = 0;
  }

  val = std::abs(mag2.get_pt_value(0.2, 0.1));
  info("Coordinate ( 0.2, 0.1) psi value = %lf", val);
  if (fabs(val - (0.602930)) > eps) {
    printf("Coordinate ( 0.2, 0.1) psi value = %lf\n", val);
    success = 0;
  }

  if (success == 1) {
    printf("Success!\n");
    return ERR_SUCCESS;
  }
  else {
    printf("Failure!\n");
    return ERR_FAILURE;
  }
}
Пример #21
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;
}
Пример #22
0
int main(int argc, char **argv) {
	int res = ERR_SUCCESS;

#ifdef WITH_PETSC
	PetscInitialize(&argc, &argv, (char *) PETSC_NULL, PETSC_NULL);
#endif
	set_verbose(false);

	if (argc < 3) error("Not enough parameters");

	printf("* Loading mesh '%s'\n", argv[1]);
	Mesh mesh;
	H3DReader mesh_loader;
	if (!mesh_loader.load(argv[1], &mesh)) error("Loading mesh file '%s'\n", argv[1]);

	int o;
	sscanf(argv[2], "%d", &o);
	printf("  - Setting uniform order to %d\n", o);

	printf("* Setting the space up\n");
	H1Space space(&mesh, bc_types, NULL, o);

	int ndofs = space.assign_dofs();
	printf("  - Number of DOFs: %d\n", ndofs);

	printf("* Calculating a solution\n");

#if defined WITH_UMFPACK
	UMFPackMatrix mat;
	UMFPackVector rhs;
	UMFPackLinearSolver solver(&mat, &rhs);
#elif defined WITH_PARDISO
	PardisoMatrix mat;
	PardisoVector rhs;
	PardisoLinearSolver solver(&mat, &rhs);
#elif defined WITH_PETSC
	PetscMatrix mat;
	PetscVector rhs;
	PetscLinearSolver solver(&mat, &rhs);
#elif defined WITH_MUMPS
	MumpsMatrix mat;
	MumpsVector rhs;
	MumpsSolver solver(&mat, &rhs);
#endif

	WeakForm wf;
	wf.add_matrix_form(FORM_CB(bilinear_form), SYM);
	wf.add_vector_form(FORM_CB(linear_form));

	DiscreteProblem dp(&wf, &space, true);

	// assemble stiffness matrix
	Timer assemble_timer("Assembling stiffness matrix");
	assemble_timer.start();
	dp.assemble(&mat, &rhs);
	assemble_timer.stop();

	// solve the stiffness matrix
	Timer solve_timer("Solving stiffness matrix");
	solve_timer.start();
	bool solved = solver.solve();
	solve_timer.stop();

	// output the measured values
	printf("%s: %s (%lf secs)\n", assemble_timer.get_name(), assemble_timer.get_human_time(), assemble_timer.get_seconds());
	printf("%s: %s (%lf secs)\n", solve_timer.get_name(), solve_timer.get_human_time(), solve_timer.get_seconds());

//	mat.dump(stdout, "a");
//	rhs.dump(stdout, "b");

	if (solved) {
		Solution sln(&mesh);
		sln.set_coeff_vector(&space, solver.get_solution() );

		ExactSolution ex_sln(&mesh, exact_solution);
		// norm
//		double h1_sln_norm = h1_norm(&sln);
		double h1_err_norm = h1_error(&sln, &ex_sln);

//		printf(" - H1 solution norm:   % le\n", h1_sln_norm);
		printf(" - H1 error norm:      % le\n", h1_err_norm);

//		double l2_sln_norm = l2_norm(&sln);
//		double l2_err_norm = l2_error(&sln, &ex_sln);
//		printf(" - L2 solution norm:   % le\n", l2_sln_norm);
//		printf(" - L2 error norm:      % le\n", l2_err_norm);

//		if (h1_err_norm > EPS || l2_err_norm > EPS) {
			// calculated solution is not enough precise
//			res = ERR_FAILURE;
//		}

#ifdef AOUTPUT_DIR
		// output
		const char *of_name = OUTPUT_DIR "/solution.pos";
		FILE *ofile = fopen(of_name, "w");
		if (ofile != NULL) {
			DiffFilter eh(&sln, &ex_sln);
//			DiffFilter eh_dx(&sln, &ex_sln, FN_DX, FN_DX);
//			DiffFilter eh_dy(&sln, &ex_sln, FN_DY, FN_DY);
//			DiffFilter eh_dz(&sln, &ex_sln, FN_DZ, FN_DZ);

			GmshOutputEngine output(ofile);
			output.out(&sln, "Uh");
//			output.out(&sln, "Uh dx", FN_DX_0);
//			output.out(&sln, "Uh dy", FN_DY_0);
//			output.out(&sln, "Uh dz", FN_DZ_0);
			output.out(&eh, "Eh");
//			output.out(&eh_dx, "Eh dx");
//			output.out(&eh_dy, "Eh dy");
//			output.out(&eh_dz, "Eh dz");
			output.out(&ex_sln, "U");
//			output.out(&ex_sln, "U dx", FN_DX_0);
//			output.out(&ex_sln, "U dy", FN_DY_0);
//			output.out(&ex_sln, "U dz", FN_DZ_0);

			fclose(ofile);
		}
		else {
			warning("Can not open '%s' for writing.", of_name);
		}
#endif
	}

#ifdef WITH_PETSC
	mat.free();
	rhs.free();
	PetscFinalize();
#endif

	return res;
}
Пример #23
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));
  wf.add_matrix_form_surf(callback(bilinear_form_surf), BDY_BOTTOM);
  wf.add_vector_form_surf(callback(linear_form_surf), BDY_BOTTOM);

  // Initialize the FE problem.
  bool is_linear = true;
  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);

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

  // Visualize the solution.
  ScalarView view("Solution", new WinGeom(0, 0, 440, 350));
  view.show(&sln);

  // Compute and show gradient magnitude.
  // (Note that the gradient at the re-entrant
  // corner needs to be truncated for visualization purposes.)
  ScalarView gradview("Gradient", new WinGeom(450, 0, 400, 350));
  MagFilter grad(Hermes::vector<MeshFunction *>(&sln, &sln), 
                 Hermes::vector<int>(H2D_FN_DX, H2D_FN_DY));
  gradview.show(&grad);

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

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

  return 0;
}
Пример #24
0
int main(int argc, char* argv[])
{
    // Load the mesh.
    Mesh mesh, basemesh;
    H2DReader mloader;
    mloader.load("domain.mesh", &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(3, INIT_REF_NUM_BDY);

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

    // Create a selector which will select optimal candidate.
    H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER);

    // Solutions for the time stepping and the Newton's method.
    Solution sln, ref_sln, u_prev_time;

    // Adapt mesh to represent initial condition with given accuracy.
    int proj_norm = 1;  // H1 norm.
    bool verbose = false;
    double err_stop_init_cond = 0.1 * ERR_STOP;
    adapt_to_exact_function(&space, proj_norm, init_cond, &selector, THRESHOLD, STRATEGY,
                            MESH_REGULARITY, ERR_STOP, NDOF_STOP,
                            verbose, &u_prev_time);

    // Assign initial condition to mesh.
    u_prev_time.set_exact(&mesh, init_cond);
    Vector *coeff_vec = new AVector(ndof);

    // Calculating initial vector for Newton.
    info("Projecting initial condition to obtain coefficient vector for Newton on coarse mesh.");
    project_global(&space, H2D_H1_NORM, &u_prev_time, &u_prev_time, coeff_vec);

    // Initialize the weak formulation.
    WeakForm wf;
    if (TIME_INTEGRATION == 1) {
        wf.add_matrix_form(jac_form_vol_euler, jac_form_vol_ord, H2D_UNSYM, H2D_ANY,
                           Tuple<MeshFunction*>(&u_prev_time));
        wf.add_matrix_form_surf(jac_form_surf_1_euler, jac_form_surf_1_ord, BDY_1);
        wf.add_matrix_form_surf(jac_form_surf_4_euler, jac_form_surf_4_ord, BDY_4);
        wf.add_matrix_form_surf(jac_form_surf_6_euler, jac_form_surf_6_ord, BDY_6);
        wf.add_vector_form(res_form_vol_euler, res_form_vol_ord, H2D_ANY,
                           Tuple<MeshFunction*>(&u_prev_time));
        wf.add_vector_form_surf(res_form_surf_1_euler, res_form_surf_1_ord, BDY_1);
        wf.add_vector_form_surf(res_form_surf_4_euler, res_form_surf_4_ord, BDY_4);
        wf.add_vector_form_surf(res_form_surf_6_euler, res_form_surf_6_ord, BDY_6);
    }
    else {
        wf.add_matrix_form(jac_form_vol_cranic, jac_form_vol_ord, H2D_UNSYM, H2D_ANY,
                           Tuple<MeshFunction*>(&u_prev_time));
        wf.add_matrix_form_surf(jac_form_surf_1_cranic, jac_form_surf_1_ord, BDY_1);
        wf.add_matrix_form_surf(jac_form_surf_4_cranic, jac_form_surf_4_ord, BDY_4);
        wf.add_matrix_form_surf(jac_form_surf_6_cranic, jac_form_surf_6_ord, BDY_6);
        wf.add_vector_form(res_form_vol_cranic, res_form_vol_ord, H2D_ANY,
                           Tuple<MeshFunction*>(&u_prev_time));
        wf.add_vector_form_surf(res_form_surf_1_cranic, res_form_surf_1_ord, BDY_1,
                                Tuple<MeshFunction*>( &u_prev_time));
        wf.add_vector_form_surf(res_form_surf_4_cranic, res_form_surf_4_ord, BDY_4,
                                Tuple<MeshFunction*>(&u_prev_time));
        wf.add_vector_form_surf(res_form_surf_6_cranic, res_form_surf_6_ord, BDY_6,
                                Tuple<MeshFunction*>(&u_prev_time));
    }

    // Initialize adaptivity parameters.
    AdaptivityParamType apt(ERR_STOP, NDOF_STOP, THRESHOLD, STRATEGY, MESH_REGULARITY);

    // Time stepping loop.
    int num_time_steps = (int)(T_FINAL/TAU + 0.5);
    for(int ts = 1; ts <= num_time_steps; ts++)
    {
        info("---- Time step %d:", ts);

        // Periodic global derefinements.
        if (ts > 1 && ts % UNREF_FREQ == 0) {
            info("Global mesh derefinement.");
            mesh.copy(&basemesh);
            space.set_uniform_order(P_INIT);
        }

        // Update the coefficient vector and u_prev_time.
        info("Projecting to obtain coefficient vector on coarse mesh.");
        project_global(&space, H2D_H1_NORM, &u_prev_time, &u_prev_time, coeff_vec);

        bool verbose = false;     // Print info during adaptivity.
        info("Projecting coarse mesh solution to obtain initial vector on new fine mesh.");
        // The NULL pointers mean that we are not interested in visualization during the Newton's loop.
        solve_newton_adapt(&space, &wf, coeff_vec, matrix_solver, H2D_H1_NORM, &sln, &ref_sln,
                           Tuple<WinGeom *>(), Tuple<WinGeom *>(), &selector, &apt,
                           NEWTON_TOL_COARSE, NEWTON_TOL_FINE, NEWTON_MAX_ITER, verbose);

        // Copy new time level reference solution into u_prev_time.
        u_prev_time.set_coeff_vector(&space, coeff_vec);
    }

    // Waiting for test.
}
Пример #25
0
int main(int argc, char* argv[])
{
    // Load the mesh.
    Mesh mesh;
    H2DReader mloader;
    mloader.load("motor.mesh", &mesh);

    // Create an H1 space with default shapeset.
    H1Space space(&mesh, bc_types, essential_bc_values, P_INIT);

    // Initialize the weak formulation.
    WeakForm wf;
    wf.add_matrix_form(callback(biform1), HERMES_SYM, OMEGA_1);
    wf.add_matrix_form(callback(biform2), HERMES_SYM, OMEGA_2);

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

    // 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 = construct_refined_space(&space);

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

        // Assemble reference problem.
        info("Solving on reference mesh.");
        bool is_linear = true;
        DiscreteProblem* dp = new DiscreteProblem(&wf, ref_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(), ref_space, &ref_sln);
        else error ("Matrix solver failed.\n");

        // Project the fine mesh solution onto the coarse mesh.
        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, HERMES_H1_NORM);
        bool solutions_for_adapt = true;
        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(&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 solver;
        delete matrix;
        delete rhs;
        delete adaptivity;
        if(done == false) delete ref_space->get_mesh();
        delete ref_space;
        delete dp;

    }
    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;
}
Пример #26
0
int main(int argc, char* argv[])
{
  // Load the mesh.
  Mesh mesh, basemesh;
  H2DReader mloader;
  mloader.load("square.mesh", &basemesh);

  // Initial mesh refinements.
  for(int i = 0; i < INIT_REF_NUM; i++) basemesh.refine_all_elements();
  mesh.copy(&basemesh);

  // 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 coarse and reference mesh solution.
  Solution sln, ref_sln;
  Solution sln_prev_time(&mesh, init_cond);

  // Initialize the weak formulation.
  WeakForm wf;
  if(TIME_DISCR == 1) {
    wf.add_matrix_form(callback(J_euler), HERMES_UNSYM, HERMES_ANY);
    wf.add_vector_form(callback(F_euler), HERMES_ANY, &sln_prev_time);
  }
  else {
    wf.add_matrix_form(callback(J_cranic), HERMES_UNSYM, HERMES_ANY);
    wf.add_vector_form(callback(F_cranic), HERMES_ANY, &sln_prev_time);
  }

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

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

  // Create a selector which will select optimal candidate.
  H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER);

  // Project the initial condition on the FE space to obtain initial
  // coefficient vector for the Newton's method.
  info("Projecting initial condition to obtain initial vector for the Newton's method.");
  scalar* coeff_vec_coarse = new scalar[ndof];
  OGProjection::project_global(&space, &sln_prev_time, coeff_vec_coarse, matrix_solver);

  // Show the projection of the initial condition.
  char title[100];
  ScalarView magview("Projection of initial condition", new WinGeom(0, 0, 440, 350));
  magview.fix_scale_width(60);
  Solution init_proj;
//  init_proj->set_coeff_vector(space, coeff_vec_coarse);
  Solution::vector_to_solution(coeff_vec_coarse, &space, &init_proj);
  AbsFilter mag(&init_proj);
  magview.show(&mag);
//  delete init_proj;
  OrderView ordview("Initial mesh", new WinGeom(450, 0, 400, 350));
  ordview.show(&space);

  // Newton's loop on the coarse mesh.
  info("Solving on coarse mesh:");
  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_coarse.assemble(coeff_vec_coarse, matrix_coarse, rhs_coarse, 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_coarse->set(i, -rhs_coarse->get(i));
    
    // Calculate the l2-norm of residual vector.
    double res_l2_norm = get_l2_norm(rhs_coarse);

    // 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 in tolerance, or the maximum number 
    // of iteration has been hit, then quit.
    if (res_l2_norm < NEWTON_TOL_COARSE || it > NEWTON_MAX_ITER) break;

    // Solve the linear system and if successful, obtain the solution.
    if(!solver_coarse->solve())
      error ("Matrix solver failed.\n");

    // Add \deltaY^{n+1} to Y^n.
    for (int i = 0; i < ndof; i++) coeff_vec_coarse[i] += solver_coarse->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_coarse, &space, &sln);

  // Cleanup after the Newton loop on the coarse mesh.
  delete matrix_coarse;
  delete rhs_coarse;
  delete solver_coarse;
  delete [] coeff_vec_coarse;
  
  // Time stepping loop.
  int num_time_steps = (int)(T_FINAL/TAU + 0.5);
  for(int ts = 1; ts <= num_time_steps; ts++)
  {
    // Periodic global derefinements.
    if (ts > 1 && ts % UNREF_FREQ == 0) 
    {
      info("Global mesh derefinement.");
      mesh.copy(&basemesh);
      space.set_uniform_order(P_INIT);

      // Project on globally derefined mesh.
      info("Projecting previous fine mesh solution on derefined mesh.");
      OGProjection::project_global(&space, &ref_sln, &sln);
    }

    // Adaptivity loop:
    bool done = false; int as = 1;
    double err_est;
    do {
      info("Time step %d, adaptivity step %d:", ts, as);

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

      scalar* coeff_vec = new scalar[Space::get_num_dofs(ref_space)];
      DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear);
      SparseMatrix* matrix = create_matrix(matrix_solver);
      Vector* rhs = create_vector(matrix_solver);
      Solver* solver = create_linear_solver(matrix_solver, matrix, rhs);

      // Calculate initial coefficient vector for Newton on the fine mesh.
      if (as == 1) {
        info("Projecting coarse mesh solution to obtain coefficient vector on new fine mesh.");
        OGProjection::project_global(ref_space, &sln, coeff_vec);
      }
      else {
        info("Projecting previous fine mesh solution to obtain coefficient vector on new fine mesh.");
        OGProjection::project_global(ref_space, &ref_sln, coeff_vec);
      }

      // Newton's loop on the fine mesh.
      info("Solving on fine mesh:");
      int it = 1;
      while (1)
      {
        // Obtain the number of degrees of freedom.
        int ndof = Space::get_num_dofs(ref_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(ref_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_FINE || 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++;
      }

      // Store the result in ref_sln.
      Solution::vector_to_solution(coeff_vec, ref_space, &ref_sln);

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

      // Calculate element errors and total error estimate.
      info("Calculating error estimate.");
      Adapt* adaptivity = new Adapt(&space, HERMES_H1_NORM);
      bool solutions_for_adapt = true;
      double err_est_rel_total = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt, HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL) * 100.;

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

      // If err_est too large, adapt the mesh.
      if (err_est_rel_total < ERR_STOP) done = true;
      else 
      {
        info("Adapting the coarse mesh.");
        done = adaptivity->adapt(&selector, THRESHOLD, STRATEGY, MESH_REGULARITY);

        if (Space::get_num_dofs(&space) >= NDOF_STOP) 
          done = true;
        else
          // Increase the counter of performed adaptivity steps.
          as++;
      }
      
      info("Projecting fine mesh solution on new coarse mesh.");
        OGProjection::project_global(&space, &ref_sln, &sln);

      // Clean up.
      delete solver;
      delete matrix;
      delete rhs;
      delete adaptivity;
      delete ref_space->get_mesh();
      delete ref_space;
      delete dp;

      // Visualize the solution and mesh.
      char title[100];
      sprintf(title, "Solution, time level %d", ts);
      magview.set_title(title);
      magview.show(&sln);
      sprintf(title, "Mesh, time level %d", ts);
      ordview.set_title(title);
      ordview.show(&space);
    }
    while (done == false);

    // Copy last reference solution into sln_prev_time.
    sln_prev_time.copy(&ref_sln);
  }

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

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

  // Initialize the weak formulation
  WeakForm wf;
  wf.add_matrix_form(callback(jac), HERMES_NONSYM, HERMES_ANY);
  wf.add_vector_form(callback(res), HERMES_ANY);

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

  // Initialize the solution.
  Solution sln;

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

  // 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, &sln);

  // Cleanup.
  delete []coeff_vec;
  delete matrix;
  delete rhs;
  delete solver;
  
  info("ndof = %d", ndof);
  info("Coordinate (1, 0) value = %lf", sln.get_pt_value(1.0, 0.0));
  info("Coordinate (3, 0) value = %lf", sln.get_pt_value(3.0, 0.0));
  info("Coordinate (5, 0) value = %lf", sln.get_pt_value(5.0, 0.0));
  info("Coordinate (7, 0) value = %lf", sln.get_pt_value(7.0, 0.0));

  double coor_x[4] = {1.0, 3.0, 5.0, 7.0};
  double coor_y = 0.0;
  double t_value[4] = {2.867436, 2.873677, 2.832594, 2.709390};
  bool success = true;

  for (int i = 0; i < 4; i++)
  {
    if (abs(t_value[i] - sln.get_pt_value(coor_x[i], coor_y)) > 1E-6) success = false;
  }

  if (success) {  // should pass with NEWTON_MAX_ITER = 9 and fail with NEWTON_MAX_ITER = 8
    printf("Success!\n");
    return ERR_SUCCESS;
  }
  else {
    printf("Failure!\n");
    return ERR_FAILURE;
  }


}
Пример #28
0
int main() 
{
  // Time measurement.
  TimePeriod cpu_time;
  cpu_time.tick();

  // Create coarse mesh, set Dirichlet BC, enumerate basis functions.
  Space* space = new Space(A, B, NELEM, DIR_BC_LEFT, DIR_BC_RIGHT, P_INIT, NEQ);

  // Enumerate basis functions, info for user.
  int ndof = Space::get_num_dofs(space);
  info("ndof: %d", ndof);

  // Initialize the weak formulation.
  WeakForm wf;
  wf.add_matrix_form(jacobian);
  wf.add_vector_form(residual);

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

  // Newton's loop on coarse mesh.
  // Fill vector coeff_vec using dof and coeffs arrays in elements.
  double *coeff_vec_coarse = new double[Space::get_num_dofs(space)];
  get_coeff_vector(space, coeff_vec_coarse);

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

  int it = 1;
  bool success = false;
  while (1) {
    // Obtain the number of degrees of freedom.
    int ndof_coarse = Space::get_num_dofs(space);

    // Assemble the Jacobian matrix and residual vector.
    dp_coarse->assemble(coeff_vec_coarse, matrix_coarse, rhs_coarse);

    // Calculate the l2-norm of residual vector.
    double res_l2_norm = get_l2_norm(rhs_coarse);

    // 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, then quit.
    // NOTE: at least one full iteration forced
    //       here because sometimes the initial
    //       residual on fine mesh is too small.
    if(res_l2_norm < NEWTON_TOL_COARSE && it > 1) break;

    // 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_coarse; i++) rhs_coarse->set(i, -rhs_coarse->get(i));

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

    // Add \deltaY^{n+1} to Y^n.
    for (int i = 0; i < ndof_coarse; i++) coeff_vec_coarse[i] += solver_coarse->get_solution()[i];

    // If the maximum number of iteration has been reached, then quit.
    if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge.");
    
    // Copy coefficients from vector y to elements.
    set_coeff_vector(coeff_vec_coarse, space);

    it++;
  }
  
  // Cleanup.
  delete matrix_coarse;
  delete rhs_coarse;
  delete solver_coarse;
  delete [] coeff_vec_coarse;
  delete dp_coarse;

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

  // 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 = construct_refined_space(space);

    // Initialize the FE problem.
    bool is_linear = false;
    DiscreteProblem* dp = new DiscreteProblem(&wf, ref_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);

    // Newton's loop on the fine mesh.
    info("Solving on fine mesh:");
    // Fill vector coeff_vec using dof and coeffs arrays in elements.
    double *coeff_vec = new double[Space::get_num_dofs(ref_space)];
    get_coeff_vector(ref_space, coeff_vec);

    int it = 1;
    while (1) 
    {
      // Obtain the number of degrees of freedom.
      int ndof = Space::get_num_dofs(ref_space);

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

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

      // If l2 norm of the residual vector is within tolerance, then quit.
      // NOTE: at least one full iteration forced
      //       here because sometimes the initial
      //       residual on fine mesh is too small.
      if(res_l2_norm < NEWTON_TOL_REF && it > 1) break;

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

      // Solve the linear system.
      if(!(success = 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 the maximum number of iteration has been reached, then quit.
      if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge.");
      
      // Copy coefficients from vector y to elements.
      set_coeff_vector(coeff_vec, ref_space);

      it++;
    }
    

    // Starting with second adaptivity step, obtain new coarse 
    // mesh solution via projecting the fine mesh solution.
    if(as > 1)
    {
      info("Projecting the fine mesh solution onto the coarse mesh.");
      // Project the fine mesh solution (defined on space_ref) onto the coarse mesh (defined on space).
      OGProjection::project_global(space, ref_space, matrix_solver);
    }

    // Calculate element errors and total error estimate.
    info("Calculating error estimate.");
    double err_est_array[MAX_ELEM_NUM]; 
    double err_est_rel = calc_err_est(NORM, 
              space, ref_space, err_est_array) * 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();

    // If exact solution available, also calculate exact error.
    if (EXACT_SOL_PROVIDED) {
      // Calculate element errors wrt. exact solution.
      double err_exact_rel = calc_err_exact(NORM, 
         space, exact_sol, NEQ, A, B) * 100;
     
      // Info for user.
      info("Relative error (exact) = %g %%", err_exact_rel);

      // Add entry to DOF and CPU convergence graphs.
      graph_dof_exact.add_values(Space::get_num_dofs(space), err_exact_rel);
      graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel);
    }

    // Add entry to DOF and CPU convergence graphs.
    graph_dof_est.add_values(Space::get_num_dofs(space), err_est_rel);
    graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel);

    // If err_est_rel too large, adapt the mesh.
    if (err_est_rel < NEWTON_TOL_REF) done = true;
    else 
    {
      info("Adapting the coarse mesh.");
      adapt(NORM, ADAPT_TYPE, THRESHOLD, err_est_array, space, ref_space);
    }

    as++;

    // Plot meshes, results, and errors.
    adapt_plotting(space, ref_space, NORM, EXACT_SOL_PROVIDED, exact_sol);

    // Cleanup.
    delete solver;
    delete matrix;
    delete rhs;
    delete ref_space;
    delete dp;
    delete [] coeff_vec;
  }
  while (done == false);

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

  // Save convergence graphs.
  graph_dof_est.save("conv_dof_est.dat");
  graph_cpu_est.save("conv_cpu_est.dat");
  graph_dof_exact.save("conv_dof_exact.dat");
  graph_cpu_exact.save("conv_cpu_exact.dat");

  // Test variable.
  info("ndof = %d.", Space::get_num_dofs(space));
  if (Space::get_num_dofs(space) > 60) success = false;

  if (success)
  {
    info("Success!");
    return ERROR_SUCCESS;
  }
  else
  {
    info("Failure!");
    return ERROR_FAILURE;
  }
}
Пример #29
0
int main(int argc, char* argv[])
{
  // Load the mesh.
  Mesh mesh;
  H2DReader mloader;
  mloader.load("domain.mesh", &mesh);

  // Perform initial mesh refinements.
  mesh.refine_element(0);

  // Create an H1 space.
  H1Space space(&mesh, bc_types, essential_bc_values, P_INIT);

  // Initialize the weak formulation.
  WeakForm wf;
  wf.add_matrix_form(callback(bilinear_form));
  wf.add_vector_form(callback(linear_form));

  // Testing n_dof and correctness of solution vector
  // for p_init = 1, 2, ..., 10
  int success = 1;
  for (int p_init = 1; p_init <= 10; p_init++) {

    printf("********* p_init = %d *********\n", p_init);
    space.set_uniform_order(p_init);

    // Initialize the FE problem.
    bool is_linear = true;
    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);

    // Initialize the solution.
    Solution sln;

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

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

    int ndof = Space::get_num_dofs(&space);
    printf("ndof = %d\n", ndof);
    double sum = 0;
    for (int i=0; i < ndof; i++) sum += solver->get_solution()[i];
    printf("coefficient sum = %g\n", sum);

    // Actual test. The values of 'sum' depend on the
    // current shapeset. If you change the shapeset,
    // you need to correct these numbers.
    if (p_init == 1 && fabs(sum - 0.1875) > 1e-3) success = 0;
    if (p_init == 2 && fabs(sum + 0.927932) > 1e-3) success = 0;
    if (p_init == 3 && fabs(sum + 0.65191) > 1e-3) success = 0;
    if (p_init == 4 && fabs(sum + 0.939909) > 1e-3) success = 0;
    if (p_init == 5 && fabs(sum + 0.63356) > 1e-3) success = 0;
    if (p_init == 6 && fabs(sum + 0.905309) > 1e-3) success = 0;
    if (p_init == 7 && fabs(sum + 0.61996) > 1e-3) success = 0;
    if (p_init == 8 && fabs(sum + 0.909494) > 1e-3) success = 0;
    if (p_init == 9 && fabs(sum + 0.610543) > 1e-3) success = 0;
    if (p_init == 10 && fabs(sum + 0.902731) > 1e-3) success = 0;
  }

  if (success == 1) {
    printf("Success!\n");
    return ERR_SUCCESS;
  }
  else {
    printf("Failure!\n");
    return ERR_FAILURE;
  }
}
Пример #30
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);

  // Previous time level solution (initialized by the initial condition).
  Solution u_prev_time(&mesh, init_cond);

  // Initialize the weak formulation.
  WeakForm wf;
  wf.add_matrix_form(callback(jac), HERMES_UNSYM, HERMES_ANY);
  wf.add_vector_form(callback(res), HERMES_ANY, &u_prev_time);

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

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

  // Time stepping loop:
  double current_time = 0.0; int ts = 1;
  do 
  {
    info("---- Time step %d, t = %g s.", ts, current_time); ts++;

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

    // Update previous time level solution.
    Solution::vector_to_solution(coeff_vec, &space, &u_prev_time);

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

  // Cleanup.
  delete [] coeff_vec;
  delete matrix;
  delete rhs;
  delete solver;
  
  ndof = Space::get_num_dofs(&space);
  info("Coordinate (-10, -10) value = %lf", u_prev_time.get_pt_value(-10.0, -10.0));
  info("Coordinate ( -6,  -6) value = %lf", u_prev_time.get_pt_value(-6.0, -6.0));
  info("Coordinate ( -2,  -2) value = %lf", u_prev_time.get_pt_value(-2.0, -2.0));
  info("Coordinate (  2,   2) value = %lf", u_prev_time.get_pt_value(2.0, 2.0));
  info("Coordinate (  6,   6) value = %lf", u_prev_time.get_pt_value(6.0, 6.0));
  info("Coordinate ( 10,  10) value = %lf", u_prev_time.get_pt_value(10.0, 10.0));


#define ERROR_SUCCESS                                0
#define ERROR_FAILURE                               -1
  double coor_x_y[6] = {-10.0, -6.0, -2.0, 2.0, 6.0, 10.0};
  double value[6] = {0.000000, 2.311376, 2.748304, 2.919943, 3.146120, 4.000000};
  for (int i = 0; i < 6; i++)
  {
    if ((value[i] - u_prev_time.get_pt_value(coor_x_y[i], coor_x_y[i])) < 1E-6)
    {
      printf("Success!\n");
    }
    else
    {
      printf("Failure!\n");
      return ERROR_FAILURE;
    }
  }
  return ERROR_SUCCESS;
}