v0.16.0
Loading...
Searching...
No Matches
dg_projection.cpp
Go to the documentation of this file.
1/**
2 * @file dg_projection.cpp
3 * @example mofem/atom_tests/dg_projection.cpp
4 *
5 * @brief Testing Discontinuous Galerkin (DG) projection operators
6 *
7 * This test validates the accuracy of DG projection algorithms used to
8 * represent functions on finite element meshes. The projection process
9 * involves solving local least-squares problems to find the best
10 * approximation of a given function in the finite element space.
11 *
12 * Mathematical background:
13 * - DG projection finds coefficients c_i such that ∑c_i φ_i minimizes
14 * ||u - ∑c_i φ_i||_{L2} where u is the target function and φ_i are basis functions
15 * - This leads to the normal equation: M c = f, where M is the mass matrix
16 * and f is the load vector from projecting the target function
17 * - The test verifies that the projection accurately represents a polynomial
18 * function that should be exactly representable in the chosen finite element space
19 *
20 * Test workflow:
21 * 1. Setup finite element space with polynomial basis functions
22 * 2. Assemble mass matrix and load vector for the projection problem
23 * 3. Solve the projection system to get approximation coefficients
24 * 4. Evaluate the projected function and compare with analytical values
25 */
26
27#include <MoFEM.hpp>
28
29using namespace MoFEM;
30
31static char help[] = "DG Projection Test - validates discontinuous Galerkin "
32 "projection accuracy\n\n";
33
34constexpr char FIELD_NAME[] = "U";
35constexpr int BASE_DIM = 1;
36constexpr int FIELD_DIM = 1;
37constexpr int SPACE_DIM = 2;
38constexpr int order = 2;
39
40template <int DIM> struct ElementsAndOps {};
41
42template <> struct ElementsAndOps<2> {
45};
46
48using DomainEleOp = DomainEle::UserDataOperator;
50
51auto fun = [](const double x, const double y, const double z) {
52 return x + y + x * x + y * y;
53};
54
57
60
61struct AtomTest {
62
63 AtomTest(MoFEM::Interface &m_field) : mField(m_field) {}
64
66
67private:
70
76
77 struct CommonData {
78 boost::shared_ptr<MatrixDouble> invJacPtr;
79 boost::shared_ptr<VectorDouble> approxVals;
80 boost::shared_ptr<MatrixDouble> approxGradVals;
81 boost::shared_ptr<MatrixDouble> approxHessianVals;
83 };
84
85 struct OpError;
86};
87
88struct AtomTest::OpError : public DomainEleOp {
89 boost::shared_ptr<CommonData> commonDataPtr;
90
91 OpError(boost::shared_ptr<MatrixDouble> data_ptr)
92 : DomainEleOp(NOSPACE, OPSPACE), dataPtr(data_ptr) {}
93
94 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
96
97 const int nb_integration_pts = getGaussPts().size2();
98
99 auto t_val = getFTensor1FromMat<1>(*(dataPtr));
100 auto t_coords = getFTensor1CoordsAtGaussPts();
101
102 for (int gg = 0; gg != nb_integration_pts; ++gg) {
103
104 double projected_value = t_val(0);
105 double analytical_value = fun(t_coords(0), t_coords(1), t_coords(2));
106 double error = projected_value - analytical_value;
107
108 constexpr double eps = 1e-8;
109 if (std::abs(error) > eps) {
110 MOFEM_LOG("SELF", Sev::error)
111 << "Projection error too large: " << error << " at point ("
112 << t_coords(0) << ", " << t_coords(1) << ")"
113 << " projected=" << projected_value
114 << " analytical=" << analytical_value;
115 SETERRQ(PETSC_COMM_SELF, MOFEM_ATOM_TEST_INVALID,
116 "DG projection failed accuracy test");
117 }
118
119 ++t_val;
120 ++t_coords;
121 }
122
123 MOFEM_LOG("SELF", Sev::noisy) << "DG projection accuracy validation passed";
124
126 }
127
128private:
129 boost::shared_ptr<MatrixDouble> dataPtr;
130};
131
132//! [Run programme]
141}
142//! [Run programme]
143
144//! [Read mesh]
147
149
151
153
155}
156//! [Read mesh]
157
158//! [Set up problem]
161
164
166
168
170}
171//! [Set up problem]
172
173//! [Push operators to pipeline]
176
177 auto rule = [](int, int, int p) -> int { return 2 * p; };
178
180
181 CHKERR pipeline_mng->setDomainLhsIntegrationRule(rule);
182 CHKERR pipeline_mng->setDomainRhsIntegrationRule(rule);
183
184 auto beta = [](const double, const double, const double) { return 1; };
185
186 pipeline_mng->getOpDomainLhsPipeline().push_back(
188
189 pipeline_mng->getOpDomainRhsPipeline().push_back(
191
193}
194//! [Push operators to pipeline]
195
196//! [Solve]
200
201 MOFEM_LOG("WORLD", Sev::inform) << "Solving DG projection system";
202
203 auto solver = pipeline_mng->createKSP();
204 CHKERR KSPSetFromOptions(solver);
205 CHKERR KSPSetUp(solver);
206
207 auto dm = simpleInterface->getDM();
208 auto D = createDMVector(dm);
209 auto F = vectorDuplicate(D);
210
211 CHKERR KSPSolve(solver, F, D);
212
213 CHKERR VecGhostUpdateBegin(D, INSERT_VALUES, SCATTER_FORWARD);
214 CHKERR VecGhostUpdateEnd(D, INSERT_VALUES, SCATTER_FORWARD);
215
216 CHKERR DMoFEMMeshToLocalVector(dm, D, INSERT_VALUES, SCATTER_REVERSE);
217
219}
220//! [Solve]
221
222//! [Check results]
226 auto pipeline_mng = mField.getInterface<PipelineManager>();
227
228 auto rule = [](int, int, int p) -> int { return 2 * p + 1; };
229 CHKERR pipeline_mng->setEvaluationIntegrationRule(rule);
230
231 auto entity_data_l2 = boost::make_shared<EntitiesFieldData>(MBENTITYSET);
232
233 auto mass_ptr = boost::make_shared<MatrixDouble>();
234 auto coeffs_ptr = boost::make_shared<MatrixDouble>();
235 auto data_ptr = boost::make_shared<MatrixDouble>();
236
237 auto op_this =
238 new OpLoopThis<DomainEle>(mField, simple->getDomainFEName(), Sev::noisy);
239 pipeline_mng->getOpEvaluationPipeline().push_back(op_this);
240
241 pipeline_mng->getOpEvaluationPipeline().push_back(
242 new OpDGProjectionEvaluation(data_ptr, coeffs_ptr, entity_data_l2,
244
245 pipeline_mng->getOpEvaluationPipeline().push_back(new OpError(data_ptr));
246
247 auto fe_physics_ptr = op_this->getThisFEPtr();
248 fe_physics_ptr->getRuleHook = [](int, int, int p) { return 2 * p; };
249
250 fe_physics_ptr->getOpPtrVector().push_back(new OpDGProjectionMassMatrix(
251 order, mass_ptr, entity_data_l2, AINSWORTH_LEGENDRE_BASE, L2));
252
253 fe_physics_ptr->getOpPtrVector().push_back(
255
256 fe_physics_ptr->getOpPtrVector().push_back(new OpDGProjectionCoefficients(
257 data_ptr, coeffs_ptr, mass_ptr, entity_data_l2, AINSWORTH_LEGENDRE_BASE,
258 L2, Sev::noisy));
259
260 CHKERR pipeline_mng->loopFiniteElementsEvaluation();
261
263}
264//! [Check results]
265
266int main(int argc, char *argv[]) {
267
268 MoFEM::Core::Initialize(&argc, &argv, NULL, help);
269
270 try {
271
272 //! [Register MoFEM discrete manager in PETSc]
273 DMType dm_name = "DMMOFEM";
274 CHKERR DMRegister_MoFEM(dm_name);
275 //! [Register MoFEM discrete manager in PETSc]
276
277 //! [Create MoAB]
278 moab::Core mb_instance;
279 moab::Interface &moab = mb_instance;
280 //! [Create MoAB]
281
282 //! [Create MoFEM]
283 MoFEM::Core core(moab);
284 MoFEM::Interface &m_field = core;
285 //! [Create MoFEM]
286
287 //! [Execute DG Projection Test]
288 AtomTest ex(m_field);
289 CHKERR ex.runProblem();
290 //! [Execute DG Projection Test]
291 }
293
295}
std::string type
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
int main()
static const double eps
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< 1, FIELD_DIM > OpDomainSource
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< 1, FIELD_DIM > OpDomainMass
#define CATCH_ERRORS
Catch errors.
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ L2
field with C-1 continuity
Definition definitions.h:88
@ H1
continuous field
Definition definitions.h:85
@ NOSPACE
Definition definitions.h:83
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_ATOM_TEST_INVALID
Definition definitions.h:40
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
static char help[]
constexpr char FIELD_NAME[]
auto fun
constexpr int SPACE_DIM
constexpr int FIELD_DIM
constexpr int BASE_DIM
constexpr int order
@ F
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode, RowColData rc=RowColData::COL)
set local (or ghosted) vector values on mesh for partition only
Definition DMMoFEM.cpp:514
PetscErrorCode DMRegister_MoFEM(const char sname[])
Register MoFEM problem.
Definition DMMoFEM.cpp:43
auto createDMVector(DM dm, RowColData rc=RowColData::COL)
Get smart vector from DM.
Definition DMMoFEM.hpp:1237
boost::ptr_deque< UserDataOperator > & getOpDomainLhsPipeline()
Get the Op Domain Lhs Pipeline object.
SmartPetscObj< KSP > createKSP(SmartPetscObj< DM > dm=nullptr)
Create KSP (linear) solver.
boost::ptr_deque< UserDataOperator > & getOpDomainRhsPipeline()
Get the Op Domain Rhs Pipeline object.
@ PETSC
Standard PETSc assembly.
#define MOFEM_LOG(channel, severity)
Log.
constexpr char FIELD_NAME[]
auto fun
Function to approximate.
constexpr int FIELD_DIM
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::BiLinearForm< GAUSS >::OpMass< BASE_DIM, FIELD_DIM > OpDomainMass
OPerator to integrate mass matrix for least square approximation.
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< BASE_DIM, FIELD_DIM > OpDomainSource
Operator to integrate the right hand side matrix for the problem.
double D
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
SmartPetscObj< Vec > vectorDuplicate(Vec vec)
Create duplicate vector of smart vector.
Collected data use d by operator to evaluate errors for the test.
boost::shared_ptr< VectorDouble > approxVals
SmartPetscObj< Vec > L2Vec
boost::shared_ptr< MatrixDouble > invJacPtr
boost::shared_ptr< MatrixDouble > approxHessianVals
boost::shared_ptr< MatrixDouble > approxGradVals
Operator to evaluate errors.
boost::shared_ptr< CommonData > commonDataPtr
OpError(boost::shared_ptr< MatrixDouble > data_ptr)
boost::shared_ptr< MatrixDouble > dataPtr
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
Simple * simpleInterface
MoFEMErrorCode checkResults()
[Solve]
MoFEMErrorCode solveSystem()
AtomTest(MoFEM::Interface &m_field)
MoFEMErrorCode setupProblem()
MoFEMErrorCode readMesh()
MoFEMErrorCode assembleSystem()
MoFEM::Interface & mField
MoFEMErrorCode runProblem()
[Operators_definition]
Core (interface) class.
Definition Core.hpp:83
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:68
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:123
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
Specialization for MatrixDouble vector field values calculation.
Evaluate field for given DG projection coefficients.
Evaluate right hand side for given data coefficients.
Execute "this" element in the operator.
PipelineManager interface.
MoFEM::FaceElementForcesAndSourcesCore FaceEle
MoFEMErrorCode setDomainRhsIntegrationRule(RuleHookFun rule)
Set integration rule for domain right-hand side finite element.
MoFEMErrorCode setDomainLhsIntegrationRule(RuleHookFun rule)
Set integration rule for domain left-hand side finite element.
Simple interface for fast problem set-up.
Definition Simple.hpp:27
MoFEMErrorCode addDomainField(const std::string name, const FieldSpace space, const FieldApproximationBase base, const FieldCoefficientsNumber nb_of_coefficients, const TagType tag_type=MB_TAG_SPARSE, const enum MoFEMTypes bh=MF_ZERO, int verb=-1)
Add field on domain.
Definition Simple.cpp:261
MoFEMErrorCode loadFile(const std::string options, const std::string mesh_file_name, LoadFileFunc loadFunc=defaultLoadFileFunc)
Load mesh file.
Definition Simple.cpp:191
MoFEMErrorCode getOptions()
get options
Definition Simple.cpp:180
MoFEMErrorCode getDM(DM *dm)
Get DM.
Definition Simple.cpp:799
MoFEMErrorCode setFieldOrder(const std::string field_name, const int order, const Range *ents=NULL)
Set field order.
Definition Simple.cpp:575
MoFEMErrorCode setUp(const PetscBool is_partitioned=PETSC_TRUE)
Setup problem.
Definition Simple.cpp:735
intrusive_ptr for managing petsc objects
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.