Exemplo n.º 1
0
//-----------------------------------------------------------------------------
void SLEPcEigenSolver::get_eigenpair(double& lr, double& lc,
                                     PETScVector& r, PETScVector& c,
                                     std::size_t i) const
{
  const dolfin::la_index ii = static_cast<dolfin::la_index>(i);

  // Get number of computed eigenvectors/values
  dolfin::la_index num_computed_eigenvalues;
  EPSGetConverged(_eps, &num_computed_eigenvalues);

  if (ii < num_computed_eigenvalues)
  {
    dolfin_assert(_matA);
    _matA->init_vector(r, 0);
    _matA->init_vector(c, 0);

    dolfin_assert(r.vec());
    dolfin_assert(c.vec());
    EPSGetEigenpair(_eps, ii, &lr, &lc, r.vec(), c.vec());
  }
  else
  {
    dolfin_error("SLEPcEigenSolver.cpp",
                 "extract eigenpair from SLEPc eigenvalue solver",
                 "Requested eigenpair (%d) has not been computed", i);
  }
}
Exemplo n.º 2
0
void setVector(PETScVector& v,
               std::initializer_list<double> values)
{
    std::vector<double> const vals(values);
    std::vector<PETScVector::IndexType> idcs(vals.size());
    std::iota(idcs.begin(), idcs.end(), 0);

    v.set(idcs, vals);
}
Exemplo n.º 3
0
void PETScVector::shallowCopy(const PETScVector &v)
{
    destroy();

    VecDuplicate(v.getRawVector(), &_v);

    _start_rank   = v._start_rank;
    _end_rank     = v._end_rank;
    _size         = v._size;
    _size_loc     = v._size_loc;
    _size_ghosts  = v._size_ghosts;
    _has_ghost_id = v._has_ghost_id;

    VecSetOption(_v, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE);
}
Exemplo n.º 4
0
void applyKnownSolution(PETScMatrix &A, PETScVector &b, PETScVector &x,
                        const std::vector<PetscInt>  &vec_knownX_id,
                        const std::vector<PetscScalar> &vec_knownX_x)
{
    A.finalizeAssembly();

    A.setRowsColumnsZero(vec_knownX_id);
    A.finalizeAssembly();

    x.finalizeAssembly();
    b.finalizeAssembly();
    if(vec_knownX_id.size() > 0)
    {
        x.set(vec_knownX_id, vec_knownX_x);
        b.set(vec_knownX_id, vec_knownX_x);
    }

    x.finalizeAssembly();
    b.finalizeAssembly();
}
Exemplo n.º 5
0
//-----------------------------------------------------------------------------
void SLEPcEigenSolver::get_eigenpair(double& lr, double& lc,
                                     PETScVector& r, PETScVector& c,
                                     std::size_t i) const
{
  dolfin_assert(_eps);
  const PetscInt ii = static_cast<PetscInt>(i);

  // Get number of computed eigenvectors/values
  PetscInt num_computed_eigenvalues;
  EPSGetConverged(_eps, &num_computed_eigenvalues);

  if (ii < num_computed_eigenvalues)
  {
    dolfin_assert(_eps);

    if (r.empty() or c.empty())
    {
      // Get operators
      Mat A, B;
      EPSGetOperators(_eps, &A, &B);

      // Wrap operator and initialize r and c
      PETScMatrix A_wrapped(A);
      if (r.empty())
        A_wrapped.init_vector(r, 0);
      if (c.empty())
        A_wrapped.init_vector(c, 0);
    }

    // Get eigen pairs
    EPSGetEigenpair(_eps, ii, &lr, &lc, r.vec(), c.vec());
  }
  else
  {
    dolfin_error("SLEPcEigenSolver.cpp",
                 "extract eigenpair from SLEPc eigenvalue solver",
                 "Requested eigenpair (%d) has not been computed", i);
  }
}
Exemplo n.º 6
0
void finalizeVectorAssembly(PETScVector &vec)
{
    vec.finalizeAssembly();
}
Exemplo n.º 7
0
bool SAMpatchPETSc::expandSolution(const SystemVector& solVec,
                                   Vector& dofVec, Real scaleSD) const
{
  PETScVector* Bptr = const_cast<PETScVector*>(dynamic_cast<const PETScVector*>(&solVec));
  if (!Bptr)
    return false;

#ifdef HAVE_MPI
  if (adm.isParallel()) {
    if (!glob2LocEq) {
      std::vector<int> mlgeq(adm.dd.getMLGEQ());
      for (auto& it : mlgeq)
        --it;

      ISCreateGeneral(*adm.getCommunicator(),adm.dd.getMLGEQ().size(),
                      mlgeq.data(), PETSC_COPY_VALUES, &glob2LocEq);
    }

    Vec solution;
    VecCreateSeq(PETSC_COMM_SELF, Bptr->dim(), &solution);
    VecScatter ctx;
    VecScatterCreate(Bptr->getVector(), glob2LocEq, solution, nullptr, &ctx);
    VecScatterBegin(ctx, Bptr->getVector(), solution, INSERT_VALUES, SCATTER_FORWARD);
    VecScatterEnd(ctx, Bptr->getVector(),solution,INSERT_VALUES,SCATTER_FORWARD);
    VecScatterDestroy(&ctx);
    PetscScalar* data;
    VecGetArray(solution, &data);
    std::copy(data, data + Bptr->dim(), Bptr->getPtr());
    VecDestroy(&solution);
  } else
#endif
  {
    PetscScalar* data;
    VecGetArray(Bptr->getVector(), &data);
    std::copy(data, data + Bptr->dim(), Bptr->getPtr());
    VecRestoreArray(Bptr->getVector(), &data);
  }

  return this->SAMpatch::expandSolution(solVec, dofVec, scaleSD);
}
Exemplo n.º 8
0
//-----------------------------------------------------------------------------
std::size_t TAOLinearBoundSolver::solve(const PETScMatrix& A1,
                                        PETScVector& x,
					const PETScVector& b1,
                                        const PETScVector& xl,
					const PETScVector& xu)
{

  // Check symmetry
  dolfin_assert(A1.size(0) == A1.size(1));

  // Set operators (A and b)
  std::shared_ptr<const PETScMatrix> _matA(&A1, NoDeleter());
  std::shared_ptr<const PETScVector> _b(&b1, NoDeleter());
  set_operators(_matA,_b);
  dolfin_assert(A->mat());
  //dolfin_assert(b->vec());

  // Set initial vector
  dolfin_assert(_tao);
  TaoSetInitialVector(_tao, x.vec());

  // Set the bound on the variables
  TaoSetVariableBounds(_tao, xl.vec(), xu.vec());

  // Set the user function, gradient, hessian evaluation routines and
  // data structures
  TaoSetObjectiveAndGradientRoutine(_tao,
                                    __TAOFormFunctionGradientQuadraticProblem,
                                    this);
  TaoSetHessianRoutine(_tao, A->mat(), A->mat(),
                       __TAOFormHessianQuadraticProblem, this);

  // Set parameters from local parameters, including ksp parameters
  read_parameters();

  // Clear previous monitors
  TaoCancelMonitors(_tao);

  // Set the monitor
  if (parameters["monitor_convergence"])
    TaoSetMonitor(_tao, __TAOMonitor, this, PETSC_NULL);


  // Check for any tao command line options
  std::string prefix = std::string(parameters["options_prefix"]);
  if (prefix != "default")
  {
    // Make sure that the prefix has a '_' at the end if the user
    // didn't provide it
    char lastchar = *prefix.rbegin();
    if (lastchar != '_')
      prefix += "_";

    TaoSetOptionsPrefix(_tao, prefix.c_str());
  }
  TaoSetFromOptions(_tao);

  // Solve the bound constrained problem
  Timer timer("TAO solver");
  const char* tao_type;
  TaoGetType(_tao, &tao_type);
  log(PROGRESS, "Tao solver %s starting to solve %i x %i system", tao_type,
      A->size(0), A->size(1));

  // Solve
  TaoSolve(_tao);

  // Update ghost values
  x.update_ghost_values();

  // Print the report on convergences and methods used
  if (parameters["report"])
    TaoView(_tao, PETSC_VIEWER_STDOUT_WORLD);

  // Check for convergence
  TaoConvergedReason reason;
  TaoGetConvergedReason(_tao, &reason);

  // Get the number of iterations
  PetscInt num_iterations = 0;
  TaoGetMaximumIterations(_tao, &num_iterations);

  // Report number of iterations
  if (reason >= 0)
    log(PROGRESS, "Tao solver converged\n");
  else
  {
    bool error_on_nonconvergence = parameters["error_on_nonconvergence"];
    if (error_on_nonconvergence)
    {
      TaoView(_tao, PETSC_VIEWER_STDOUT_WORLD);
      dolfin_error("TAOLinearBoundSolver.cpp",
                   "solve linear system using Tao solver",
                   "Solution failed to converge in %i iterations (TAO reason %d)",
                   num_iterations, reason);
    }
    else
    {
      log(WARNING,  "Tao solver %s failed to converge. Try a different TAO method," \
	  " adjust some parameters", tao_type);
    }
  }

  return num_iterations;
}
Exemplo n.º 9
0
void setVector(PETScVector& v, MatrixVectorTraits<PETScVector>::Index const index,
               double const value)
{
    v.set(index, value); // TODO handle negative indices
}
Exemplo n.º 10
0
bool PETScLinearSolver::solve(PETScMatrix& A, PETScVector& b, PETScVector& x)
{
    BaseLib::RunTime wtimer;
    wtimer.start();

// define TEST_MEM_PETSC
#ifdef TEST_MEM_PETSC
    PetscLogDouble mem1, mem2;
    PetscMemoryGetCurrentUsage(&mem1);
#endif

#if (PETSC_VERSION_NUMBER > 3040)
    KSPSetOperators(_solver, A.getRawMatrix(), A.getRawMatrix());
#else
    KSPSetOperators(_solver, A.getRawMatrix(), A.getRawMatrix(),
                    DIFFERENT_NONZERO_PATTERN);
#endif

    KSPSolve(_solver, b.getRawVector(), x.getRawVector());

    KSPConvergedReason reason;
    KSPGetConvergedReason(_solver, &reason);

    bool converged = true;
    if (reason > 0)
    {
        const char* ksp_type;
        const char* pc_type;
        KSPGetType(_solver, &ksp_type);
        PCGetType(_pc, &pc_type);

        PetscPrintf(PETSC_COMM_WORLD,
                    "\n================================================");
        PetscPrintf(PETSC_COMM_WORLD,
                    "\nLinear solver %s with %s preconditioner", ksp_type,
                    pc_type);

        PetscInt its;
        KSPGetIterationNumber(_solver, &its);
        PetscPrintf(PETSC_COMM_WORLD, "\nconverged in %d iterations", its);
        switch (reason)
        {
            case KSP_CONVERGED_RTOL:
                PetscPrintf(PETSC_COMM_WORLD,
                            " (relative convergence criterion fulfilled).");
                break;
            case KSP_CONVERGED_ATOL:
                PetscPrintf(PETSC_COMM_WORLD,
                            " (absolute convergence criterion fulfilled).");
                break;
            default:
                PetscPrintf(PETSC_COMM_WORLD, ".");
        }

        PetscPrintf(PETSC_COMM_WORLD,
                    "\n================================================\n");
    }
    else if (reason == KSP_DIVERGED_ITS)
    {
        const char* ksp_type;
        const char* pc_type;
        KSPGetType(_solver, &ksp_type);
        PCGetType(_pc, &pc_type);
        PetscPrintf(PETSC_COMM_WORLD,
                    "\nLinear solver %s with %s preconditioner", ksp_type,
                    pc_type);
        PetscPrintf(PETSC_COMM_WORLD,
                    "\nWarning: maximum number of iterations reached.\n");
    }
    else
    {
        converged = false;
        if (reason == KSP_DIVERGED_INDEFINITE_PC)
        {
            PetscPrintf(PETSC_COMM_WORLD,
                        "\nDivergence because of indefinite preconditioner,");
            PetscPrintf(PETSC_COMM_WORLD,
                        "\nTry to run again with "
                        "-pc_factor_shift_positive_definite option.\n");
        }
        else if (reason == KSP_DIVERGED_BREAKDOWN_BICG)
        {
            PetscPrintf(PETSC_COMM_WORLD,
                        "\nKSPBICG method was detected so the method could not "
                        "continue to enlarge the Krylov space.");
            PetscPrintf(PETSC_COMM_WORLD,
                        "\nTry to run again with another solver.\n");
        }
        else if (reason == KSP_DIVERGED_NONSYMMETRIC)
        {
            PetscPrintf(PETSC_COMM_WORLD,
                        "\nMatrix or preconditioner is unsymmetric but KSP "
                        "requires symmetric.\n");
        }
        else
        {
            PetscPrintf(PETSC_COMM_WORLD,
                        "\nDivergence detected, use command option "
                        "-ksp_monitor or -log_summary to check the details.\n");
        }
    }

#ifdef TEST_MEM_PETSC
    PetscMemoryGetCurrentUsage(&mem2);
    PetscPrintf(
        PETSC_COMM_WORLD,
        "###Memory usage by solver. Before: %f After: %f Increase: %d\n", mem1,
        mem2, (int)(mem2 - mem1));
#endif

    _elapsed_ctime += wtimer.elapsed();

    return converged;
}
Exemplo n.º 11
0
//-----------------------------------------------------------------------------
void SLEPcEigenSolver::set_deflation_space(const PETScVector& deflation_space)
{
  Vec x = deflation_space.vec();
  EPSSetDeflationSpace(_eps, 1, &x);
}
Exemplo n.º 12
0
int main()
{
  #ifdef HAS_PETSC
  // Create mesh and function space
  auto mesh = std::make_shared<UnitSquareMesh>(128, 128);
  auto V = std::make_shared<Poisson::FunctionSpace>(mesh);

  // Define variational problem
  Poisson::BilinearForm a(V, V);
  Poisson::LinearForm L(V);
  auto f = std::make_shared<Source>();
  auto g = std::make_shared<Flux>();
  L.f = f;
  L.g = g;

  // Assemble system
  auto A = std::make_shared<PETScMatrix>();
  PETScVector b;
  assemble(*A, a);
  assemble(b, L);

  // Create constant vector that spans null space (normalised)
  auto null_space_vector = b.copy();
  *null_space_vector = sqrt(1.0/null_space_vector->size());

  // Create null space basis object and attach to PETSc matrix
  VectorSpaceBasis null_space({null_space_vector});
  A->set_nullspace(null_space);

  // Orthogonalize b with respect to the null space (this gurantees
  // that a solution exists)
  null_space.orthogonalize(b);

  // Set PETSc solve type (conjugate gradient) and preconditioner
  // (algebraic multigrid)
  PETScOptions::set("ksp_type", "cg");
  PETScOptions::set("pc_type", "gamg");

  // Since we have a singular problem, use SVD solver on the multigrid
  // 'coarse grid'
  PETScOptions::set("mg_coarse_ksp_type", "preonly");
  PETScOptions::set("mg_coarse_pc_type", "svd");

  // Set the solver tolerance
  PETScOptions::set("ksp_rtol", 1.0e-8);

  // Print PETSc solver configuration
  PETScOptions::set("ksp_view");
  PETScOptions::set("ksp_monitor");

  // Create PETSc Krylov solver and attach operator
  PETScKrylovSolver solver;
  solver.set_operator(A);

  // Set PETSc options on the solver
  solver.set_from_options();

  // Create solution Function
  Function u(V);

  // Solve
  solver.solve(*u.vector(), b);

  // Check residual
  Vector residual(*u.vector());
  A->mult(*u.vector(), residual);
  residual.axpy(-1.0, b);
  info("Norm of residual: %lf", residual.norm("l2"));

  // Write out solution to XDMF file.
  XDMFFile("u.xdmf").write(u);

  #else
  cout << "This demo requires DOLFIN to be confugured with PETSc." << endl;
  #endif

  return 0;
}