v0.15.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 pipeline_mng->getDomainLhsFE().reset();
229 pipeline_mng->getDomainRhsFE().reset();
230 pipeline_mng->getOpDomainRhsPipeline().clear();
231
232 auto rule = [](int, int, int p) -> int { return 2 * p + 1; };
233 CHKERR pipeline_mng->setDomainRhsIntegrationRule(rule);
234
235 auto entity_data_l2 = boost::make_shared<EntitiesFieldData>(MBENTITYSET);
236
237 auto mass_ptr = boost::make_shared<MatrixDouble>();
238 auto coeffs_ptr = boost::make_shared<MatrixDouble>();
239 auto data_ptr = boost::make_shared<MatrixDouble>();
240
241 auto op_this =
242 new OpLoopThis<DomainEle>(mField, simple->getDomainFEName(), Sev::noisy);
243 pipeline_mng->getOpDomainRhsPipeline().push_back(op_this);
244
245 pipeline_mng->getOpDomainRhsPipeline().push_back(new OpDGProjectionEvaluation(
246 data_ptr, coeffs_ptr, entity_data_l2, AINSWORTH_LEGENDRE_BASE, L2));
247
248 pipeline_mng->getOpDomainRhsPipeline().push_back(new OpError(data_ptr));
249
250 auto fe_physics_ptr = op_this->getThisFEPtr();
251 fe_physics_ptr->getRuleHook = [](int, int, int p) { return 2 * p; };
252
253 fe_physics_ptr->getOpPtrVector().push_back(new OpDGProjectionMassMatrix(
254 order, mass_ptr, entity_data_l2, AINSWORTH_LEGENDRE_BASE, L2));
255
256 fe_physics_ptr->getOpPtrVector().push_back(
258
259 fe_physics_ptr->getOpPtrVector().push_back(new OpDGProjectionCoefficients(
260 data_ptr, coeffs_ptr, mass_ptr, entity_data_l2, AINSWORTH_LEGENDRE_BASE,
261 L2));
262
263 CHKERR pipeline_mng->loopFiniteElements();
264
266}
267//! [Check results]
268
269int main(int argc, char *argv[]) {
270
271 MoFEM::Core::Initialize(&argc, &argv, NULL, help);
272
273 try {
274
275 //! [Register MoFEM discrete manager in PETSc]
276 DMType dm_name = "DMMOFEM";
277 CHKERR DMRegister_MoFEM(dm_name);
278 //! [Register MoFEM discrete manager in PETSc]
279
280 //! [Create MoAB]
281 moab::Core mb_instance;
282 moab::Interface &moab = mb_instance;
283 //! [Create MoAB]
284
285 //! [Create MoFEM]
286 MoFEM::Core core(moab);
287 MoFEM::Interface &m_field = core;
288 //! [Create MoFEM]
289
290 //! [Execute DG Projection Test]
291 AtomTest ex(m_field);
292 CHKERR ex.runProblem();
293 //! [Execute DG Projection Test]
294 }
296
298}
void simple(double P1[], double P2[], double P3[], double c[], const int N)
Definition acoustic.cpp:69
int main()
static const double eps
ElementsAndOps< SPACE_DIM >::DomainEle DomainEle
FormsIntegrators< DomainEleOp >::Assembly< PETSC >::LinearForm< GAUSS >::OpSource< 1, FIELD_DIM > OpDomainSource
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
Order displacement.
@ F
PetscErrorCode DMoFEMMeshToLocalVector(DM dm, Vec l, InsertMode mode, ScatterMode scatter_mode)
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)
Get smart vector from DM.
Definition DMMoFEM.hpp:1234
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()
Core (interface) class.
Definition Core.hpp:82
static MoFEMErrorCode Initialize(int *argc, char ***args, const char file[], const char help[])
Initializes the MoFEM database PETSc, MOAB and MPI.
Definition Core.cpp:72
static MoFEMErrorCode Finalize()
Checks for options to be called at the conclusion of the program.
Definition Core.cpp:118
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
Specialization for double precision vector field values calculation.
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:800
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:736
intrusive_ptr for managing petsc objects
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.