IPPL API Reference
Independent Parallel Particle Layer C++ API
Loading...
Searching...
No Matches
FEMPoissonSolver.h
1// Class FEMPoissonSolver
2// Solves the poisson equation using finite element methods and Conjugate
3// Gradient
4
5#ifndef IPPL_FEMPOISSONSOLVER_H
6#define IPPL_FEMPOISSONSOLVER_H
7
8#include "EvalFunctor.h"
9#include "LinearSolvers/PCG.h"
10#include "Poisson.h"
11
12namespace ippl {
13
21 template <typename FieldLHS, typename FieldRHS = FieldLHS, unsigned Order = 1,
22 unsigned QuadNumNodes = 5>
23 class FEMPoissonSolver : public Poisson<FieldLHS, FieldRHS> {
24 constexpr static unsigned Dim = FieldLHS::dim;
25 using Tlhs = typename FieldLHS::value_type;
26
27 public:
29 using typename Base::lhs_type, typename Base::rhs_type;
30 using MeshType = typename FieldRHS::Mesh_t;
31
32 // PCG (Preconditioned Conjugate Gradient) is the solver algorithm used
35
36 // FEM Space types
37 using ElementType =
38 std::conditional_t<Dim == 1, ippl::EdgeElement<Tlhs>,
39 std::conditional_t<Dim == 2, ippl::QuadrilateralElement<Tlhs>,
41
43
44 using LagrangeType =
46
47 // default constructor (compatibility with Alpine)
49 : Base()
50 , refElement_m()
51 , quadrature_m(refElement_m, 0.0, 0.0)
52 , lagrangeSpace_m(*(new MeshType(NDIndex<Dim>(Vector<unsigned, Dim>(0)),
54 refElement_m, quadrature_m) {
56 }
57
58 FEMPoissonSolver(lhs_type& lhs, rhs_type& rhs)
59 : Base(lhs, rhs)
60 , refElement_m()
61 , quadrature_m(refElement_m, 0.0, 0.0)
62 , lagrangeSpace_m(rhs.get_mesh(), refElement_m, quadrature_m, rhs.getLayout()) {
63 static_assert(std::is_floating_point<Tlhs>::value, "Not a floating point type");
65 pcg_algo_m.initializeFields(rhs.get_mesh(), rhs.getLayout());
66 }
67
68 void setRhs(rhs_type& rhs) override {
69 Base::setRhs(rhs);
70
71 lagrangeSpace_m.initialize(rhs.get_mesh(), rhs.getLayout());
72 pcg_algo_m.initializeFields(rhs.get_mesh(), rhs.getLayout());
73 }
74
78 LagrangeType& getSpace() { return lagrangeSpace_m; }
79
84 void solve() override {
85 // create load vector for the problem
86 this->rhs_mp->fillHalo();
87 lagrangeSpace_m.evaluateLoadVector(*(this->rhs_mp));
88
89 const Vector<size_t, Dim> zeroNdIndex = Vector<size_t, Dim>(0);
90
91 // We can pass the zeroNdIndex here, since the transformation jacobian does not depend
92 // on translation
93 const auto firstElementVertexPoints =
94 lagrangeSpace_m.getElementMeshVertexPoints(zeroNdIndex);
95
96 // Compute Inverse Transpose Transformation Jacobian ()
97 const Vector<Tlhs, Dim> DPhiInvT =
98 refElement_m.getInverseTransposeTransformationJacobian(firstElementVertexPoints);
99
100 // Compute absolute value of the determinant of the transformation jacobian (|det D
101 // Phi_K|)
102 const Tlhs absDetDPhi = Kokkos::abs(
103 refElement_m.getDeterminantOfTransformationJacobian(firstElementVertexPoints));
104
105 EvalFunctor<Tlhs, Dim, LagrangeType::numElementDOFs> poissonEquationEval(DPhiInvT,
106 absDetDPhi);
107
108 // get BC type of our RHS
109 BConds<FieldRHS, Dim>& bcField = (this->rhs_mp)->getFieldBC();
110 FieldBC bcType = bcField[0]->getBCType();
111
112 const auto algoOperator = [poissonEquationEval, &bcField,
113 this](rhs_type field) -> lhs_type {
114 // set appropriate BCs for the field as the info gets lost in the CG iteration
115 field.setFieldBC(bcField);
116
117 field.fillHalo();
118
119 auto return_field = lagrangeSpace_m.evaluateAx(field, poissonEquationEval);
120
121 return return_field;
122 };
123
124 pcg_algo_m.setOperator(algoOperator);
125
126 // send boundary values to RHS (load vector) i.e. lifting (Dirichlet BCs)
127 if (bcType == CONSTANT_FACE) {
128 // Set per-face Dirichlet values on physical boundary nodes before halo exchange;
129 // fillHalo must see the correct boundary state after load vector assembly.
130 bcField.apply(*(this->rhs_mp));
131 bcField.assignGhostToPhysical(*(this->rhs_mp));
132 this->rhs_mp->fillHalo();
133 *(this->rhs_mp) =
134 *(this->rhs_mp)
135 - lagrangeSpace_m.evaluateAx_lift(*(this->rhs_mp), poissonEquationEval);
136 }
137
138 // start a timer
139 static IpplTimings::TimerRef pcgTimer = IpplTimings::getTimer("pcg");
140 IpplTimings::startTimer(pcgTimer);
141
142 pcg_algo_m(*(this->lhs_mp), *(this->rhs_mp), this->params_m);
143
144 (this->lhs_mp)->fillHalo();
145
146 IpplTimings::stopTimer(pcgTimer);
147 }
148
154 int getIterationCount() { return pcg_algo_m.getIterationCount(); }
155
160 Tlhs getResidue() const { return pcg_algo_m.getResidue(); }
161
168 template <typename F>
169 Tlhs getL2Error(const F& analytic) {
170 Tlhs error_norm = this->lagrangeSpace_m.computeErrorL2(*(this->lhs_mp), analytic);
171 return error_norm;
172 }
173
179 Tlhs getAvg(bool Vol = false) {
180 Tlhs avg = this->lagrangeSpace_m.computeAvg(*(this->lhs_mp));
181 if (Vol) {
182 lhs_type unit((this->lhs_mp)->get_mesh(), (this->lhs_mp)->getLayout());
183 unit = 1.0;
184 Tlhs vol = this->lagrangeSpace_m.computeAvg(unit);
185 return avg / vol;
186 } else {
187 return avg;
188 }
189 }
190
191 protected:
192 PCGSolverAlgorithm_t pcg_algo_m;
193
194 virtual void setDefaultParameters() override {
195 this->params_m.add("max_iterations", 1000);
196 this->params_m.add("tolerance", (Tlhs)1e-13);
197 }
198
199 ElementType refElement_m;
200 QuadratureType quadrature_m;
201 LagrangeType lagrangeSpace_m;
202 };
203
204} // namespace ippl
205
206#endif
Definition BConds.h:23
Definition PCG.h:37
virtual int getIterationCount()
Definition PCG.h:106
virtual void setOperator(OperatorF op)
Definition PCG.h:70
A solver for the poisson equation using finite element methods and Conjugate Gradient (CG)
Definition FEMPoissonSolver.h:23
void setRhs(rhs_type &rhs) override
Definition FEMPoissonSolver.h:68
virtual void setDefaultParameters() override
Definition FEMPoissonSolver.h:194
Tlhs getResidue() const
Definition FEMPoissonSolver.h:160
int getIterationCount()
Definition FEMPoissonSolver.h:154
LagrangeType & getSpace()
Return the LagrangeSpace object.
Definition FEMPoissonSolver.h:78
Tlhs getL2Error(const F &analytic)
Definition FEMPoissonSolver.h:169
Tlhs getAvg(bool Vol=false)
Definition FEMPoissonSolver.h:179
void solve() override
Solve the poisson equation using finite element methods. The problem is described by -laplace(lhs) = ...
Definition FEMPoissonSolver.h:84
KOKKOS_FUNCTION vertex_points_t getElementMeshVertexPoints(const indices_t &elementNDIndex) const
Get all the global vertex points of an element (given by its NDIndex).
Definition FiniteElementSpace.hpp:271
This is class represents the Gauss-Jacobi quadrature rule on a reference element.
Definition GaussJacobiQuadrature.h:27
Definition HexahedralElement.h:14
A class representing a Lagrange space for finite element methods on a structured, rectilinear grid.
Definition LagrangeSpace.h:36
T computeAvg(const FieldLHS &u_h) const
Given a field, compute the average.
Definition LagrangeSpace.hpp:1609
void initialize(UniformCartesian< T, Dim > &mesh, Layout_t &layout)
Initialize a LagrangeSpace object created with the default constructor.
Definition LagrangeSpace.hpp:41
void evaluateLoadVector(FieldRHS &field) const
Assemble the load vector b of the system Ax = b.
Definition LagrangeSpace.hpp:1330
FieldLHS evaluateAx(FieldLHS &field, F &evalFunction)
Assembly operations ///////////////////////////////////////////////.
Definition LagrangeSpace.hpp:372
T computeErrorL2(const FieldLHS &u_h, const F &u_sol) const
Error norm computations ///////////////////////////////////////////.
Definition LagrangeSpace.hpp:1525
FieldLHS evaluateAx_lift(FieldLHS &field, F &evalFunction)
Assemble the left stiffness matrix A of the system but only for the boundary values,...
Definition LagrangeSpace.hpp:1212
Definition NDIndex.h:21
void add(const std::string &key, const T &value)
Definition ParameterList.h:44
Definition Poisson.h:16
virtual void setRhs(rhs_type &rhs)
Definition Poisson.h:96
Definition Vector.h:23
Definition Archive.h:20
Representation of the lhs of the problem we are trying to solve.
Definition FEMMaxwellDiffusionSolver.h:29