예제 #1
0
void PetscSparseStorage::genmult ( double beta,  PetscVector& py,
				   double alpha, PetscVector& px,
				   int trans )
{
  int ierr;
  int my, nx;
  if( trans ) {
    this->getSize( nx, my );
  } else {
    this->getSize( my, nx );
  }

  if( alpha == 0.0 ) {
    py.scale( beta );
  } else {
    if ( alpha != 1.0 || beta != 1.0 ) {
      py.scale( beta/alpha );
    }

    if( trans ) {
      ierr = MatMultTransposeAdd(M, px.pv, py.pv, py.pv ); assert( ierr  == 0);
    } else {
      ierr = MatMultAdd(M, px.pv, py.pv, py.pv ); assert( ierr  == 0);
    }
    if( alpha != 1.0 ) {
      py.scale(alpha);
    }
  }
}
예제 #2
0
std::pair<Real, Real> SlepcEigenSolver<T>::get_eigenpair(unsigned int i,
							 NumericVector<T> &solution_in)
{
  int ierr=0;

  PetscReal re, im;

  // Make sure the NumericVector passed in is really a PetscVector
  PetscVector<T>* solution = libmesh_cast_ptr<PetscVector<T>*>(&solution_in);

  // real and imaginary part of the ith eigenvalue.
  PetscScalar kr, ki;

  solution->close();

  ierr = EPSGetEigenpair(_eps, i, &kr, &ki, solution->vec(), PETSC_NULL);
         LIBMESH_CHKERRABORT(ierr);

#ifdef LIBMESH_USE_COMPLEX_NUMBERS
  re = PetscRealPart(kr);
  im = PetscImaginaryPart(kr);
#else
  re = kr;
  im = ki;
#endif

  return std::make_pair(re, im);
}
  std::pair<unsigned int, Real>
  PetscDMNonlinearSolver<T>::solve (SparseMatrix<T>& jac_in,  // System Jacobian Matrix
				    NumericVector<T>& x_in,   // Solution vector
				    NumericVector<T>& r_in,   // Residual vector
				    const double,             // Stopping tolerance
				    const unsigned int)
  {
    START_LOG("solve()", "PetscNonlinearSolver");
    this->init ();

    // Make sure the data passed in are really of Petsc types
    libmesh_cast_ptr<PetscMatrix<T>*>(&jac_in);
    libmesh_cast_ptr<PetscVector<T>*>(&r_in);

    // Extract solution vector
    PetscVector<T>* x = libmesh_cast_ptr<PetscVector<T>*>(&x_in);

    int ierr=0;
    int n_iterations =0;

    // Should actually be a PetscReal, but I don't know which version of PETSc first introduced PetscReal
    Real final_residual_norm=0.;

    if (this->user_presolve)
      this->user_presolve(this->system());

    //Set the preconditioning matrix
    if (this->_preconditioner)
      this->_preconditioner->set_matrix(jac_in);

    ierr = SNESSolve (this->_snes, PETSC_NULL, x->vec());
    CHKERRABORT(libMesh::COMM_WORLD,ierr);

    ierr = SNESGetIterationNumber(this->_snes,&n_iterations);
    CHKERRABORT(libMesh::COMM_WORLD,ierr);

    ierr = SNESGetLinearSolveIterations(this->_snes, &this->_n_linear_iterations);
    CHKERRABORT(libMesh::COMM_WORLD,ierr);

    ierr = SNESGetFunctionNorm(this->_snes,&final_residual_norm);
    CHKERRABORT(libMesh::COMM_WORLD,ierr);

    // Get and store the reason for convergence
    SNESGetConvergedReason(this->_snes, &this->_reason);

    //Based on Petsc 2.3.3 documentation all diverged reasons are negative
    this->converged = (this->_reason >= 0);

    this->clear();

    STOP_LOG("solve()", "PetscNonlinearSolver");

    // return the # of its. and the final residual norm.
    return std::make_pair(n_iterations, final_residual_norm);
  }
