1#ifndef DUNE_FEM_PETSCINVERSEOPERATORS_HH 
    2#define DUNE_FEM_PETSCINVERSEOPERATORS_HH 
    6#include <dune/fem/function/common/scalarproducts.hh> 
    7#include <dune/fem/operator/common/operator.hh> 
    8#include <dune/fem/io/parameter.hh> 
    9#include <dune/fem/solver/inverseoperatorinterface.hh> 
   13#include <dune/fem/operator/linear/petscoperator.hh> 
   14#include <dune/fem/misc/petsc/petsccommon.hh> 
   15#include <dune/fem/function/petscdiscretefunction.hh> 
   16#include <dune/fem/solver/parameter.hh> 
   17#include <dune/fem/solver/petscavailable.hh> 
   35    template< 
class DF, 
class Op = Dune::Fem::Operator< DF, DF > >
 
   36    class PetscInverseOperator;
 
   38    template <
class DF, 
class Op >
 
   39    struct PetscInverseOperatorTraits
 
   42      typedef typename DF :: DiscreteFunctionSpaceType 
SpaceType ;
 
   45      typedef Op                                   OperatorType;
 
   46      typedef OperatorType                         PreconditionerType;
 
   47      typedef PetscDiscreteFunction< SpaceType >   SolverDiscreteFunctionType;
 
   48      typedef PetscLinearOperator< DF, DF >        AssembledOperatorType;
 
   50      typedef PetscSolverParameter                 SolverParameterType;
 
   55    template< 
class DF, 
class Op >
 
   56    class PetscInverseOperator
 
   57    : 
public InverseOperatorInterface< PetscInverseOperatorTraits< DF, Op > >,
 
   58      public PetscInverseOperatorAvailable
 
   63      monitor (KSP ksp, PetscInt it, PetscReal rnorm, 
void *mctx)
 
   67          std::cout << 
"PETSc::KSP:  it = " 
   68                    << std::setw(3) << std::left << it
 
   69                    << 
"   res = " << rnorm << std::endl;
 
   71        return PetscErrorCode(0);
 
   77        void operator() ( KSP* p )
 const 
   82          ::Dune::Petsc::KSPDestroy( p );
 
   87      typedef PetscInverseOperatorTraits< DF, Op > Traits;
 
   88      typedef InverseOperatorInterface< Traits > BaseType;
 
   89      friend class InverseOperatorInterface< Traits >;
 
   91      using PetscInverseOperatorAvailable::PetscSolver;
 
   94      using PetscInverseOperatorAvailable::supportedSolverMethods;
 
   95      using PetscInverseOperatorAvailable::supportedPreconditionMethods;
 
   96      using PetscInverseOperatorAvailable::extraPreconditionMethods;
 
  101      static const bool preconditioningAvailable = 
false;
 
  103      typedef typename BaseType :: SolverDiscreteFunctionType    PetscDiscreteFunctionType;
 
  104      typedef typename BaseType :: OperatorType                  OperatorType;
 
  105      typedef typename BaseType :: PreconditionerType            PreconditionerType;
 
  107      PetscInverseOperator ( 
const PetscSolverParameter ¶meter = PetscSolverParameter(Parameter::container()) )
 
  108      : BaseType( parameter )
 
  111      PetscInverseOperator (  
const OperatorType &op, 
const PetscSolverParameter ¶meter = PetscSolverParameter(Parameter::container()) )
 
  112      : BaseType( parameter )
 
  117      void bind ( 
const OperatorType &op )
 
  119        BaseType :: bind( op );
 
  120        initialize( *parameter_ );
 
  123      void bind ( 
const OperatorType &op, 
const PreconditionerType& p )
 
  125        DUNE_THROW(NotImplemented,
"PetscInverseOperator::bind: preconditioners cannot be set from outside!");
 
  130        BaseType :: unbind();
 
  134      void printTexInfo(std::ostream& out)
 const 
  136        out << 
"Solver: " << solverName_ << 
" eps = " << parameter_->tolerance() ;
 
  141      template <
class Reader>
 
  142      bool parseAndSetOptions(
const Reader& reader, 
const std::string& optionsKey)
 const 
  144        if( reader.exists(optionsKey) )
 
  146          std::string opts = reader.template getValue< std::string > (optionsKey);
 
  148          std::stringstream options( opts );
 
  155          while (! options.eof() )
 
  165            if( key.length() == 0 )
 
  170            if ( value.length() > 0 && value[0] == 
'-')
 
  179            ::Dune::Petsc::PetscOptionsSetValue( key, value);
 
  185          std::cout << 
