14 template <
typename OperatorRet,
typename LowerRet,
typename UpperRet,
typename UpperLowerRet,
15 typename InverseDiagRet,
typename DiagRet,
typename FieldLHS,
16 typename FieldRHS = FieldLHS>
19 typedef typename Base::lhs_type::value_type
T;
30 virtual ~CG() =
default;
39 [[maybe_unused]]
LowerF&& lower,
40 [[maybe_unused]]
UpperF&& upper,
45 [[maybe_unused]]
DiagF&& diagonal,
46 [[maybe_unused]]
double alpha,
47 [[maybe_unused]]
double beta,
48 [[maybe_unused]] std::string preconditioner_type =
50 [[maybe_unused]]
int level =
53 [[maybe_unused]]
int degree =
56 [[maybe_unused]]
int richardson_iterations =
59 [[maybe_unused]]
int inner =
62 [[maybe_unused]]
int outer =
64 [[maybe_unused]]
double omega =
78 typename lhs_type::Mesh_t mesh = lhs.get_mesh();
79 typename lhs_type::Layout_t layout = lhs.getLayout();
82 const int maxIterations = params.
get<
int>(
"max_iterations");
90 bc_type lhsBCs = lhs.getFieldBC();
93 bool allFacesPeriodic =
true;
94 for (
unsigned int i = 0; i < 2 *
Dim; ++i) {
95 FieldBC bcType = lhsBCs[i]->getBCType();
98 bc[i] = std::make_shared<PeriodicFace<lhs_type>>(i);
102 bc[i] = std::make_shared<ZeroFace<lhs_type>>(i);
103 allFacesPeriodic =
false;
106 "Only periodic or constant BCs for LHS supported.");
118 const T tolerance = params.
get<
T>(
"tolerance") *
norm(rhs);
126 lhs = lhs + alpha * d;
138 T beta = delta1 / delta0;
145 if (allFacesPeriodic) {
146 T avg = lhs.getVolumeAverage();
160 template <
typename OperatorRet,
typename LowerRet,
typename UpperRet,
typename UpperLowerRet,
161 typename InverseDiagRet,
typename T>
183 [[maybe_unused]]
LowerF&& lower,
184 [[maybe_unused]]
UpperF&& upper,
189 [[maybe_unused]]
double alpha,
190 [[maybe_unused]]
double beta,
191 [[maybe_unused]] std::string preconditioner_type =
193 [[maybe_unused]]
int level =
196 [[maybe_unused]]
int degree =
199 [[maybe_unused]]
int richardson_iterations =
202 [[maybe_unused]]
int inner =
205 [[maybe_unused]]
int outer = 1
223 const int maxIterations = params.
get<
int>(
"max_iterations");
240 const T tolerance = params.
get<
T>(
"tolerance") *
norm(rhs);
250 lhs = lhs + alpha * d;
263 T beta = delta1 / delta0;
282 template <
typename OperatorRet,
typename LowerRet,
typename UpperRet,
typename UpperLowerRet,
283 typename InverseDiagRet,
typename DiagRet,
typename FieldLHS,
284 typename FieldRHS = FieldLHS>
285 class PCG :
public CG<OperatorRet, LowerRet, UpperRet, UpperLowerRet, InverseDiagRet, DiagRet,
286 FieldLHS, FieldRHS> {
288 typedef typename Base::lhs_type::value_type
T;
300 :
CG<OperatorRet, LowerRet, UpperRet, UpperLowerRet, InverseDiagRet, DiagRet, FieldLHS,
317 std::string preconditioner_type =
"",
322 int richardson_iterations = 4,
328 double omega = 1.57079632679
333 if (preconditioner_type ==
"jacobi") {
342 std::move(inverse_diagonal)));
343 }
else if (preconditioner_type ==
"newton") {
346 std::move(op), alpha, beta, level, 1e-3));
347 }
else if (preconditioner_type ==
"chebyshev") {
350 std::move(op), alpha, beta, degree, 1e-3));
351 }
else if (preconditioner_type ==
"richardson") {
353 std::move(std::make_unique<
355 std::move(upper_and_lower), std::move(inverse_diagonal),
356 richardson_iterations));
357 }
else if (preconditioner_type ==
"richardson_alt") {
359 std::move(std::make_unique<
361 std::move(op), std::move(inverse_diagonal),
362 richardson_iterations));
363 }
else if (preconditioner_type ==
"gauss-seidel") {
366 std::move(lower), std::move(upper), std::move(inverse_diagonal), inner,
368 }
else if (preconditioner_type ==
"ssor") {
370 std::move(std::make_unique<
372 std::move(lower), std::move(upper), std::move(inverse_diagonal),
373 std::move(diagonal), inner, outer, omega));
380 constexpr unsigned Dim = lhs_type::dim;
384 "Preconditioner has not been set for PCG solver");
387 typename lhs_type::Mesh_t mesh = lhs.get_mesh();
388 typename lhs_type::Layout_t layout = lhs.getLayout();
391 const int maxIterations = params.
get<
int>(
"max_iterations");
403 bc_type lhsBCs = lhs.getFieldBC();
406 bool allFacesPeriodic =
true;
407 for (
unsigned int i = 0; i < 2 *
Dim; ++i) {
408 FieldBC bcType = lhsBCs[i]->getBCType();
411 bc[i] = std::make_shared<PeriodicFace<lhs_type>>(i);
415 bc[i] = std::make_shared<ZeroFace<lhs_type>>(i);
416 allFacesPeriodic =
false;
419 "Only periodic or constant BCs for LHS supported.");
424 r = rhs - this->
op_m(lhs);
430 this->
residueNorm = Kokkos::sqrt(Kokkos::abs(delta1));
436 lhs = lhs + alpha * d;
451 T beta = delta1 / delta0;
452 this->
residueNorm = Kokkos::sqrt(Kokkos::abs(delta1));
458 if (allFacesPeriodic) {
459 T avg = lhs.getVolumeAverage();
T innerProduct(const FEMVector< T > &a, const FEMVector< T > &b)
Calculate the inner product between two ippl::FEMVector(s).
T norm(const FEMVector< T > &v, int p=2)
1D vector used in the context of FEM.
static constexpr unsigned dim
Dummy parameter in order for the detail::Expression defined operators to work.
FEMVector< T > deepCopy() const
Create a deep copy, where all the information of this vector is copied to a new one.
void setHalo(T setValue)
Set the halo cells to setValue.
std::function< LowerRet(lhs_type)> LowerF
virtual T getResidue() const
std::function< OperatorRet(lhs_type)> OperatorF
std::function< InverseDiagRet(lhs_type)> InverseDiagF
virtual int getIterationCount()
virtual void setOperator(OperatorF op)
std::function< UpperLowerRet(lhs_type)> UpperLowerF
virtual void setPreconditioner(OperatorF &&op, LowerF &&lower, UpperF &&upper, UpperLowerF &&upper_and_lower, InverseDiagF &&inverse_diagonal, DiagF &&diagonal, double alpha, double beta, std::string preconditioner_type="", int level=5, int degree=31, int richardson_iterations=1, int inner=5, int outer=1, double omega=1)
std::function< UpperRet(lhs_type)> UpperF
virtual void operator()(lhs_type &lhs, rhs_type &rhs, const ParameterList ¶ms) override
std::function< DiagRet(lhs_type)> DiagF
Base::lhs_type::value_type T
SolverAlgorithm< FieldLHS, FieldRHS > Base
std::function< InverseDiagRet(lhs_type)> InverseDiagF
virtual void operator()(lhs_type &lhs, rhs_type &rhs, const ParameterList ¶ms) override
virtual int getIterationCount()
virtual void setPreconditioner(OperatorF &&op, LowerF &&lower, UpperF &&upper, UpperLowerF &&upper_and_lower, InverseDiagF &&inverse_diagonal, double alpha, double beta, std::string preconditioner_type="", int level=5, int degree=31, int richardson_iterations=1, int inner=5, int outer=1)
std::function< UpperRet(lhs_type)> UpperF
virtual void setOperator(OperatorF op)
std::function< LowerRet(lhs_type)> LowerF
virtual T getResidue() const
SolverAlgorithm< FEMVector< T >, FEMVector< T > > Base
std::function< OperatorRet(lhs_type)> OperatorF
std::function< UpperLowerRet(lhs_type)> UpperLowerF
std::function< LowerRet(lhs_type)> LowerF
void setPreconditioner(OperatorF &&op, LowerF &&lower, UpperF &&upper, UpperLowerF &&upper_and_lower, InverseDiagF &&inverse_diagonal, DiagF &&diagonal, double alpha, double beta, std::string preconditioner_type="", int level=5, int degree=31, int richardson_iterations=4, int inner=2, int outer=2, double omega=1.57079632679) override
std::function< DiagRet(lhs_type)> DiagF
void operator()(lhs_type &lhs, rhs_type &rhs, const ParameterList ¶ms) override
std::function< UpperRet(lhs_type)> UpperF
Base::lhs_type::value_type T
SolverAlgorithm< FieldLHS, FieldRHS > Base
std::function< InverseDiagRet(lhs_type)> InverseDiagF
std::function< UpperLowerRet(lhs_type)> UpperLowerF
std::function< OperatorRet(lhs_type)> OperatorF
std::unique_ptr< preconditioner< FieldRHS > > preconditioner_m
T get(const std::string &key) const