/*
* Copyright (c) 2017-2022 Dominik Thoennes, Nils Kohl.
*
* This file is part of HyTeG
* (see https://i10git.cs.fau.de/hyteg/hyteg).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#pragma once
#include
#include "hyteg/solvers/Solver.hpp"
#include "PETScSparseMatrix.hpp"
#include "PETScVector.hpp"
#ifdef HYTEG_BUILD_WITH_PETSC
namespace hyteg {
template < class OperatorType >
class PETScCGSolver : public Solver< OperatorType >
{
public:
typedef typename OperatorType::srcType FunctionType;
PETScCGSolver( const std::shared_ptr< PrimitiveStorage >& storage,
const uint_t& level,
const real_t relativeTolerance = 1e-30,
const real_t absoluteTolerance = 1e-12,
const PetscInt maxIterations = std::numeric_limits< PetscInt >::max() )
: allocatedLevel_( level )
, petscCommunicator_( storage->getSplitCommunicatorByPrimitiveDistribution() )
, num( "numerator", storage, level, level )
, Amat( "Amat", petscCommunicator_ )
, AmatNonEliminatedBC( "AmatNonEliminatedBC", petscCommunicator_ )
, xVec( "xVec", petscCommunicator_ )
, bVec( "bVec", petscCommunicator_ )
, nullspaceVec_( "nullspaceVec", petscCommunicator_ )
, flag_( hyteg::All )
, nullSpaceSet_( false )
, reassembleMatrix_( false )
{
KSPCreate( petscCommunicator_, &ksp );
KSPSetType( ksp, KSPCG );
KSPSetTolerances( ksp, relativeTolerance, absoluteTolerance, PETSC_DEFAULT, maxIterations );
KSPSetInitialGuessNonzero( ksp, PETSC_TRUE );
KSPSetFromOptions( ksp );
}
~PETScCGSolver()
{
KSPDestroy( &ksp );
if ( nullSpaceSet_ )
MatNullSpaceDestroy( &nullspace_ );
}
void reassembleMatrix( bool reassembleMatrix ) { reassembleMatrix_ = reassembleMatrix; }
void setNullSpace( const FunctionType& nullspace )
{
nullSpaceSet_ = true;
nullspaceVec_.createVectorFromFunction( nullspace, num, allocatedLevel_ );
MatNullSpaceCreate( petscCommunicator_, PETSC_FALSE, 1, &nullspaceVec_.get(), &nullspace_ );
}
void solve( const OperatorType& A, const FunctionType& x, const FunctionType& b, const uint_t level )
{
WALBERLA_CHECK_EQUAL( level, allocatedLevel_ );
x.getStorage()->getTimingTree()->start( "PETSc CG Solver" );
num.copyBoundaryConditionFromFunction( x );
num.enumerate( level );
xVec.createVectorFromFunction( x, num, level );
bVec.createVectorFromFunction( b, num, level, All );
if ( reassembleMatrix_ )
{
AmatNonEliminatedBC.zeroEntries();
Amat.zeroEntries();
AmatNonEliminatedBC.createMatrixFromOperator( A, level, num, All );
Amat.createMatrixFromOperator( A, level, num, All );
}
else
{
AmatNonEliminatedBC.createMatrixFromOperatorOnce( A, level, num, All );
Amat.createMatrixFromOperatorOnce( A, level, num, All );
}
MatCopy( AmatNonEliminatedBC.get(), Amat.get(), SAME_NONZERO_PATTERN );
Amat.applyDirichletBCSymmetrically( x, num, bVec, level );
if ( nullSpaceSet_ )
{
MatSetNullSpace( Amat.get(), nullspace_ );
}
KSPSetOperators( ksp, Amat.get(), Amat.get() );
KSPGetPC( ksp, &pc );
PCSetType( pc, PCNONE );
KSPSolve( ksp, bVec.get(), xVec.get() );
xVec.createFunctionFromVector( x, num, level, flag_ );
x.getStorage()->getTimingTree()->stop( "PETSc CG Solver" );
}
private:
uint_t allocatedLevel_;
MPI_Comm petscCommunicator_;
typename OperatorType::srcType::template FunctionType< idx_t > num;
PETScSparseMatrix< OperatorType > Amat;
PETScSparseMatrix< OperatorType > AmatNonEliminatedBC;
PETScVector< typename FunctionType::valueType, OperatorType::srcType::template FunctionType > xVec;
PETScVector< typename FunctionType::valueType, OperatorType::srcType::template FunctionType > bVec;
PETScVector< typename FunctionType::valueType, OperatorType::srcType::template FunctionType > nullspaceVec_;
KSP ksp;
PC pc;
MatNullSpace nullspace_;
hyteg::DoFType flag_;
bool nullSpaceSet_;
bool reassembleMatrix_;
};
} // namespace hyteg
#endif