"WARNING: 'kspoptions' selected but no options delivered with '" << optionsKey << 
"'!" << std::endl;
 
  191      void initialize ( 
const PetscSolverParameter& parameter )
 
  193        if( !assembledOperator_ )
 
  194          DUNE_THROW(NotImplemented,
"Petsc solver with matrix free implementations not yet supported!");
 
  197        ksp_.reset( 
new KSP() );
 
  198        const auto& comm = assembledOperator_->domainSpace().gridPart().comm();
 
  200        ::Dune::Petsc::KSPCreate( comm, &ksp() );
 
  203        Mat& A = assembledOperator_->exportMatrix();
 
  204#if PETSC_VERSION_MAJOR <= 3 && PETSC_VERSION_MINOR < 5 
  205        ::Dune::Petsc::KSPSetOperators( ksp(), A, A, SAME_PRECONDITIONER);
 
  207        ::Dune::Petsc::KSPSetOperators( ksp(), A, A );
 
  211        ::Dune::Petsc::KSPSetInitialGuessNonzero( ksp(), PETSC_TRUE );
 
  214        PetscInt  maxits    = parameter_->maxIterations();
 
  215        PetscReal tolerance = parameter_->tolerance();
 
  216        PetscReal omega     = parameter_->relaxation();
 
  217        if (parameter_->errorMeasure() == 0)
 
  218          ::Dune::Petsc::KSPSetTolerances(ksp(), 1e-50, tolerance, PETSC_DEFAULT, maxits);
 
  220          ::Dune::Petsc::KSPSetTolerances(ksp(), tolerance, 1e-50, PETSC_DEFAULT, maxits);
 
  224        const auto& reader = parameter.parameter();
 
  225        PetscSolver kspType = PetscSolver::gmres;
 
  226        if( reader.exists(
"petsc.kspsolver.method") )
 
  229          const std::string kspNames[] = { 
"default", 
"cg", 
"bicgstab", 
"gmres", 
"minres", 
"gradient", 
"loop", 
"superlu", 
"bicg", 
"preonly"  };
 
  230          kspType = 
static_cast< PetscSolver 
>( reader.getEnum(
"petsc.kspsolver.method", kspNames, 
int(PetscSolver::gmres) ) );
 
  231          std::cout << 
"WARNING: using deprecated parameter 'petsc.kpsolver.method' use " 
  232                    << parameter.keyPrefix() << 
"method instead\n";
 
  235          kspType = 