예제 #4
0
 virtual void setupInternal(NumericVector<Number> &X) {
   PetscVector<Number> *pX = cast_ptr<PetscVector<Number> *>(&X);
   PetscErrorCode ierr;
   ierr = TSSetIFunction(this->_ts,PETSC_NULL,this->_computeIFunction,this);
   CHKERRABORT(libMesh::COMM_WORLD,ierr);
   PetscMatrix<Number> *mat = cast_ptr<PetscMatrix<Number> *>(this->_fe_problem.getNonlinearSystem().sys().matrix);
   Mat pmat = mat->mat();
   ierr = TSSetIJacobian(this->_ts,pmat,pmat,this->_computeIJacobian,this);
   CHKERRABORT(libMesh::COMM_WORLD,ierr);
   ierr = TSSetFromOptions(this->_ts);
   CHKERRABORT(libMesh::COMM_WORLD,ierr);
   ierr = TSSetSolution(_ts,pX->vec());
   CHKERRABORT(libMesh::COMM_WORLD,ierr);
 }
예제 #5
0
std::pair<unsigned int, Real>
PetscNonlinearSolver<T>::solve (SparseMatrix<T>&  jac_in,  // System Jacobian Matrix
				NumericVector<T>& x_in,    // Solution vector
				NumericVector<T>& r_in,    // Residual vector
				const double,              // Stopping tolerance
				const unsigned int)
{
  START_LOG("solve()", "PetscNonlinearSolver");
  this->init ();

  // Make sure the data passed in are really of Petsc types
  PetscMatrix<T>* jac = libmesh_cast_ptr<PetscMatrix<T>*>(&jac_in);
  PetscVector<T>* x   = libmesh_cast_ptr<PetscVector<T>*>(&x_in);
  PetscVector<T>* r   = libmesh_cast_ptr<PetscVector<T>*>(&r_in);

  PetscErrorCode ierr=0;
  PetscInt n_iterations =0;
  // Should actually be a PetscReal, but I don't know which version of PETSc first introduced PetscReal
  Real final_residual_norm=0.;

  ierr = SNESSetFunction (_snes, r->vec(), __libmesh_petsc_snes_residual, this);
         LIBMESH_CHKERRABORT(ierr);

   // Only set the jacobian function if we've been provided with something to call.
   // This allows a user to set their own jacobian function if they want to
   if (this->jacobian || this->jacobian_object || this->residual_and_jacobian_object)
   {
     ierr = SNESSetJacobian (_snes, jac->mat(), jac->mat(), __libmesh_petsc_snes_jacobian, this);
     LIBMESH_CHKERRABORT(ierr);
   }
#if !PETSC_VERSION_LESS_THAN(3,3,0)
   // Only set the nullspace if we have a way of computing it and the result is non-empty.
   if (this->nullspace || this->nullspace_object)
   {
     MatNullSpace msp;
     this->build_mat_null_space(this->nullspace_object, this->nullspace, &msp);
     if (msp)
       {
         ierr = MatSetNullSpace(jac->mat(), msp);
         LIBMESH_CHKERRABORT(ierr);

         ierr = MatNullSpaceDestroy(&msp);
         LIBMESH_CHKERRABORT(ierr);
       }
   }

   // Only set the nearnullspace if we have a way of computing it and the result is non-empty.
   if (this->nearnullspace || this->nearnullspace_object)
   {
     MatNullSpace msp = PETSC_NULL;
     this->build_mat_null_space(this->nearnullspace_object, this->nearnullspace, &msp);

     if(msp) {
       ierr = MatSetNearNullSpace(jac->mat(), msp);
       LIBMESH_CHKERRABORT(ierr);

       ierr = MatNullSpaceDestroy(&msp);
       LIBMESH_CHKERRABORT(ierr);
     }
   }
#endif
   // Have the Krylov subspace method use our good initial guess rather than 0
   KSP ksp;
   ierr = SNESGetKSP (_snes, &ksp);
          LIBMESH_CHKERRABORT(ierr);

  // Set the tolerances for the iterative solver.  Use the user-supplied
  // tolerance for the relative residual & leave the others at default values
  ierr = KSPSetTolerances (ksp, this->initial_linear_tolerance, PETSC_DEFAULT,
                           PETSC_DEFAULT, this->max_linear_iterations);
         LIBMESH_CHKERRABORT(ierr);

  // Set the tolerances for the non-linear solver.
  ierr = SNESSetTolerances(_snes, this->absolute_residual_tolerance, this->relative_residual_tolerance,
                           this->relative_step_tolerance, this->max_nonlinear_iterations, this->max_function_evaluations);
         LIBMESH_CHKERRABORT(ierr);

  //Pull in command-line options
  KSPSetFromOptions(ksp);
  SNESSetFromOptions(_snes);

  if (this->user_presolve)
    this->user_presolve(this->system());

  //Set the preconditioning matrix
  if(this->_preconditioner)
  {
    this->_preconditioner->set_matrix(jac_in);
    this->_preconditioner->init();
  }

//    ierr = KSPSetInitialGuessNonzero (ksp, PETSC_TRUE);
//           LIBMESH_CHKERRABORT(ierr);

// Older versions (at least up to 2.1.5) of SNESSolve took 3 arguments,
// the last one being a pointer to an int to hold the number of iterations required.
# if PETSC_VERSION_LESS_THAN(2,2,0)

 ierr = SNESSolve (_snes, x->vec(), &n_iterations);
        LIBMESH_CHKERRABORT(ierr);

// 2.2.x style
#elif PETSC_VERSION_LESS_THAN(2,3,0)

 ierr = SNESSolve (_snes, x->vec());
        LIBMESH_CHKERRABORT(ierr);

// 2.3.x & newer style
#else

  ierr = SNESSolve (_snes, PETSC_NULL, x->vec());
         LIBMESH_CHKERRABORT(ierr);

  ierr = SNESGetIterationNumber(_snes,&n_iterations);
         LIBMESH_CHKERRABORT(ierr);

  ierr = SNESGetLinearSolveIterations(_snes, &_n_linear_iterations);
         LIBMESH_CHKERRABORT(ierr);

  ierr = SNESGetFunctionNorm(_snes,&final_residual_norm);
	 LIBMESH_CHKERRABORT(ierr);

#endif

  // Get and store the reason for convergence
  SNESGetConvergedReason(_snes, &_reason);

  //Based on Petsc 2.3.3 documentation all diverged reasons are negative
  this->converged = (_reason >= 0);

  this->clear();

  STOP_LOG("solve()", "PetscNonlinearSolver");

  // return the # of its. and the final residual norm.
  return std::make_pair(n_iterations, final_residual_norm);
}
예제 #6
0
void
PetscNonlinearSolver<T>::build_mat_null_space(NonlinearImplicitSystem::ComputeVectorSubspace* computeSubspaceObject,
                                              void (*computeSubspace)(std::vector<NumericVector<Number>*>&, sys_type&),
                                              MatNullSpace *msp)
{
  PetscErrorCode ierr;
  std::vector<NumericVector<Number>* > sp;
  if (computeSubspaceObject)
    (*computeSubspaceObject)(sp, this->system());
  else
    (*computeSubspace)(sp, this->system());

  *msp = PETSC_NULL;
  if (sp.size())
    {
      Vec *modes;
      PetscScalar *dots;
      PetscInt nmodes = sp.size();

      ierr = PetscMalloc2(nmodes,Vec,&modes,nmodes,PetscScalar,&dots);
      LIBMESH_CHKERRABORT(ierr);

      for (PetscInt i=0; i<nmodes; ++i)
        {
          PetscVector<T>* pv = libmesh_cast_ptr<PetscVector<T>*>(sp[i]);
          Vec v = pv->vec();

          ierr = VecDuplicate(v, modes+i);
          LIBMESH_CHKERRABORT(ierr);

          ierr = VecCopy(v,modes[i]);
          LIBMESH_CHKERRABORT(ierr);
        }

      // Normalize.
      ierr = VecNormalize(modes[0],PETSC_NULL);
      LIBMESH_CHKERRABORT(ierr);

      for (PetscInt i=1; i<nmodes; i++)
        {
          // Orthonormalize vec[i] against vec[0:i-1]
          ierr = VecMDot(modes[i],i,modes,dots);
          LIBMESH_CHKERRABORT(ierr);

          for (PetscInt j=0; j<i; j++)
            dots[j] *= -1.;

          ierr = VecMAXPY(modes[i],i,dots,modes);
          LIBMESH_CHKERRABORT(ierr);

          ierr = VecNormalize(modes[i],PETSC_NULL);
          LIBMESH_CHKERRABORT(ierr);
        }

      ierr = MatNullSpaceCreate(this->comm().get(), PETSC_FALSE, nmodes, modes, msp);
      LIBMESH_CHKERRABORT(ierr);

      for (PetscInt i=0; i<nmodes; ++i)
        {
          ierr = VecDestroy(modes+i);
          LIBMESH_CHKERRABORT(ierr);
        }

      ierr = PetscFree2(modes,dots);
      LIBMESH_CHKERRABORT(ierr);
    }
}
예제 #7
0
 virtual void interpolate(Real time,NumericVector<Number> &X) {
   PetscVector<Number> *pX = cast_ptr<PetscVector<Number> *>(&X);
   PetscErrorCode ierr;
   ierr = TSInterpolate(this->_ts,time,pX->vec());
   CHKERRABORT(libMesh::COMM_WORLD,ierr);
 }
