Beispiel #1
0
bool calc_errors(Hermes::Tuple<Solution* > left, Hermes::Tuple<Solution *> right, Hermes::Tuple<double> & err_abs, Hermes::Tuple<double> & norm_vals, 
                 double & err_abs_total, double & norm_total, double & err_rel_total, Hermes::Tuple<ProjNormType> norms)
{
  bool default_norms = false;
  // Checks.
  if(left.size() != right.size())
    return false;
  if (norms != Hermes::Tuple<ProjNormType>())
  {
    if(left.size() != norms.size())
      return false;
  }
  else
    default_norms = true;
  
  // Zero the resulting Tuples.
  err_abs.clear();
  norm_vals.clear();

  // Zero the sums.
  err_abs_total = 0;
  norm_total = 0;
  err_rel_total = 0;
  
  // Calculation.
  for(unsigned int i = 0; i < left.size(); i++)
  {
    err_abs.push_back(calc_abs_error(left[i], right[i], default_norms ? HERMES_H1_NORM : norms[i]));
    norm_vals.push_back(calc_norm(right[i], default_norms ? HERMES_H1_NORM : norms[i]));
    err_abs_total += err_abs[i] * err_abs[i];
    norm_total += norm_vals[i] * norm_vals[i];
  }

  err_abs_total = sqrt(err_abs_total);
  norm_total = sqrt(norm_total);
  err_rel_total = err_abs_total / norm_total * 100.;
  
  // Everything went well, return appropriate flag.
  return true;
}
Beispiel #2
0
int main(int argc, char* argv[])
{
  if (NUMBER_OF_EIGENVALUES > 6) error("Maximum number of eigenvalues is 6.");
  info("Desired number of eigenvalues: %d.", NUMBER_OF_EIGENVALUES);

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

  // Enter boundary markers. 
  // Note: "essential" means that solution value is prescribed.
  BCTypes bc_types;
  bc_types.add_bc_dirichlet(Hermes::Tuple<int>(BDY_BOTTOM, BDY_RIGHT, BDY_TOP, BDY_LEFT));

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

  // Initialize the weak formulation for the left hand side i.e. H 
  WeakForm wf_left, wf_right;
  wf_left.add_matrix_form(callback(bilinear_form_left));
  wf_right.add_matrix_form(callback(bilinear_form_right));

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

  // Initialize views.
  ScalarView sview_1("", new WinGeom(0, 0, 350, 250));
  sview_1.show_mesh(false);
  sview_1.fix_scale_width(60);
  ScalarView sview_2("", new WinGeom(360, 0, 350, 250));
  sview_2.show_mesh(false);
  sview_2.fix_scale_width(60);
  ScalarView sview_3("", new WinGeom(720, 0, 350, 250));
  sview_3.show_mesh(false);
  sview_3.fix_scale_width(60);
  ScalarView sview_4("", new WinGeom(0, 305, 350, 250));
  sview_4.show_mesh(false);
  sview_4.fix_scale_width(60);
  ScalarView sview_5("", new WinGeom(360, 305, 350, 250));
  sview_5.show_mesh(false);
  sview_5.fix_scale_width(60);
  ScalarView sview_6("", new WinGeom(720, 305, 350, 250));
  sview_6.show_mesh(false);
  sview_6.fix_scale_width(60);
  OrderView  oview("Polynomial orders", new WinGeom(1080, 0, 410, 350));

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

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

  Solution sln[NUMBER_OF_EIGENVALUES], ref_sln[NUMBER_OF_EIGENVALUES];

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

    // Construct globally refined reference mesh and setup reference space.
    Space* ref_space = construct_refined_space(&space);
    int ref_ndof = Space::get_num_dofs(ref_space);
    info("ref_ndof: %d.", ref_ndof);

    // Initialize matrices and matrix solver on referenc emesh.
    SparseMatrix* matrix_left = create_matrix(matrix_solver);
    SparseMatrix* matrix_right = create_matrix(matrix_solver);
    Solver* solver = create_linear_solver(matrix_solver, matrix_left);

    // Assemble the matrices on reference mesh.
    bool is_linear = true;
    DiscreteProblem* dp_left = new DiscreteProblem(&wf_left, ref_space, is_linear);
    dp_left->assemble(matrix_left);
    DiscreteProblem* dp_right = new DiscreteProblem(&wf_right, ref_space, is_linear);
    dp_right->assemble(matrix_right);

    // Time measurement.
    cpu_time.tick();

    // Write matrix_left in MatrixMarket format.
    write_matrix_mm("mat_left.mtx", matrix_left);

    // Write matrix_left in MatrixMarket format.
    write_matrix_mm("mat_right.mtx", matrix_right);

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

    // Calling Python eigensolver. Solution will be written to "eivecs.dat".
    info("Calling Pysparse...");
    char call_cmd[255];
    sprintf(call_cmd, "python solveGenEigenFromMtx.py mat_left.mtx mat_right.mtx %g %d %g %d", 
	    TARGET_VALUE, NUMBER_OF_EIGENVALUES, TOL, MAX_ITER);
    system(call_cmd);
    info("Pysparse finished.");

    // Initializing solution vector, solution and ScalarView.
    double* ref_coeff_vec = new double[ref_ndof];
    //Solution sln[NUMBER_OF_EIGENVALUES], ref_sln[NUMBER_OF_EIGENVALUES];
    //ScalarView view("Solution", new WinGeom(0, 0, 440, 350));

    // Reading solution vectors from file and visualizing.
    double eigenval[NUMBER_OF_EIGENVALUES];
    FILE *file = fopen("eivecs.dat", "r");
    char line [64];                  // Maximum line size.
    fgets(line, sizeof line, file);  // ref_ndof
    int n = atoi(line);            
    if (n != ref_ndof) error("Mismatched ndof in the eigensolver output file.");  
    fgets(line, sizeof line, file);  // Number of eigenvectors in the file.
    int neig = atoi(line);
    if (neig != NUMBER_OF_EIGENVALUES) error("Mismatched number of eigenvectors in the eigensolver output file.");  
    for (int ieig = 0; ieig < NUMBER_OF_EIGENVALUES; ieig++) {
      // Get next eigenvalue from the file
      fgets(line, sizeof line, file);  // eigenval
      eigenval[ieig] = atof(line);            
      // Get the corresponding eigenvector.
      for (int i = 0; i < ref_ndof; i++) {  
        fgets(line, sizeof line, file);
        ref_coeff_vec[i] = atof(line);
      }

      // Convert coefficient vector into a Solution.
      Solution::vector_to_solution(ref_coeff_vec, ref_space, &(ref_sln[ieig]));

      // Project the fine mesh solution onto the coarse mesh.
      info("Projecting reference solution %d on coarse mesh.", ieig);
      OGProjection::project_global(&space, &(ref_sln[ieig]), &(sln[ieig]), matrix_solver);
    }  
    fclose(file);
    delete [] ref_coeff_vec;

    // FIXME: Below, the adaptivity is done for the last eigenvector only,
    // this needs to be changed to take into account all eigenvectors.

    // View the coarse mesh solution and polynomial orders.
    
    char title[100];
    if (NUMBER_OF_EIGENVALUES > 0) {
      sprintf(title, "Solution 0, val = %g", eigenval[0]);
      sview_1.set_title(title);
      sview_1.show(&(sln[0]));
    }
    if (NUMBER_OF_EIGENVALUES > 1) {
      sprintf(title, "Solution 1, val = %g", eigenval[1]);
      sview_2.set_title(title);
      sview_2.show(&(sln[1]));
    }
    if (NUMBER_OF_EIGENVALUES > 2) {
      sprintf(title, "Solution 2, val = %g", eigenval[2]);
      sview_3.set_title(title);
      sview_3.show(&(sln[2]));
    }
    if (NUMBER_OF_EIGENVALUES > 3) {
      sprintf(title, "Solution 3, val = %g", eigenval[3]);
      sview_4.set_title(title);
      sview_4.show(&(sln[3]));
    }
    if (NUMBER_OF_EIGENVALUES > 4) {
      sprintf(title, "Solution 4, val = %g", eigenval[4]);
      sview_5.set_title(title);
      sview_5.show(&(sln[4]));
    }
    if (NUMBER_OF_EIGENVALUES > 5) {
      sprintf(title, "Solution 5, val = %g", eigenval[5]);
      sview_6.set_title(title);
      sview_6.show(&(sln[5]));
    }
    oview.show(&space);

    // Calculate element errors and total error estimate.
    info("Calculating error estimate.");
    Hermes::Tuple<Space *> spaces;
    for(int i = 0; i < NUMBER_OF_EIGENVALUES; i++)
        spaces.push_back(&space);
    Hermes::Tuple<ProjNormType> proj_norms;
    for(int i = 0; i < NUMBER_OF_EIGENVALUES; i++)
        proj_norms.push_back(HERMES_H1_NORM);
    Adapt* adaptivity = new Adapt(spaces, proj_norms);
    bool solutions_for_adapt = true;
    
    Hermes::Tuple<Solution *> slns;
    if (NUMBER_OF_EIGENVALUES > 0) slns.push_back(&sln[0]);
    if (NUMBER_OF_EIGENVALUES > 1) slns.push_back(&sln[1]);
    if (NUMBER_OF_EIGENVALUES > 2) slns.push_back(&sln[2]);
    if (NUMBER_OF_EIGENVALUES > 3) slns.push_back(&sln[3]);
    if (NUMBER_OF_EIGENVALUES > 4) slns.push_back(&sln[4]);
    if (NUMBER_OF_EIGENVALUES > 5) slns.push_back(&sln[5]);
    
    Hermes::Tuple<Solution *> ref_slns;
    if (NUMBER_OF_EIGENVALUES > 0) ref_slns.push_back(&ref_sln[0]);
    if (NUMBER_OF_EIGENVALUES > 1) ref_slns.push_back(&ref_sln[1]);
    if (NUMBER_OF_EIGENVALUES > 2) ref_slns.push_back(&ref_sln[2]);
    if (NUMBER_OF_EIGENVALUES > 3) ref_slns.push_back(&ref_sln[3]);
    if (NUMBER_OF_EIGENVALUES > 4) ref_slns.push_back(&ref_sln[4]);
    if (NUMBER_OF_EIGENVALUES > 5) ref_slns.push_back(&ref_sln[5]);
    Hermes::Tuple<double> component_errors;
    double err_est_rel = adaptivity->calc_err_est(slns, ref_slns, solutions_for_adapt, 
                         HERMES_TOTAL_ERROR_REL | HERMES_ELEMENT_ERROR_REL, &component_errors) * 100;

    // Report results.
    info("ndof_coarse: %d, ndof_fine: %d.", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space));
    if (NUMBER_OF_EIGENVALUES > 0) info("err_est_rel[0]: %g%%", component_errors[0] * 100);
    if (NUMBER_OF_EIGENVALUES > 1) info("err_est_rel[1]: %g%%", component_errors[1] * 100);
    if (NUMBER_OF_EIGENVALUES > 2) info("err_est_rel[2]: %g%%", component_errors[2] * 100);
    if (NUMBER_OF_EIGENVALUES > 3) info("err_est_rel[3]: %g%%", component_errors[3] * 100);
    if (NUMBER_OF_EIGENVALUES > 4) info("err_est_rel[4]: %g%%", component_errors[4] * 100);
    if (NUMBER_OF_EIGENVALUES > 5) info("err_est_rel[5]: %g%%", component_errors[5] * 100);
   
    // 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");

    // If err_est too large, adapt the mesh.
    if (err_est_rel < ERR_STOP) done = true;
    else
    {
      info("Adapting coarse mesh.");
      Hermes::Tuple<RefinementSelectors::Selector *> selectors;
      for(int i = 0; i < NUMBER_OF_EIGENVALUES; i++)
        selectors.push_back(&selector);
      done = adaptivity->adapt(selectors, 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_left;
    delete matrix_right;
    delete adaptivity;
    if(done == false) delete ref_space->get_mesh();
    delete ref_space;
    delete dp_left;
    delete dp_right;
  }
  while (done == false);

  // Wait for all views to be closed.
  View::wait();
  return 0;
};
Beispiel #3
0
Adapt::Adapt(Hermes::Tuple< Space* > spaces_,
             Hermes::Tuple<ProjNormType> proj_norms) :
    num_act_elems(-1),
    have_errors(false),
    have_coarse_solutions(false),
    have_reference_solutions(false)
{
    // sanity check
    if (proj_norms.size() > 0 && spaces_.size() != proj_norms.size())
        error("Mismatched numbers of spaces and projection types in Adapt::Adapt().");

    this->num = spaces_.size();

    // sanity checks
    error_if(this->num <= 0, "Too few components (%d), only %d supported.", this->num, H2D_MAX_COMPONENTS);
    error_if(this->num >= H2D_MAX_COMPONENTS, "Too many components (%d), only %d supported.", this->num, H2D_MAX_COMPONENTS);
    for (int i = 0; i < this->num; i++) {
        if (spaces_[i] == NULL) error("spaces[%d] is NULL in Adapt::Adapt().", i);
        this->spaces.push_back(spaces_[i]);
    }

    // reset values
    memset(errors, 0, sizeof(errors));
    memset(form, 0, sizeof(form));
    memset(ord, 0, sizeof(ord));
    memset(sln, 0, sizeof(sln));
    memset(rsln, 0, sizeof(rsln));

    // if norms were not set by the user, set them to defaults
    // according to spaces
    if (proj_norms.size() == 0) {
        for (int i = 0; i < this->num; i++) {
            switch (spaces[i]->get_type()) {
            case HERMES_H1_SPACE:
                proj_norms.push_back(HERMES_H1_NORM);
                break;
            case HERMES_HCURL_SPACE:
                proj_norms.push_back(HERMES_HCURL_NORM);
                break;
            case HERMES_HDIV_SPACE:
                proj_norms.push_back(HERMES_HDIV_NORM);
                break;
            case HERMES_L2_SPACE:
                proj_norms.push_back(HERMES_L2_NORM);
                break;
            default:
                error("Unknown space type in Adapt::Adapt().");
            }
        }
    }

    // assign norm weak forms  according to norms selection
    for (int i = 0; i < this->num; i++) {
        switch (proj_norms[i]) {
        case HERMES_H1_NORM:
            form[i][i] = h1_form<double, scalar>;
            ord[i][i] = h1_form<Ord, Ord>;
            //printf("H1 norm.\n");
            break;
        case HERMES_H1_SEMINORM:
            form[i][i] = h1_semi_form<double, scalar>;
            ord[i][i] = h1_semi_form<Ord, Ord>;
            //printf("H1 semi norm.\n");
            break;
        case HERMES_HCURL_NORM:
            form[i][i] = hcurl_form<double, scalar>;
            ord[i][i] = hcurl_form<Ord, Ord>;
            //printf("Hcurl norm.\n");
            break;
        case HERMES_HDIV_NORM:
            form[i][i] = hdiv_form<double, scalar>;
            ord[i][i] = hdiv_form<Ord, Ord>;
            //printf("Hdiv norm.\n");
            break;
        case HERMES_L2_NORM:
            form[i][i] = l2_form<double, scalar>;
            ord[i][i] = l2_form<Ord, Ord>;
            //printf("L2 norm.\n");
            break;
        default:
            error("Unknown projection type in Adapt::Adapt().");
        }
    }
}