static_cast< PetscSolver 
>(
 
  236              parameter.solverMethod (
 
  237                supportedSolverMethods(), { 
"kspoptions" } )
 
  240        if (kspType > PetscSolver::kspoptions)
 
  241          solverName_ = SolverParameter::solverMethodTable( 
static_cast< int >( kspType ) );
 
  243          solverName_ = 
"kspoptions";
 
  248          case PetscSolver::cg:
 
  249            ::Dune::Petsc::KSPSetType( ksp(), KSPCG );
 
  251          case PetscSolver::bicgstab:
 
  252            ::Dune::Petsc::KSPSetType( ksp(), KSPBCGS );
 
  254          case PetscSolver::gmres:
 
  256              ::Dune::Petsc::KSPSetType( ksp(), KSPGMRES );
 
  257              PetscInt restart = 10;
 
  258              if( reader.exists(
"petsc.gmresrestart") )
 
  260                restart = reader.getValue<
int>(
"petsc.gmresrestart", restart );
 
  261                std::cout << 
"WARNING: using deprecated parameter 'petsc.gmresrestart' use " 
  262                    << parameter.keyPrefix() << 
"gmres.restart instead\n";
 
  265                restart = parameter.gmresRestart() ;
 
  267              ::Dune::Petsc::KSPGMRESSetRestart( ksp(), restart );
 
  270          case PetscSolver::minres:
 
  271            ::Dune::Petsc::KSPSetType( ksp(), KSPMINRES );
 
  273          case PetscSolver::bicg:
 
  274            ::Dune::Petsc::KSPSetType( ksp(), KSPBICG );
 
  276          case PetscSolver::preonly:
 
  277            ::Dune::Petsc::KSPSetType( ksp(), KSPPREONLY );
 
  279          case PetscSolver::kspoptions:
 
  281              const std::string key = parameter.keyPrefix() + 
"kspoptions";
 
  282              const bool foundOptions = parseAndSetOptions( reader, key );
 
  285              ::Dune::Petsc::KSPSetFromOptions( ksp() );
 
  286              ::Dune::Petsc::KSPSetUp( ksp() );
 
  290                ::Dune::Petsc::PetscOptionsClear();
 
  296            DUNE_THROW(InvalidStateException,
"PetscInverseOperator: invalid solver choosen." );
 
  298        if ( parameter_->knollTrick() )
 
  300          ::Dune::Petsc::KSPSetInitialGuessKnoll( ksp(), PETSC_TRUE );
 
  308        if( reader.exists(
"petsc.preconditioning.method") )
 
  310          const std::string pcNames[] = { 
"default", 
"none", 
"asm", 
"sor", 
"jacobi", 
"ilu", 
"icc", 
"superlu", 
"hypre", 
"ml", 
"lu" };
 
  311          pcType = reader.getEnum(
"petsc.preconditioning.method", pcNames, 0 );
 
  312          std::cout << 
"WARNING: using deprecated parameter 'petsc.preconditioning.method' use " 
  313                    << parameter.keyPrefix() << 
".preconditioning.method instead\n";
 
  319          pcType = parameter.preconditionMethod(
 
  320                 supportedPreconditionMethods(),
 
  321                 extraPreconditionMethods() );
 
  326        ::Dune::Petsc::KSPGetPC( ksp(), &pc );
 
  332            if ( kspType != PetscSolver::kspoptions )
 
  334              const std::string key = parameter.keyPrefix() + 
"kspoptions";
 
  335              const bool foundOptions = parseAndSetOptions( reader, key );
 
  338              ::Dune::Petsc::PCSetFromOptions( pc );
 
  339              ::Dune::Petsc::PCSetUp( pc );
 
  343                ::Dune::Petsc::PetscOptionsClear();
 
  348            ::Dune::Petsc::PCSetType( pc, PCNONE );
 
  350          case SolverParameter::oas:
 
  352              ::Dune::Petsc::PCSetType( pc, PCASM );
 
  353              ::Dune::Petsc::PCSetUp( pc );
 
  356          case SolverParameter::gauss_seidel:
 
  357            ::Dune::Petsc::PCSetType( pc, PCSOR );
 
  358            ::Dune::Petsc::PCSORSetOmega( pc, 1.0 );
 
  360          case SolverParameter::sor:
 
  361            ::Dune::Petsc::PCSetType( pc, PCSOR );
 
  362            ::Dune::Petsc::PCSORSetOmega( pc, omega );
 
  364          case SolverParameter::ssor:
 
  365            ::Dune::Petsc::PCSetType( pc, PCSOR );
 
  367            ::Dune::Petsc::PCSORSetSymmetric( pc, SOR_LOCAL_SYMMETRIC_SWEEP );
 
  368            ::Dune::Petsc::PCSORSetOmega( pc, omega );
 
  370          case SolverParameter::jacobi:
 
  371            ::Dune::Petsc::PCSetType( pc, PCJACOBI );
 
  375#ifdef PETSC_HAVE_HYPRE 
  377              int hypreType = parameter.hypreMethod();
 
  379              if ( hypreType == PetscSolverParameter::boomeramg )
 
  381              else if ( hypreType == PetscSolverParameter::parasails )
 
  383              else if ( hypreType == PetscSolverParameter::pilut )
 
  386                DUNE_THROW( InvalidStateException, 
"PetscInverseOperator: invalid hypre preconditioner choosen." );
 
  388              ::Dune::Petsc::PCSetType( pc, PCHYPRE );
 
  389              ::Dune::Petsc::PCHYPRESetType( pc, hypre.c_str() );
 
  390              ::Dune::Petsc::PCSetUp( pc );
 
  392              DUNE_THROW( InvalidStateException, 
"PetscInverseOperator: petsc not build with hypre support." );
 
  398            ::Dune::Petsc::PCSetType( pc, PCML );
 
  400              DUNE_THROW( InvalidStateException, 
"PetscInverseOperator: petsc not build with ml support." );
 
  403          case SolverParameter::ilu:
 
  405              if ( MPIManager::size() > 1 )
 
  406                DUNE_THROW( InvalidStateException, 
"PetscInverseOperator: ilu preconditioner does not work in parallel." );
 
  410              if( reader.exists(
"petsc.preconditioning.levels") )
 
  412                pcLevel = reader.getValue<
int>(
"petsc.preconditioning.levels", 0 );
 
  413                std::cout << 
"WARNING: using deprecated parameter 'petsc.preconditioning.levels' use " 
  414                    << parameter.keyPrefix() << 
"preconditioning.level instead\n";
 
  417                pcLevel = parameter.preconditionerLevel() ;
 
  419              ::Dune::Petsc::PCSetType( pc, PCILU );
 
  420              ::Dune::Petsc::PCFactorSetLevels( pc, pcLevel );
 
  423            ::Dune::Petsc::PCSetType( pc, PCML );
 
  425          case SolverParameter::icc:
 
  428              if ( MPIManager::size() > 1 )
 
  429                DUNE_THROW( InvalidStateException, 
"PetscInverseOperator: icc preconditioner does not worl in parallel." );
 
  433              if( reader.exists(
"petsc.preconditioning.levels") )
 
  435                pcLevel = reader.getValue<
int>(
"petsc.preconditioning.levels", 0 );
 
  436                std::cout << 
"WARNING: using deprecated parameter 'petsc.preconditioning.levels' use " 
  437                    << parameter.keyPrefix() << 
"preconditioning.level instead\n";
 
  440                pcLevel = parameter.preconditionerLevel() ;
 
  443              ::Dune::Petsc::PCSetType( pc, PCICC );
 
  444              ::Dune::Petsc::PCFactorSetLevels( pc, pcLevel );
 
  446              DUNE_THROW( InvalidStateException, 
"PetscInverseOperator: petsc not build with icc support." );
 
  451          case SolverParameter::superlu:
 
  453              enum class Factorization { petsc = 0, superlu = 1, mumps = 2 };
 
  454              Factorization factorType = Factorization::superlu;
 
  455              if (pcType != SolverParameter::superlu)
 
  456                factorType = 
static_cast<Factorization
>(parameter.superluMethod());
 
  458              ::Dune::Petsc::PCSetType( pc, PCLU );
 
  460              if ( factorType == Factorization::petsc )
 
  461                ::Dune::Petsc::PCFactorSetMatSolverPackage( pc, MATSOLVERPETSC );
 
  462              else if ( factorType == Factorization::superlu )
 
  463                ::Dune::Petsc::PCFactorSetMatSolverPackage( pc, MATSOLVERSUPERLU_DIST );
 
  464              else if ( factorType == Factorization::mumps )
 
  465                ::Dune::Petsc::PCFactorSetMatSolverPackage( pc, MATSOLVERMUMPS );
 
  467                DUNE_THROW( InvalidStateException, 
"PetscInverseOperator: invalid factorization package choosen." );
 
  469              ::Dune::Petsc::PCSetUp( pc );
 
  474            if( parameter.blockedMode() )
 
  476              DUNE_THROW(NotImplemented,
"PetscInverseOperator: 'pcgamg' requires 'aij' matrix. Set 'petsc.blockedmode' to false!");
 
  478            ::Dune::Petsc::PCSetType( pc, PCGAMG );
 
  482            DUNE_THROW( InvalidStateException, 
"PetscInverseOperator: invalid preconditioner choosen." );
 
  491            ::Dune::Petsc::KSPView( comm, ksp() );
 
  493          ::Dune::Petsc::KSPMonitorSet( ksp(), &monitor, PETSC_NULLPTR, PETSC_NULLPTR);
 
  497      int apply( 
const PetscDiscreteFunctionType& arg, PetscDiscreteFunctionType& dest )
 const 
  500        if( dest.space().continuous() )
 
  501          dest.dofVector().clearGhost();
 
  504        ::Dune::Petsc::KSPSolve( *ksp_, *arg.petscVec() , *dest.petscVec() );
 
  507        if( dest.space().continuous() )
 
  514        ::Dune::Petsc::KSPGetIterationNumber( *ksp_, &its );
 
  515        KSPConvergedReason reason;
 
  516        ::Dune::Petsc::KSPGetConvergedReason( *ksp_, &reason );
 
  518        bool converged = int(reason) >= 0 ;
 
  525            std::cout << 
"Converged    reason: ";
 
  527            std::cout << 
"**Diverged** reason: ";
 
  528          std::cout << reason << 
"  linear iterations: " << its << std::endl;
 
  531        return (converged) ? its : -its;
 
  535      KSP & ksp () { assert( ksp_ ); 
return *ksp_; }
 
  537      using BaseType :: assembledOperator_;
 
  538      using BaseType :: parameter_;
 
  539      using BaseType :: iterations_;
 
  541      std::unique_ptr< KSP, KSPDeleter > ksp_;   
 
  543      std::string solverName_;
 
Inverse operator base on CG method. Uses a runtime parameter fem.preconditioning which enables diagon...
Definition: cginverseoperator.hh:408
 
A vector valued function space.
Definition: functionspace.hh:60
 
static bool verbose()
obtain the cached value for fem.verbose with default verbosity level 2
Definition: parameter.hh:466
 
forward declaration
Definition: discretefunction.hh:51
 
#define DUNE_THROW(E,...)
Definition: exceptions.hh:314
 
constexpr GeometryType none(unsigned int dim)
Returns a GeometryType representing a singular of dimension dim.
Definition: type.hh:471
 
Dune namespace.
Definition: alignedallocator.hh:13