v0.15.0
Loading...
Searching...
No Matches
DGProjection.cpp
Go to the documentation of this file.
1/**
2 * @file DGProjection.cpp
3 */
4
5namespace MoFEM {
6
7static auto dg_save_range(moab::Interface &moab, const std::string name,
8 const Range r, std::vector<Tag> tags = {}) {
10 auto out_meshset = get_temp_meshset_ptr(moab);
11 CHKERR moab.add_entities(*out_meshset, r);
12 if (r.size()) {
13 CHKERR moab.write_file(name.c_str(), "VTK", "", out_meshset->get_ptr(), 1,
14 tags.data(), tags.size());
15 } else {
16 MOFEM_LOG("SELF", Sev::warning) << "Empty range for " << name;
17 }
19};
20
22
24 return 2 * (p + 1);
25 };
26
27 DGSetIntegration(boost::shared_ptr<Range> edges_ptr,
29 : edgesPtr(edges_ptr), funRule(fun_rule) {};
30
32 int order_col, int order_data) {
34
35 constexpr bool debug = false;
36
37 constexpr int numNodes = 3;
38 constexpr int numEdges = 3;
39 constexpr int refinementLevels = 1;
40
41 auto &m_field = fe_raw_ptr->mField;
42 auto fe_ptr = static_cast<Fe *>(fe_raw_ptr);
43 auto fe_handle = fe_ptr->getFEEntityHandle();
44 auto type = type_from_handle(fe_handle);
45 if (type != MBTRI) {
46 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
47 "only MBTRI is implemented");
48 }
49
50
51
52 auto set_base_quadrature = [&]() {
54 int rule = funRule(order_row, order_col, order_data);
55 if (rule < QUAD_2D_TABLE_SIZE) {
56 if (QUAD_2D_TABLE[rule]->dim != 2) {
57 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "wrong dimension");
58 }
59 if (QUAD_2D_TABLE[rule]->order < rule) {
60 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
61 "wrong order %d != %d", QUAD_2D_TABLE[rule]->order, rule);
62 }
63 const size_t nb_gauss_pts = QUAD_2D_TABLE[rule]->npoints;
64 fe_ptr->gaussPts.resize(3, nb_gauss_pts, false);
65 cblas_dcopy(nb_gauss_pts, &QUAD_2D_TABLE[rule]->points[1], 3,
66 &fe_ptr->gaussPts(0, 0), 1);
67 cblas_dcopy(nb_gauss_pts, &QUAD_2D_TABLE[rule]->points[2], 3,
68 &fe_ptr->gaussPts(1, 0), 1);
69 cblas_dcopy(nb_gauss_pts, QUAD_2D_TABLE[rule]->weights, 1,
70 &fe_ptr->gaussPts(2, 0), 1);
71 auto &data = fe_ptr->dataOnElement[H1];
72 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 3,
73 false);
74 double *shape_ptr =
75 &*data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().begin();
76 cblas_dcopy(3 * nb_gauss_pts, QUAD_2D_TABLE[rule]->points, 1, shape_ptr,
77 1);
78 data->dataOnEntities[MBVERTEX][0].getDiffN(NOBASE).resize(3, 2, false);
79 std::copy(
81 data->dataOnEntities[MBVERTEX][0].getDiffN(NOBASE).data().begin());
82
83 } else {
84 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
85 "rule > quadrature order %d < %d", rule, QUAD_3D_TABLE_SIZE);
86 }
88 };
89
90 CHKERR set_base_quadrature();
91
92 if (edgesPtr) {
93
94 auto get_edges = [&]() {
95 std::bitset<numEdges> edges;
96 for (int ee = 0; ee != numEdges; ee++) {
97 EntityHandle edge;
98 CHKERR m_field.get_moab().side_element(fe_handle, 1, ee, edge);
99 if (edgesPtr->find(edge) != edgesPtr->end()) {
100 edges.set(ee);
101 } else {
102 edges.reset(ee);
103 }
104 }
105 return edges;
106 };
107
108 auto set_gauss_pts = [&](auto &ref_gauss_pts) {
110 fe_ptr->gaussPts.swap(ref_gauss_pts);
111 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
112 auto &data = fe_ptr->dataOnElement[H1];
113 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).resize(nb_gauss_pts, 4);
114 auto *shape_ptr =
115 data->dataOnEntities[MBVERTEX][0].getN(NOBASE).data().data();
116 CHKERR Tools::shapeFunMBTRI(shape_ptr, &fe_ptr->gaussPts(0, 0),
117 &fe_ptr->gaussPts(1, 0), nb_gauss_pts);
119 };
120
121 auto refine_quadrature = [&]() {
123
124 const int max_level = refinementLevels;
125
126 moab::Core moab_ref;
127 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0};
128 EntityHandle nodes[numNodes];
129 for (int nn = 0; nn != numNodes; nn++)
130 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
131 EntityHandle tri;
132 CHKERR moab_ref.create_element(MBTRI, nodes, numNodes, tri);
133 MoFEM::CoreTmp<-1> mofem_ref_core(moab_ref, PETSC_COMM_SELF, -2);
134 MoFEM::Interface &m_field_ref = mofem_ref_core;
135 {
136 Range tris(tri, tri);
137 Range edges;
138 CHKERR m_field_ref.get_moab().get_adjacencies(tris, 1, true, edges,
139 moab::Interface::UNION);
140 CHKERR m_field_ref.getInterface<BitRefManager>()->setBitRefLevel(
141 tris, BitRefLevel().set(0), false, VERBOSE);
142 }
143
144 auto edges = get_edges();
145
146 EntityHandle meshset;
147 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
148 for (int ee = 0; ee != numEdges; ee++) {
149 if (edges[ee]) {
150 EntityHandle ent;
151 CHKERR moab_ref.side_element(tri, 1, ee, ent);
152 CHKERR moab_ref.add_entities(meshset, &ent, 1);
153 }
154 }
155
156 // refine mesh
157 auto *m_ref = m_field_ref.getInterface<MeshRefinement>();
158 for (int ll = 0; ll != max_level; ll++) {
159 Range ref_edges;
160 CHKERR moab_ref.get_entities_by_type(meshset, MBEDGE, ref_edges,
161 true);
162 CHKERR m_field_ref.getInterface<BitRefManager>()
163 ->filterEntitiesByRefLevel(BitRefLevel().set(ll),
164 BitRefLevel().set(), ref_edges);
165
166 Range tris;
167 CHKERR m_field_ref.getInterface<BitRefManager>()
168 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(ll),
169 BitRefLevel().set(), MBTRI, tris);
170 CHKERR m_ref->addVerticesInTheMiddleOfEdges(
171 ref_edges, BitRefLevel().set(ll + 1));
172 CHKERR m_ref->refineTris(tris, BitRefLevel().set(ll + 1));
173 CHKERR m_field_ref.getInterface<BitRefManager>()
174 ->updateMeshsetByEntitiesChildren(
175 meshset, BitRefLevel().set(ll + 1), meshset, MBEDGE, true);
176 }
177
178 // get ref coords
179 Range tris;
180 CHKERR m_field_ref.getInterface<BitRefManager>()
181 ->getEntitiesByTypeAndRefLevel(BitRefLevel().set(max_level),
182 BitRefLevel().set(), MBTRI, tris);
183
184 if (debug) {
185 CHKERR dg_save_range(moab_ref, "ref_tris.vtk", tris);
186 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "debug");
187 }
188
189 MatrixDouble ref_coords(tris.size(), 9, false);
190 int tt = 0;
191 for (Range::iterator tit = tris.begin(); tit != tris.end();
192 tit++, tt++) {
193 int num_nodes;
194 const EntityHandle *conn;
195 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes, false);
196 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
197 }
198
199 auto &data = fe_ptr->dataOnElement[H1];
200 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
201 MatrixDouble ref_gauss_pts(3, nb_gauss_pts * ref_coords.size1());
202 MatrixDouble &shape_n = data->dataOnEntities[MBVERTEX][0].getN(NOBASE);
203 int gg = 0;
204 for (size_t tt = 0; tt != ref_coords.size1(); tt++) {
205 double *tri_coords = &ref_coords(tt, 0);
207 CHKERR Tools::getTriNormal(tri_coords, &t_normal(0));
208 auto det = t_normal.l2();
209 for (size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
210 for (int dd = 0; dd != 2; dd++) {
211 ref_gauss_pts(dd, gg) = shape_n(ggg, 0) * tri_coords[3 * 0 + dd] +
212 shape_n(ggg, 1) * tri_coords[3 * 1 + dd] +
213 shape_n(ggg, 2) * tri_coords[3 * 2 + dd];
214 }
215 ref_gauss_pts(2, gg) = fe_ptr->gaussPts(2, ggg) * det;
216 }
217 }
218
220 };
221
222 CHKERR refine_quadrature();
223 }
224
226 }
227
228private:
229 struct Fe : public ForcesAndSourcesCore {
231
232 private:
234 };
235
236 boost::shared_ptr<Range> edgesPtr;
237
238};
239
240template <>
244 boost::shared_ptr<Range> edges_ptr) {
246 set_hook = DGSetIntegration(edges_ptr, rule);
248}
249
251 int order, boost::shared_ptr<MatrixDouble> mass_ptr,
252 boost::shared_ptr<EntitiesFieldData> data_l2,
253 const FieldApproximationBase b, const FieldSpace s, int verb, Sev sev)
254 : OpBaseDerivativesBase(mass_ptr, data_l2, b, s, verb, sev),
255 baseOrder(order) {}
256
258OpDGProjectionMassMatrix::doWork(int side, EntityType type,
261
262 if (sPace != L2) {
263 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
264 "Space should be set to L2");
265 }
266
268
269 [this]() { return this->baseOrder; }
270
271 );
273
275}
276
278 boost::shared_ptr<MatrixDouble> data_ptr,
279 boost::shared_ptr<MatrixDouble> coeffs_ptr,
280 boost::shared_ptr<MatrixDouble> mass_ptr,
281 boost::shared_ptr<EntitiesFieldData> data_l2,
282 const FieldApproximationBase b, const FieldSpace s,
284 : OpBaseDerivativesBase(mass_ptr, data_l2, b, s, VERBOSE, sev),
285 dataPtr(data_ptr), coeffsPtr(coeffs_ptr) {}
286
288OpDGProjectionCoefficients::doWork(int side, EntityType type,
291 auto nb_integration_pts = getGaussPts().size2();
292
293 const auto fe_type = getFEType();
294 constexpr auto side_number = 0;
295 auto &ent_data = dataL2->dataOnEntities[fe_type][side_number];
296 auto nb_base_functions = ent_data.getN(base).size2();
297
298 auto nb_data_coeffs = dataPtr->size1();
299 auto &rhs = *coeffsPtr;
300 auto &data = *dataPtr;
301
302 rhs.resize(nb_base_functions, nb_data_coeffs, false);
303 rhs.clear();
304
306 MatrixDouble trans_data = trans(data);
307
308 // assemble rhs
309 auto t_base = ent_data.getFTensor0N(base, 0, 0);
310 auto t_w = getFTensor0IntegrationWeight();
311 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
312 Tensor0 t_rhs(&*rhs.data().begin());
313 for (auto bb = 0; bb != nb_base_functions; ++bb) {
314 double alpha = t_w * t_base;
315 Tensor0 t_data(&trans_data(gg, 0));
316 for (auto cc = 0; cc != nb_data_coeffs; ++cc) {
317 t_rhs += alpha * t_data;
318 ++t_data;
319 ++t_rhs;
320 }
321 ++t_base;
322 }
323 ++t_w;
324 }
325
326 // solve for coefficients
327 for (auto cc = 0; cc != nb_data_coeffs; ++cc) {
328 ublas::matrix_column<MatrixDouble> mc(rhs, cc);
329 cholesky_solve(*baseMassPtr, mc, ublas::lower());
330 }
331
333}
334
336 boost::shared_ptr<MatrixDouble> data_ptr,
337 boost::shared_ptr<MatrixDouble> coeffs_ptr,
338 boost::shared_ptr<EntitiesFieldData> data_l2,
339 const FieldApproximationBase b, const FieldSpace s,
341 : OpDGProjectionCoefficients(data_ptr, coeffs_ptr,
342 boost::make_shared<MatrixDouble>(), data_l2, b,
343 s, sev) {}
344
346OpDGProjectionEvaluation::doWork(int side, EntityType type,
348
350
351 if (sPace != L2) {
352 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
353 "Space should be set to L2");
354 }
355
356 auto fe_type = getFEType();
357 constexpr auto side_number = 0;
358 auto order = dataL2->dataOnEntities[fe_type][side_number].getOrder();
360
361 [order]() { return order; }
362
363 );
364
365 auto &ent_data = dataL2->dataOnEntities[fe_type][side_number];
366 const auto nb_base_functions = ent_data.getN(base).size2();
367 auto nb_data_coeffs = dataPtr->size1();
368 if (!nb_data_coeffs) {
369 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
370 "Number of data coefficients should be set");
371 }
372 auto &data = *dataPtr;
373 auto &coeffs = *coeffsPtr;
374
375 auto nb_integration_pts = getGaussPts().size2();
376 data.resize(nb_integration_pts, nb_data_coeffs);
377 data.clear();
378
380
381 auto t_base = ent_data.getFTensor0N(base, 0, 0);
382 for (auto gg = 0; gg != nb_integration_pts; ++gg) {
383 Tensor0 t_coeffs(&*coeffs.data().begin());
384 for (auto bb = 0; bb != nb_base_functions; ++bb) {
385 double alpha = t_base;
386 Tensor0 t_data(&data(gg, 0));
387 for (auto cc = 0; cc != nb_data_coeffs; ++cc) {
388 t_data += alpha * t_coeffs;
389 ++t_data;
390 ++t_coeffs;
391 }
392 ++t_base;
393 }
394 }
395
396 *dataPtr = trans(*dataPtr);
397
399}
400} // namespace MoFEM
void cholesky_solve(const TRIA &L, VEC &x, ublas::lower)
solve system L L^T x = b inplace
Definition cholesky.hpp:221
@ VERBOSE
FieldApproximationBase
approximation base
Definition definitions.h:58
@ NOBASE
Definition definitions.h:59
FieldSpace
approximation spaces
Definition definitions.h:82
@ L2
field with C-1 continuity
Definition definitions.h:88
@ H1
continuous field
Definition definitions.h:85
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
constexpr int order
Order displacement.
#define MOFEM_LOG(channel, severity)
Log.
SeverityLevel
Severity levels.
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
Definition Types.hpp:40
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
auto type_from_handle(const EntityHandle h)
get type from entity handle
static const bool debug
MoFEMErrorCode setDGSetIntegrationPoints< 2 >(ForcesAndSourcesCore::GaussHookFun &set_hook, ForcesAndSourcesCore::RuleHookFun rule, boost::shared_ptr< Range > edges_ptr)
static auto dg_save_range(moab::Interface &moab, const std::string name, const Range r, std::vector< Tag > tags={})
auto get_temp_meshset_ptr(moab::Interface &moab)
Create smart pointer to temporary meshset.
#define QUAD_2D_TABLE_SIZE
Definition quad.h:174
#define QUAD_3D_TABLE_SIZE
Definition quad.h:186
static QUAD *const QUAD_2D_TABLE[]
Definition quad.h:175
Managing BitRefLevels.
virtual moab::Interface & get_moab()=0
DGSetIntegration(boost::shared_ptr< Range > edges_ptr, ForcesAndSourcesCore::RuleHookFun fun_rule)
boost::shared_ptr< Range > edgesPtr
MoFEMErrorCode operator()(ForcesAndSourcesCore *fe_raw_ptr, int order_row, int order_col, int order_data)
ForcesAndSourcesCore::RuleHookFun funRule
Deprecated interface functions.
Data on single entity (This is passed as argument to DataOperator::doWork)
EntityHandle getFEEntityHandle() const
Get the entity handle of the current finite element.
EntityType getFEType() const
Get dimension of finite element.
auto getFTensor0IntegrationWeight()
Get integration weights.
MatrixDouble & getGaussPts()
matrix of integration (Gauss) points for Volume Element
structure to get information from mofem into EntitiesFieldData
ForcesAndSourcesCore(Interface &m_field)
boost::function< MoFEMErrorCode(ForcesAndSourcesCore *fe_raw_ptr, int order_row, int order_col, int order_data)> GaussHookFun
const std::array< boost::shared_ptr< EntitiesFieldData >, LASTSPACE > dataOnElement
Entity data on element entity rows fields.
boost::function< int(int order_row, int order_col, int order_data)> RuleHookFun
Mesh refinement interface.
boost::shared_ptr< EntitiesFieldData > dataL2
MoFEMErrorCode calculateBase(GetOrderFun get_order)
boost::shared_ptr< MatrixDouble > baseMassPtr
boost::shared_ptr< MatrixDouble > coeffsPtr
boost::shared_ptr< MatrixDouble > dataPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpDGProjectionCoefficients(boost::shared_ptr< MatrixDouble > data_ptr, boost::shared_ptr< MatrixDouble > coeffs_ptr, boost::shared_ptr< MatrixDouble > mass_ptr, boost::shared_ptr< EntitiesFieldData > data_l2, const FieldApproximationBase b, const FieldSpace s, const LogManager::SeverityLevel sev=Sev::noisy)
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpDGProjectionEvaluation(boost::shared_ptr< MatrixDouble > data_ptr, boost::shared_ptr< MatrixDouble > coeffs_ptr, boost::shared_ptr< EntitiesFieldData > data_l2, const FieldApproximationBase b, const FieldSpace s, const LogManager::SeverityLevel sev=Sev::noisy)
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpDGProjectionMassMatrix(int order, boost::shared_ptr< MatrixDouble > mass_ptr, boost::shared_ptr< EntitiesFieldData > data_l2, const FieldApproximationBase b, const FieldSpace s, int verb=QUIET, Sev sev=Sev::verbose)
static constexpr std::array< double, 6 > diffShapeFunMBTRI
Definition Tools.hpp:104
static MoFEMErrorCode getTriNormal(const double *coords, double *normal, double *d_normal=nullptr)
Get the Tri Normal objectGet triangle normal.
Definition Tools.cpp:353
static MoFEMErrorCode shapeFunMBTRI(double *shape, const double *ksi, const double *eta, const int nb)
Calculate shape functions on triangle.
Definition Tools.hpp:728
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
int npoints
Definition quad.h:29