Ejemplo n.º 1
0
int main (int argc, char* argv[]) {
  
  // load the mesh file
  Mesh Cmesh, phimesh, basemesh;

  H2DReader mloader;
  mloader.load("small.mesh", &basemesh);
  
  basemesh.refine_towards_boundary(TOP_MARKER, REF_INIT);
  basemesh.refine_towards_boundary(BOT_MARKER, REF_INIT - 1);
  Cmesh.copy(&basemesh);
  phimesh.copy(&basemesh);

  // Spaces for concentration and the voltage.
  H1Space C(&Cmesh, C_bc_types, NULL, P_INIT);
  H1Space phi(MULTIMESH ? &phimesh : &Cmesh, phi_bc_types, essential_bc_values, P_INIT);

  // set polynomial degrees.
  C.set_uniform_order(P_INIT);
  phi.set_uniform_order(P_INIT);
  info("ndof: %d", C.get_num_dofs() + phi.get_num_dofs());

  // The weak form for 2 equations.
  WeakForm wf(2);

  Solution C_prev_time,    // prveious time step solution, for the time integration
           C_prev_newton,   // solution convergin during the Newton's iteration
           phi_prev_time,
           phi_prev_newton;

  // Add the bilinear and linear forms
  // generally, the equation system is described:
  // a11(u1, v1) + a12(u2, v1) + a1n(un, v1) = l1(v1)
  // a21(u1, v2) + a22(u2, v2) + a2n(un, v2) = l2(v2)
  // an1(u1, vn) + an2(u2, vn) + ann(un, vn) = ln(vn)
  wf.add_matrix_form(0, 0, callback(J_euler_DFcDYc), H2D_UNSYM, H2D_ANY, &phi_prev_newton);
  wf.add_matrix_form(0, 1, callback(J_euler_DFcDYphi), H2D_UNSYM, H2D_ANY, &C_prev_newton);
  wf.add_matrix_form(1, 0, callback(J_euler_DFphiDYc), H2D_UNSYM);
  wf.add_matrix_form(1, 1, callback(J_euler_DFphiDYphi), H2D_UNSYM);

  wf.add_vector_form(0, callback(Fc_euler), H2D_ANY, Tuple<MeshFunction*>(&C_prev_time, &C_prev_newton, &phi_prev_newton));
  wf.add_vector_form(1, callback(Fphi_euler), H2D_ANY, Tuple<MeshFunction*>(&C_prev_newton, &phi_prev_newton));

  // Neumann voltage boundary.
  wf.add_vector_form_surf(1, callback(linear_form_surf_top), TOP_MARKER);

  // Nonlinear solver.
  NonlinSystem nls(&wf, Tuple<Space*>(&C, &phi));

  info("UmfpackSolver initialized");

  // View initial guess for Newton's method
  // initial BC
  
  C_prev_time.set_const(&Cmesh, C0);
  phi_prev_time.set_const(MULTIMESH ? &phimesh : &Cmesh, 0);

  //  phi_prev_time.set_exact(MULTIMESH ? &phimesh : &Cmesh, voltage_ic);
  //  C_prev_time.set_exact(&Cmesh, concentration_ic);
  C_prev_newton.copy(&C_prev_time);
  phi_prev_newton.copy(&phi_prev_time);

  nls.project_global(Tuple<MeshFunction*>(&C_prev_newton, &phi_prev_newton), 
                     Tuple<Solution*>(&C_prev_newton, &phi_prev_newton));

  bool success = solveAdaptive(Cmesh, phimesh, basemesh, nls, C, phi, C_prev_time,
        C_prev_newton, phi_prev_time, phi_prev_newton);
  // bool success = solveNonadaptive(Cmesh, nls, C_prev_time, C_prev_newton, 
  // phi_prev_time, phi_prev_newton);

  if (success) {
    printf("SUCCESSFUL\n");
    } else {
    printf("FAIL\n");
  }
  #define ERROR_SUCCESS 0
  #define ERROR_FAILURE -1

  return success ? ERROR_SUCCESS : ERROR_FAILURE;
}
Ejemplo n.º 2
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);

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

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

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

  return ERR_FAILURE;

}
Ejemplo n.º 3
0
int main(int argc, char **argv)
{
  // Instantiate a class with global functions.
  Hermes2D hermes2d;

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

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

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

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

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

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

  // Initialize the linear discrete problem.
  DiscreteProblem dp1(&wf1, &space);
    
  // 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);
  
  if (matrix_solver == SOLVER_AZTECOO) 
  {
    ((AztecOOSolver*) solver)->set_solver(iterative_method);
    ((AztecOOSolver*) solver)->set_precond(preconditioner);
    // Using default iteration parameters (see solver/aztecoo.h).
  }
  
  // Begin time measurement of assembly.
  cpu_time.tick(HERMES_SKIP);

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

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

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

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

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

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

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

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

  // Set initial vector for NOX.
  // NOTE: Using zero vector was causing convergence problems.
  info("Projecting to obtain initial vector for the Newton's method.");
  Solution init_sln(&mesh, 0.0);
  OGProjection::project_global(&space, &init_sln, coeff_vec);

  // Initialize the NOX solver with the vector "coeff_vec".
  info("Initializing NOX.");
  // "" stands for preconditioning that is set later.
  NoxSolver nox_solver(&dp2, message_type, iterative_method, "Newton", ls_tolerance, "", 
                       flag_absresid, abs_resid, flag_relresid, rel_resid, max_iters);
  nox_solver.set_init_sln(coeff_vec);
  
  delete coeff_vec;

  // Choose preconditioning.
  RCP<Precond> pc = rcp(new MlPrecond("sa"));
  if (PRECOND)
  {
    if (TRILINOS_JFNK) nox_solver.set_precond(pc);
    else nox_solver.set_precond(preconditioner);
  }

  // Assemble and solve using NOX.
  Solution sln2;
  if (nox_solver.solve())
  {
    Solution::vector_to_solution(nox_solver.get_solution(), &space, &sln2);

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

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

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

  // Calculate errors.
  double rel_err_2 = hermes2d.calc_rel_error(&sln2, &exact, HERMES_H1_NORM) * 100;
  info("CPU time: %g s.", time);
  info("Exact H1 error: %g%%.", rel_err_2);
 
  // Wait for all views to be closed.
  View::wait();
  
  return 0;
}
Ejemplo n.º 4
0
int main(int argc, char* argv[])
{
  // Instantiate a class with global functions.
  Hermes2D hermes2d;

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

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

  // Initialize boundary conditions
  DefaultEssentialBCConst bc_essential("Bottom", T1);
  EssentialBCs bcs(&bc_essential);

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

  // Initialize the weak formulation.
  CustomWeakFormPoissonNewton wf(LAMBDA, ALPHA, T0, "Heat_flux");

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

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

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

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

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

  // Visualize the solution.
  ScalarView view("Solution", new WinGeom(0, 0, 300, 400));
  view.show(&sln, HERMES_EPS_VERYHIGH);
  ScalarView gradview("Gradient", new WinGeom(310, 0, 300, 400));
  MagFilter grad(Hermes::vector<MeshFunction *>(&sln, &sln), 
                 Hermes::vector<int>(H2D_FN_DX, H2D_FN_DY));
  gradview.show(&grad, HERMES_EPS_VERYHIGH);

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

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

  return 0;
}
Ejemplo n.º 5
0
int main(int argc, char* argv[])
{
  /* So far the DG assembling is very slow for higher order polynomials,
      so only constant functions are used here.
  if(argc < 3)
    error("Too few arguments in example-euler-gamm-explicit");

  Ord2 P_INIT= Ord2(atoi(argv[1]), atoi(argv[2]));
  */

  Ord2 P_INIT= Ord2(0, 0);

  // Load the mesh.
  Mesh mesh;
  H2DReader mloader;
  mloader.load("GAMM-channel.mesh", &mesh);

  // Perform initial mesh refinements.
  for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements();
  mesh.refine_towards_boundary(1, 1);
  mesh.refine_element_id(1053);
  mesh.refine_element_id(1054);
  mesh.refine_element_id(1087);
  mesh.refine_element_id(1088);
  mesh.refine_element_id(1117);
  mesh.refine_element_id(1118);
  mesh.refine_element_id(1151);
  mesh.refine_element_id(1152);

  // Enter boundary markers.  
  BCTypes bc_types;
  bc_types.add_bc_neumann(Hermes::vector<int>(BDY_SOLID_WALL, BDY_INLET_OUTLET));

  // Create L2 spaces with default shapesets.
  L2Space space_rho(&mesh, &bc_types, P_INIT);
  L2Space space_rho_v_x(&mesh, &bc_types, P_INIT);
  L2Space space_rho_v_y(&mesh, &bc_types, P_INIT);
  L2Space space_e(&mesh, &bc_types, P_INIT);

  // Initialize solutions, set initial conditions.
  Solution sln_rho, sln_rho_v_x, sln_rho_v_y, sln_e, prev_rho, prev_rho_v_x, prev_rho_v_y, prev_e;
  sln_rho.set_exact(&mesh, ic_density);
  sln_rho_v_x.set_exact(&mesh, ic_density_vel_x);
  sln_rho_v_y.set_exact(&mesh, ic_density_vel_y);
  sln_e.set_exact(&mesh, ic_energy);
  prev_rho.set_exact(&mesh, ic_density);
  prev_rho_v_x.set_exact(&mesh, ic_density_vel_x);
  prev_rho_v_y.set_exact(&mesh, ic_density_vel_y);
  prev_e.set_exact(&mesh, ic_energy);

  // Initialize weak formulation.
  WeakForm wf(4);

  // Bilinear forms coming from time discretization by explicit Euler's method.
  wf.add_matrix_form(0, 0, callback(bilinear_form_0_0_time));
  wf.add_matrix_form(1, 1, callback(bilinear_form_1_1_time));
  wf.add_matrix_form(2, 2, callback(bilinear_form_2_2_time));
  wf.add_matrix_form(3, 3, callback(bilinear_form_3_3_time));

  // Volumetric linear forms.
  // Linear forms coming from the linearization by taking the Eulerian fluxes' Jacobian matrices 
  // from the previous time step.
  // Unnecessary for FVM.
  if(P_INIT.order_h > 0 || P_INIT.order_v > 0) {
    // First flux.
    wf.add_vector_form(0, callback(linear_form_0_1), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho_v_x));
    
    wf.add_vector_form(1, callback(linear_form_1_0_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(1, callback(linear_form_1_1_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(1, callback(linear_form_1_2_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(1, callback(linear_form_1_3_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(2, callback(linear_form_2_0_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(2, callback(linear_form_2_1_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(2, callback(linear_form_2_2_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(2, callback(linear_form_2_3_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(3, callback(linear_form_3_0_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(3, callback(linear_form_3_1_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(3, callback(linear_form_3_2_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(3, callback(linear_form_3_3_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    // Second flux.
    
    wf.add_vector_form(0, callback(linear_form_0_2), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho_v_y));
    wf.add_vector_form(1, callback(linear_form_1_0_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(1, callback(linear_form_1_1_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(1, callback(linear_form_1_2_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(1, callback(linear_form_1_3_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(2, callback(linear_form_2_0_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(2, callback(linear_form_2_1_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(2, callback(linear_form_2_2_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(2, callback(linear_form_2_3_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(3, callback(linear_form_3_0_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(3, callback(linear_form_3_1_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(3, callback(linear_form_3_2_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(3, callback(linear_form_3_3_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  }

  // Volumetric linear forms coming from the time discretization.
  wf.add_vector_form(0, linear_form, linear_form_order, HERMES_ANY, &prev_rho);
  wf.add_vector_form(1, linear_form, linear_form_order, HERMES_ANY, &prev_rho_v_x);
  wf.add_vector_form(2, linear_form, linear_form_order, HERMES_ANY, &prev_rho_v_y);
  wf.add_vector_form(3, linear_form, linear_form_order, HERMES_ANY, &prev_e);

  // Surface linear forms - inner edges coming from the DG formulation.
  wf.add_vector_form_surf(0, linear_form_interface_0, linear_form_order, H2D_DG_INNER_EDGE, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(1, linear_form_interface_1, linear_form_order, H2D_DG_INNER_EDGE, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(2, linear_form_interface_2, linear_form_order, H2D_DG_INNER_EDGE, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(3, linear_form_interface_3, linear_form_order, H2D_DG_INNER_EDGE, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));

  // Surface linear forms - inlet / outlet edges.
  wf.add_vector_form_surf(0, bdy_flux_inlet_outlet_comp_0, linear_form_order, BDY_INLET_OUTLET, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(1, bdy_flux_inlet_outlet_comp_1, linear_form_order, BDY_INLET_OUTLET, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(2, bdy_flux_inlet_outlet_comp_2, linear_form_order, BDY_INLET_OUTLET, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(3, bdy_flux_inlet_outlet_comp_3, linear_form_order, BDY_INLET_OUTLET, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));

  
  // Surface linear forms - Solid wall edges.
  wf.add_vector_form_surf(0, bdy_flux_solid_wall_comp_0, linear_form_order, BDY_SOLID_WALL, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(1, bdy_flux_solid_wall_comp_1, linear_form_order, BDY_SOLID_WALL, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(2, bdy_flux_solid_wall_comp_2, linear_form_order, BDY_SOLID_WALL, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(3, bdy_flux_solid_wall_comp_3, linear_form_order, BDY_SOLID_WALL, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));


  // Initialize the FE problem.
  bool is_linear = true;
  
  DiscreteProblem dp(&wf, Hermes::vector<Space*>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), is_linear);
  
  // If the FE problem is in fact a FV problem.
  if(P_INIT.order_h == 0 && P_INIT.order_v == 0)
    dp.set_fvm();

  // Iteration number.
  int iteration = 0;
  
  // 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);

  // For testing purposes.
  double l2_norms[5][4];
  for(unsigned int i = 0; i < 5; i++)
    for(unsigned int j = 0; j < 4; j++)
      l2_norms[i][j] = 0.0;
  double point_values[5][3];
  for(unsigned int i = 0; i < 5; i++)
    for(unsigned int j = 0; j < 3; j++)
      point_values[i][j] = 0.0;
  // Calculate the special point where we will evaluate the solution.
  double x = 0.75;
  double y = sqrt((double)(1.-x*x)) + 0.001;

  for(unsigned int time_step = 0; time_step < 5; time_step++)
  {
    iteration++;

    bool rhs_only = (iteration == 1 ? false : true);
    // Assemble stiffness matrix and rhs or just rhs.
    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);

        
    // Solve the matrix problem.
    info("Solving the matrix problem.");
    if(solver->solve())
      Solution::vector_to_solutions(solver->get_solution(), Hermes::vector<Space *>(&space_rho, &space_rho_v_x, 
      &space_rho_v_y, &space_e), Hermes::vector<Solution *>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e));
    else
    error ("Matrix solver failed.\n");

    // Approximate the time derivative of the solution.
    if(CALC_TIME_DER) {
      Adapt *adapt_for_time_der_calc = new Adapt(Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e));
      bool solutions_for_adapt = false;
      double difference = iteration == 1 ? 0 : 
        adapt_for_time_der_calc->calc_err_est(Hermes::vector<Solution *>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), 
					      Hermes::vector<Solution *>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e), 
                                              (Hermes::vector<double>*) NULL, solutions_for_adapt, 
                                              HERMES_TOTAL_ERROR_ABS | HERMES_ELEMENT_ERROR_ABS) / TAU;
      delete adapt_for_time_der_calc;
    }

    // Determine the time step according to the CFL condition.
    // Only mean values on an element of each solution component are taken into account.
    double *solution_vector = solver->get_solution();
    double min_condition = 0;
    Element *e;
    for (int _id = 0, _max = mesh.get_max_element_id(); _id < _max; _id++) \
          if (((e) = mesh.get_element_fast(_id))->used) \
            if ((e)->active) {
              AsmList al;
              space_rho.get_element_assembly_list(e, &al);
              double rho = solution_vector[al.dof[0]];
              space_rho_v_x.get_element_assembly_list(e, &al);
              double v1 = solution_vector[al.dof[0]] / rho;
              space_rho_v_y.get_element_assembly_list(e, &al);
              double v2 = solution_vector[al.dof[0]] / rho;
              space_e.get_element_assembly_list(e, &al);
              double energy = solution_vector[al.dof[0]];
              double condition = e->get_area() / (std::sqrt(v1*v1 + v2*v2) + calc_sound_speed(rho, rho*v1, rho*v2, energy));
              if(condition < min_condition || min_condition == 0.)
                min_condition = condition;
            }
    if(TAU > min_condition)
      TAU = min_condition;
    if(TAU < min_condition * 0.9)
      TAU = min_condition;

    // Storing the testing values.
    for(unsigned int j = 0; j < 4; j++)
      for(unsigned int k = j*space_rho.get_num_dofs(); k < (j+1)*space_rho.get_num_dofs(); k++)
        l2_norms[time_step][j] += solver->get_solution()[k];    

    point_values[time_step][0] = sln_rho_v_x.get_pt_value(0.5, 0.001);
    point_values[time_step][1] = sln_rho_v_x.get_pt_value(x, y);
    point_values[time_step][2] = sln_rho_v_x.get_pt_value(1.5, 0.001);

    // Copy the solutions into the previous time level ones.
    prev_rho.copy(&sln_rho);
    prev_rho_v_x.copy(&sln_rho_v_x);
    prev_rho_v_y.copy(&sln_rho_v_y);
    prev_e.copy(&sln_e);
  }
  bool okay = true;
  switch(P_INIT.order_h* 10 + P_INIT.order_v) {
  case 0:
    if(std::abs(l2_norms[0][0] - 888.0) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[0][1] - 1110) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[0][2]) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[0][3] - 6243.75) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[1][0] - 887.99997637865545) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[1][1] - 1109.9997956458228) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[1][2] - 3.1927018090871903e-008) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[1][3] - 6243.7496921971369) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[2][0] - 887.99993429457072) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[2][1] - 1109.9994322038613) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[2][2] + 5.3556469633245445e-008) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[2][3] - 6243.7491437826511) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[3][0] - 887.99987376550200) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[3][1] - 1109.9989102977672) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[3][2] + 3.6958140470412712e-007) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[3][3] - 6243.7483549661320) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[4][0] - 887.99979481320088) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[4][1] - 1109.9982305630808) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[4][2] + 1.0303296924184822e-006) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[4][3] - 6243.7473260085462) > 1E-8)
      okay = false;

    // points
    if(std::abs(point_values[0][0] - 1.25) > 1E-8)
      okay = false;
    if(std::abs(point_values[0][1] - 1.25) > 1E-8)
      okay = false;
    if(std::abs(point_values[0][2] - 1.2459744738974898) > 1E-8)
      okay = false;
    if(std::abs(point_values[1][0] - 1.2499951035194972) > 1E-8)
      okay = false;
    if(std::abs(point_values[1][1] - 1.25) > 1E-8)
      okay = false;
    if(std::abs(point_values[1][2] - 1.2428402692519325) > 1E-8)
      okay = false;
    if(std::abs(point_values[2][0] - 1.2499864002215795) > 1E-8)
      okay = false;
    if(std::abs(point_values[2][1] - 1.25) > 1E-8)
      okay = false;
    if(std::abs(point_values[2][2] - 1.2397180160697001) > 1E-8)
      okay = false;
    if(std::abs(point_values[3][0] - 1.2499739085927257) > 1E-8)
      okay = false;
    if(std::abs(point_values[3][1] - 1.25) > 1E-8)
      okay = false;
    if(std::abs(point_values[3][2] - 1.2366079101139087) > 1E-8)
      okay = false;
    if(std::abs(point_values[4][0] - 1.2499576472516911) > 1E-8)
      okay = false;
    if(std::abs(point_values[4][1] - 1.25) > 1E-8)
      okay = false;
    if(std::abs(point_values[4][2] - 1.2335101392959738) > 1E-8)
      okay = false;
    break;
  }

  if (okay) {      // ndofs was 908 at the time this test was created
    printf("Success!\n");
    return ERR_SUCCESS;
  }
  else {
    printf("Failure!\n");
    return ERR_FAILURE;
  } 
}
Ejemplo n.º 6
0
int main(int argc, char* argv[])
{
  // Load the mesh
  Mesh mesh;
  H2DReader mloader;
  mloader.load("domain.mesh", &mesh);
  mesh.refine_all_elements();

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

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

  // Enumerate basis functions
  space.assign_dofs();

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

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

  // Matrix solver
  UmfpackSolver solver;

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

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

    // Time measurement
    begin_time();

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

    // Time measurement
    cpu += end_time();

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

    // Time measurement
    begin_time();

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

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

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

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

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

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

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

  // Wait for keyboard or mouse input
  View::wait("Waiting for all views to be closed.");
  return 0;
}
Ejemplo n.º 7
0
int main(int argc, char* argv[])
{
  // Instantiate a class with global functions.
  Hermes2D hermes2d;

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

  // Perform initial mesh refinements.
  for (int i = 0; i<INIT_REF_NUM; i++) mesh.refine_all_elements();
  
  // Define exact solution.
  CustomExactSolution exact_sln(&mesh, SLOPE);

  // Initialize the weak formulation.
  CustomWeakFormPoisson wf(SLOPE);
  
  // Initialize boundary conditions.
  DefaultEssentialBCNonConst bc_essential(BDY_DIRICHLET, &exact_sln);
  EssentialBCs bcs(&bc_essential);

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

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

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

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

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

    // Assemble the 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.
    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);
    double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln) * 100;

    // Calculate exact error.
    double err_exact_rel = hermes2d.calc_rel_error(&sln, &exact_sln, HERMES_H1_NORM) * 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 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;
}
Ejemplo n.º 8
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_towards_vertex(3, CORNER_REF_LEVEL);

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

  // Enter Dirichlet boudnary values.
  BCValues bc_values;
  bc_values.add_zero(BDY_INNER);

  // 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_vector_form(callback(linear_form));
  wf.add_vector_form_surf(callback(linear_form_surf_bottom), BDY_BOTTOM);
  wf.add_vector_form_surf(callback(linear_form_surf_outer), BDY_OUTER);
  wf.add_vector_form_surf(callback(linear_form_surf_left), BDY_LEFT);

  // 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 approximation.
  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::Tuple<MeshFunction *>(&sln, &sln), Hermes::Tuple<int>(H2D_FN_DX, H2D_FN_DY));
  gradview.show(&grad);

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

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

  return 0;
}
Ejemplo n.º 9
0
int main(int argc, char* argv[])
{
  // Time measurement.
  TimePeriod cpu_time;
  cpu_time.tick();

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

  // Perform initial mesh refinements.
  for (int i=0; i<INIT_REF; i++) mesh.refine_all_elements();
  
  // Create an L2 space with default shapeset.
  L2Space space(&mesh, bc_types, NULL, Ord2(P_H, P_V));
  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_vector_form(callback(linear_form));
  wf.add_matrix_form_surf(callback(bilinear_form_boundary), H2D_DG_BOUNDARY_EDGE);
  wf.add_vector_form_surf(callback(linear_form_boundary), H2D_DG_BOUNDARY_EDGE);
  wf.add_matrix_form_surf(callback(bilinear_form_interface), H2D_DG_INNER_EDGE);

  // 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).
  }
    
  // 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;
  
  info("ndof = %d", ndof);
  info("Coordinate ( 0.1, 0.1) value = %lf", sln.get_pt_value(0.1, 0.1));
  info("Coordinate ( 0.3, 0.3) value = %lf", sln.get_pt_value(0.3, 0.3));
  info("Coordinate ( 0.5, 0.5) value = %lf", sln.get_pt_value(0.5, 0.5));
  info("Coordinate ( 0.7, 0.7) value = %lf", sln.get_pt_value(0.7, 0.7));

  double coor_xy[4] = {0.1, 0.3, 0.5, 0.7};
  double value[4] = {0.999885, 0.844340, 0.000000, 0.000000};
  for (int i = 0; i < 4; i++)
  {
    if ((value[i] - sln.get_pt_value(coor_xy[i], coor_xy[i])) < 1E-6)
    {
      printf("Success!\n");
    }
    else
    {
      printf("Failure!\n");
      return ERR_FAILURE;
    }
  }
  return ERR_SUCCESS;
}
Ejemplo n.º 10
0
int main(int argc, char* argv[])
{
  // Instantiate a class with global functions.
  Hermes2D hermes2d;

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

  // Perform uniform mesh refinement.
  mesh.refine_all_elements();

  // Initialize boundary conditions.
  DefaultEssentialBCConst zero_disp("Bottom", 0.0);
  EssentialBCs bcs(&zero_disp);

  // Create x- and y- displacement space using the default H1 shapeset.
  H1Space u1_space(&mesh, &bcs, P_INIT);
  H1Space u2_space(&mesh, &bcs, P_INIT);
  info("ndof = %d.", Space::get_num_dofs(Hermes::vector<Space *>(&u1_space, &u2_space)));

  // Initialize the weak formulation.
  CustomWeakFormLinearElasticity wf(E, nu, rho*g1, "Top", f0, f1);

  // Testing n_dof and correctness of solution vector
  // for p_init = 1, 2, ..., 10
  int success = 1;
  Solution xsln, ysln;
  for (int p_init = 1; p_init <= 6; p_init++) {
    printf("********* p_init = %d *********\n", p_init);
    u1_space.set_uniform_order(p_init);
    u2_space.set_uniform_order(p_init);
    int ndof = Space::get_num_dofs(Hermes::vector<Space *>(&u1_space, &u2_space));
    info("ndof = %d", ndof);

    // Initialize the FE problem.
    DiscreteProblem dp(&wf, Hermes::vector<Space *>(&u1_space, &u2_space));

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

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

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

    // Translate the resulting coefficient vector into the Solution sln.
    Solution u1_sln, u2_sln;
    Solution::vector_to_solutions(coeff_vec, Hermes::vector<Space *>(&u1_space, &u2_space), 
                                  Hermes::vector<Solution *>(&u1_sln, &u2_sln));

    double sum = 0;
    for (int i=0; i < ndof; i++) sum += coeff_vec[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 - 1.41886e-05) > 1e-5) success = 0;
    if (p_init == 2 && fabs(sum - 1.60006e-05) > 1e-5) success = 0;
    if (p_init == 3 && fabs(sum - 1.60810e-05) > 1e-5) success = 0;
    if (p_init == 4 && fabs(sum - 1.61106e-05) > 1e-5) success = 0;
    if (p_init == 5 && fabs(sum - 1.61065e-05) > 1e-5) success = 0;
    if (p_init == 6 && fabs(sum - 1.61112e-05) > 1e-5) success = 0;

    delete [] coeff_vec;
    delete solver;
    delete matrix;
    delete rhs;
  }

  if (success == 1) {
    printf("Success!\n");
    return ERR_SUCCESS;
  }
  else {
    printf("Failure!\n");
    return ERR_FAILURE;
  }
}
Ejemplo n.º 11
0
int main(int argc, char* argv[])
{
  // load the mesh file
  Mesh mesh;
  H2DReader mloader;
  mloader.load("sample.mesh", &mesh);

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

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

  // create the y displacement space
  H1Space ydisp(&mesh, &shapeset);
  ydisp.set_bc_types(bc_types);
  ydisp.set_bc_values(bc_values);

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

  // initialize the linear system and solver
  UmfpackSolver umfpack;
  LinSystem sys(&wf, &umfpack);
  sys.set_spaces(2, &xdisp, &ydisp);
  sys.set_pss(1, &pss);

  // 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);
    xdisp.set_uniform_order(p_init);
    int ndofs = xdisp.assign_dofs(0);
    ydisp.set_uniform_order(p_init);
    ndofs += ydisp.assign_dofs(ndofs);

    // assemble the stiffness matrix and solve the system
    Solution xsln, ysln;
    sys.assemble();
    sys.solve(2, &xsln, &ysln);

    scalar *sol_vector;
    int n_dof;
    sys.get_solution_vector(sol_vector, n_dof);
    printf("n_dof = %d\n", n_dof);
    double sum = 0;
    for (int i=0; i < n_dof; i++) sum += sol_vector[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 - 3.50185e-06) > 1e-3) success = 0;
    if (p_init == 2 && fabs(sum - 4.34916e-06) > 1e-3) success = 0;
    if (p_init == 3 && fabs(sum - 4.60553e-06) > 1e-3) success = 0;
    if (p_init == 4 && fabs(sum - 4.65616e-06) > 1e-3) success = 0;
    if (p_init == 5 && fabs(sum - 4.62893e-06) > 1e-3) success = 0;
    if (p_init == 6 && fabs(sum - 4.64336e-06) > 1e-3) success = 0;
    if (p_init == 7 && fabs(sum - 4.63724e-06) > 1e-3) success = 0;
    if (p_init == 8 && fabs(sum - 4.64491e-06) > 1e-3) success = 0;
    if (p_init == 9 && fabs(sum - 4.64582e-06) > 1e-3) success = 0;
    if (p_init == 10 && fabs(sum - 4.65028e-06) > 1e-3) success = 0;
  }

#define ERROR_SUCCESS                               0
#define ERROR_FAILURE                               -1
  if (success == 1) {
    printf("Success!\n");
    return ERROR_SUCCESS;
  }
  else {
    printf("Failure!\n");
    return ERROR_FAILURE;
  }
}
Ejemplo n.º 12
0
int main(int argc, char* argv[])
{
  // Instantiate a class with global functions.
  Hermes2D hermes2d;

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

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

  // Initialize the weak formulation.
  CustomWeakFormPoissonDirichlet wf("Aluminum", LAMBDA_AL, "Copper", 
                                    LAMBDA_CU, VOLUME_HEAT_SRC);
  
  // Initialize boundary conditions.
  CustomDirichletCondition bc_essential(Hermes::vector<std::string>("Bottom", "Inner", "Outer", "Left"),
                                        BDY_A_PARAM, BDY_B_PARAM, BDY_C_PARAM);
  EssentialBCs bcs(&bc_essential);

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

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

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

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

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

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

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

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

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

  bool success = true;
  if (fabs(sum + 4.2471) > 1e-3) success = 0;

  if (success == 1) {
    printf("Success!\n");
    return ERR_SUCCESS;
  }
  else {
    printf("Failure!\n");
    return ERR_FAILURE;
  }

}
Ejemplo n.º 13
0
int main (int argc, char* argv[]) {

  // Initialize the library's global functions.
  Hermes2D hermes2D;

  // Load the mesh file.
  Mesh C_mesh, phi_mesh, u1_mesh, u2_mesh, basemesh;
  H2DReader mloader;
  mloader.load("small.mesh", &basemesh);
#ifdef TWO_BASE_MESH

  Mesh basemesh_electrochem;  // Base mesh to hold C and phi
  Mesh basemesh_deformation;  // Base mesh for deformation displacements u1 and u2

  basemesh_electrochem.copy(&basemesh);
  basemesh_deformation.copy(&basemesh);

  basemesh_electrochem.refine_towards_boundary(BDY_BOT, REF_INIT - 1);
  basemesh_electrochem.refine_all_elements(1);
  C_mesh.copy(&basemesh_electrochem);
  phi_mesh.copy(&basemesh_electrochem);

  for (int i = 0; i < REF_INIT - 1; i++) {
    basemesh_deformation.refine_all_elements(1); //horizontal
    basemesh_deformation.refine_all_elements(2); //vertical
  }

  u1_mesh.copy(&basemesh_deformation);
  u2_mesh.copy(&basemesh_deformation);

#else
  basemesh.refine_towards_boundary(BDY_BOT, REF_INIT);
  basemesh.refine_towards_boundary(BDY_SIDE_FIXED, REF_INIT);
  basemesh.refine_towards_boundary(BDY_SIDE_FREE, REF_INIT - 1);
  basemesh.refine_all_elements(1);
  C_mesh.copy(&basemesh);
  phi_mesh.copy(&basemesh);
  u1_mesh.copy(&basemesh);
  u2_mesh.copy(&basemesh);
#endif

  // Enter Dirichlet and Neumann boundary markers for Poisson.
  DefaultEssentialBCConst bc_phi_voltage(BDY_TOP, VOLTAGE);
  DefaultEssentialBCConst bc_phi_zero(BDY_BOT, 0.0);
  EssentialBCs bcs_phi(Hermes::vector<EssentialBC*>(&bc_phi_voltage, &bc_phi_zero));

  DefaultEssentialBCConst bc_u1(BDY_SIDE_FIXED, 0.0);
  EssentialBCs bcs_u1(&bc_u1);

  DefaultEssentialBCConst bc_u2(BDY_SIDE_FIXED, 0.0);
  EssentialBCs bcs_u2(&bc_u2);

  // Spaces for concentration and the voltage.
  H1Space C_space(&C_mesh, P_INIT);
  H1Space phi_space(MULTIMESH ? &phi_mesh : &C_mesh, &bcs_phi, P_INIT);
  H1Space u1_space(MULTIMESH ? &u1_mesh : &C_mesh, &bcs_u1, P_INIT);
  H1Space u2_space(MULTIMESH ? &u2_mesh : &C_mesh, &bcs_u2, P_INIT);

  int ndof = Space::get_num_dofs(Hermes::vector<Space*>(&C_space, &phi_space, &u1_space, &u2_space));

  Solution C_sln, C_ref_sln;
  Solution phi_sln, phi_ref_sln; 
  Solution u1_sln, u1_ref_sln;
  Solution u2_sln, u2_ref_sln;

  // Assign initial condition to mesh.
  InitialSolutionConcentration C_prev_time(&C_mesh, C0);
  InitialSolutionVoltage phi_prev_time(MULTIMESH ? &phi_mesh : &C_mesh);
  InitialSolutionU1 u1_prev_time(MULTIMESH ? &u1_mesh : &C_mesh);
  InitialSolutionU2 u2_prev_time(MULTIMESH ? &u2_mesh : &C_mesh);

  // The weak form for 2 equations.
  CustomWeakFormNernstPlanckEuler wf(TAU, C0, lin_force_coup, mech_lambda, mech_mu, K, L, D, &C_prev_time);
  // Add the bilinear and linear forms.
  if (TIME_DISCR == 2)
	  error("Crank-Nicholson forms are not implemented yet");

  // 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(Hermes::vector<Space *>(&C_space, &phi_space, &u1_space, &u2_space),
                               Hermes::vector<MeshFunction *>(&C_prev_time, &phi_prev_time, &u1_prev_time, &u2_prev_time),
                               coeff_vec_coarse, matrix_solver);

  // Initialize the FE problem.
  bool is_linear = false;
  DiscreteProblem dp_coarse(&wf, Hermes::vector<Space *>(&C_space, &phi_space, &u1_space, &u2_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);

  // Visualization windows.
  char title[1000];
  ScalarView Cview("Concentration [mol/m3]", new WinGeom(0, 0, 400, 300));
  ScalarView phiview("Voltage [V]", new WinGeom(10, 0, 400, 300));
  ScalarView u1view("X displacement [m]", new WinGeom(320, 0, 600, 400));
  ScalarView u2view("Y displacement [m]", new WinGeom(830, 0, 600, 400));
  OrderView Cordview("C order", new WinGeom(0, 470, 400, 300));
  OrderView phiordview("Phi order", new WinGeom(10, 470, 400, 300));
  OrderView u1ordview("u1 order", new WinGeom(320, 470, 600, 400));
  OrderView u2ordview("u2 order", new WinGeom(830, 470, 600, 400));

  // Visualize the solution.
  ScalarView deformationview("Von Mises stress [Pa]", new WinGeom(1240, 0, 300, 300));


  Cview.show(&C_prev_time);
  Cordview.show(&C_space);

  phiview.show(&phi_prev_time);
  phiordview.show(&phi_space);

  u1view.show(&u1_prev_time);
  u1ordview.show(&u1_space);

  u2view.show(&u2_prev_time);
  u2ordview.show(&u2_space);

  // Newton's loop on the coarse mesh.
  info("Solving on coarse mesh:");
  bool verbose = true;
  if (!hermes2D.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 Solution sln.
  Solution::vector_to_solutions(coeff_vec_coarse, Hermes::vector<Space *>(&C_space, &phi_space, &u1_space, &u2_space),
                                Hermes::vector<Solution *>(&C_sln, &phi_sln, &u1_sln, &u2_sln));

  Cview.show(&C_sln);
  phiview.show(&phi_sln);
  u1view.show(&u1_sln);
  u2view.show(&u2_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.
  PidTimestepController pid(T_FINAL, true, INIT_TAU);
  TAU = pid.timestep;
  info("Starting time iteration with the step %g", *TAU);

  do {
    pid.begin_step();
    // Periodic global derefinements.
    if (pid.get_timestep_number() > 1 && pid.get_timestep_number() % UNREF_FREQ == 0) {
      info("Global mesh derefinement.");

#ifdef TWO_BASE_MESH
      C_mesh.copy(&basemesh_electrochem);
#else
      C_mesh.copy(&basemesh);
#endif
      if (MULTIMESH) {
#ifdef TWO_BASE_MESH
        phi_mesh.copy(&basemesh_electrochem);
        u1_mesh.copy(&basemesh_deformation);
        u2_mesh.copy(&basemesh_deformation);
#else
        phi_mesh.copy(&basemesh);
        u1_mesh.copy(&basemesh);
        u2_mesh.copy(&basemesh);
#endif

      }
      C_space.set_uniform_order(P_INIT);
      phi_space.set_uniform_order(P_INIT);
      u1_space.set_uniform_order(P_INIT);
      u2_space.set_uniform_order(P_INIT);

      // Project on globally derefined mesh.
      //info("Projecting previous fine mesh solution on derefined mesh.");
      //OGProjection::project_global(Hermes::vector<Space *>(&C, &phi), Hermes::vector<Solution *>(&C_ref_sln, &phi_ref_sln), 
       //                            Hermes::vector<Solution *>(&C_sln, &phi_sln));
    }

    // Adaptivity loop. Note: C_prev_time and Phi_prev_time must not be changed during spatial adaptivity.
    bool done = false; int as = 1;
    double err_est;
    do {
      info("Time step %d, adaptivity step %d:", pid.get_timestep_number(), as);

      // Construct globally refined reference mesh
      // and setup reference space.
      Hermes::vector<Space *>* ref_spaces = Space::construct_refined_spaces(
          Hermes::vector<Space *>(&C_space, &phi_space, &u1_space, &u2_space));

      scalar* coeff_vec = new scalar[Space::get_num_dofs(*ref_spaces)];
      DiscreteProblem dp(&wf, *ref_spaces, 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 && pid.get_timestep_number() == 1) {
        info("Projecting coarse mesh solution to obtain coefficient vector on new fine mesh.");
        OGProjection::project_global(*ref_spaces, Hermes::vector<MeshFunction *>(&C_sln, &phi_sln, &u1_sln, &u2_sln),
                                     coeff_vec, matrix_solver);
      }
      else {
        info("Projecting previous fine mesh solution to obtain coefficient vector on new fine mesh.");
        OGProjection::project_global(*ref_spaces,
            Hermes::vector<MeshFunction *>(&C_ref_sln, &phi_ref_sln, &u1_ref_sln, &u2_ref_sln),
            coeff_vec, matrix_solver);
      }
      if (as > 1) {
        // Now deallocate the previous mesh
        info("Delallocating the previous mesh");
        delete C_ref_sln.get_mesh();
        delete phi_ref_sln.get_mesh();
        delete u1_ref_sln.get_mesh();
        delete u2_ref_sln.get_mesh();
      }

      // Newton's loop on the fine mesh.
      info("Solving on fine mesh:");
      if (!hermes2D.solve_newton(coeff_vec, &dp, solver, matrix, rhs, 
	  	      NEWTON_TOL_FINE, NEWTON_MAX_ITER, verbose)) error("Newton's iteration failed.");


      // Store the result in ref_sln.
      Solution::vector_to_solutions(coeff_vec, *ref_spaces, 
                                    Hermes::vector<Solution *>(&C_ref_sln, &phi_ref_sln, &u1_ref_sln, &u2_ref_sln));
      // Projecting reference solution onto the coarse mesh
      info("Projecting fine mesh solution on coarse mesh.");
      OGProjection::project_global(Hermes::vector<Space *>(&C_space, &phi_space, &u1_space, &u2_space),
                                   Hermes::vector<Solution *>(&C_ref_sln, &phi_ref_sln, &u1_ref_sln, &u2_ref_sln),
                                   Hermes::vector<Solution *>(&C_sln, &phi_sln, &u1_sln, &u2_sln),
                                   matrix_solver);

      // Calculate element errors and total error estimate.
      info("Calculating error estimate.");
      Adapt adaptivity (Hermes::vector<Space *>(&C_space, &phi_space, &u1_space, &u2_space));
      Hermes::vector<double> err_est_rel;
      double err_est_rel_total = adaptivity.calc_err_est(Hermes::vector<Solution *>(&C_sln, &phi_sln, &u1_sln, &u2_sln),
                                 Hermes::vector<Solution *>(&C_ref_sln, &phi_ref_sln, &u1_ref_sln, &u2_ref_sln),
                                 &err_est_rel) * 100;

      // Report results.
      info("ndof_coarse[0]: %d, ndof_fine[0]: %d",
           C_space.get_num_dofs(), (*ref_spaces)[0]->get_num_dofs());
      info("err_est_rel[0]: %g%%", err_est_rel[0]*100);
      info("ndof_coarse[1]: %d, ndof_fine[1]: %d",
           phi_space.get_num_dofs(), (*ref_spaces)[1]->get_num_dofs());
      info("err_est_rel[1]: %g%%", err_est_rel[1]*100);
      info("ndof_coarse[2]: %d, ndof_fine[2]: %d",
           u1_space.get_num_dofs(), (*ref_spaces)[2]->get_num_dofs());
      info("err_est_rel[2]: %g%%", err_est_rel[3]*100);
      info("ndof_coarse[3]: %d, ndof_fine[3]: %d",
            u2_space.get_num_dofs(), (*ref_spaces)[3]->get_num_dofs());
      info("err_est_rel[3]: %g%%", err_est_rel[3]*100);

      // Report results.
      info("ndof_coarse_total: %d, ndof_fine_total: %d, err_est_rel: %g%%", 
           Space::get_num_dofs(Hermes::vector<Space *>(&C_space, &phi_space, &u1_space, &u2_space)),
                               Space::get_num_dofs(*ref_spaces), 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(Hermes::vector<RefinementSelectors::Selector *>(&selector, &selector, &selector, &selector),
          THRESHOLD, STRATEGY, MESH_REGULARITY);
        
        info("Adapted...");

        if (Space::get_num_dofs(Hermes::vector<Space *>(&C_space, &phi_space, &u1_space, &u2_space)) >= NDOF_STOP)
          done = true;
        else
          // Increase the counter of performed adaptivity steps.
          as++;
      }

      // Visualize the solution and mesh.
      info("Visualization procedures: C");
      char title[100];
      sprintf(title, "Solution[C], time step# %d, step size %g, time %g",
          pid.get_timestep_number(), *TAU, pid.get_time());
      Cview.set_title(title);
      Cview.show(&C_ref_sln);
      sprintf(title, "Mesh[C], time step# %d, step size %g, time %g",
          pid.get_timestep_number(), *TAU, pid.get_time());
      Cordview.set_title(title);
      Cordview.show(&C_space);
      
      info("Visualization procedures: phi");
      sprintf(title, "Solution[phi], time step# %d, step size %g, time %g",
          pid.get_timestep_number(), *TAU, pid.get_time());
      phiview.set_title(title);
      phiview.show(&phi_ref_sln);
      sprintf(title, "Mesh[phi], time step# %d, step size %g, time %g",
          pid.get_timestep_number(), *TAU, pid.get_time());
      phiordview.set_title(title);
      phiordview.show(&phi_space);

      info("Visualization procedures: u1");
      sprintf(title, "Solution[u1], time step# %d, step size %g, time %g",
          pid.get_timestep_number(), *TAU, pid.get_time());
      u1view.set_title(title);
      u1view.show(&u1_ref_sln);
      sprintf(title, "Mesh[u1], time step# %d, step size %g, time %g",
          pid.get_timestep_number(), *TAU, pid.get_time());
      u1ordview.set_title(title);
      u1ordview.show(&u1_space);

       info("Visualization procedures: u2");
       sprintf(title, "Solution[u2], time step# %d, step size %g, time %g",
           pid.get_timestep_number(), *TAU, pid.get_time());
       u2view.set_title(title);
       u2view.show(&u2_ref_sln);
       sprintf(title, "Mesh[u2], time step# %d, step size %g, time %g",
           pid.get_timestep_number(), *TAU, pid.get_time());
       u2ordview.set_title(title);
       u2ordview.show(&u2_space);

       /*
       info("Von Mises filter");
       VonMisesFilter stress(Hermes::vector<MeshFunction *>(&u1_prev_time, &u2_prev_time), mech_lambda, mech_mu);
       deformationview.show_mesh(false);
       deformationview.show(&stress, HERMES_EPS_HIGH, H2D_FN_VAL_0, &u1_prev_time, &u2_prev_time, 1.5e10);
       */

      // Clean up.
      delete solver;
      delete matrix;
      delete rhs;
      delete ref_spaces;
      delete[] coeff_vec;
    }
    while (done == false);


    pid.end_step(Hermes::vector<Solution*> (&C_ref_sln, &phi_ref_sln, &u1_ref_sln, &u2_ref_sln),
        Hermes::vector<Solution*> (&C_prev_time, &phi_prev_time, &u1_prev_time, &u2_prev_time));
    // TODO! Time step reduction when necessary.

    // Copy last reference solution into sln_prev_time.
    C_prev_time.copy(&C_ref_sln);
    phi_prev_time.copy(&phi_ref_sln);
    u1_prev_time.copy(&u1_ref_sln);
    u2_prev_time.copy(&u2_ref_sln);

  } while (pid.has_next());

  // Wait for all views to be closed.
  View::wait();
  return 0;
}
Ejemplo n.º 14
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.
  mesh.refine_all_elements();

  // Enter boundary markers.
  BCTypes bc_types;
  bc_types.add_bc_dirichlet(BDY_HORIZONTAL);
  bc_types.add_bc_neumann(BDY_VERTICAL);

  // Enter Dirichlet boundary values.
  BCValues bc_values;
  bc_values.add_function(BDY_HORIZONTAL, 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(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 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;

  // 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."); 
    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_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);
    }
    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;
    
    // Increase counter.
    as++;
  }
  while (done == false);
  
  verbose("Total running time: %g s", cpu_time.accumulated());

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

  printf("ndof allowed = %d\n", 430);
  printf("ndof actual = %d\n", ndof);
  if (ndof < 430) {      // ndofs was 414 at the time this test was created
    printf("Success!\n");
    return ERR_SUCCESS;
  }
  else {
    printf("Failure!\n");
    return ERR_FAILURE;
  }
}
Ejemplo n.º 15
0
int main(int argc, char* argv[])
{
  // Load the mesh.
  Mesh mesh;
  H2DReader mloader;
  // We load the mesh on a triangle [-1,-1][1,-1][-1,1] domain.
  mloader.load("ref_triangle.mesh", &mesh);            

  // Initialize boundary conditions.
  // (If no markers are entered, default is a natural BC).
  BCTypes bc_types;

  // Create an H1 space with default shapeset,
  // natural BC, and linear elements.
  H1Space space(&mesh, &bc_types, P_INIT);
  // The type of element, mesh_mode = 3 means a triangle element.
  int mesh_mode = 3;
  int n = Space::get_num_dofs(&space);
  info("ndof = %d", n);

  int *fn_idx = new int [n];
  int m = 0;
  int order = P_INIT;
  int vertex1 = 0;
  int vertex2 = 1;
  int vertex3 = 2;

  double x = 0.0, y = 0.0, value = 0.0;
  double x1 = -1.0, y1 = -1.0;
  double x2 =  1.0, y2 = -1.0;
  double x3 = -1.0, y3 =  1.0;

  info("Testing................");
  // Check vertex functions.
  info("Check vertex functions.");
  for (int i = 0; i < mesh_mode; i++, m++)
  {
    fn_idx[m] = space.get_shapeset()->get_vertex_index(i);
    info("Check vertex function [%d]", m);

    if (i == vertex1)
    {
      // Vertices.
      value = space.get_shapeset()->get_fn_value(fn_idx[i], x2, y2, 0);
      if (value >= EPS)
      {
        printf("... Failed\n");
        return ERR_FAILURE;
      }

      value = space.get_shapeset()->get_fn_value(fn_idx[i], x3, y3, 0);
      if (value >= EPS)
      {
        printf("... Failed\n");
        return ERR_FAILURE;
      }
      printf("Vertices... Ok\n");

      // Edges.
      printf("Edge  2.");
      for (int j = 0; j < order-1; j++)
      {
        x = x3 - (j+1)*(x3 - x2)/order;
        y = y3 - (j+1)*(y3 - y2)/order;
        value = space.get_shapeset()->get_fn_value(fn_idx[i], x, y, 0);
        if (value >= EPS)
        {
          printf("\nx = %f, y = %f, value = %.20lf", x, y, value);
          printf("... Failed\n");
          return ERR_FAILURE;
        }
      }
      printf("... Ok\n");
    }    

    if (i == vertex2)
    {
      // Vertices.
      value = space.get_shapeset()->get_fn_value(fn_idx[i], x1, y1, 0);
      if (value >= EPS)
      {
        printf("... Failed\n");
        return ERR_FAILURE;
      }
      value = space.get_shapeset()->get_fn_value(fn_idx[i], x3, y3, 0);
      if (value >= EPS)
      {
        printf("... Failed\n");
        return ERR_FAILURE;
      }
      printf("Vertices... Ok\n");

      // Edges.
      printf("Edge  3.");
      for (int j = 0; j < order-1; j++)
      {
        x = x3 - (j+1)*(x3 - x1)/order;
        y = y3 - (j+1)*(y3 - y1)/order;
        value = space.get_shapeset()->get_fn_value(fn_idx[i], x, y, 0);
        if (value >= EPS)
        {
          printf("\nx = %f, y = %f, value = %.20lf", x, y, value);
          printf("... Failed\n");
          return ERR_FAILURE;
        }
      }
      printf("... Ok\n");
    }    

    if (i == vertex3)
    {
      // Vertices.
      value = space.get_shapeset()->get_fn_value(fn_idx[i], x1, y1, 0);
      if (value >= EPS)
      {
        printf("... Failed\n");
        return ERR_FAILURE;
      }
      value = space.get_shapeset()->get_fn_value(fn_idx[i], x2, y2, 0);
      if (value >= EPS)
      {
        printf("... Failed\n");
        return ERR_FAILURE;
      }
      printf("Vertices... Ok\n");

      // Edges.
      printf("Edge  1.");
      for (int j = 0; j < order-1; j++)
      {
        x = x1 - (j+1)*(x1 - x2)/order;
        y = y1 - (j+1)*(y1 - y2)/order;
        value = space.get_shapeset()->get_fn_value(fn_idx[i], x, y, 0);
        if (value >= EPS)
        {
          printf("\nx = %f, y = %f, value = %.20lf", x, y, value);
          printf("... Failed\n");
          return ERR_FAILURE;
        }
      }
      printf("... Ok\n");
    }    
  }

  // Check edge functions.
  info("Check edge functions.");
  for (int edge_order = 2; edge_order <= order; edge_order++)
  {
    for (int j = 0; j < mesh_mode; j++, m++)
    {
      fn_idx[m] = space.get_shapeset()->get_edge_index(j, 0, edge_order);
      info("Check edge function [%d]", m);

      // Vertices.
      value = space.get_shapeset()->get_fn_value(fn_idx[m], x1, y1, 0);
      if (value >= EPS)
      {
        printf("... Failed\n");
        return ERR_FAILURE;
      }
      value = space.get_shapeset()->get_fn_value(fn_idx[m], x2, y2, 0);
      if (value >= EPS)
      {
        printf("... Failed\n");
        return ERR_FAILURE;
      }
      value = space.get_shapeset()->get_fn_value(fn_idx[m], x3, y3, 0);
      if (value >= EPS)
      {
        printf("... Failed\n");
        return ERR_FAILURE;
      }
      printf("Vertices... Ok\n");

      // Edge 1.
      if (m%mesh_mode == 0)
      {
        printf("Edge  1.");
        // Check edge 2.
        for (int j = 0; j < order-1; j++)
        {
          x = x2 - (j+1)*(x2 - x3)/order;
          y = y2 - (j+1)*(y2 - y3)/order;
          value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0);
          if (value >= EPS)
          {
            printf("\nx = %f, y = %f, value = %.20lf", x, y, value);
            printf("... Failed\n");
            return ERR_FAILURE;
          }
        }
        // Check edge 3.
        for (int j = 0; j < order-1; j++)
        {
          x = x3 - (j+1)*(x3 - x1)/order;
          y = y3 - (j+1)*(y3 - y1)/order;
          value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0);
          if (value >= EPS)
          {
            printf("\nx = %f, y = %f, value = %.20lf", x, y, value);
            printf("... Failed\n");
            return ERR_FAILURE;
          }
        }
        printf("... Ok\n");
      }

      // Edge 2.
      if (m%mesh_mode == 1)
      {
        printf("Edge  2.");
        // Check edge 1.
        for (int j = 0; j < order-1; j++)
        {
          x = x2 - (j+1)*(x2 - x1)/order;
          y = y2 - (j+1)*(y2 - y1)/order;
          value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0);
          if (value >= EPS)
          {
            printf("\nx = %f, y = %f, value = %.20lf", x, y, value);
            printf("... Failed\n");
            return ERR_FAILURE;
          }
        }
        // Check edge 3.
        for (int j = 0; j < order-1; j++)
        {
          x = x3 - (j+1)*(x3 - x1)/order;
          y = y3 - (j+1)*(y3 - y1)/order;
          value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0);
          if (value >= EPS)
          {
            printf("\nx = %f, y = %f, value = %.20lf", x, y, value);
            printf("... Failed\n");
            return ERR_FAILURE;
          }
        }
        printf("... Ok\n");
      }

      // Edge 3.
      if (m%mesh_mode == 2)
      {
        printf("Edge  3.");
        // Check edge 2.
        for (int j = 0; j < order-1; j++)
        {
          x = x2 - (j+1)*(x2 - x3)/order;
          y = y2 - (j+1)*(y2 - y3)/order;
          value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0);
          if (value >= EPS)
          {
            printf("\nx = %f, y = %f, value = %.20lf", x, y, value);
            printf("... Failed\n");
            return ERR_FAILURE;
          }
        }
        // Check edge 1.
        for (int j = 0; j < order-1; j++)
        {
          x = x1 - (j+1)*(x1 - x2)/order;
          y = y1 - (j+1)*(y1 - y2)/order;
          value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0);
          if (value >= EPS)
          {
            printf("\nx = %f, y = %f, value = %.20lf", x, y, value);
            printf("... Failed\n");
            return ERR_FAILURE;
          }
        }
        printf("... Ok\n");
      }
    }
  }

  // Check bubble functions.
  info("Check bubble functions.");
  int number_bubble = space.get_shapeset()->get_num_bubbles(order);
  int *bubble_idx = space.get_shapeset()->get_bubble_indices(order);
  for (int i = 0; i < number_bubble; i++, m++ )
  {
    fn_idx[m] = bubble_idx[i];
    info("Check bubble function [%d]", m);

    printf("Edge 1 and vertex 1.");
    // Check edge 1 and vertex 1.
    for (int j = 0; j < order; j++)
    {
      x = x1 - (j)*(x1 - x2)/order;
      y = y1 - (j)*(y1 - y2)/order;
      value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0);
      if (value >= EPS)
      {
        printf("\nx = %f, y = %f, value = %.20lf", x, y, value);
        printf("... Failed\n");
        return ERR_FAILURE;
      }
    }
    printf("... Ok\n");

    printf("Edge 2 and vertex 2.");
    // Check edge 2 and vertex 2.
    for (int j = 0; j < order; j++)
    {
      x = x2 - (j)*(x2 - x3)/order;
      y = y2 - (j)*(y2 - y3)/order;
      value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0);
      if (value >= EPS)
      {
        printf("\nx = %f, y = %f, value = %.20lf", x, y, value);
        printf("... Failed\n");
        return ERR_FAILURE;
      }
    }
    printf("... Ok\n");

    printf("Edge 3 and vertex 3.");
    // Check edge 3 and vertex 3.
    for (int j = 0; j < order; j++)
    {
      x = x3 - (j)*(x3 - x1)/order;
      y = y3 - (j)*(y3 - y1)/order;
      value = space.get_shapeset()->get_fn_value(fn_idx[m], x, y, 0);
      if (value >= EPS)
      {
        printf("\nx = %f, y = %f, value = %.20lf", x, y, value);
        printf("... Failed\n");
        return ERR_FAILURE;
      }
    }
    printf("... Ok\n");
  }
  info("ndof = %d", n);

  printf("Success!\n");
 
  delete [] fn_idx;
  return ERR_SUCCESS;
}
Ejemplo n.º 16
0
int main(int argc, char* argv[])
{
  Hermes2D hermes_2D;

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

  // Initial mesh refinements.
  for (int i=0; i < 4; i++) mesh.refine_all_elements();
  mesh.refine_towards_boundary(HERMES_ANY, 4);

  // Initialize boundary conditions.
  DefaultEssentialBCConst zero_vel_bc_x_brl(Hermes::vector<std::string>("Bottom", "Right", "Left"), 0.0);
  DefaultEssentialBCConst vel_bc_x_top(Hermes::vector<std::string>("Top"), XVEL_TOP);
  EssentialBCs bcs_vel_x(Hermes::vector<EssentialBoundaryCondition*>(&vel_bc_x_top, &zero_vel_bc_x_brl));
  DefaultEssentialBCConst zero_vel_bc_y(Hermes::vector<std::string>("Bottom", "Right", "Top", "Left"), 0.0);
  EssentialBCs bcs_vel_y(&zero_vel_bc_y);
  EssentialBCs bcs_pressure;

  // Spaces for velocity components and pressure.
  H1Space xvel_space(&mesh, &bcs_vel_x, P_INIT_VEL);
  H1Space yvel_space(&mesh, &bcs_vel_y, P_INIT_VEL);
#ifdef PRESSURE_IN_L2
  L2Space p_space(&mesh, &bcs_pressure, P_INIT_PRESSURE);
#else
  H1Space p_space(&mesh, &bcs_pressure, P_INIT_PRESSURE);
#endif
  Hermes::vector<Space *> spaces = Hermes::vector<Space *>(&xvel_space, &yvel_space, &p_space);

  // Calculate and report the number of degrees of freedom.
  int ndof = Space::get_num_dofs(Hermes::vector<Space *>(&xvel_space, &yvel_space, &p_space));
  info("ndof = %d.", ndof);

  // Define projection norms.
  ProjNormType vel_proj_norm = HERMES_H1_NORM;
#ifdef PRESSURE_IN_L2
  ProjNormType p_proj_norm = HERMES_L2_NORM;
#else
  ProjNormType p_proj_norm = HERMES_H1_NORM;
#endif
  ProjNormType t_proj_norm = HERMES_H1_NORM;

  // Solutions for the Newton's iteration and time stepping.
  info("Setting initial conditions.");
  Solution xvel_prev_time, yvel_prev_time, p_prev_time; 
  xvel_prev_time.set_zero(&mesh);
  yvel_prev_time.set_zero(&mesh);
  p_prev_time.set_zero(&mesh);
  Hermes::vector<Solution*> slns = Hermes::vector<Solution*>(&xvel_prev_time, &yvel_prev_time, 
                                                             &p_prev_time);

  // Initialize weak formulation.
  WeakForm* wf = new WeakFormDrivenCavity(Re, "Top", time_step, 
                                          &xvel_prev_time, &yvel_prev_time);

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

  // 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.
  VectorView vview("velocity", new WinGeom(0, 0, 400, 400));
  ScalarView pview("pressure", new WinGeom(410, 0, 400, 400));
  //vview.set_min_max_range(0, 1.6);
  vview.fix_scale_width(80);
  pview.fix_scale_width(80);
  pview.show_mesh(true);

  // Project the initial condition on the FE space to obtain initial
  // coefficient vector for the Newton's method.
  scalar* coeff_vec = new scalar[Space::get_num_dofs(spaces)];
  info("Projecting initial condition to obtain initial vector for the Newton's method.");
  OGProjection::project_global(spaces, slns, coeff_vec, matrix_solver, 
                               Hermes::vector<ProjNormType>(vel_proj_norm, vel_proj_norm, p_proj_norm, t_proj_norm));

  // Time-stepping loop:
  char title[100];
  double current_time = 0;
  int num_time_steps = T_FINAL / time_step;
  for (int ts = 1; ts <= num_time_steps; ts++)
  {
    info("---- Time step %d, time = %g:", ts, current_time);

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

    // Update previous time level solutions.
    Solution::vector_to_solutions(coeff_vec, spaces, slns);
    // Show the solution at the end of time step.
    sprintf(title, "Velocity, time %g", current_time);
    vview.set_title(title);
    vview.show(&xvel_prev_time, &yvel_prev_time);
    sprintf(title, "Pressure, time %g", current_time);
    pview.set_title(title);
    pview.show(&p_prev_time);

    // Update current time.
    current_time += time_step;
  }

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

  // Wait for all views to be closed.
  View::wait();
  return 0;
}
Ejemplo n.º 17
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));

  // Initialize the linear system.
  LinSystem ls(&wf, &space);

  // Testing n_dof and correctness of solution vector
  // for p_init = 1, 2, ..., 10
  int success = 1;
  Solution sln;
  for (int p_init = 1; p_init <= 10; p_init++) {
    printf("********* p_init = %d *********\n", p_init);
    space.set_uniform_order(p_init);

    // Assemble and solve the matrix problem.
    ls.assemble();
    ls.solve(&sln);

    scalar *sol_vector;
    int n_dof;
    ls.get_solution_vector(sol_vector, n_dof);
    printf("n_dof = %d\n", n_dof);
    double sum = 0;
    for (int i=0; i < n_dof; i++) sum += sol_vector[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;
  }

#define ERROR_SUCCESS                               0
#define ERROR_FAILURE                               -1
  if (success == 1) {
    printf("Success!\n");
    return ERROR_SUCCESS;
  }
  else {
    printf("Failure!\n");
    return ERROR_FAILURE;
  }
}
Ejemplo n.º 18
0
int main(int argc, char* argv[])
{
  // Load the mesh.
  Mesh mesh;
  H2DReader mloader;
  mloader.load("square.mesh", &mesh);

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

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

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

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

  // Project the function init_cond() on the FE space
  // to obtain initial coefficient vector for the Newton's method.
  scalar* coeff_vec = new scalar[Space::get_num_dofs(&space)];
  info("Projecting initial condition to obtain initial vector for the Newton's method.");
  OGProjection::project_global(&space, init_cond, coeff_vec, matrix_solver);
  Solution::vector_to_solution(coeff_vec, &space, &u_prev_time);
  
  // Time stepping loop:
  double current_time = 0.0;
  int t_step = 1;
  do {
    info("---- Time step %d, t = %g s.", t_step, current_time); t_step++;

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

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

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

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

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

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

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

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

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

      it++;
    }

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

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

    // Update time.
    current_time += TAU;

  } while (current_time < T_FINAL);
  
  delete [] coeff_vec;

  info("Coordinate (  0,   0) value = %lf", u_prev_time.get_pt_value(0.0, 0.0));
  info("Coordinate ( 25,  25) value = %lf", u_prev_time.get_pt_value(25.0, 25.0));
  info("Coordinate ( 50,  50) value = %lf", u_prev_time.get_pt_value(50.0, 50.0));
  info("Coordinate ( 75,  75) value = %lf", u_prev_time.get_pt_value(75.0, 75.0));
  info("Coordinate (100, 100) value = %lf", u_prev_time.get_pt_value(100.0, 100.0));

  double coor_x_y[5] = {0.0, 25.0, 50.0, 75.0, 100.0};
  double value[5] = {-1000.000000, -969.316013, -836.504249, -651.433710, -1000.000000};
  for (int i = 0; i < 5; i++)
  {
    if ((value[i] - u_prev_time.get_pt_value(coor_x_y[i], coor_x_y[i])) < 1E-6)
    {
    }
    else
    {
      printf("Failure!\n");
      return ERR_FAILURE;
    }
  }
  printf("Success!\n");
  return ERR_SUCCESS;
}
Ejemplo n.º 19
0
int main(int argc, char* argv[])
{
  // Load the mesh.
  Mesh mesh;
  H2DReader mloader;
  if (ALIGN_MESH) mloader.load("../oven_load_circle.mesh", &mesh);
  else mloader.load("../oven_load_square.mesh", &mesh);
  
  // Perform initial mesh refinemets.
  for (int i = 0; i < INIT_REF_NUM; i++)  mesh.refine_all_elements();

  // Initialize the weak formulation.
  CustomWeakForm wf(e_0, mu_0, mu_r, kappa, omega, J, ALIGN_MESH);

  // Initialize boundary conditions
  DefaultEssentialBCConst bc_essential(BDY_PERFECT_CONDUCTOR, std::complex<double>(0.0, 0.0));
  EssentialBCs bcs(&bc_essential);

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

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

  // Initialize refinements selector.
  HcurlProjBasedSelector 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 = 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 the 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); 

    // 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);
  
  ndof = Space::get_num_dofs(&space);

  int n_dof_allowed = 1230;
  printf("n_dof_actual = %d\n", ndof); // was 1218 at the time this test was last revisited
  printf("n_dof_allowed = %d\n", n_dof_allowed);
  if (ndof <= n_dof_allowed) {
    printf("Success!\n");
    return ERR_SUCCESS;
  }
  else {
    printf("Failure!\n");
    return ERR_FAILURE;
  }
}
Ejemplo n.º 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;
  }
}
Ejemplo n.º 21
0
int main(int argc, char **argv)
{
  // Instantiate a class with global functions.
  Hermes2D hermes2d;

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

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

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

  // Set exact solution.
  CustomExactSolution exact(&mesh);
  
  // Initialize the weak formulation.
  WeakFormPoisson wf1;

  // Initialize boundary conditions
  DefaultEssentialBCNonConst bc_essential(BDY_DIRICHLET, &exact);
  EssentialBCs bcs(&bc_essential);
 
  // Create an H1 space with default shapeset.
  H1Space space(&mesh, &bcs, P_INIT);
  int ndof = Space::get_num_dofs(&space);
  info("ndof: %d", ndof);

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

  // Initialize the solution.
  Solution sln1;
  
  // Initialize the linear discrete problem.
  bool is_linear = true;
  DiscreteProblem dp1(&wf1, &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);
  
  if (matrix_solver == SOLVER_AZTECOO) 
  {
    ((AztecOOSolver*) solver)->set_solver(iterative_method);
    ((AztecOOSolver*) solver)->set_precond(preconditioner);
    // Using default iteration parameters (see solver/aztecoo.h).
  }
  
  // Begin time measurement of assembly.
  cpu_time.tick(HERMES_SKIP);

  // Assemble the stiffness matrix and right-hand side vector.
  info("Assembling the stiffness matrix and right-hand side vector.");
  dp1.assemble(matrix, rhs);
  
  // Record assembly time.
  double time1 = cpu_time.tick().last();
  cpu_time.reset();

  // Solve the linear system and if successful, obtain the solution.
  info("Solving the matrix problem by %s.", MatrixSolverNames[matrix_solver].c_str());
  if(solver->solve())
    Solution::vector_to_solution(solver->get_solution(), &space, &sln1);
  else
    error ("Matrix solver failed.\n");

  // CPU time needed by UMFpack to solve the matrix problem.
  double time2 = cpu_time.tick().last();

  // Calculate errors.
  double rel_err_1 = hermes2d.calc_rel_error(&sln1, &exact, HERMES_H1_NORM) * 100;
  info("Assembly time: %g s, matrix solver time: %g s.", time1, time2);
  info("Xxact H1 error: %g%%.", rel_err_1);

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

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

  // Initialize the weak formulation for Trilinos.
  bool is_matrix_free = JFNK;
  WeakFormPoissonNox wf2(is_matrix_free);
  
  // Initialize DiscreteProblem.
  is_linear = false;
  DiscreteProblem dp2(&wf2, &space, is_linear);
  
  // Time measurement.
  cpu_time.tick(HERMES_SKIP);

  // Set initial vector for NOX.
  info("Projecting to obtain initial vector for the Newton's method.");
  scalar* coeff_vec = new scalar[ndof];
  Solution* init_sln = new Solution(&mesh, 0.0);
  OGProjection::project_global(&space, init_sln, coeff_vec);
  delete init_sln;
  
  // Measure the projection time.
  double proj_time = cpu_time.tick().last();
  
  // Initialize the NOX solver with the vector "coeff_vec".
  info("Initializing NOX.");
  // "" stands for preconditioning that is set later.
  NoxSolver nox_solver(&dp2, message_type, "GMRES", "Newton", ls_tolerance, "", flag_absresid, abs_resid, 
                       flag_relresid, rel_resid, max_iters);
  nox_solver.set_init_sln(coeff_vec);
  
  delete coeff_vec;

  // Choose preconditioning.
  RCP<Precond> pc = rcp(new MlPrecond("sa"));
  if (PRECOND)
  {
    if (JFNK) nox_solver.set_precond(pc);
    else nox_solver.set_precond("ML");
  }

  // Assemble and solve using NOX.
  Solution sln2;
  if (nox_solver.solve())
  {
    Solution::vector_to_solution(nox_solver.get_solution(), &space, &sln2);

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

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

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

  // Calculate errors.
  double rel_err_2 = hermes2d.calc_rel_error(&sln2, &exact, HERMES_H1_NORM) * 100;
  info("Projection time: %g s, NOX assembly/solution time: %g s.", proj_time, time2);
  info("Exact H1 error: %g%%.)", rel_err_2);
 

  /* TESTING */

  info("Coordinate (-0.6, -0.6) hermes value = %lf", sln1.get_pt_value(-0.6, -0.6));
  info("Coordinate ( 0.4, -0.6) hermes value = %lf", sln1.get_pt_value( 0.4, -0.6));
  info("Coordinate ( 0.4,  0.4) hermes value = %lf", sln1.get_pt_value( 0.4,  0.4));
  info("Coordinate (-0.6,  0.0) hermes value = %lf", sln1.get_pt_value(-0.6,  0.0));
  info("Coordinate ( 0.0,  0.0) hermes value = %lf", sln1.get_pt_value( 0.0,  0.0));

  info("Coordinate (-0.6, -0.6) nox value = %lf", sln2.get_pt_value(-0.6, -0.6));
  info("Coordinate ( 0.4, -0.6) nox value = %lf", sln2.get_pt_value( 0.4, -0.6));
  info("Coordinate ( 0.4,  0.4) nox value = %lf", sln2.get_pt_value( 0.4,  0.4));
  info("Coordinate (-0.6,  0.0) nox value = %lf", sln2.get_pt_value(-0.6,  0.0));
  info("Coordinate ( 0.0,  0.0) nox value = %lf", sln2.get_pt_value( 0.0,  0.0));

#define ERROR_SUCCESS                                0
#define ERROR_FAILURE                               -1
  int success = 1;
  double eps = 1e-5;
  if (fabs(sln2.get_pt_value(-0.6, -0.6) - 0.720000) > eps) {
    printf("Coordinate (-0.6, -0.6) nox value is %g\n", sln2.get_pt_value(-0.6, -0.6));
    success = 0;
  }
  if (fabs(sln2.get_pt_value( 0.4, -0.6) - 0.520000) > eps) {
    printf("Coordinate ( 0.4, -0.6) nox value is %g\n", sln2.get_pt_value( 0.4, -0.6));
    success = 0;
  }
  if (fabs(sln2.get_pt_value( 0.4,  0.4) - 0.320000) > eps) {
    printf("Coordinate ( 0.4,  0.4) nox value is %g\n", sln2.get_pt_value( 0.4,  0.4));
    success = 0;
  }
  if (fabs(sln2.get_pt_value(-0.6,  0.0) - 0.360000) > eps) {
    printf("Coordinate (-0.6,  0.0) nox value is %g\n", sln2.get_pt_value(-0.6,  0.0));
    success = 0;
  }
  if (fabs(sln2.get_pt_value( 0.0,  0.0) - 0.000000) > eps) {
    printf("Coordinate ( 0.0,  0.0) nox value is %g\n", sln2.get_pt_value( 0.0,  0.0));
    success = 0;
  }

  if (fabs(sln1.get_pt_value(-0.6, -0.6) - 0.720000) > eps) {
    printf("Coordinate (-0.6, -0.6) hermes value is %g\n", sln1.get_pt_value(-0.6, -0.6));
    success = 0;
  }
  if (fabs(sln1.get_pt_value( 0.4, -0.6) - 0.520000) > eps) {
    printf("Coordinate ( 0.4, -0.6) hermes value is %g\n", sln1.get_pt_value( 0.4, -0.6));
    success = 0;
  }
  if (fabs(sln1.get_pt_value( 0.4,  0.4) - 0.320000) > eps) {
    printf("Coordinate ( 0.4,  0.4) hermes value is %g\n", sln1.get_pt_value( 0.4,  0.4));
    success = 0;
  }
  if (fabs(sln1.get_pt_value(-0.6,  0.0) - 0.360000) > eps) {
    printf("Coordinate (-0.6,  0.0) hermes value is %g\n", sln1.get_pt_value(-0.6,  0.0));
    success = 0;
  }
  if (fabs(sln1.get_pt_value( 0.0,  0.0) - 0.000000) > eps) {
    printf("Coordinate ( 0.0,  0.0) hermes value is %g\n", sln1.get_pt_value( 0.0,  0.0));
    success = 0;
  }

  if (success == 1) {
    printf("Success!\n");
    return ERROR_SUCCESS;
  }
  else {
    printf("Failure!\n");
    return ERROR_FAILURE;
  }
}
Ejemplo n.º 22
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("domain.mesh", &mesh);

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

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

  // Initialize the weak formulation.
  CustomWeakFormWave wf(C_SQUARED);
  
  // Initialize boundary conditions
  DefaultEssentialBCConst bc_essential(BDY, 0.0);
  EssentialBCs bcs(&bc_essential);

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

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

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

  // Initialize Runge-Kutta time stepping.
  RungeKutta runge_kutta(&dp, &bt, matrix_solver);

  // Time stepping loop.
  double current_time = 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 s, time_step = %g s, stages: %d).", 
         current_time, time_step, bt.get_size());
    bool verbose = true;
    bool jacobian_changed = true;
    if (!runge_kutta.rk_time_step(current_time, time_step, slns, slns, jacobian_changed, verbose))
      error("Runge-Kutta time step failed, try to decrease time step size.");

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

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

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

  return 0;
}
Ejemplo n.º 23
0
int main(int argc, char* argv[])
{
    // Load the mesh.
    Mesh mesh;
    H2DReader mloader;
    mloader.load("GAMM-channel.mesh", &mesh);

    // Perform initial mesh refinements.
    for (int i = 0; i < INIT_REF_NUM; i++)
        mesh.refine_all_elements(0, true);
    mesh.refine_towards_boundary(BDY_SOLID_WALL_BOTTOM, INIT_REF_NUM_BOUNDARY_ANISO, true, false, true);
    mesh.refine_towards_boundary(BDY_SOLID_WALL_BOTTOM, INIT_REF_NUM_BOUNDARY_ISO, false, false, true);

    // Initialize boundary condition types and spaces with default shapesets.
    L2Space space_rho(&mesh, P_INIT);
    L2Space space_rho_v_x(&mesh, P_INIT);
    L2Space space_rho_v_y(&mesh,P_INIT);
    L2Space space_e(&mesh, P_INIT);
    int ndof = Space::get_num_dofs(Hermes::vector<Space*>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e));
    info("ndof: %d", ndof);

    // Initialize solutions, set initial conditions.
    InitialSolutionEulerDensity sln_rho(&mesh, RHO_EXT);
    InitialSolutionEulerDensityVelX sln_rho_v_x(&mesh, RHO_EXT * V1_EXT);
    InitialSolutionEulerDensityVelY sln_rho_v_y(&mesh, RHO_EXT * V2_EXT);
    InitialSolutionEulerDensityEnergy sln_e(&mesh, QuantityCalculator::calc_energy(RHO_EXT, RHO_EXT * V1_EXT, RHO_EXT * V2_EXT, P_EXT, KAPPA));

    InitialSolutionEulerDensity prev_rho(&mesh, RHO_EXT);
    InitialSolutionEulerDensityVelX prev_rho_v_x(&mesh, RHO_EXT * V1_EXT);
    InitialSolutionEulerDensityVelY prev_rho_v_y(&mesh, RHO_EXT * V2_EXT);
    InitialSolutionEulerDensityEnergy prev_e(&mesh, QuantityCalculator::calc_energy(RHO_EXT, RHO_EXT * V1_EXT, RHO_EXT * V2_EXT, P_EXT, KAPPA));

    Solution rsln_rho, rsln_rho_v_x, rsln_rho_v_y, rsln_e;

    // Numerical flux.
    OsherSolomonNumericalFlux num_flux(KAPPA);

    // Initialize weak formulation.
    EulerEquationsWeakFormImplicitMultiComponent wf(&num_flux, KAPPA, RHO_EXT, V1_EXT, V2_EXT, P_EXT, BDY_SOLID_WALL_BOTTOM, BDY_SOLID_WALL_TOP,
            BDY_INLET, BDY_OUTLET, &prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e, PRECONDITIONING);

    wf.set_time_step(time_step);

    // Filters for visualization of Mach number, pressure and entropy.
    MachNumberFilter Mach_number(Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), KAPPA);
    PressureFilter pressure(Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), KAPPA);
    EntropyFilter entropy(Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), KAPPA, RHO_EXT, P_EXT);

    ScalarView pressure_view("Pressure", new WinGeom(0, 0, 600, 300));
    ScalarView Mach_number_view("Mach number", new WinGeom(700, 0, 600, 300));
    ScalarView entropy_production_view("Entropy estimate", new WinGeom(0, 400, 600, 300));

    /*
    ScalarView s1("1", new WinGeom(0, 0, 600, 300));
    ScalarView s2("2", new WinGeom(700, 0, 600, 300));
    ScalarView s3("3", new WinGeom(0, 400, 600, 300));
    ScalarView s4("4", new WinGeom(700, 400, 600, 300));
    */

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

    // Select preconditioner.
    RCP<Precond> pc = rcp(new IfpackPrecond("point-relax"));

    int iteration = 0;
    double t = 0;
    for(t = 0.0; t < 3.0; t += time_step) {
        info("---- Time step %d, time %3.5f.", iteration++, t);

        // Periodic global derefinements.
        if (iteration > 1 && iteration % UNREF_FREQ == 0 && REFINEMENT_COUNT > 0) {
            REFINEMENT_COUNT = 0;
            info("Global mesh derefinement.");
            mesh.unrefine_all_elements();
            space_rho.adjust_element_order(-1, P_INIT);
            space_rho_v_x.adjust_element_order(-1, P_INIT);
            space_rho_v_y.adjust_element_order(-1, P_INIT);
            space_e.adjust_element_order(-1, P_INIT);
        }

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

            // Construct globally refined reference mesh and setup reference space.
            // Global polynomial order increase;
            int order_increase = 1;
            Hermes::vector<Space *>* ref_spaces = Space::construct_refined_spaces(Hermes::vector<Space *>(&space_rho, &space_rho_v_x,
                                                  &space_rho_v_y, &space_e), order_increase);

            // Report NDOFs.
            info("ndof_coarse: %d, ndof_fine: %d.",
                 Space::get_num_dofs(Hermes::vector<Space *>(&space_rho, &space_rho_v_x,
                                     &space_rho_v_y, &space_e)), Space::get_num_dofs(*ref_spaces));

            // Project the previous time level solution onto the new fine mesh
            // in order to obtain initial vector for NOX.
            info("Projecting initial solution on the FE mesh.");
            scalar* coeff_vec = new scalar[Space::get_num_dofs(*ref_spaces)];
            OGProjection::project_global(*ref_spaces, Hermes::vector<MeshFunction *>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), coeff_vec);

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

            // Initialize NOX solver.
            NoxSolver solver(&dp, NOX_MESSAGE_TYPE);
            solver.set_ls_tolerance(NOX_LINEAR_TOLERANCE);
            solver.disable_abs_resid();
            solver.set_conv_rel_resid(NOX_NONLINEAR_TOLERANCE);

            if(PRECONDITIONING)
                solver.set_precond(pc);

            info("Assembling by DiscreteProblem, solving by NOX.");

            solver.set_init_sln(coeff_vec);
            scalar* solution_vector = NULL;

            if (solver.solve()) {
                solution_vector = solver.get_solution();
                Solution::vector_to_solutions(solution_vector, *ref_spaces,
                                              Hermes::vector<Solution *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e));
            }
            else
                error("NOX failed.");

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

            if(SHOCK_CAPTURING) {
                DiscontinuityDetector discontinuity_detector(*ref_spaces,
                        Hermes::vector<Solution *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e));

                std::set<int> discontinuous_elements = discontinuity_detector.get_discontinuous_element_ids(DISCONTINUITY_DETECTOR_PARAM);

                FluxLimiter flux_limiter(solution_vector, *ref_spaces,
                                         Hermes::vector<Solution *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e));

                flux_limiter.limit_according_to_detector(discontinuous_elements);
            }

            // Project the fine mesh solution onto the coarse mesh.
            info("Projecting reference solution on coarse mesh.");
            OGProjection::project_global(Hermes::vector<Space *>(&space_rho, &space_rho_v_x,
                                         &space_rho_v_y, &space_e), Hermes::vector<Solution *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e),
                                         Hermes::vector<Solution *>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e), matrix_solver,
                                         Hermes::vector<ProjNormType>(HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM));

            // Calculate element errors and total error estimate.
            info("Calculating error estimate.");
            Adapt* adaptivity = new Adapt(Hermes::vector<Space *>(&space_rho, &space_rho_v_x,
                                          &space_rho_v_y, &space_e), Hermes::vector<ProjNormType>(HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM, HERMES_L2_NORM));
            double err_est_rel_total = adaptivity->calc_err_est(Hermes::vector<Solution *>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e),
                                       Hermes::vector<Solution *>(&rsln_rho, &rsln_rho_v_x, &rsln_rho_v_y, &rsln_e)) * 100;

            // Report results.
            info("err_est_rel: %g%%", err_est_rel_total);

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

                REFINEMENT_COUNT++;
                if (Space::get_num_dofs(Hermes::vector<Space *>(&space_rho, &space_rho_v_x,
                                        &space_rho_v_y, &space_e)) >= NDOF_STOP)
                    done = true;
                else
                    // Increase the counter of performed adaptivity steps.
                    as++;
            }

            // Clean up.
            delete adaptivity;
            if(!done)
                for(unsigned int i = 0; i < ref_spaces->size(); i++)
                    delete (*ref_spaces)[i]->get_mesh();
            for(unsigned int i = 0; i < ref_spaces->size(); i++)
                delete (*ref_spaces)[i];
        }
        while (done == false);

        // Copy the solutions into the previous time level ones.
        prev_rho.copy(&rsln_rho);
        prev_rho_v_x.copy(&rsln_rho_v_x);
        prev_rho_v_y.copy(&rsln_rho_v_y);
        prev_e.copy(&rsln_e);

        // Visualization.
        if((iteration - 1) % EVERY_NTH_STEP == 0) {
            // Hermes visualization.
            if(HERMES_VISUALIZATION) {
                Mach_number.reinit();
                pressure.reinit();
                entropy.reinit();
                pressure_view.show(&pressure);
                entropy_production_view.show(&entropy);
                Mach_number_view.show(&Mach_number);
                /*
                s1.show(&prev_rho);
                s2.show(&prev_rho_v_x);
                s3.show(&prev_rho_v_y);
                s4.show(&prev_e);
                */
            }
            // Output solution in VTK format.
            if(VTK_VISUALIZATION) {
                pressure.reinit();
                Mach_number.reinit();
                Linearizer lin;
                char filename[40];
                sprintf(filename, "pressure-%i.vtk", iteration - 1);
                lin.save_solution_vtk(&pressure, filename, "Pressure", false);
                sprintf(filename, "pressure-3D-%i.vtk", iteration - 1);
                lin.save_solution_vtk(&pressure, filename, "Pressure", true);
                sprintf(filename, "Mach number-%i.vtk", iteration - 1);
                lin.save_solution_vtk(&Mach_number, filename, "MachNumber", false);
                sprintf(filename, "Mach number-3D-%i.vtk", iteration - 1);
                lin.save_solution_vtk(&Mach_number, filename, "MachNumber", true);
            }
        }
    }

    pressure_view.close();
    entropy_production_view.close();
    Mach_number_view.close();

    /*
    s1.close();
    s2.close();
    s3.close();
    s4.close();
    */

    return 0;
}
Ejemplo n.º 24
0
int main(int argc, char* argv[])
{
  // Load the mesh.
  Mesh mesh;
  H2DReader mloader;
  mloader.load("../domain.mesh", &mesh);

  // Initialize boundary conditions.
  DefaultEssentialBCConst essential_bc(BDY_BOTTOM, 0.0);
  EssentialBCs bcs(&essential_bc);

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

  // Initialize the weak formulation.
  CustomWeakForm wf(A_SE, A_NE, A_SW, A_NW, RHS);
  
  // Initialize refinement selector.
  H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER);

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

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

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

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

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

  printf("ndof allowed = %d\n", 210);
  printf("ndof actual = %d\n", ndof);
  if (ndof < 210) {      // ndofs was 208 at the time this test was created
    printf("Success!\n");
    return ERR_SUCCESS;
  }
  else {
    printf("Failure!\n");
    return ERR_FAILURE;
  }

}
Ejemplo n.º 25
0
int main(int argc, char* argv[])
{
  // Time measurement.
  TimePeriod cpu_time;
  cpu_time.tick();

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

  // Perform 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::vector<int>(BDY_BOTTOM, BDY_RIGHT, BDY_TOP, BDY_LEFT));

  // Enter Dirichlet boundary values.
  BCValues bc_values;
  bc_values.add_zero(Hermes::vector<int>(BDY_BOTTOM, BDY_RIGHT, BDY_TOP, BDY_LEFT));

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

  info("Assembling by DiscreteProblem, solving by Umfpack:");

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

  // Initialize weak formulation,
  WeakForm wf1;
  wf1.add_matrix_form(callback(jacobian_form_hermes), HERMES_NONSYM, HERMES_ANY);
  wf1.add_vector_form(callback(residual_form_hermes), HERMES_ANY);

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

  // Set up the solver, matrix, and rhs for the coarse mesh 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_hermes;

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

  // 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* sln_tmp = new Solution(&mesh, init_cond);
  OGProjection::project_global(&space, sln_tmp, coeff_vec, matrix_solver);
  delete sln_tmp;

  // 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.
    dp1.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).
    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_vec[i] += solver->get_solution()[i];
    
    if (it >= NEWTON_MAX_ITER)
      error ("Newton method did not converge.");

    it++;
  }

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

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

  // CPU time needed by UMFpack
  double umf_time = cpu_time.tick().last();

  // Time measurement.
  cpu_time.tick(HERMES_SKIP);
 
  // TRILINOS PART:

  // Project the initial condition on the FE space.
  info("Projecting initial condition on the FE space.");
  // The NULL pointer means that we do not want the projection result as a Solution.
  sln_tmp = new Solution(&mesh, init_cond);
  OGProjection::project_global(&space, sln_tmp, coeff_vec, matrix_solver);
  delete sln_tmp;

  // Measure the projection time.
  double proj_time = cpu_time.tick().last();

  // Initialize the weak formulation for Trilinos.
  WeakForm wf2(1, JFNK ? true : false);
  if (!JFNK || (JFNK && PRECOND == 1)) wf2.add_matrix_form(callback(jacobian_form_nox), HERMES_SYM);
  if (JFNK && PRECOND == 2) wf2.add_matrix_form(callback(precond_form_nox), HERMES_SYM);
  wf2.add_vector_form(callback(residual_form_nox));

  // Initialize DiscreteProblem.
  DiscreteProblem dp2(&wf2, &space);

  // Initialize the NOX solver with the vector "coeff_vec".
  info("Initializing NOX.");
  NoxSolver nox_solver(&dp2);
  nox_solver.set_init_sln(coeff_vec);

  // Choose preconditioning.
  RCP<Precond> pc = rcp(new MlPrecond("sa"));
  if (PRECOND)
  {
    if (JFNK) nox_solver.set_precond(pc);
    else nox_solver.set_precond("ML");
  }

  // Solve the matrix problem using NOX.
  info("Assembling by DiscreteProblem, solving by NOX.");
  bool solved = nox_solver.solve();
  Solution sln_nox;
  if (solved)
  {
    double *coeffs = nox_solver.get_solution();
    Solution::vector_to_solution(coeffs, &space, &sln_nox);
    info("Number of nonlin iterations: %d (norm of residual: %g)", 
         nox_solver.get_num_iters(), nox_solver.get_residual());
    info("Total number of iterations in linsolver: %d (achieved tolerance in the last step: %g)", 
         nox_solver.get_num_lin_iters(), nox_solver.get_achieved_tol());
  }
  else
    error("NOX failed.");

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

  // Calculate errors.
  Solution ex;
  ex.set_exact(&mesh, &exact);
  Adapt adaptivity(&space);
  bool solutions_for_adapt = false;
  double err_est_rel_1 = adaptivity.calc_err_exact(&sln_hermes, &ex, solutions_for_adapt) * 100;
  info("Solution 1 (DiscreteProblem + %s): exact H1 error: %g (time %g [s])", MatrixSolverNames[matrix_solver].c_str(), err_est_rel_1, umf_time);
  double err_est_rel_2 = adaptivity.calc_err_exact(&sln_nox, &ex, solutions_for_adapt) * 100;
  info("Solution 2 (DiscreteProblem + NOX): exact H1 error: %g (time %g + %g = %g [s])", err_est_rel_2, proj_time, nox_time, proj_time+nox_time);

  info("Coordinate ( 0.6,  0.6) sln_hermes value = %lf", sln_hermes.get_pt_value( 0.6,  0.6));
  info("Coordinate ( 0.4,  0.6) sln_hermes value = %lf", sln_hermes.get_pt_value( 0.4,  0.6));
  info("Coordinate ( 0.4,  0.4) sln_hermes value = %lf", sln_hermes.get_pt_value( 0.4,  0.4));
  info("Coordinate ( 0.6,  0.0) sln_hermes value = %lf", sln_hermes.get_pt_value( 0.6,  0.0));
  info("Coordinate ( 0.5,  0.5) sln_hermes value = %lf", sln_hermes.get_pt_value( 0.5,  0.5));

  info("Coordinate ( 0.6,  0.6) sln_nox value = %lf", sln_nox.get_pt_value( 0.6,  0.6));
  info("Coordinate ( 0.4,  0.6) sln_nox value = %lf", sln_nox.get_pt_value( 0.4,  0.6));
  info("Coordinate ( 0.4,  0.4) sln_nox value = %lf", sln_nox.get_pt_value( 0.4,  0.4));
  info("Coordinate ( 0.6,  0.0) sln_nox value = %lf", sln_nox.get_pt_value( 0.6,  0.0));
  info("Coordinate ( 0.5,  0.5) sln_nox value = %lf", sln_nox.get_pt_value( 0.5,  0.5));

