Esempio n. 1
0
bool calc_errors(Hermes::vector<Solution* > left, Hermes::vector<Solution *> right, Hermes::vector<double> & err_abs, Hermes::vector<double> & norm_vals,
                 double & err_abs_total, double & norm_total, double & err_rel_total, Hermes::vector<ProjNormType> norms)
{
  bool default_norms = false;
  // Checks.
  if(left.size() != right.size())
    return false;
  if (norms != Hermes::vector<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;
}
Esempio n. 2
0
QList<SolutionArray *> SolutionAgros::solveSolutioArray(Hermes::vector<EssentialBCs> bcs)
{
    QTime time;

    // solution agros array
    QList<SolutionArray *> solutionArrayList;

    // load the mesh file
    mesh = readMeshFromFile(tempProblemFileName() + ".mesh");
    refineMesh(mesh, true, true);

    // create an H1 space
    Hermes::vector<Space *> space;
    // create hermes solution array
    Hermes::vector<Solution *> solution;
    // create reference solution
    Hermes::vector<Solution *> solutionReference;

    // projection norms
    Hermes::vector<ProjNormType> projNormType;

    // prepare selector
    Hermes::vector<RefinementSelectors::Selector *> selector;

    // error marker
    bool isError = false;

    RefinementSelectors::Selector *select = NULL;
    switch (adaptivityType)
    {
    case AdaptivityType_H:
        select = new RefinementSelectors::HOnlySelector();
        break;
    case AdaptivityType_P:
        select = new RefinementSelectors::H1ProjBasedSelector(RefinementSelectors::H2D_P_ANISO,
                                                              Util::config()->convExp,
                                                              H2DRS_DEFAULT_ORDER);
        break;
    case AdaptivityType_HP:
        select = new RefinementSelectors::H1ProjBasedSelector(RefinementSelectors::H2D_HP_ANISO,
                                                              Util::config()->convExp,
                                                              H2DRS_DEFAULT_ORDER);
        break;
    }

    for (int i = 0; i < numberOfSolution; i++)
    {
        space.push_back(new H1Space(mesh, &bcs[i], polynomialOrder));

        // set order by element
        for (int j = 0; j < Util::scene()->labels.count(); j++)
            if (Util::scene()->labels[j]->material != Util::scene()->materials[0])
                space.at(i)->set_uniform_order(Util::scene()->labels[j]->polynomialOrder > 0 ? Util::scene()->labels[j]->polynomialOrder : polynomialOrder,
                                               QString::number(j).toStdString());

        // solution agros array
        solution.push_back(new Solution());

        if (adaptivityType != AdaptivityType_None)
        {
            // add norm
            projNormType.push_back(Util::config()->projNormType);
            // add refinement selector
            selector.push_back(select);
            // reference solution
            solutionReference.push_back(new Solution());
        }
    }

    // check for DOFs
    if (Space::get_num_dofs(space) == 0)
    {
        m_progressItemSolve->emitMessage(QObject::tr("DOF is zero"), true);
    }
    else
    {
        for (int i = 0; i < numberOfSolution; i++)
        {
            // transient
            if (analysisType == AnalysisType_Transient)
            {
                // constant initial solution
                solution.at(i)->set_const(mesh, initialCondition);
                solutionArrayList.append(solutionArray(solution.at(i)));
            }

            // nonlinear
            if ((linearityType != LinearityType_Linear) && (analysisType != AnalysisType_Transient))
            {
                solution.at(i)->set_const(mesh, 0.0);
            }
        }

        actualTime = 0.0;

        // update time function
        Util::scene()->problemInfo()->hermes()->updateTimeFunctions(actualTime);

        m_wf->set_current_time(actualTime);
        m_wf->solution = solution;
        m_wf->delete_all();
        m_wf->registerForms();

        // emit message
        if (adaptivityType != AdaptivityType_None)
            m_progressItemSolve->emitMessage(QObject::tr("Adaptivity type: %1").arg(adaptivityTypeString(adaptivityType)), false);

        double error = 0.0;

        // solution
        int maxAdaptivitySteps = (adaptivityType == AdaptivityType_None) ? 1 : adaptivitySteps;
        int actualAdaptivitySteps = -1;
        for (int i = 0; i<maxAdaptivitySteps; i++)
        {
            // set up the solver, matrix, and rhs according to the solver selection.
            SparseMatrix *matrix = create_matrix(matrixSolver);
            Vector *rhs = create_vector(matrixSolver);
            Solver *solver = create_linear_solver(matrixSolver, matrix, rhs);

            if (adaptivityType == AdaptivityType_None)
            {
                if (analysisType != AnalysisType_Transient)
                    solve(space, solution, solver, matrix, rhs);
            }
            else
            {
                // construct globally refined reference mesh and setup reference space.
                Hermes::vector<Space *> spaceReference = *Space::construct_refined_spaces(space);

                // assemble reference problem.
                solve(spaceReference, solutionReference, solver, matrix, rhs);

                if (!isError)
                {
                    // project the fine mesh solution onto the coarse mesh.
                    OGProjection::project_global(space, solutionReference, solution, matrixSolver);

                    // Calculate element errors and total error estimate.
                    Adapt adaptivity(space, projNormType);

                    // Calculate error estimate for each solution component and the total error estimate.
                    error = adaptivity.calc_err_est(solution,
                                                    solutionReference) * 100;

                    // emit signal
                    m_progressItemSolve->emitMessage(QObject::tr("Adaptivity rel. error (step: %2/%3, DOFs: %4/%5): %1%").
                                                     arg(error, 0, 'f', 3).
                                                     arg(i + 1).
                                                     arg(maxAdaptivitySteps).
                                                     arg(Space::get_num_dofs(space)).
                                                     arg(Space::get_num_dofs(spaceReference)), false, 1);
                    // add error to the list
                    m_progressItemSolve->addAdaptivityError(error, Space::get_num_dofs(space));

                    if (error < adaptivityTolerance || Space::get_num_dofs(space) >= adaptivityMaxDOFs)
                    {
                        break;
                    }
                    if (i != maxAdaptivitySteps-1) adaptivity.adapt(selector,
                                                                    Util::config()->threshold,
                                                                    Util::config()->strategy,
                                                                    Util::config()->meshRegularity);
                    actualAdaptivitySteps = i+1;
                }

                if (m_progressItemSolve->isCanceled())
                {
                    isError = true;
                    break;
                }

                // delete reference space
                for (int i = 0; i < spaceReference.size(); i++)
                {
                    delete spaceReference.at(i)->get_mesh();
                    delete spaceReference.at(i);
                }
                spaceReference.clear();
            }

            // clean up.
            delete solver;
            delete matrix;
            delete rhs;
        }

        // delete reference solution
        for (int i = 0; i < solutionReference.size(); i++)
            delete solutionReference.at(i);
        solutionReference.clear();

        // delete selector
        if (select) delete select;
        selector.clear();

        // timesteps
        if (!isError)
        {
            SparseMatrix *matrix = NULL;
            Vector *rhs = NULL;
            Solver *solver = NULL;

            // allocate dp for transient solution
            DiscreteProblem *dpTran = NULL;
            if (analysisType == AnalysisType_Transient)
            {
                // set up the solver, matrix, and rhs according to the solver selection.
                matrix = create_matrix(matrixSolver);
                rhs = create_vector(matrixSolver);
                solver = create_linear_solver(matrixSolver, matrix, rhs);
                // solver->set_factorization_scheme(HERMES_REUSE_FACTORIZATION_COMPLETELY);

                dpTran = new DiscreteProblem(m_wf, space, true);
            }

            int timesteps = (analysisType == AnalysisType_Transient) ? floor(timeTotal/timeStep) : 1;
            for (int n = 0; n<timesteps; n++)
            {
                // set actual time
                actualTime = (n+1)*timeStep;

                // update essential bc values
                Space::update_essential_bc_values(space, actualTime);
                // update timedep values
                Util::scene()->problemInfo()->hermes()->updateTimeFunctions(actualTime);

                m_wf->set_current_time(actualTime);
                m_wf->delete_all();
                m_wf->registerForms();

                // transient
                if ((timesteps > 1) && (linearityType == LinearityType_Linear))
                    isError = !solveLinear(dpTran, space, solution,
                                           solver, matrix, rhs);
                if ((timesteps > 1) && (linearityType != LinearityType_Linear))
                    isError = !solve(space, solution,
                                     solver, matrix, rhs);

                // output
                for (int i = 0; i < numberOfSolution; i++)
                {
                    solutionArrayList.append(solutionArray(solution.at(i), space.at(i), error, actualAdaptivitySteps, (n+1)*timeStep));
                }

                if (analysisType == AnalysisType_Transient)
                    m_progressItemSolve->emitMessage(QObject::tr("Transient time step (%1/%2): %3 s").
                                                     arg(n+1).
                                                     arg(timesteps).
                                                     arg(actualTime, 0, 'e', 2), false, n+2);
                if (m_progressItemSolve->isCanceled())
                {
                    isError = true;
                    break;
                }
            }

            // clean up
            if (solver) delete solver;
            if (matrix) delete matrix;
            if (rhs) delete rhs;

            if (dpTran) delete dpTran;
        }
    }
    // delete mesh
    delete mesh;

    // delete space
    for (unsigned int i = 0; i < space.size(); i++)
    {
        // delete space.at(i)->get_mesh();
        delete space.at(i);
    }
    space.clear();

    // delete last solution
    for (unsigned int i = 0; i < solution.size(); i++)
        delete solution.at(i);
    solution.clear();

    if (isError)
    {
        for (int i = 0; i < solutionArrayList.count(); i++)
            delete solutionArrayList.at(i);
        solutionArrayList.clear();
    }
    return solutionArrayList;
}
Esempio n. 3
0
int main() 
{
  // Create space, set Dirichlet BC, enumerate basis functions.
  Space* space = new Space(A, B, NELEM, DIR_BC_LEFT, Hermes::vector<BCSpec *>(), P_INIT, NEQ, NEQ);
 
  // Enumerate basis functions, info for user.
  int ndof = Space::get_num_dofs(space);
  info("ndof: %d", ndof);

  // Initialize the weak formulation.
  WeakForm wf(2);
  wf.add_matrix_form(0, 0, jacobian_0_0);
  wf.add_matrix_form(0, 1, jacobian_0_1);
  wf.add_matrix_form(1, 0, jacobian_1_0);
  wf.add_matrix_form(1, 1, jacobian_1_1);
  wf.add_vector_form(0, residual_0);
  wf.add_vector_form(1, residual_1);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  // Cleanup.
  for(unsigned i = 0; i < DIR_BC_LEFT.size(); i++)
      delete DIR_BC_LEFT[i];
  DIR_BC_LEFT.clear();

  for(unsigned i = 0; i < DIR_BC_RIGHT.size(); i++)
      delete DIR_BC_RIGHT[i];
  DIR_BC_RIGHT.clear();

  delete matrix;
  delete rhs;
  delete solver;
  delete[] coeff_vec;
  delete dp;
  delete space;

  info("Done.");
  return 0;
}
Esempio n. 4
0
    void WeakForm<Scalar>::get_stages(Hermes::vector<const Space<Scalar> *> spaces, Hermes::vector<Solution<Scalar> *>& u_ext,
      Hermes::vector<Stage<Scalar> >& stages, bool want_matrix, bool want_vector, bool one_stage) const
    {
      _F_;

      if (!want_matrix && !want_vector) return;

      unsigned int i;
      stages.clear();

      if (want_matrix || want_vector)
      {
        // This is because of linear problems where
        // matrix terms with the Dirichlet lift go to rhs.
        // Process volume matrix forms.
        for (i = 0; i < mfvol.size(); i++)
        {
          unsigned int ii = mfvol[i]->i, jj = mfvol[i]->j;
          Mesh* m1 = spaces[ii]->get_mesh();
          Mesh* m2 = spaces[jj]->get_mesh();
          Stage<Scalar>* s = find_stage(stages, ii, jj, m1, m2, mfvol[i]->ext, u_ext, one_stage);
          s->mfvol.push_back(mfvol[i]);
        }

        // Process surface matrix forms.
        for (i = 0; i < mfsurf.size(); i++)
        {
          unsigned int ii = mfsurf[i]->i, jj = mfsurf[i]->j;
          Mesh* m1 = spaces[ii]->get_mesh();
          Mesh* m2 = spaces[jj]->get_mesh();
          Stage<Scalar>* s = find_stage(stages, ii, jj, m1, m2, mfsurf[i]->ext, u_ext, one_stage);
          s->mfsurf.push_back(mfsurf[i]);
        }

        // Multi component forms.
        for (unsigned i = 0; i < mfvol_mc.size(); i++)
        {
          Mesh* the_one_mesh = spaces[mfvol_mc.at(i)->coordinates.at(0).first]->get_mesh();
          for(unsigned int form_i = 0; form_i < mfvol_mc.at(i)->coordinates.size(); form_i++)
          {
            if(spaces[mfvol_mc.at(i)->coordinates.at(form_i).first]->get_mesh()->get_seq() != the_one_mesh->get_seq())
              error("When using multi-component forms, the Meshes have to be identical.");
            if(spaces[mfvol_mc.at(i)->coordinates.at(form_i).second]->get_mesh()->get_seq() != the_one_mesh->get_seq())
              error("When using multi-component forms, the Meshes have to be identical.");
          }

          Stage<Scalar>* s = find_stage(stages, mfvol_mc.at(i)->coordinates, the_one_mesh, the_one_mesh, mfvol_mc[i]->ext, u_ext, one_stage);
          s->mfvol_mc.push_back(mfvol_mc[i]);
        }
        for (unsigned i = 0; i < mfsurf_mc.size(); i++)
        {
          Mesh* the_one_mesh = spaces[mfsurf_mc.at(i)->coordinates.at(0).first]->get_mesh();
          for(unsigned int form_i = 0; form_i < mfsurf_mc.at(i)->coordinates.size(); form_i++)
          {
            if(spaces[mfsurf_mc.at(i)->coordinates.at(form_i).first]->get_mesh()->get_seq() != the_one_mesh->get_seq())
              error("When using multi-component forms, the Meshes have to be identical.");
            if(spaces[mfsurf_mc.at(i)->coordinates.at(form_i).second]->get_mesh()->get_seq() != the_one_mesh->get_seq())
              error("When using multi-component forms, the Meshes have to be identical.");
          }

          Stage<Scalar>* s = find_stage(stages, mfsurf_mc.at(i)->coordinates, the_one_mesh, the_one_mesh, mfsurf_mc[i]->ext, u_ext, one_stage);
          s->mfsurf_mc.push_back(mfsurf_mc[i]);
        }
      }
      if (want_vector)
      {
        // Process volume vector forms.
        for (unsigned i = 0; i < vfvol.size(); i++)
        {
          unsigned int ii = vfvol[i]->i;
          Mesh *m = spaces[ii]->get_mesh();
          Stage<Scalar>*s = find_stage(stages, ii, ii, m, m, vfvol[i]->ext, u_ext, one_stage);
          s->vfvol.push_back(vfvol[i]);
        }

        // Process surface vector forms.
        for (unsigned i = 0; i < vfsurf.size(); i++)
        {
          unsigned int ii = vfsurf[i]->i;
          Mesh *m = spaces[ii]->get_mesh();
          Stage<Scalar>*s = find_stage(stages, ii, ii, m, m, vfsurf[i]->ext, u_ext, one_stage);
          s->vfsurf.push_back(vfsurf[i]);
        }

        // Multi component forms.
        for (unsigned i = 0; i < vfvol_mc.size(); i++)
        {
          Mesh* the_one_mesh = spaces[vfvol_mc.at(i)->coordinates.at(0)]->get_mesh();
          for(unsigned int form_i = 0; form_i < vfvol_mc.at(i)->coordinates.size(); form_i++)
            if(spaces[vfvol_mc.at(i)->coordinates.at(form_i)]->get_mesh()->get_seq() != the_one_mesh->get_seq())
              error("When using multi-component forms, the Meshes have to be identical.");

          Stage<Scalar>*s = find_stage(stages, vfvol_mc.at(i)->coordinates, the_one_mesh, the_one_mesh, vfvol_mc[i]->ext, u_ext, one_stage);
          s->vfvol_mc.push_back(vfvol_mc[i]);
        }

        for (unsigned i = 0; i < vfsurf_mc.size(); i++)
        {
          Mesh* the_one_mesh = spaces[vfsurf_mc.at(i)->coordinates.at(0)]->get_mesh();
          for(unsigned int form_i = 0; form_i < vfsurf_mc.at(i)->coordinates.size(); form_i++)
            if(spaces[vfsurf_mc.at(i)->coordinates.at(form_i)]->get_mesh()->get_seq() != the_one_mesh->get_seq())
              error("When using multi-component forms, the Meshes have to be identical.");

          Stage<Scalar>*s = find_stage(stages, vfsurf_mc.at(i)->coordinates, the_one_mesh, the_one_mesh, vfsurf_mc[i]->ext, u_ext, one_stage);
          s->vfsurf_mc.push_back(vfsurf_mc[i]);
        }
      }

      // Helper macro for iterating in a set,
#define set_for_each(myset, type) \
  for (typename std::set<type>::iterator it = (myset).begin(); it != (myset).end(); it++)

      // Initialize the arrays meshes and fns needed by Traverse for each stage.
      for (i = 0; i < stages.size(); i++)
      {
        Stage<Scalar>* s = &stages[i];

        // First, initialize arrays for the test functions. A pointer to the PrecalcShapeset
        // corresponding to each space will be assigned to s->fns later during assembling.
        set_for_each(s->idx_set, int)
        {
          s->idx.push_back(*it);
          s->meshes.push_back(spaces[*it]->get_mesh());
          s->fns.push_back(NULL);
        }

        // Next, append to the existing arrays the external functions (including the solutions
        // from previous Newton iteration) and their meshes. Also fill in a special array with
        // these external functions only.
        set_for_each(s->ext_set, MeshFunction<Scalar>*)
        {
          s->ext.push_back(*it);
          s->meshes.push_back((*it)->get_mesh());
          s->fns.push_back(*it);
        }

        s->idx_set.clear();
        s->seq_set.clear();
        s->ext_set.clear();
      }
    }