예제 #8
0
std::pair<unsigned int, Real>
PetscDMNonlinearSolver<T>::solve (SparseMatrix<T>& jac_in,  // System Jacobian Matrix
                                  NumericVector<T>& x_in,   // Solution vector
                                  NumericVector<T>& r_in,   // Residual vector
                                  const double,             // Stopping tolerance
                                  const unsigned int)
{
  START_LOG("solve()", "PetscNonlinearSolver");
  this->init ();

  // Make sure the data passed in are really of Petsc types
  libmesh_cast_ptr<PetscMatrix<T>*>(&jac_in);
  libmesh_cast_ptr<PetscVector<T>*>(&r_in);

  // Extract solution vector
  PetscVector<T>* x = libmesh_cast_ptr<PetscVector<T>*>(&x_in);

  PetscErrorCode ierr=0;
  PetscInt n_iterations =0;


  PetscReal final_residual_norm=0.;

  if (this->user_presolve)
    this->user_presolve(this->system());

  //Set the preconditioning matrix
  if (this->_preconditioner)
    this->_preconditioner->set_matrix(jac_in);

  ierr = SNESSolve (this->_snes, PETSC_NULL, x->vec());
  LIBMESH_CHKERRABORT(ierr);

  ierr = SNESGetIterationNumber(this->_snes,&n_iterations);
  LIBMESH_CHKERRABORT(ierr);

  ierr = SNESGetLinearSolveIterations(this->_snes, &this->_n_linear_iterations);
  LIBMESH_CHKERRABORT(ierr);

#if PETSC_VERSION_LESS_THAN(3,5,0)
  // SNESGetFunctionNorm was removed in PETSc 3.5.0
  ierr = SNESGetFunctionNorm(this->_snes,&final_residual_norm);
  LIBMESH_CHKERRABORT(ierr);
#else
  {
    /* PB: Not sure where r_in is coming from and it's not used here, so we'll
           just get the residual from PETSc */
    Vec r;
    ierr = SNESGetFunction(this->_snes,&r,NULL,NULL);LIBMESH_CHKERRABORT(ierr);
    ierr = VecNorm(r,NORM_2,&final_residual_norm);LIBMESH_CHKERRABORT(ierr);
  }
#endif

  // Get and store the reason for convergence
  SNESGetConvergedReason(this->_snes, &this->_reason);

  //Based on Petsc 2.3.3 documentation all diverged reasons are negative
  this->converged = (this->_reason >= 0);

  this->clear();

  STOP_LOG("solve()", "PetscNonlinearSolver");

  // return the # of its. and the final residual norm.
  return std::make_pair(n_iterations, final_residual_norm);
}