#define ERROR_SUCCESS                                0
#define ERROR_FAILURE                               -1
  int success = 1;
  double eps = 1e-5;
  if (fabs(sln_nox.get_pt_value(0.6, 0.6) - 0.057600) > eps) {
    printf("Coordinate (0.6, 0.6) sln_nox value is %g\n", sln_nox.get_pt_value(0.6, 0.6));
    success = 0;
  }
  if (fabs(sln_nox.get_pt_value( 0.4, 0.6) - 0.057600) > eps) {
    printf("Coordinate ( 0.4, 0.6) sln_nox value is %g\n", sln_nox.get_pt_value( 0.4, 0.6));
    success = 0;
  }
  if (fabs(sln_nox.get_pt_value( 0.4,  0.4) - 0.057600) > eps) {
    printf("Coordinate ( 0.4,  0.4) sln_nox value is %g\n", sln_nox.get_pt_value( 0.4,  0.4));
    success = 0;
  }
  if (fabs(sln_nox.get_pt_value(0.6,  0.0) - 0.000000) > eps) {
    printf("Coordinate (0.6,  0.0) sln_nox value is %g\n", sln_nox.get_pt_value(0.6,  0.0));
    success = 0;
  }
  if (fabs(sln_nox.get_pt_value( 0.5,  0.5) - 0.062500) > eps) {
    printf("Coordinate ( 0.5,  0.5) sln_nox value is %g\n", sln_nox.get_pt_value( 0.5,  0.5));
    success = 0;
  }

  if (fabs(sln_hermes.get_pt_value(0.6, 0.6) - 0.057600) > eps) {
    printf("Coordinate (0.6, 0.6) sln_hermes value is %g\n", sln_hermes.get_pt_value(0.6, 0.6));
    success = 0;
  }
  if (fabs(sln_hermes.get_pt_value( 0.4, 0.6) - 0.057600) > eps) {
    printf("Coordinate ( 0.4, 0.6) sln_hermes value is %g\n", sln_hermes.get_pt_value( 0.4, 0.6));
    success = 0;
  }
  if (fabs(sln_hermes.get_pt_value( 0.4,  0.4) - 0.057600) > eps) {
    printf("Coordinate ( 0.4,  0.4) sln_hermes value is %g\n", sln_hermes.get_pt_value( 0.4,  0.4));
    success = 0;
  }
  if (fabs(sln_hermes.get_pt_value(0.6,  0.0) - 0.000000) > eps) {
    printf("Coordinate (0.6,  0.0) sln_hermes value is %g\n", sln_hermes.get_pt_value(0.6,  0.0));
    success = 0;
  }
  if (fabs(sln_hermes.get_pt_value( 0.5,  0.5) - 0.062500) > eps) {
    printf("Coordinate ( 0.5,  0.5) sln_hermes value is %g\n", sln_hermes.get_pt_value( 0.5,  0.5));
    success = 0;
  }

  if (success == 1) {
    printf("Success!\n");
    return ERROR_SUCCESS;
  }
  else {
    printf("Failure!\n");
    return ERROR_FAILURE;
  }
}
Ejemplo n.º 26
0
int main(int argc, char* argv[])
{
    // Load the mesh file.
    Mesh basemesh, mesh;
    H2DReader mloader;
    mloader.load("domain.mesh", &basemesh);  // Master mesh.

    // Perform initial mesh refinements.
    for (int i=0; i < INIT_REF_NUM; i++) basemesh.refine_all_elements();
    basemesh.refine_towards_boundary(bdy_obstacle, INIT_REF_NUM_BDY, false); // 'true' stands for anisotropic refinements,
    basemesh.refine_towards_boundary(bdy_top, INIT_REF_NUM_BDY, true);       // 'false' for isotropic.
    basemesh.refine_towards_boundary(bdy_bottom, INIT_REF_NUM_BDY, true);
    mesh.copy(&basemesh);

    // Create spaces with default shapesets.
    H1Space* xvel_space = new H1Space(&mesh, xvel_bc_type, essential_bc_values_xvel, P_INIT_VEL);
    H1Space* yvel_space = new H1Space(&mesh, yvel_bc_type, essential_bc_values_yvel, P_INIT_VEL);
#ifdef PRESSURE_IN_L2
    L2Space* p_space = new L2Space(&mesh, P_INIT_PRESSURE);
#else
    H1Space* p_space = new H1Space(&mesh, p_bc_type, NULL, P_INIT_PRESSURE);
#endif

    // Calculate and report the number of degrees of freedom.
    int ndof = get_num_dofs(Tuple<Space *>(xvel_space, yvel_space, p_space));
    info("ndof = %d.", ndof);

    // Define projection norms.
    int vel_proj_norm = H2D_H1_NORM;
#ifdef PRESSURE_IN_L2
    int p_proj_norm = H2D_L2_NORM;
#else
    int p_proj_norm = H2D_H1_NORM;
#endif

    // Solutions for the Newton's iteration and time stepping.
    info("Setting initial conditions.");
//  Solution xvel_fine, yvel_fine, p_fine;
    Solution xvel_sln, yvel_sln, p_sln;
    Solution xvel_ref_sln, yvel_ref_sln, p_ref_sln;
    Solution xvel_prev_time, yvel_prev_time, p_prev_time;

    // Define initial conditions on the coarse mesh.
    xvel_prev_time.set_zero(&mesh);
    yvel_prev_time.set_zero(&mesh);
    p_prev_time.set_zero(&mesh);

    // Initialize the weak formulation.
    WeakForm wf(3);
    wf.add_matrix_form(0, 0, callback(bilinear_form_sym_0_0_1_1), H2D_SYM);
    wf.add_matrix_form(0, 0, callback(newton_bilinear_form_unsym_0_0), H2D_UNSYM, H2D_ANY);
    wf.add_matrix_form(0, 1, callback(newton_bilinear_form_unsym_0_1), H2D_UNSYM, H2D_ANY);
    wf.add_matrix_form(0, 2, callback(bilinear_form_unsym_0_2), H2D_ANTISYM);
    wf.add_matrix_form(1, 0, callback(newton_bilinear_form_unsym_1_0), H2D_UNSYM, H2D_ANY);
    wf.add_matrix_form(1, 1, callback(bilinear_form_sym_0_0_1_1), H2D_SYM);
    wf.add_matrix_form(1, 1, callback(newton_bilinear_form_unsym_1_1), H2D_UNSYM, H2D_ANY);
    wf.add_matrix_form(1, 2, callback(bilinear_form_unsym_1_2), H2D_ANTISYM);
    wf.add_vector_form(0, callback(newton_F_0), H2D_ANY, Tuple<MeshFunction*>(&xvel_prev_time, &yvel_prev_time));
    wf.add_vector_form(1, callback(newton_F_1), H2D_ANY, Tuple<MeshFunction*>(&xvel_prev_time, &yvel_prev_time));
    wf.add_vector_form(2, callback(newton_F_2), H2D_ANY);

    // Initialize adaptivity parameters.
    AdaptivityParamType apt(ERR_STOP, NDOF_STOP, THRESHOLD, STRATEGY, MESH_REGULARITY);
    // Create a selector which will select optimal candidate.
    H1ProjBasedSelector selector(CAND_LIST, CONV_EXP, H2DRS_DEFAULT_ORDER);
    // Assign initial condition to mesh.
    Vector *coeff_vec = new AVector(ndof);

    // Time-stepping loop:
    char title[100];
    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);
            xvel_space->set_uniform_order(P_INIT_VEL);
            yvel_space->set_uniform_order(P_INIT_VEL);
            p_space->set_uniform_order(P_INIT_PRESSURE);
        }

        // Update the coefficient vector and u_prev_time.
        info("Projecting to obtain coefficient vector on coarse mesh.");
        project_global(Tuple<Space *>(xvel_space, yvel_space, p_space),
                       Tuple<int>(vel_proj_norm, vel_proj_norm, p_proj_norm),
                       Tuple<MeshFunction*>(&xvel_prev_time, &yvel_prev_time, &p_prev_time),
                       Tuple<Solution*>(&xvel_prev_time, &yvel_prev_time, &p_prev_time),
                       coeff_vec);

        // Adaptivity loop (in space):
        bool verbose = true;     // 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(Tuple<Space *>(xvel_space, yvel_space, p_space), &wf, coeff_vec, matrix_solver,
                           Tuple<int>(vel_proj_norm, vel_proj_norm, p_proj_norm),
                           Tuple<Solution *>(&xvel_sln, &yvel_sln, &p_sln),
                           Tuple<Solution *>(&xvel_ref_sln, &yvel_ref_sln, &p_ref_sln),
                           Tuple<WinGeom *>(), Tuple<WinGeom *>(),
                           Tuple<RefinementSelectors::Selector *>(&selector, &selector, &selector), &apt,
                           NEWTON_TOL_COARSE, NEWTON_TOL_FINE, NEWTON_MAX_ITER, verbose);

        // Copy new time level reference solution into prev_time.
        xvel_prev_time.set_coeff_vector(xvel_space, coeff_vec);
        yvel_prev_time.set_coeff_vector(yvel_space, coeff_vec);
        p_prev_time.set_coeff_vector(p_space, coeff_vec);
    }

    ndof = get_num_dofs(Tuple<Space *>(xvel_space, yvel_space, p_space));
    info("ndof = %d", ndof);

    // Waiting for tests.
}
Ejemplo n.º 27
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("../domain.mesh", &mesh);

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

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

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

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

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

  // Initialize Runge-Kutta time stepping.
  RungeKutta runge_kutta(&dp, &bt, matrix_solver);

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

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

  double coord_x[4] = {0.3, 0.6, 0.9, 1.4};
  double coord_y[4] = {0, 0.3, 0.5, 0.7};

  info("Coordinate (0.3, 0.0) value = %lf", B_sln.get_pt_value(coord_x[0], coord_y[0]));
  info("Coordinate (0.6, 0.3) value = %lf", B_sln.get_pt_value(coord_x[1], coord_y[1]));
  info("Coordinate (0.9, 0.5) value = %lf", B_sln.get_pt_value(coord_x[2], coord_y[2]));
  info("Coordinate (1.4, 0.7) value = %lf", B_sln.get_pt_value(coord_x[3], coord_y[3]));

  double t_value[4] = {0.0, -0.065100, -0.146515, -0.247677};
  bool success = true;

  for (int i = 0; i < 4; i++)
  {
    if (fabs(t_value[i] - B_sln.get_pt_value(coord_x[i], coord_y[i])) > 1E-6) success = false;
  }

  if (success) {  
    printf("Success!\n");
    return ERR_SUCCESS;
  }
  else {
    printf("Failure!\n");
    return ERR_FAILURE;
  }
}
Ejemplo n.º 28
0
int main(int argc, char* argv[])
{
    // Load the mesh.
    Mesh mesh;
    H2DReader mloader;
    mloader.load("../domain.mesh", &mesh);

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

    // Initialize the weak formulation.
    CustomWeakFormPoissonNeumann wf("Aluminum", LAMBDA_AL, "Copper", LAMBDA_CU, VOLUME_HEAT_SRC,
                                    "Outer", ALPHA, T_EXTERIOR);

    // Initialize boundary conditions.
    CustomDirichletCondition bc_essential(Hermes::vector<std::string>("Bottom", "Inner", "Left"),
                                          BDY_A_PARAM, BDY_B_PARAM, BDY_C_PARAM);
    EssentialBCs bcs(&bc_essential);

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

    // Testing n_dof and correctness of solution vector
    // for p_init = 1, 2, ..., 10
    int success = 1;
    Solution sln;
    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 - 61.8227) > 1e-1) success = 0;
        if (p_init == 2 && fabs(sum - 60.8105) > 1e-1) success = 0;
        if (p_init == 3 && fabs(sum - 61.5511) > 1e-1) success = 0;
        if (p_init == 4 && fabs(sum - 60.8191) > 1e-1) success = 0;
        if (p_init == 5 && fabs(sum - 61.5304) > 1e-1) success = 0;
        if (p_init == 6 && fabs(sum - 60.8064) > 1e-1) success = 0;
        if (p_init == 7 && fabs(sum - 61.5323) > 1e-1) success = 0;
        if (p_init == 8 && fabs(sum - 60.7863) > 1e-1) success = 0;
        if (p_init == 9 && fabs(sum - 61.5408) > 1e-1) success = 0;
        if (p_init == 10 && fabs(sum - 60.7637) > 1e-1) success = 0;
    }

    if (success == 1) {
        printf("Success!\n");
        return ERR_SUCCESS;
    }
    else {
        printf("Failure!\n");
        return ERR_FAILURE;
    }
}
Ejemplo n.º 29
0
int main(int argc, char* argv[])
{
  // Instantiate a class with global functions.
  Hermes2D hermes2d;

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

  // Initialize boundary conditions.
  CustomEssentialBCNonConst bc_essential("Bdy");
  EssentialBCs bcs(&bc_essential);

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

  // Initialize the weak formulation
  CustomNonlinearity lambda(alpha);
  HermesFunction src(-heat_src);
  WeakFormsH1::DefaultWeakFormPoisson wf(HERMES_ANY, &lambda, &src);

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

  // 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.
  // NOTE: If you want to start from the zero vector, just define 
  // coeff_vec to be a vector of ndof zeros (no projection is needed).
  info("Projecting to obtain initial vector for the Newton's method.");
  scalar* coeff_vec = new scalar[Space::get_num_dofs(&space)] ;
  CustomInitialCondition init_sln(&mesh);
  OGProjection::project_global(&space, &init_sln, coeff_vec, matrix_solver); 

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

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

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

  // Visualise the solution and mesh.
  ScalarView s_view("Solution", new WinGeom(0, 0, 440, 350));
  s_view.show_mesh(false);
  s_view.show(&sln);
  OrderView o_view("Mesh", new WinGeom(450, 0, 400, 350));
  o_view.show(&space);

  // Wait for all views to be closed.
  View::wait();
  return 0;
}
Ejemplo n.º 30
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::vector<int>(BDY_1, BDY_6));
  bc_types.add_bc_newton(Hermes::vector<int>(BDY_2, BDY_3, BDY_4, BDY_5));

  // Enter Dirichlet boundary values.
  BCValues bc_values;
  bc_values.add_zero(Hermes::vector<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);

  // Initialize views.
  VectorView v_view("Solution (magnitude)", new WinGeom(0, 0, 460, 350));
  v_view.set_min_max_range(0, 1.5);
  OrderView  o_view("Polynomial orders", new WinGeom(470, 0, 400, 350));
  
  // 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);
 
    // 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 the 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");

    // 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); 
   
    // View the coarse mesh solution and polynomial orders.
    v_view.show(&sln);
    o_view.show(&space);

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

  // Show the reference solution - the final result.
  v_view.set_title("Fine mesh solution (magnitude)");
  v_view.show(&ref_sln);
  
  // Wait for all views to be closed.
  View::wait();
  return 0;
}