v0.16.3
Loading...
Searching...
No Matches
TetPolynomialBase.cpp
Go to the documentation of this file.
1/** \file TetPolynomialBase.cpp
2\brief Implementation of hierarchical bases on tetrahedral
3
4A l2, h1, h-div and h-curl spaces are implemented.
5
6*/
7
8using namespace MoFEM;
9
11
13 int order;
15 mutable MatrixDouble N;
17 };
18
20
21 int order;
23
24 // Number of permeations for tetrahedron
25 // That is P(3, 4) = 24
26
27 int n0;
28 int n1;
29 int n2;
30
31 mutable MatrixDouble N;
33 };
34
35 using BaseCacheMI = boost::multi_index_container<
37 boost::multi_index::indexed_by<
38
39 boost::multi_index::hashed_unique<
40
41 composite_key<
42
44 member<BaseCacheItem, int, &BaseCacheItem::order>,
45 member<BaseCacheItem, int, &BaseCacheItem::nb_gauss_pts>>>>
46
47 >;
48
49 using HDivBaseFaceCacheMI = boost::multi_index_container<
51 boost::multi_index::indexed_by<
52
53 boost::multi_index::hashed_unique<
54
55 composite_key<
56
58 member<HDivBaseCacheItem, int, &HDivBaseCacheItem::order>,
59 member<HDivBaseCacheItem, int,
61 member<HDivBaseCacheItem, int, &HDivBaseCacheItem::n0>,
62 member<HDivBaseCacheItem, int, &HDivBaseCacheItem::n1>,
63 member<HDivBaseCacheItem, int, &HDivBaseCacheItem::n2>>>>
64
65 >;
66
67 static std::array<std::map<const void *, BaseCacheMI>, LASTBASE>
69 static std::array<std::map<const void *, BaseCacheMI>, LASTBASE>
71 static std::array<std::map<const void *, HDivBaseFaceCacheMI>, LASTBASE>
73 static std::array<std::map<const void *, BaseCacheMI>, LASTBASE>
75};
76
77std::array<std::map<const void *, TetBaseCache::BaseCacheMI>, LASTBASE>
79std::array<std::map<const void *, TetBaseCache::BaseCacheMI>, LASTBASE>
81std::array<std::map<const void *, TetBaseCache::HDivBaseFaceCacheMI>, LASTBASE>
83std::array<std::map<const void *, TetBaseCache::BaseCacheMI>, LASTBASE>
85
87TetPolynomialBase::query_interface(boost::typeindex::type_index type_index,
88 UnknownInterface **iface) const {
89
91 *iface = const_cast<TetPolynomialBase *>(this);
93}
94
95TetPolynomialBase::TetPolynomialBase(const void *ptr) : vPtr(ptr) {}
96
98 if (vPtr) {
99
100 auto erase = [&](auto cache) {
101 if (cache.find(vPtr) != cache.end())
102 cache.erase(vPtr);
103 };
104
105 for (auto b = 0; b != LASTBASE; ++b) {
109 }
110 }
111}
112
115
116 switch (cTx->bAse) {
120 break;
123 break;
124 default:
125 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not implemented");
126 }
127
129}
130
133
134 EntitiesFieldData &data = cTx->dAta;
135 const FieldApproximationBase base = cTx->bAse;
136 PetscErrorCode (*base_polynomials)(int p, double s, double *diff_s, double *L,
137 double *diffL, const int dim) =
139
140 int nb_gauss_pts = pts.size2();
141
142 int sense[6], order[6];
143 if (data.spacesOnEntities[MBEDGE].test(H1)) {
144 // edges
145 if (data.dataOnEntities[MBEDGE].size() != 6) {
146 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
147 }
148 double *h1_edge_n[6], *diff_h1_egde_n[6];
149 for (int ee = 0; ee != 6; ++ee) {
150 if (data.dataOnEntities[MBEDGE][ee].getSense() == 0) {
151 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
152 "data inconsistency");
153 }
154 sense[ee] = data.dataOnEntities[MBEDGE][ee].getSense();
155 order[ee] = data.dataOnEntities[MBEDGE][ee].getOrder();
156 int nb_dofs = NBEDGE_H1(data.dataOnEntities[MBEDGE][ee].getOrder());
157 data.dataOnEntities[MBEDGE][ee].getN(base).resize(nb_gauss_pts, nb_dofs,
158 false);
159 data.dataOnEntities[MBEDGE][ee].getDiffN(base).resize(nb_gauss_pts,
160 3 * nb_dofs, false);
161 h1_edge_n[ee] =
162 &*data.dataOnEntities[MBEDGE][ee].getN(base).data().begin();
163 diff_h1_egde_n[ee] =
164 &*data.dataOnEntities[MBEDGE][ee].getDiffN(base).data().begin();
165 }
167 sense, order,
168 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
169 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
170 h1_edge_n, diff_h1_egde_n, nb_gauss_pts, base_polynomials);
171 } else {
172 for (int ee = 0; ee != 6; ++ee) {
173 data.dataOnEntities[MBEDGE][ee].getN(base).resize(0, 0, false);
174 data.dataOnEntities[MBEDGE][ee].getDiffN(base).resize(0, 0, false);
175 }
176 }
177
178 if (data.spacesOnEntities[MBTRI].test(H1)) {
179 // faces
180 if (data.dataOnEntities[MBTRI].size() != 4) {
181 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
182 }
183 double *h1_face_n[4], *diff_h1_face_n[4];
184 for (int ff = 0; ff != 4; ++ff) {
185 if (data.dataOnEntities[MBTRI][ff].getSense() == 0) {
186 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
187 "data inconsistency");
188 }
189 int nb_dofs = NBFACETRI_H1(data.dataOnEntities[MBTRI][ff].getOrder());
190 order[ff] = data.dataOnEntities[MBTRI][ff].getOrder();
191 data.dataOnEntities[MBTRI][ff].getN(base).resize(nb_gauss_pts, nb_dofs,
192 false);
193 data.dataOnEntities[MBTRI][ff].getDiffN(base).resize(nb_gauss_pts,
194 3 * nb_dofs, false);
195 h1_face_n[ff] =
196 &*data.dataOnEntities[MBTRI][ff].getN(base).data().begin();
197 diff_h1_face_n[ff] =
198 &*data.dataOnEntities[MBTRI][ff].getDiffN(base).data().begin();
199 }
200 if (data.facesNodes.size1() != 4) {
201 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
202 }
203 if (data.facesNodes.size2() != 3) {
204 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
205 }
207 &*data.facesNodes.data().begin(), order,
208 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
209 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
210 h1_face_n, diff_h1_face_n, nb_gauss_pts, base_polynomials);
211
212 } else {
213 for (int ff = 0; ff != 4; ++ff) {
214 data.dataOnEntities[MBTRI][ff].getN(base).resize(0, false);
215 data.dataOnEntities[MBTRI][ff].getDiffN(base).resize(0, 0, false);
216 }
217 }
218
219 if (data.spacesOnEntities[MBTET].test(H1)) {
220 // volume
221 int order = data.dataOnEntities[MBTET][0].getOrder();
222 int nb_vol_dofs = NBVOLUMETET_H1(order);
223 data.dataOnEntities[MBTET][0].getN(base).resize(nb_gauss_pts, nb_vol_dofs,
224 false);
225 data.dataOnEntities[MBTET][0].getDiffN(base).resize(nb_gauss_pts,
226 3 * nb_vol_dofs, false);
228 data.dataOnEntities[MBTET][0].getOrder(),
229 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
230 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
231 &*data.dataOnEntities[MBTET][0].getN(base).data().begin(),
232 &*data.dataOnEntities[MBTET][0].getDiffN(base).data().begin(),
233 nb_gauss_pts, base_polynomials);
234 } else {
235 data.dataOnEntities[MBTET][0].getN(base).resize(0, 0, false);
236 data.dataOnEntities[MBTET][0].getDiffN(base).resize(0, 0, false);
237 }
238
240}
241
245
246 EntitiesFieldData &data = cTx->dAta;
247 const std::string field_name = cTx->fieldName;
248 const int nb_gauss_pts = pts.size2();
249
250 if (data.dataOnEntities[MBVERTEX][0].getN(NOBASE).size1() !=
251 (unsigned int)nb_gauss_pts)
252 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
253 "Base functions or nodes has wrong number of integration points "
254 "for base %s",
256 auto &lambda = data.dataOnEntities[MBVERTEX][0].getN(NOBASE);
257
258 auto get_alpha = [field_name](auto &data) -> MatrixInt & {
259 auto &ptr = data.getBBAlphaIndicesSharedPtr(field_name);
260 if (!ptr)
261 ptr.reset(new MatrixInt());
262 return *ptr;
263 };
264
265 auto get_base = [field_name](auto &data) -> MatrixDouble & {
266 auto &ptr = data.getBBNSharedPtr(field_name);
267 if (!ptr)
268 ptr.reset(new MatrixDouble());
269 return *ptr;
270 };
271
272 auto get_diff_base = [field_name](auto &data) -> MatrixDouble & {
273 auto &ptr = data.getBBDiffNSharedPtr(field_name);
274 if (!ptr)
275 ptr.reset(new MatrixDouble());
276 return *ptr;
277 };
278
279 auto get_alpha_by_name_ptr =
280 [](auto &data,
281 const std::string &field_name) -> boost::shared_ptr<MatrixInt> & {
282 return data.getBBAlphaIndicesSharedPtr(field_name);
283 };
284
285 auto get_base_by_name_ptr =
286 [](auto &data,
287 const std::string &field_name) -> boost::shared_ptr<MatrixDouble> & {
288 return data.getBBNSharedPtr(field_name);
289 };
290
291 auto get_diff_base_by_name_ptr =
292 [](auto &data,
293 const std::string &field_name) -> boost::shared_ptr<MatrixDouble> & {
294 return data.getBBDiffNSharedPtr(field_name);
295 };
296
297 auto get_alpha_by_order_ptr =
298 [](auto &data, const size_t o) -> boost::shared_ptr<MatrixInt> & {
299 return data.getBBAlphaIndicesByOrderSharedPtr(o);
300 };
301
302 auto get_base_by_order_ptr =
303 [](auto &data, const size_t o) -> boost::shared_ptr<MatrixDouble> & {
304 return data.getBBNByOrderSharedPtr(o);
305 };
306
307 auto get_diff_base_by_order_ptr =
308 [](auto &data, const size_t o) -> boost::shared_ptr<MatrixDouble> & {
309 return data.getBBDiffNByOrderSharedPtr(o);
310 };
311
312 auto &vert_ent_data = data.dataOnEntities[MBVERTEX][0];
313 auto &vertex_alpha = get_alpha(vert_ent_data);
314 vertex_alpha.resize(4, 4, false);
315 vertex_alpha.clear();
316 for (int n = 0; n != 4; ++n)
317 vertex_alpha(n, n) = data.dataOnEntities[MBVERTEX][0].getBBNodeOrder()[n];
318
319 auto &vert_get_n = get_base(vert_ent_data);
320 auto &vert_get_diff_n = get_diff_base(vert_ent_data);
321 vert_get_n.resize(nb_gauss_pts, 4, false);
322 vert_get_diff_n.resize(nb_gauss_pts, 12, false);
324 1, lambda.size1(), vertex_alpha.size1(), &vertex_alpha(0, 0),
325 &lambda(0, 0), Tools::diffShapeFunMBTET.data(), &vert_get_n(0, 0),
326 &vert_get_diff_n(0, 0));
327 for (int n = 0; n != 4; ++n) {
328 const double f = boost::math::factorial<double>(
329 data.dataOnEntities[MBVERTEX][0].getBBNodeOrder()[n]);
330 for (int g = 0; g != nb_gauss_pts; ++g) {
331 vert_get_n(g, n) *= f;
332 for (int d = 0; d != 3; ++d)
333 vert_get_diff_n(g, 3 * n + d) *= f;
334 }
335 }
336
337 // edges
338 if (data.spacesOnEntities[MBEDGE].test(H1)) {
339 if (data.dataOnEntities[MBEDGE].size() != 6)
340 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
341 "Wrong size of ent data");
342
343 constexpr int edges_nodes[6][2] = {{0, 1}, {1, 2}, {2, 0},
344 {0, 3}, {1, 3}, {2, 3}};
345 for (int ee = 0; ee != 6; ++ee) {
346 auto &ent_data = data.dataOnEntities[MBEDGE][ee];
347 const int sense = ent_data.getSense();
348 if (sense == 0)
349 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
350 "Sense of the edge unknown");
351 const int order = ent_data.getOrder();
352 const int nb_dofs = NBEDGE_H1(order);
353
354 if (nb_dofs) {
355 if (get_alpha_by_order_ptr(ent_data, order)) {
356 get_alpha_by_name_ptr(ent_data, field_name) =
357 get_alpha_by_order_ptr(ent_data, order);
358 get_base_by_name_ptr(ent_data, field_name) =
359 get_base_by_order_ptr(ent_data, order);
360 get_diff_base_by_name_ptr(ent_data, field_name) =
361 get_diff_base_by_order_ptr(ent_data, order);
362 } else {
363 auto &get_n = get_base(ent_data);
364 auto &get_diff_n = get_diff_base(ent_data);
365 get_n.resize(nb_gauss_pts, nb_dofs, false);
366 get_diff_n.resize(nb_gauss_pts, 3 * nb_dofs, false);
367
368 auto &edge_alpha = get_alpha(data.dataOnEntities[MBEDGE][ee]);
369 edge_alpha.resize(nb_dofs, 4, false);
371 &edge_alpha(0, 0));
372 if (sense == -1) {
373 for (int i = 0; i != edge_alpha.size1(); ++i) {
374 int a = edge_alpha(i, edges_nodes[ee][0]);
375 edge_alpha(i, edges_nodes[ee][0]) =
376 edge_alpha(i, edges_nodes[ee][1]);
377 edge_alpha(i, edges_nodes[ee][1]) = a;
378 }
379 }
381 order, lambda.size1(), edge_alpha.size1(), &edge_alpha(0, 0),
382 &lambda(0, 0), Tools::diffShapeFunMBTET.data(), &get_n(0, 0),
383 &get_diff_n(0, 0));
384
385 get_alpha_by_order_ptr(ent_data, order) =
386 get_alpha_by_name_ptr(ent_data, field_name);
387 get_base_by_order_ptr(ent_data, order) =
388 get_base_by_name_ptr(ent_data, field_name);
389 get_diff_base_by_order_ptr(ent_data, order) =
390 get_diff_base_by_name_ptr(ent_data, field_name);
391 }
392 }
393 }
394 } else {
395 for (int ee = 0; ee != 6; ++ee) {
396 auto &ent_data = data.dataOnEntities[MBEDGE][ee];
397 ent_data.getBBAlphaIndicesSharedPtr(field_name).reset();
398 auto &get_n = get_base(ent_data);
399 auto &get_diff_n = get_diff_base(ent_data);
400 get_n.resize(nb_gauss_pts, 0, false);
401 get_diff_n.resize(nb_gauss_pts, 0, false);
402 }
403 }
404
405 // face
406 if (data.spacesOnEntities[MBTRI].test(H1)) {
407 if (data.dataOnEntities[MBTRI].size() != 4)
408 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
409 "Wrong size of ent data");
410 if (data.facesNodes.size1() != 4)
411 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
412 if (data.facesNodes.size2() != 3)
413 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
414
415 for (int ff = 0; ff != 4; ++ff) {
416 auto &ent_data = data.dataOnEntities[MBTRI][ff];
417 const int order = ent_data.getOrder();
418 const int nb_dofs = NBFACETRI_H1(order);
419
420 if (nb_dofs) {
421 if (get_alpha_by_order_ptr(ent_data, order)) {
422 get_alpha_by_name_ptr(ent_data, field_name) =
423 get_alpha_by_order_ptr(ent_data, order);
424 get_base_by_name_ptr(ent_data, field_name) =
425 get_base_by_order_ptr(ent_data, order);
426 get_diff_base_by_name_ptr(ent_data, field_name) =
427 get_diff_base_by_order_ptr(ent_data, order);
428 } else {
429
430 auto &get_n = get_base(ent_data);
431 auto &get_diff_n = get_diff_base(ent_data);
432 get_n.resize(nb_gauss_pts, nb_dofs, false);
433 get_diff_n.resize(nb_gauss_pts, 3 * nb_dofs, false);
434
435 auto &face_alpha = get_alpha(ent_data);
436 face_alpha.resize(nb_dofs, 4, false);
437
439 &face_alpha(0, 0));
440 senseFaceAlpha.resize(face_alpha.size1(), face_alpha.size2(), false);
441 senseFaceAlpha.clear();
442 constexpr int tri_nodes[4][3] = {
443 {0, 1, 3}, {1, 2, 3}, {0, 2, 3}, {0, 1, 2}};
444 for (int d = 0; d != nb_dofs; ++d)
445 for (int n = 0; n != 3; ++n)
446 senseFaceAlpha(d, data.facesNodes(ff, n)) =
447 face_alpha(d, tri_nodes[ff][n]);
448 face_alpha.swap(senseFaceAlpha);
450 order, lambda.size1(), face_alpha.size1(), &face_alpha(0, 0),
451 &lambda(0, 0), Tools::diffShapeFunMBTET.data(), &get_n(0, 0),
452 &get_diff_n(0, 0));
453
454 get_alpha_by_order_ptr(ent_data, order) =
455 get_alpha_by_name_ptr(ent_data, field_name);
456 get_base_by_order_ptr(ent_data, order) =
457 get_base_by_name_ptr(ent_data, field_name);
458 get_diff_base_by_order_ptr(ent_data, order) =
459 get_diff_base_by_name_ptr(ent_data, field_name);
460 }
461 }
462 }
463 } else {
464 for (int ff = 0; ff != 4; ++ff) {
465 auto &ent_data = data.dataOnEntities[MBTRI][ff];
466 ent_data.getBBAlphaIndicesSharedPtr(field_name).reset();
467 auto &get_n = get_base(ent_data);
468 auto &get_diff_n = get_diff_base(ent_data);
469 get_n.resize(nb_gauss_pts, 0, false);
470 get_diff_n.resize(nb_gauss_pts, 0, false);
471 }
472 }
473
474 if (data.spacesOnEntities[MBTET].test(H1)) {
475 if (data.dataOnEntities[MBTET].size() != 1)
476 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
477 "Wrong size ent of ent data");
478
479 auto &ent_data = data.dataOnEntities[MBTET][0];
480 const int order = ent_data.getOrder();
481 const int nb_dofs = NBVOLUMETET_H1(order);
482 if (get_alpha_by_order_ptr(ent_data, order)) {
483 get_alpha_by_name_ptr(ent_data, field_name) =
484 get_alpha_by_order_ptr(ent_data, order);
485 get_base_by_name_ptr(ent_data, field_name) =
486 get_base_by_order_ptr(ent_data, order);
487 get_diff_base_by_name_ptr(ent_data, field_name) =
488 get_diff_base_by_order_ptr(ent_data, order);
489 } else {
490
491 auto &get_n = get_base(ent_data);
492 auto &get_diff_n = get_diff_base(ent_data);
493 get_n.resize(nb_gauss_pts, nb_dofs, false);
494 get_diff_n.resize(nb_gauss_pts, 3 * nb_dofs, false);
495 if (nb_dofs) {
496 auto &tet_alpha = get_alpha(ent_data);
497 tet_alpha.resize(nb_dofs, 4, false);
498
501 order, lambda.size1(), tet_alpha.size1(), &tet_alpha(0, 0),
502 &lambda(0, 0), Tools::diffShapeFunMBTET.data(), &get_n(0, 0),
503 &get_diff_n(0, 0));
504
505 get_alpha_by_order_ptr(ent_data, order) =
506 get_alpha_by_name_ptr(ent_data, field_name);
507 get_base_by_order_ptr(ent_data, order) =
508 get_base_by_name_ptr(ent_data, field_name);
509 get_diff_base_by_order_ptr(ent_data, order) =
510 get_diff_base_by_name_ptr(ent_data, field_name);
511 }
512 }
513 } else {
514 auto &ent_data = data.dataOnEntities[MBTET][0];
515 ent_data.getBBAlphaIndicesSharedPtr(field_name).reset();
516 auto &get_n = get_base(ent_data);
517 auto &get_diff_n = get_diff_base(ent_data);
518 get_n.resize(nb_gauss_pts, 0, false);
519 get_diff_n.resize(nb_gauss_pts, 0, false);
520 }
521
523}
524
527
528 switch (cTx->bAse) {
533 break;
536 break;
537 default:
538 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not implemented");
539 }
540
542}
543
546
547 EntitiesFieldData &data = cTx->dAta;
548 const FieldApproximationBase base = cTx->bAse;
549 PetscErrorCode (*base_polynomials)(int p, double s, double *diff_s, double *L,
550 double *diffL, const int dim) =
552
553 int nb_gauss_pts = pts.size2();
554 int volume_order = data.dataOnEntities[MBTET][0].getOrder();
555 int nb_dofs = NBVOLUMETET_L2(volume_order);
556
557 data.dataOnEntities[MBTET][0].getN(base).resize(nb_gauss_pts, nb_dofs, false);
558 data.dataOnEntities[MBTET][0].getDiffN(base).resize(nb_gauss_pts, 3 * nb_dofs,
559 false);
560
561 if (!nb_dofs)
563
564 auto get_interior_cache = [this](auto base) -> TetBaseCache::BaseCacheMI * {
565 if (vPtr) {
566 auto it = TetBaseCache::l2BaseInterior[base].find(vPtr);
567 if (it != TetBaseCache::l2BaseInterior[base].end()) {
568 return &it->second;
569 }
570 }
571 return nullptr;
572 };
573
574 auto interior_cache_ptr = get_interior_cache(base);
575
576 if (interior_cache_ptr) {
577 auto it =
578 interior_cache_ptr->find(boost::make_tuple(volume_order, nb_gauss_pts));
579 if (it != interior_cache_ptr->end()) {
580 noalias(data.dataOnEntities[MBTET][0].getN(base)) = it->N;
581 noalias(data.dataOnEntities[MBTET][0].getDiffN(base)) = it->diffN;
583 }
584 }
585
587 data.dataOnEntities[MBTET][0].getOrder(),
588 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
589 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
590 &*data.dataOnEntities[MBTET][0].getN(base).data().begin(),
591 &*data.dataOnEntities[MBTET][0].getDiffN(base).data().begin(),
592 nb_gauss_pts, base_polynomials);
593
594 if (interior_cache_ptr) {
595 auto p = interior_cache_ptr->emplace(
596 TetBaseCache::BaseCacheItem{volume_order, nb_gauss_pts});
597 p.first->N = data.dataOnEntities[MBTET][0].getN(base);
598 p.first->diffN = data.dataOnEntities[MBTET][0].getDiffN(base);
599 }
600
602}
603
607
608 EntitiesFieldData &data = cTx->dAta;
609 const std::string field_name = cTx->fieldName;
610 const int nb_gauss_pts = pts.size2();
611
612 if (data.dataOnEntities[MBVERTEX][0].getN(NOBASE).size1() !=
613 (unsigned int)nb_gauss_pts)
614 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
615 "Base functions or nodes has wrong number of integration points "
616 "for base %s",
618 auto &lambda = data.dataOnEntities[MBVERTEX][0].getN(NOBASE);
619
620 auto get_alpha = [field_name](auto &data) -> MatrixInt & {
621 auto &ptr = data.getBBAlphaIndicesSharedPtr(field_name);
622 if (!ptr)
623 ptr.reset(new MatrixInt());
624 return *ptr;
625 };
626
627 auto get_base = [field_name](auto &data) -> MatrixDouble & {
628 auto &ptr = data.getBBNSharedPtr(field_name);
629 if (!ptr)
630 ptr.reset(new MatrixDouble());
631 return *ptr;
632 };
633
634 auto get_diff_base = [field_name](auto &data) -> MatrixDouble & {
635 auto &ptr = data.getBBDiffNSharedPtr(field_name);
636 if (!ptr)
637 ptr.reset(new MatrixDouble());
638 return *ptr;
639 };
640
641 auto get_alpha_by_name_ptr =
642 [](auto &data,
643 const std::string &field_name) -> boost::shared_ptr<MatrixInt> & {
644 return data.getBBAlphaIndicesSharedPtr(field_name);
645 };
646
647 auto get_base_by_name_ptr =
648 [](auto &data,
649 const std::string &field_name) -> boost::shared_ptr<MatrixDouble> & {
650 return data.getBBNSharedPtr(field_name);
651 };
652
653 auto get_diff_base_by_name_ptr =
654 [](auto &data,
655 const std::string &field_name) -> boost::shared_ptr<MatrixDouble> & {
656 return data.getBBDiffNSharedPtr(field_name);
657 };
658
659 auto get_alpha_by_order_ptr =
660 [](auto &data, const size_t o) -> boost::shared_ptr<MatrixInt> & {
661 return data.getBBAlphaIndicesByOrderSharedPtr(o);
662 };
663
664 auto get_base_by_order_ptr =
665 [](auto &data, const size_t o) -> boost::shared_ptr<MatrixDouble> & {
666 return data.getBBNByOrderSharedPtr(o);
667 };
668
669 auto get_diff_base_by_order_ptr =
670 [](auto &data, const size_t o) -> boost::shared_ptr<MatrixDouble> & {
671 return data.getBBDiffNByOrderSharedPtr(o);
672 };
673
674 if (data.spacesOnEntities[MBTET].test(L2)) {
675 if (data.dataOnEntities[MBTET].size() != 1)
676 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
677 "Wrong size ent of ent data");
678
679 auto &ent_data = data.dataOnEntities[MBTET][0];
680 const int order = ent_data.getOrder();
681 const int nb_dofs = NBVOLUMETET_L2(order);
682
683 if (get_alpha_by_order_ptr(ent_data, order)) {
684 get_alpha_by_name_ptr(ent_data, field_name) =
685 get_alpha_by_order_ptr(ent_data, order);
686 get_base_by_name_ptr(ent_data, field_name) =
687 get_base_by_order_ptr(ent_data, order);
688 get_diff_base_by_name_ptr(ent_data, field_name) =
689 get_diff_base_by_order_ptr(ent_data, order);
690 } else {
691
692 auto &get_n = get_base(ent_data);
693 auto &get_diff_n = get_diff_base(ent_data);
694 get_n.resize(nb_gauss_pts, nb_dofs, false);
695 get_diff_n.resize(nb_gauss_pts, 3 * nb_dofs, false);
696
697 if (nb_dofs) {
698
699 if (order == 0) {
700
701 if (nb_dofs != 1)
702 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
703 "Inconsistent number of DOFs");
704
705 auto &tri_alpha = get_alpha(ent_data);
706 tri_alpha.clear();
707 get_n(0, 0) = 1;
708 get_diff_n.clear();
709
710 } else {
711
712 if (nb_dofs != 4 + 6 * NBEDGE_H1(order) + 4 * NBFACETRI_H1(order) +
714 nb_dofs != NBVOLUMETET_L2(order))
715 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
716 "Inconsistent number of DOFs");
717
718 auto &tet_alpha = get_alpha(ent_data);
719 tet_alpha.resize(nb_dofs, 4, false);
720
722 &tet_alpha(0, 0));
723 if (order > 1) {
724 std::array<int, 6> edge_n{order, order, order, order, order, order};
725 std::array<int *, 6> tet_edge_ptr{
726 &tet_alpha(4, 0),
727 &tet_alpha(4 + 1 * NBEDGE_H1(order), 0),
728 &tet_alpha(4 + 2 * NBEDGE_H1(order), 0),
729 &tet_alpha(4 + 3 * NBEDGE_H1(order), 0),
730 &tet_alpha(4 + 4 * NBEDGE_H1(order), 0),
731 &tet_alpha(4 + 5 * NBEDGE_H1(order), 0)};
733 tet_edge_ptr.data());
734 if (order > 2) {
735 std::array<int, 6> face_n{order, order, order, order};
736 std::array<int *, 6> tet_face_ptr{
737 &tet_alpha(4 + 6 * NBEDGE_H1(order), 0),
738 &tet_alpha(4 + 6 * NBEDGE_H1(order) + 1 * NBFACETRI_H1(order),
739 0),
740 &tet_alpha(4 + 6 * NBEDGE_H1(order) + 2 * NBFACETRI_H1(order),
741 0),
742 &tet_alpha(4 + 6 * NBEDGE_H1(order) + 3 * NBFACETRI_H1(order),
743 0),
744 };
746 face_n.data(), tet_face_ptr.data());
747 if (order > 3)
749 order,
750 &tet_alpha(
751 4 + 6 * NBEDGE_H1(order) + 4 * NBFACETRI_H1(order), 0));
752 }
753 }
754
756 order, lambda.size1(), tet_alpha.size1(), &tet_alpha(0, 0),
757 &lambda(0, 0), Tools::diffShapeFunMBTET.data(), &get_n(0, 0),
758 &get_diff_n(0, 0));
759
760 get_alpha_by_order_ptr(ent_data, order) =
761 get_alpha_by_name_ptr(ent_data, field_name);
762 get_base_by_order_ptr(ent_data, order) =
763 get_base_by_name_ptr(ent_data, field_name);
764 get_diff_base_by_order_ptr(ent_data, order) =
765 get_diff_base_by_name_ptr(ent_data, field_name);
766 }
767 }
768 }
769 } else {
770 auto &ent_data = data.dataOnEntities[MBTET][0];
771 ent_data.getBBAlphaIndicesSharedPtr(field_name).reset();
772 auto &get_n = get_base(ent_data);
773 auto &get_diff_n = get_diff_base(ent_data);
774 get_n.resize(nb_gauss_pts, 0, false);
775 get_diff_n.resize(nb_gauss_pts, 0, false);
776 }
777
779}
780
782
783 MatrixDouble &pts,
784
785 MatrixDouble &shape_functions, MatrixDouble &diff_shape_functions,
786
787 int volume_order, std::array<int, 4> &faces_order,
788 std::array<int, 3 * 4> &faces_nodes,
789
790 boost::function<int(int)> broken_nbfacetri_edge_hdiv,
791 boost::function<int(int)> broken_nbfacetri_face_hdiv,
792 boost::function<int(int)> broken_nbvolumetet_edge_hdiv,
793 boost::function<int(int)> broken_nbvolumetet_face_hdiv,
794 boost::function<int(int)> broken_nbvolumetet_volume_hdiv
795
796) {
798
799 PetscErrorCode (*base_polynomials)(int p, double s, double *diff_s, double *L,
800 double *diffL, const int dim) =
802
803 int nb_gauss_pts = pts.size2();
804
805 // face shape functions
806
807 double *phi_f_e[4][3];
808 double *phi_f[4];
809 double *diff_phi_f_e[4][3];
810 double *diff_phi_f[4];
811
812 N_face_edge.resize(4, 3, false);
813 N_face_bubble.resize(4, false);
814 diffN_face_edge.resize(4, 3, false);
815 diffN_face_bubble.resize(4, false);
816
817 for (int ff = 0; ff != 4; ++ff) {
818 const auto face_edge_dofs = NBFACETRI_AINSWORTH_EDGE_HDIV(
819 broken_nbfacetri_edge_hdiv(faces_order[ff]));
820 // three edges on face
821 for (int ee = 0; ee < 3; ee++) {
822 N_face_edge(ff, ee).resize(nb_gauss_pts, 3 * face_edge_dofs, false);
823 diffN_face_edge(ff, ee).resize(nb_gauss_pts, 9 * face_edge_dofs, false);
824 phi_f_e[ff][ee] = &*N_face_edge(ff, ee).data().begin();
825 diff_phi_f_e[ff][ee] = &*diffN_face_edge(ff, ee).data().begin();
826 }
827 auto face_bubble_dofs = NBFACETRI_AINSWORTH_FACE_HDIV(
828 broken_nbfacetri_face_hdiv(faces_order[ff]));
829 N_face_bubble[ff].resize(nb_gauss_pts, 3 * face_bubble_dofs, false);
830 diffN_face_bubble[ff].resize(nb_gauss_pts, 9 * face_bubble_dofs, false);
831 phi_f[ff] = &*(N_face_bubble[ff].data().begin());
832 diff_phi_f[ff] = &*(diffN_face_bubble[ff].data().begin());
833 }
834
835 constexpr int nb_nodes_on_tet = 4;
836
837 for (int ff = 0; ff < 4; ff++) {
839 &faces_nodes[3 * ff], broken_nbfacetri_edge_hdiv(faces_order[ff]),
840 &*shape_functions.data().begin(), &*diff_shape_functions.data().begin(),
841 phi_f_e[ff], diff_phi_f_e[ff], nb_gauss_pts, nb_nodes_on_tet,
842 base_polynomials);
843 }
844
845 for (int ff = 0; ff < 4; ff++) {
847 &faces_nodes[3 * ff], broken_nbfacetri_face_hdiv(faces_order[ff]),
848 &*shape_functions.data().begin(), &*diff_shape_functions.data().begin(),
849 phi_f[ff], diff_phi_f[ff], nb_gauss_pts, nb_nodes_on_tet,
850 base_polynomials);
851 }
852
853 // volume shape functions
854
855 double *phi_v_e[6];
856 double *phi_v_f[4];
857 double *phi_v;
858 double *diff_phi_v_e[6];
859 double *diff_phi_v_f[4];
860 double *diff_phi_v;
861
862 const auto volume_edge_dofs = NBVOLUMETET_AINSWORTH_EDGE_HDIV(
863 broken_nbvolumetet_edge_hdiv(volume_order));
864 N_volume_edge.resize(6, false);
865 diffN_volume_edge.resize(6, false);
866 for (int ee = 0; ee != 6; ++ee) {
867 N_volume_edge[ee].resize(nb_gauss_pts, 3 * volume_edge_dofs, false);
868 diffN_volume_edge[ee].resize(nb_gauss_pts, 9 * volume_edge_dofs, false);
869 phi_v_e[ee] = &*(N_volume_edge[ee].data().begin());
870 diff_phi_v_e[ee] = &*(diffN_volume_edge[ee].data().begin());
871 }
872 if (volume_edge_dofs)
874 broken_nbvolumetet_edge_hdiv(volume_order),
875 &*shape_functions.data().begin(), &*diff_shape_functions.data().begin(),
876 phi_v_e, diff_phi_v_e, nb_gauss_pts, base_polynomials);
877
878 const auto volume_face_dofs = NBVOLUMETET_AINSWORTH_FACE_HDIV(
879 broken_nbvolumetet_face_hdiv(volume_order));
880 N_volume_face.resize(4, false);
881 diffN_volume_face.resize(4, false);
882 for (int ff = 0; ff != 4; ++ff) {
883 N_volume_face[ff].resize(nb_gauss_pts, 3 * volume_face_dofs, false);
884 diffN_volume_face[ff].resize(nb_gauss_pts, 9 * volume_face_dofs, false);
885 phi_v_f[ff] = &*(N_volume_face[ff].data().begin());
886 diff_phi_v_f[ff] = &*(diffN_volume_face[ff].data().begin());
887 }
888 if (volume_face_dofs)
890 broken_nbvolumetet_face_hdiv(volume_order),
891 &*shape_functions.data().begin(), &*diff_shape_functions.data().begin(),
892 phi_v_f, diff_phi_v_f, nb_gauss_pts, base_polynomials);
893
894 auto volume_bubble_dofs = NBVOLUMETET_AINSWORTH_VOLUME_HDIV(
895 broken_nbvolumetet_volume_hdiv(volume_order));
896 N_volume_bubble.resize(nb_gauss_pts, 3 * volume_bubble_dofs, false);
897 diffN_volume_bubble.resize(nb_gauss_pts, 9 * volume_bubble_dofs, false);
898 phi_v = &*(N_volume_bubble.data().begin());
899 diff_phi_v = &*(diffN_volume_bubble.data().begin());
900 if (volume_bubble_dofs)
902 broken_nbvolumetet_volume_hdiv(volume_order),
903 &*shape_functions.data().begin(), &*diff_shape_functions.data().begin(),
904 phi_v, diff_phi_v, nb_gauss_pts, base_polynomials);
905
907}
908
911
912 std::array<int, 4> faces_order;
913 std::array<int, 4 * 3> faces_nodes;
914
916 EntitiesFieldData &data = cTx->dAta;
917
918 int volume_order = data.dataOnEntities[MBTET][0].getOrder();
919 std::copy(data.facesNodes.data().begin(), data.facesNodes.data().end(),
920 faces_nodes.begin());
921 for (int ff = 0; ff != 4; ff++) {
922 faces_order[ff] = cTx->dAta.dataOnEntities[MBTRI][ff].getOrder();
923 }
924
926 pts, data.dataOnEntities[MBVERTEX][0].getN(base),
927 data.dataOnEntities[MBVERTEX][0].getDiffN(base), volume_order,
928 faces_order, faces_nodes,
929
935
936 );
937
938 // Set shape functions into data structure Shape functions hast to be put
939 // in arrays in order which guarantee hierarchical series of degrees of
940 // freedom, i.e. in other words dofs form sub-entities has to be group
941 // by order.
942
943 FTENSOR_INDEX(3, i);
944 FTENSOR_INDEX(3, j);
945
946 int nb_gauss_pts = pts.size2();
947
948 // faces
949 if (data.dataOnEntities[MBTRI].size() != 4) {
950 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
951 }
952
953 // face-face
954 using Tensor1Ptr3 =
955 decltype(getFTensor1FromPtr<3>(static_cast<double *>(nullptr)));
956 Tensor1Ptr3 t_base_f_f[] = {
957 getFTensor1FromPtr<3>(&*(N_face_bubble[0].data().begin())),
958 getFTensor1FromPtr<3>(&*(N_face_bubble[1].data().begin())),
959 getFTensor1FromPtr<3>(&*(N_face_bubble[2].data().begin())),
960 getFTensor1FromPtr<3>(&*(N_face_bubble[3].data().begin()))};
961 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_f_f[] = {
962 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_bubble[0].data().begin())),
963 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_bubble[1].data().begin())),
964 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_bubble[2].data().begin())),
965 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_bubble[3].data().begin()))};
966 // face-edge
967 Tensor1Ptr3 t_base_f_e[] = {
968 getFTensor1FromPtr<3>(&*(N_face_edge(0, 0).data().begin())),
969 getFTensor1FromPtr<3>(&*(N_face_edge(0, 1).data().begin())),
970 getFTensor1FromPtr<3>(&*(N_face_edge(0, 2).data().begin())),
971 getFTensor1FromPtr<3>(&*(N_face_edge(1, 0).data().begin())),
972 getFTensor1FromPtr<3>(&*(N_face_edge(1, 1).data().begin())),
973 getFTensor1FromPtr<3>(&*(N_face_edge(1, 2).data().begin())),
974 getFTensor1FromPtr<3>(&*(N_face_edge(2, 0).data().begin())),
975 getFTensor1FromPtr<3>(&*(N_face_edge(2, 1).data().begin())),
976 getFTensor1FromPtr<3>(&*(N_face_edge(2, 2).data().begin())),
977 getFTensor1FromPtr<3>(&*(N_face_edge(3, 0).data().begin())),
978 getFTensor1FromPtr<3>(&*(N_face_edge(3, 1).data().begin())),
979 getFTensor1FromPtr<3>(&*(N_face_edge(3, 2).data().begin()))};
980 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_f_e[] = {
981 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(0, 0).data().begin())),
982 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(0, 1).data().begin())),
983 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(0, 2).data().begin())),
984 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(1, 0).data().begin())),
985 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(1, 1).data().begin())),
986 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(1, 2).data().begin())),
987 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(2, 0).data().begin())),
988 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(2, 1).data().begin())),
989 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(2, 2).data().begin())),
990 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(3, 0).data().begin())),
991 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(3, 1).data().begin())),
992 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(3, 2).data().begin()))};
993
994 for (int ff = 0; ff != 4; ff++) {
995 int face_order = faces_order[ff];
996 auto face_dofs =
1001 data.dataOnEntities[MBTRI][ff].getN(base).resize(nb_gauss_pts,
1002 3 * face_dofs, false);
1003 data.dataOnEntities[MBTRI][ff].getDiffN(base).resize(nb_gauss_pts,
1004 9 * face_dofs, false);
1005 if (face_dofs) {
1006 double *base_ptr =
1007 &*data.dataOnEntities[MBTRI][ff].getN(base).data().begin();
1008 double *diff_base_ptr =
1009 &*data.dataOnEntities[MBTRI][ff].getDiffN(base).data().begin();
1010 auto t_base = getFTensor1FromPtr<3>(base_ptr);
1011 auto t_diff_base = getFTensor2HVecFromPtr<3, 3>(diff_base_ptr);
1012
1013 auto max_face_order =
1014 std::max(face_order,
1016 max_face_order =
1017 std::max(max_face_order,
1019
1020 for (int gg = 0; gg != nb_gauss_pts; gg++) {
1021 for (int oo = 0; oo != max_face_order; oo++) {
1022
1023 // face-edge
1025 for (int dd = NBFACETRI_AINSWORTH_EDGE_HDIV(oo);
1026 dd != NBFACETRI_AINSWORTH_EDGE_HDIV(oo + 1); dd++) {
1027 for (int ee = 0; ee != 3; ++ee) {
1028 t_base(i) = t_base_f_e[ff * 3 + ee](i);
1029 ++t_base;
1030 ++t_base_f_e[ff * 3 + ee];
1031 }
1032 for (int ee = 0; ee != 3; ++ee) {
1033 t_diff_base(i, j) = t_diff_base_f_e[ff * 3 + ee](i, j);
1034 ++t_diff_base;
1035 ++t_diff_base_f_e[ff * 3 + ee];
1036 }
1037 }
1038
1039 // face-face
1041 for (int dd = NBFACETRI_AINSWORTH_FACE_HDIV(oo);
1042 dd != NBFACETRI_AINSWORTH_FACE_HDIV(oo + 1); dd++) {
1043 t_base(i) = t_base_f_f[ff](i);
1044 ++t_base;
1045 ++t_base_f_f[ff];
1046 t_diff_base(i, j) = t_diff_base_f_f[ff](i, j);
1047 ++t_diff_base;
1048 ++t_diff_base_f_f[ff];
1049 }
1050 }
1051 }
1052 }
1053 }
1054
1055 // volume
1056 int volume_dofs =
1063 data.dataOnEntities[MBTET][0].getN(base).resize(nb_gauss_pts, 3 * volume_dofs,
1064 false);
1065 data.dataOnEntities[MBTET][0].getDiffN(base).resize(nb_gauss_pts,
1066 9 * volume_dofs, false);
1067 if (volume_dofs) {
1068 double *base_ptr =
1069 &*data.dataOnEntities[MBTET][0].getN(base).data().begin();
1070 double *diff_base_ptr =
1071 &*data.dataOnEntities[MBTET][0].getDiffN(base).data().begin();
1072 auto t_base = getFTensor1FromPtr<3>(base_ptr);
1073 auto t_diff_base = getFTensor2HVecFromPtr<3, 3>(diff_base_ptr);
1074
1075 // volume-edge
1076 using Tensor1Ptr3 =
1077 decltype(getFTensor1FromPtr<3>(static_cast<double *>(nullptr)));
1078 Tensor1Ptr3 t_base_v_e[] = {
1079 getFTensor1FromPtr<3>(&*N_volume_edge[0].data().begin()),
1080 getFTensor1FromPtr<3>(&*N_volume_edge[1].data().begin()),
1081 getFTensor1FromPtr<3>(&*N_volume_edge[2].data().begin()),
1082 getFTensor1FromPtr<3>(&*N_volume_edge[3].data().begin()),
1083 getFTensor1FromPtr<3>(&*N_volume_edge[4].data().begin()),
1084 getFTensor1FromPtr<3>(&*N_volume_edge[5].data().begin())};
1085 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_v_e[] = {
1091 getFTensor2HVecFromPtr<3, 3>(&*diffN_volume_edge[5].data().begin())};
1092
1093 // volume-faces
1094 Tensor1Ptr3 t_base_v_f[] = {
1095 getFTensor1FromPtr<3>(&*N_volume_face[0].data().begin()),
1096 getFTensor1FromPtr<3>(&*N_volume_face[1].data().begin()),
1097 getFTensor1FromPtr<3>(&*N_volume_face[2].data().begin()),
1098 getFTensor1FromPtr<3>(&*N_volume_face[3].data().begin())};
1099 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_v_f[] = {
1103 getFTensor2HVecFromPtr<3, 3>(&*diffN_volume_face[3].data().begin())};
1104
1105 // volume-bubble
1106 base_ptr = &*(N_volume_bubble.data().begin());
1107 diff_base_ptr = &*(diffN_volume_bubble.data().begin());
1108 auto t_base_v = getFTensor1FromPtr<3>(base_ptr);
1109 auto t_diff_base_v = getFTensor2HVecFromPtr<3, 3>(diff_base_ptr);
1110
1111 auto max_volume_order = std::max(
1112 volume_order,
1114 max_volume_order = std::max(
1115 max_volume_order,
1117 max_volume_order = std::max(
1118 max_volume_order,
1120
1121 for (int gg = 0; gg != nb_gauss_pts; gg++) {
1122 for (int oo = 0; oo < max_volume_order; oo++) {
1123
1124 // volume-edge
1125 if (oo <
1127 for (int dd = NBVOLUMETET_AINSWORTH_EDGE_HDIV(oo);
1128 dd != NBVOLUMETET_AINSWORTH_EDGE_HDIV(oo + 1); dd++) {
1129 for (int ee = 0; ee < 6; ee++) {
1130 t_base(i) = t_base_v_e[ee](i);
1131 ++t_base;
1132 ++t_base_v_e[ee];
1133 t_diff_base(i, j) = t_diff_base_v_e[ee](i, j);
1134 ++t_diff_base;
1135 ++t_diff_base_v_e[ee];
1136 }
1137 }
1138
1139 // volume-face
1140 if (oo <
1142 for (int dd = NBVOLUMETET_AINSWORTH_FACE_HDIV(oo);
1143 dd < NBVOLUMETET_AINSWORTH_FACE_HDIV(oo + 1); dd++) {
1144 for (int ff = 0; ff < 4; ff++) {
1145 t_base(i) = t_base_v_f[ff](i);
1146 ++t_base;
1147 ++t_base_v_f[ff];
1148 t_diff_base(i, j) = t_diff_base_v_f[ff](i, j);
1149 ++t_diff_base;
1150 ++t_diff_base_v_f[ff];
1151 }
1152 }
1153
1154 // volume-bubble
1155 if (oo <
1157 for (int dd = NBVOLUMETET_AINSWORTH_VOLUME_HDIV(oo);
1158 dd < NBVOLUMETET_AINSWORTH_VOLUME_HDIV(oo + 1); dd++) {
1159 t_base(i) = t_base_v(i);
1160 ++t_base;
1161 ++t_base_v;
1162 t_diff_base(i, j) = t_diff_base_v(i, j);
1163 ++t_diff_base;
1164 ++t_diff_base_v;
1165 }
1166 }
1167 }
1168 }
1169
1171}
1172
1176
1177 // Set shape functions into data structure Shape functions has to be put
1178 // in arrays in order which guarantee hierarchical series of degrees of
1179 // freedom, i.e. in other words dofs form sub-entities has to be group
1180 // by order.
1181
1183 EntitiesFieldData &data = cTx->dAta;
1184
1185 FTENSOR_INDEX(3, i);
1186 FTENSOR_INDEX(3, j);
1187
1188 int volume_order = data.dataOnEntities[MBTET][0].getOrder();
1189 int nb_gauss_pts = pts.size2();
1190 int nb_dofs_face =
1195 int nb_dofs_volume =
1202
1203 int nb_dofs = 4 * nb_dofs_face + nb_dofs_volume;
1204 data.dataOnEntities[MBTET][0].getN(base).resize(nb_gauss_pts, 3 * nb_dofs,
1205 false);
1206 data.dataOnEntities[MBTET][0].getDiffN(base).resize(nb_gauss_pts, 9 * nb_dofs,
1207 false);
1208 if (nb_dofs == 0)
1210
1211 auto get_interior_cache = [this](auto base) -> TetBaseCache::BaseCacheMI * {
1212 if (vPtr) {
1213 auto it = TetBaseCache::hdivBrokenBaseInterior[base].find(vPtr);
1214 if (it != TetBaseCache::hdivBrokenBaseInterior[base].end()) {
1215 return &it->second;
1216 }
1217 }
1218 return nullptr;
1219 };
1220
1221 auto interior_cache_ptr = get_interior_cache(base);
1222
1223 if (interior_cache_ptr) {
1224 auto it =
1225 interior_cache_ptr->find(boost::make_tuple(volume_order, nb_gauss_pts));
1226 if (it != interior_cache_ptr->end()) {
1227 noalias(data.dataOnEntities[MBTET][0].getN(base)) = it->N;
1228 noalias(data.dataOnEntities[MBTET][0].getDiffN(base)) = it->diffN;
1230 }
1231 }
1232
1233 std::array<int, 4 * 3> faces_nodes = {0, 1, 3, 1, 2, 3, 0, 3, 2, 0, 2, 1};
1234 std::array<int, 4> faces_order{volume_order, volume_order, volume_order,
1235 volume_order};
1237 pts, data.dataOnEntities[MBVERTEX][0].getN(base),
1238 data.dataOnEntities[MBVERTEX][0].getDiffN(base), volume_order,
1239 faces_order, faces_nodes,
1240
1246
1247 );
1248
1249 auto *base_ptr = &*data.dataOnEntities[MBTET][0].getN(base).data().begin();
1250 auto *diff_base_ptr =
1251 &*data.dataOnEntities[MBTET][0].getDiffN(base).data().begin();
1252 auto t_base = getFTensor1FromPtr<3>(base_ptr);
1253 auto t_diff_base = getFTensor2HVecFromPtr<3, 3>(diff_base_ptr);
1254
1255 // face-edge
1256 using Tensor1Ptr3 =
1257 decltype(getFTensor1FromPtr<3>(static_cast<double *>(nullptr)));
1258 Tensor1Ptr3 t_base_f_e[] = {
1259 getFTensor1FromPtr<3>(&*(N_face_edge(0, 0).data().begin())),
1260 getFTensor1FromPtr<3>(&*(N_face_edge(0, 1).data().begin())),
1261 getFTensor1FromPtr<3>(&*(N_face_edge(0, 2).data().begin())),
1262 getFTensor1FromPtr<3>(&*(N_face_edge(1, 0).data().begin())),
1263 getFTensor1FromPtr<3>(&*(N_face_edge(1, 1).data().begin())),
1264 getFTensor1FromPtr<3>(&*(N_face_edge(1, 2).data().begin())),
1265 getFTensor1FromPtr<3>(&*(N_face_edge(2, 0).data().begin())),
1266 getFTensor1FromPtr<3>(&*(N_face_edge(2, 1).data().begin())),
1267 getFTensor1FromPtr<3>(&*(N_face_edge(2, 2).data().begin())),
1268 getFTensor1FromPtr<3>(&*(N_face_edge(3, 0).data().begin())),
1269 getFTensor1FromPtr<3>(&*(N_face_edge(3, 1).data().begin())),
1270 getFTensor1FromPtr<3>(&*(N_face_edge(3, 2).data().begin()))};
1271 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_f_e[] = {
1272 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(0, 0).data().begin())),
1273 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(0, 1).data().begin())),
1274 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(0, 2).data().begin())),
1275 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(1, 0).data().begin())),
1276 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(1, 1).data().begin())),
1277 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(1, 2).data().begin())),
1278 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(2, 0).data().begin())),
1279 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(2, 1).data().begin())),
1280 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(2, 2).data().begin())),
1281 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(3, 0).data().begin())),
1282 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(3, 1).data().begin())),
1283 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_edge(3, 2).data().begin()))};
1284
1285 // face-face
1286 Tensor1Ptr3 t_base_f_f[] = {
1287 getFTensor1FromPtr<3>(&*(N_face_bubble[0].data().begin())),
1288 getFTensor1FromPtr<3>(&*(N_face_bubble[1].data().begin())),
1289 getFTensor1FromPtr<3>(&*(N_face_bubble[2].data().begin())),
1290 getFTensor1FromPtr<3>(&*(N_face_bubble[3].data().begin()))};
1291 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_f_f[] = {
1292 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_bubble[0].data().begin())),
1293 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_bubble[1].data().begin())),
1294 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_bubble[2].data().begin())),
1295 getFTensor2HVecFromPtr<3, 3>(&*(diffN_face_bubble[3].data().begin()))};
1296
1297 // volume-edge
1298 Tensor1Ptr3 t_base_v_e[] = {
1299 getFTensor1FromPtr<3>(&*N_volume_edge[0].data().begin()),
1300 getFTensor1FromPtr<3>(&*N_volume_edge[1].data().begin()),
1301 getFTensor1FromPtr<3>(&*N_volume_edge[2].data().begin()),
1302 getFTensor1FromPtr<3>(&*N_volume_edge[3].data().begin()),
1303 getFTensor1FromPtr<3>(&*N_volume_edge[4].data().begin()),
1304 getFTensor1FromPtr<3>(&*N_volume_edge[5].data().begin())};
1305 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_v_e[] = {
1311 getFTensor2HVecFromPtr<3, 3>(&*diffN_volume_edge[5].data().begin())};
1312
1313 // volume-faces
1314 Tensor1Ptr3 t_base_v_f[] = {
1315 getFTensor1FromPtr<3>(&*N_volume_face[0].data().begin()),
1316 getFTensor1FromPtr<3>(&*N_volume_face[1].data().begin()),
1317 getFTensor1FromPtr<3>(&*N_volume_face[2].data().begin()),
1318 getFTensor1FromPtr<3>(&*N_volume_face[3].data().begin())};
1319 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_v_f[] = {
1323 getFTensor2HVecFromPtr<3, 3>(&*diffN_volume_face[3].data().begin())};
1324
1325 // volume-bubble
1326 auto *base_vol_ptr = &*(N_volume_bubble.data().begin());
1327 auto *diff_base_vol_ptr = &*(diffN_volume_bubble.data().begin());
1328 auto t_base_v = getFTensor1FromPtr<3>(base_vol_ptr);
1329 auto t_diff_base_v = getFTensor2HVecFromPtr<3, 3>(diff_base_vol_ptr);
1330
1331 int count_dofs = 0;
1332 int count_dofs_face = 0;
1333 int count_dofs_volume = 0;
1334
1335 auto max_volume_order =
1336 std::max(volume_order,
1338 max_volume_order =
1339 std::max(max_volume_order,
1341 max_volume_order =
1342 std::max(max_volume_order,
1344 max_volume_order =
1345 std::max(max_volume_order,
1347 max_volume_order = std::max(
1348 max_volume_order,
1350
1351 for (int gg = 0; gg != nb_gauss_pts; gg++) {
1352 for (int oo = 0; oo < max_volume_order; oo++) {
1353
1354 // faces-edge (((P) > 0) ? (P) : 0)
1356 for (int dd = NBFACETRI_AINSWORTH_EDGE_HDIV(oo);
1357 dd != NBFACETRI_AINSWORTH_EDGE_HDIV(oo + 1); dd++) {
1358 for (auto ff = 0; ff != 4; ++ff) {
1359 for (int ee = 0; ee != 3; ++ee) {
1360 t_base(i) = t_base_f_e[ff * 3 + ee](i);
1361 ++t_base;
1362 ++t_base_f_e[ff * 3 + ee];
1363 ++count_dofs;
1364 ++count_dofs_face;
1365 }
1366 for (int ee = 0; ee != 3; ++ee) {
1367 t_diff_base(i, j) = t_diff_base_f_e[ff * 3 + ee](i, j);
1368 ++t_diff_base;
1369 ++t_diff_base_f_e[ff * 3 + ee];
1370 }
1371 }
1372 }
1373
1374 // face-face (P - 1) * (P - 2) / 2
1376 for (int dd = NBFACETRI_AINSWORTH_FACE_HDIV(oo);
1377 dd != NBFACETRI_AINSWORTH_FACE_HDIV(oo + 1); dd++) {
1378 for (auto ff = 0; ff != 4; ++ff) {
1379 t_base(i) = t_base_f_f[ff](i);
1380 ++t_base;
1381 ++t_base_f_f[ff];
1382 t_diff_base(i, j) = t_diff_base_f_f[ff](i, j);
1383 ++t_diff_base;
1384 ++t_diff_base_f_f[ff];
1385 ++count_dofs;
1386 ++count_dofs_face;
1387 }
1388 }
1389
1390 // volume-edge (P - 1)
1392 for (int dd = NBVOLUMETET_AINSWORTH_EDGE_HDIV(oo);
1393 dd != NBVOLUMETET_AINSWORTH_EDGE_HDIV(oo + 1); dd++) {
1394 for (int ee = 0; ee < 6; ++ee) {
1395 t_base(i) = t_base_v_e[ee](i);
1396 ++t_base;
1397 ++t_base_v_e[ee];
1398 t_diff_base(i, j) = t_diff_base_v_e[ee](i, j);
1399 ++t_diff_base;
1400 ++t_diff_base_v_e[ee];
1401 ++count_dofs;
1402 ++count_dofs_volume;
1403 }
1404 }
1405
1406 // volume-face (P - 1) * (P - 2)
1408 for (int dd = NBVOLUMETET_AINSWORTH_FACE_HDIV(oo);
1409 dd != NBVOLUMETET_AINSWORTH_FACE_HDIV(oo + 1); dd++) {
1410 for (int ff = 0; ff < 4; ff++) {
1411 t_base(i) = t_base_v_f[ff](i);
1412 ++t_base;
1413 ++t_base_v_f[ff];
1414 t_diff_base(i, j) = t_diff_base_v_f[ff](i, j);
1415 ++t_diff_base;
1416 ++t_diff_base_v_f[ff];
1417 ++count_dofs;
1418 ++count_dofs_volume;
1419 }
1420 }
1421
1422 // volume-bubble (P - 3) * (P - 2) * (P - 1) / 2
1423 if (oo <
1425 for (int dd = NBVOLUMETET_AINSWORTH_VOLUME_HDIV(oo);
1426 dd != NBVOLUMETET_AINSWORTH_VOLUME_HDIV(oo + 1); dd++) {
1427 t_base(i) = t_base_v(i);
1428 ++t_base;
1429 ++t_base_v;
1430 t_diff_base(i, j) = t_diff_base_v(i, j);
1431 ++t_diff_base;
1432 ++t_diff_base_v;
1433 ++count_dofs;
1434 ++count_dofs_volume;
1435 }
1436 }
1437 }
1438
1439#ifndef NDEBUG
1440 if (nb_dofs != count_dofs / nb_gauss_pts) {
1441 MOFEM_LOG_CHANNEL("SELF");
1442 MOFEM_LOG("SELF", Sev::error) << "Nb dofs face: " << 4 * nb_dofs_face
1443 << " -> " << count_dofs_face / nb_gauss_pts;
1444 MOFEM_LOG("SELF", Sev::error) << "Nb dofs volume: " << nb_dofs_volume
1445 << " -> " << count_dofs_volume / nb_gauss_pts;
1446 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1447 "Number of dofs %d is different than expected %d",
1448 count_dofs / nb_gauss_pts, nb_dofs);
1449 }
1450#endif // NDEBUG
1451
1452 if (interior_cache_ptr) {
1453 auto p = interior_cache_ptr->emplace(
1454 TetBaseCache::BaseCacheItem{volume_order, nb_gauss_pts});
1455 p.first->N = data.dataOnEntities[MBTET][0].getN(base);
1456 p.first->diffN = data.dataOnEntities[MBTET][0].getDiffN(base);
1457 }
1458
1460}
1461
1464
1465 EntitiesFieldData &data = cTx->dAta;
1466 const FieldApproximationBase base = cTx->bAse;
1467 if (base != DEMKOWICZ_JACOBI_BASE) {
1468 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1469 "This should be used only with DEMKOWICZ_JACOBI_BASE "
1470 "but base is %s",
1472 }
1473 int nb_gauss_pts = pts.size2();
1474
1475 int volume_order = data.dataOnEntities[MBTET][0].getOrder();
1476
1477 int p_f[4];
1478 double *phi_f[4];
1479 double *diff_phi_f[4];
1480
1481 auto get_face_cache_ptr = [this]() -> TetBaseCache::HDivBaseFaceCacheMI * {
1482 if (vPtr) {
1485 return &it->second;
1486 }
1487 }
1488 return nullptr;
1489 };
1490
1491 auto face_cache_ptr = get_face_cache_ptr();
1492
1493 // Calculate base function on tet faces
1494 for (int ff = 0; ff != 4; ff++) {
1495 int face_order = data.dataOnEntities[MBTRI][ff].getOrder();
1496 int order = volume_order > face_order ? volume_order : face_order;
1497 data.dataOnEntities[MBTRI][ff].getN(base).resize(
1498 nb_gauss_pts, 3 * NBFACETRI_DEMKOWICZ_HDIV(order), false);
1499 data.dataOnEntities[MBTRI][ff].getDiffN(base).resize(
1500 nb_gauss_pts, 9 * NBFACETRI_DEMKOWICZ_HDIV(order), false);
1502 continue;
1503
1504 if (face_cache_ptr) {
1505 auto it = face_cache_ptr->find(boost::make_tuple(
1506
1507 face_order, nb_gauss_pts,
1508
1509 data.facesNodes(ff, 0), data.facesNodes(ff, 1), data.facesNodes(ff, 2)
1510
1511 ));
1512 if (it != face_cache_ptr->end()) {
1513 noalias(data.dataOnEntities[MBTRI][ff].getN(base)) = it->N;
1514 noalias(data.dataOnEntities[MBTRI][ff].getDiffN(base)) = it->diffN;
1515 continue;
1516 }
1517 }
1518
1519 p_f[ff] = order;
1520 phi_f[ff] = &*data.dataOnEntities[MBTRI][ff].getN(base).data().begin();
1521 diff_phi_f[ff] =
1522 &*data.dataOnEntities[MBTRI][ff].getDiffN(base).data().begin();
1523
1525 &data.facesNodes(ff, 0), order,
1526 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
1527 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
1528 phi_f[ff], diff_phi_f[ff], nb_gauss_pts, 4);
1529 if (face_cache_ptr) {
1530 auto p = face_cache_ptr->emplace(TetBaseCache::HDivBaseCacheItem{
1531 face_order, nb_gauss_pts, data.facesNodes(ff, 0),
1532 data.facesNodes(ff, 1), data.facesNodes(ff, 2)});
1533 p.first->N = data.dataOnEntities[MBTRI][ff].getN(base);
1534 p.first->diffN = data.dataOnEntities[MBTRI][ff].getDiffN(base);
1535 }
1536 }
1537
1538 auto get_interior_cache = [this]() -> TetBaseCache::BaseCacheMI * {
1539 if (vPtr) {
1540 auto it =
1543 return &it->second;
1544 }
1545 }
1546 return nullptr;
1547 };
1548
1549 auto interior_cache_ptr = get_interior_cache();
1550
1551 // Calculate base functions in tet interior
1552 if (NBVOLUMETET_DEMKOWICZ_HDIV(volume_order) > 0) {
1553 data.dataOnEntities[MBTET][0].getN(base).resize(
1554 nb_gauss_pts, 3 * NBVOLUMETET_DEMKOWICZ_HDIV(volume_order), false);
1555 data.dataOnEntities[MBTET][0].getDiffN(base).resize(
1556 nb_gauss_pts, 9 * NBVOLUMETET_DEMKOWICZ_HDIV(volume_order), false);
1557
1558 for (int v = 0; v != 1; ++v) {
1559 if (interior_cache_ptr) {
1560 auto it = interior_cache_ptr->find(
1561 boost::make_tuple(volume_order, nb_gauss_pts));
1562 if (it != interior_cache_ptr->end()) {
1563 noalias(data.dataOnEntities[MBTET][0].getN(base)) = it->N;
1564 noalias(data.dataOnEntities[MBTET][0].getDiffN(base)) = it->diffN;
1565 continue;
1566 }
1567 }
1568
1569 double *phi_v = &*data.dataOnEntities[MBTET][0].getN(base).data().begin();
1570 double *diff_phi_v =
1571 &*data.dataOnEntities[MBTET][0].getDiffN(base).data().begin();
1572
1574 volume_order, &data.dataOnEntities[MBVERTEX][0].getN(base)(0, 0),
1575 &data.dataOnEntities[MBVERTEX][0].getDiffN(base)(0, 0), p_f, phi_f,
1576 diff_phi_f, phi_v, diff_phi_v, nb_gauss_pts);
1577 if (interior_cache_ptr) {
1578 auto p = interior_cache_ptr->emplace(
1579 TetBaseCache::BaseCacheItem{volume_order, nb_gauss_pts});
1580 p.first->N = data.dataOnEntities[MBTET][0].getN(base);
1581 p.first->diffN = data.dataOnEntities[MBTET][0].getDiffN(base);
1582 }
1583 }
1584 }
1585
1586 // Set size of face base correctly
1587 for (int ff = 0; ff != 4; ff++) {
1588 int face_order = data.dataOnEntities[MBTRI][ff].getOrder();
1589 data.dataOnEntities[MBTRI][ff].getN(base).resize(
1590 nb_gauss_pts, 3 * NBFACETRI_DEMKOWICZ_HDIV(face_order), true);
1591 data.dataOnEntities[MBTRI][ff].getDiffN(base).resize(
1592 nb_gauss_pts, 9 * NBFACETRI_DEMKOWICZ_HDIV(face_order), true);
1593 }
1594
1596}
1597
1601
1602 EntitiesFieldData &data = cTx->dAta;
1603 const FieldApproximationBase base = cTx->bAse;
1604 if (base != DEMKOWICZ_JACOBI_BASE) {
1605 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1606 "This should be used only with DEMKOWICZ_JACOBI_BASE "
1607 "but base is %s",
1609 }
1610 int nb_gauss_pts = pts.size2();
1611
1612 int volume_order = data.dataOnEntities[MBTET][0].getOrder();
1613 int nb_dofs_face = NBFACETRI_DEMKOWICZ_HDIV(volume_order);
1614 int nb_dofs_volume = NBVOLUMETET_DEMKOWICZ_HDIV(volume_order);
1615 int nb_dofs = 4 * nb_dofs_face + nb_dofs_volume;
1616 data.dataOnEntities[MBTET][0].getN(base).resize(nb_gauss_pts, 3 * nb_dofs,
1617 false);
1618 data.dataOnEntities[MBTET][0].getDiffN(base).resize(nb_gauss_pts, 9 * nb_dofs,
1619 false);
1620 if (nb_dofs == 0)
1622
1623 auto get_interior_cache = [this]() -> TetBaseCache::BaseCacheMI * {
1624 if (vPtr) {
1625 auto it =
1627 vPtr);
1628 if (it !=
1630 return &it->second;
1631 }
1632 }
1633 return nullptr;
1634 };
1635
1636 auto interior_cache_ptr = get_interior_cache();
1637
1638 if (interior_cache_ptr) {
1639 auto it =
1640 interior_cache_ptr->find(boost::make_tuple(volume_order, nb_gauss_pts));
1641 if (it != interior_cache_ptr->end()) {
1642 noalias(data.dataOnEntities[MBTET][0].getN(base)) = it->N;
1643 noalias(data.dataOnEntities[MBTET][0].getDiffN(base)) = it->diffN;
1645 }
1646 }
1647
1648 std::array<MatrixDouble, 4> face_base_fun{
1649 MatrixDouble(nb_gauss_pts, 3 * nb_dofs_face),
1650 MatrixDouble(nb_gauss_pts, 3 * nb_dofs_face),
1651 MatrixDouble(nb_gauss_pts, 3 * nb_dofs_face),
1652 MatrixDouble(nb_gauss_pts, 3 * nb_dofs_face)};
1653 std::array<MatrixDouble, 4> face_diff_base{
1654 MatrixDouble(nb_gauss_pts, 9 * nb_dofs_face),
1655 MatrixDouble(nb_gauss_pts, 9 * nb_dofs_face),
1656 MatrixDouble(nb_gauss_pts, 9 * nb_dofs_face),
1657 MatrixDouble(nb_gauss_pts, 9 * nb_dofs_face)};
1658
1659 int faces_nodes[4][3] = {{0, 1, 3}, {1, 2, 3}, {0, 3, 2}, {0, 2, 1}};
1660
1661 std::array<int, 4> p_f{volume_order, volume_order, volume_order,
1662 volume_order};
1663 std::array<double *, 4> phi_f{
1664 &*face_base_fun[0].data().begin(), &*face_base_fun[1].data().begin(),
1665 &*face_base_fun[2].data().begin(), &*face_base_fun[3].data().begin()};
1666 std::array<double *, 4> diff_phi_f{
1667 &*face_diff_base[0].data().begin(), &*face_diff_base[1].data().begin(),
1668 &*face_diff_base[2].data().begin(), &*face_diff_base[3].data().begin()};
1669
1670 // Calculate base function on tet faces
1671 for (int ff = 0; ff != 4; ff++) {
1673 // &data.facesNodes(ff, 0)
1674 faces_nodes[ff], p_f[ff],
1675 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
1676 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
1677 phi_f[ff], diff_phi_f[ff], nb_gauss_pts, 4);
1678 }
1679
1680 MatrixDouble vol_bases(nb_gauss_pts, 3 * nb_dofs_volume);
1681 MatrixDouble vol_diff_bases(nb_gauss_pts, 9 * nb_dofs_volume);
1682 auto *phi_v = &*vol_bases.data().begin();
1683 auto *diff_phi_v = &*vol_diff_bases.data().begin();
1685 volume_order, &data.dataOnEntities[MBVERTEX][0].getN(base)(0, 0),
1686 &data.dataOnEntities[MBVERTEX][0].getDiffN(base)(0, 0), p_f.data(),
1687 phi_f.data(), diff_phi_f.data(), phi_v, diff_phi_v, nb_gauss_pts);
1688
1689 // faces
1690 using Tensor1Ptr3 =
1691 decltype(getFTensor1FromPtr<3>(static_cast<double *>(nullptr)));
1692 Tensor1Ptr3 t_base_v_f[] = {
1693 getFTensor1FromPtr<3>(phi_f[0]), getFTensor1FromPtr<3>(phi_f[1]),
1694 getFTensor1FromPtr<3>(phi_f[2]), getFTensor1FromPtr<3>(phi_f[3])};
1695 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_v_f[] = {
1696 getFTensor2HVecFromPtr<3, 3>(diff_phi_f[0]),
1697 getFTensor2HVecFromPtr<3, 3>(diff_phi_f[1]),
1698 getFTensor2HVecFromPtr<3, 3>(diff_phi_f[2]),
1699 getFTensor2HVecFromPtr<3, 3>(diff_phi_f[3])};
1700
1701 // volumes
1702 auto t_base_v = getFTensor1FromPtr<3>(&*vol_bases.data().begin());
1704 getFTensor2HVecFromPtr<3, 3>(&*vol_diff_bases.data().begin());
1705
1706 auto t_base = getFTensor1FromPtr<3>(
1707 &*data.dataOnEntities[MBTET][0].getN(base).data().begin());
1708 auto t_diff_base = getFTensor2HVecFromPtr<3, 3>(
1709 &*data.dataOnEntities[MBTET][0].getDiffN(base).data().begin());
1710
1711 FTENSOR_INDEX(3, i);
1712 FTENSOR_INDEX(3, j);
1713
1714 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
1715 for (int oo = 0; oo < volume_order; oo++) {
1716 // face
1717 for (auto dd = NBFACETRI_DEMKOWICZ_HDIV(oo);
1718 dd != NBFACETRI_DEMKOWICZ_HDIV(oo + 1); ++dd) {
1719 for (auto ff = 0; ff != 4; ++ff) {
1720 t_base(i) = t_base_v_f[ff](i);
1721 ++t_base;
1722 ++t_base_v_f[ff];
1723 t_diff_base(i, j) = t_diff_base_v_f[ff](i, j);
1724 ++t_diff_base;
1725 ++t_diff_base_v_f[ff];
1726 }
1727 }
1728 // volume
1729 for (auto dd = NBVOLUMETET_DEMKOWICZ_HDIV(oo);
1730 dd != NBVOLUMETET_DEMKOWICZ_HDIV(oo + 1); ++dd) {
1731 t_base(i) = t_base_v(i);
1732 ++t_base;
1733 ++t_base_v;
1734 t_diff_base(i, j) = t_diff_base_v(i, j);
1735 ++t_diff_base;
1736 ++t_diff_base_v;
1737 }
1738 }
1739 }
1740
1741 if (interior_cache_ptr) {
1742 auto p = interior_cache_ptr->emplace(
1743 TetBaseCache::BaseCacheItem{volume_order, nb_gauss_pts});
1744 p.first->N = data.dataOnEntities[MBTET][0].getN(base);
1745 p.first->diffN = data.dataOnEntities[MBTET][0].getDiffN(base);
1746 }
1747
1749}
1750
1753
1754 switch (cTx->spaceContinuity) {
1755 case CONTINUOUS:
1756 switch (cTx->bAse) {
1762 default:
1763 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not implemented");
1764 }
1765 break;
1766 case DISCONTINUOUS:
1767 switch (cTx->bAse) {
1773 default:
1774 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not implemented");
1775 }
1776 break;
1777
1778 default:
1779 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Unknown continuity");
1780 }
1781
1783}
1784
1788
1789 EntitiesFieldData &data = cTx->dAta;
1790 const FieldApproximationBase base = cTx->bAse;
1791 PetscErrorCode (*base_polynomials)(int p, double s, double *diff_s, double *L,
1792 double *diffL, const int dim) =
1794
1795 int nb_gauss_pts = pts.size2();
1796
1797 // edges
1798 if (data.spacesOnEntities[MBEDGE].test(HCURL)) {
1799 int sense[6], order[6];
1800 if (data.dataOnEntities[MBEDGE].size() != 6) {
1801 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
1802 }
1803 double *hcurl_edge_n[6], *diff_hcurl_edge_n[6];
1804 for (int ee = 0; ee != 6; ee++) {
1805 if (data.dataOnEntities[MBEDGE][ee].getSense() == 0) {
1806 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1807 "data inconsistency");
1808 }
1809 sense[ee] = data.dataOnEntities[MBEDGE][ee].getSense();
1810 order[ee] = data.dataOnEntities[MBEDGE][ee].getOrder();
1811 int nb_dofs =
1812 NBEDGE_AINSWORTH_HCURL(data.dataOnEntities[MBEDGE][ee].getOrder());
1813 data.dataOnEntities[MBEDGE][ee].getN(base).resize(nb_gauss_pts,
1814 3 * nb_dofs, false);
1815 data.dataOnEntities[MBEDGE][ee].getDiffN(base).resize(nb_gauss_pts,
1816 9 * nb_dofs, false);
1817 hcurl_edge_n[ee] =
1818 &*data.dataOnEntities[MBEDGE][ee].getN(base).data().begin();
1819 diff_hcurl_edge_n[ee] =
1820 &*data.dataOnEntities[MBEDGE][ee].getDiffN(base).data().begin();
1821 }
1823 sense, order,
1824 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
1825 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
1826 hcurl_edge_n, diff_hcurl_edge_n, nb_gauss_pts, base_polynomials);
1827 } else {
1828 for (int ee = 0; ee != 6; ee++) {
1829 data.dataOnEntities[MBEDGE][ee].getN(base).resize(nb_gauss_pts, 0, false);
1830 data.dataOnEntities[MBEDGE][ee].getDiffN(base).resize(nb_gauss_pts, 0,
1831 false);
1832 }
1833 }
1834
1835 // triangles
1836 if (data.spacesOnEntities[MBTRI].test(HCURL)) {
1837 int order[4];
1838 // faces
1839 if (data.dataOnEntities[MBTRI].size() != 4) {
1840 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
1841 }
1842 double *hcurl_base_n[4], *diff_hcurl_base_n[4];
1843 for (int ff = 0; ff != 4; ff++) {
1844 if (data.dataOnEntities[MBTRI][ff].getSense() == 0) {
1845 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1846 "data inconsistency");
1847 }
1848 order[ff] = data.dataOnEntities[MBTRI][ff].getOrder();
1849 int nb_dofs = NBFACETRI_AINSWORTH_HCURL(order[ff]);
1850 data.dataOnEntities[MBTRI][ff].getN(base).resize(nb_gauss_pts,
1851 3 * nb_dofs, false);
1852 data.dataOnEntities[MBTRI][ff].getDiffN(base).resize(nb_gauss_pts,
1853 9 * nb_dofs, false);
1854 hcurl_base_n[ff] =
1855 &*data.dataOnEntities[MBTRI][ff].getN(base).data().begin();
1856 diff_hcurl_base_n[ff] =
1857 &*data.dataOnEntities[MBTRI][ff].getDiffN(base).data().begin();
1858 }
1859 if (data.facesNodes.size1() != 4) {
1860 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
1861 }
1862 if (data.facesNodes.size2() != 3) {
1863 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
1864 }
1866 &*data.facesNodes.data().begin(), order,
1867 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
1868 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
1869 hcurl_base_n, diff_hcurl_base_n, nb_gauss_pts, base_polynomials);
1870 } else {
1871 for (int ff = 0; ff != 4; ff++) {
1872 data.dataOnEntities[MBTRI][ff].getN(base).resize(nb_gauss_pts, 0, false);
1873 data.dataOnEntities[MBTRI][ff].getDiffN(base).resize(nb_gauss_pts, 0,
1874 false);
1875 }
1876 }
1877
1878 if (data.spacesOnEntities[MBTET].test(HCURL)) {
1879
1880 // volume
1881 int order = data.dataOnEntities[MBTET][0].getOrder();
1882 int nb_vol_dofs = NBVOLUMETET_AINSWORTH_HCURL(order);
1883 data.dataOnEntities[MBTET][0].getN(base).resize(nb_gauss_pts,
1884 3 * nb_vol_dofs, false);
1885 data.dataOnEntities[MBTET][0].getDiffN(base).resize(nb_gauss_pts,
1886 9 * nb_vol_dofs, false);
1888 data.dataOnEntities[MBTET][0].getOrder(),
1889 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
1890 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
1891 &*data.dataOnEntities[MBTET][0].getN(base).data().begin(),
1892 &*data.dataOnEntities[MBTET][0].getDiffN(base).data().begin(),
1893 nb_gauss_pts, base_polynomials);
1894
1895 } else {
1896 data.dataOnEntities[MBTET][0].getN(base).resize(nb_gauss_pts, 0, false);
1897 data.dataOnEntities[MBTET][0].getDiffN(base).resize(nb_gauss_pts, 0, false);
1898 }
1899
1901}
1902
1906
1907 EntitiesFieldData &data = cTx->dAta;
1908 const FieldApproximationBase base = cTx->bAse;
1909 if (base != DEMKOWICZ_JACOBI_BASE) {
1910 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1911 "This should be used only with DEMKOWICZ_JACOBI_BASE "
1912 "but base is %s",
1914 }
1915
1916 int nb_gauss_pts = pts.size2();
1917
1918 // edges
1919 if (data.spacesOnEntities[MBEDGE].test(HCURL)) {
1920 int sense[6], order[6];
1921 if (data.dataOnEntities[MBEDGE].size() != 6) {
1922 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1923 "wrong size of data structure, expected space for six edges "
1924 "but is %zu",
1925 data.dataOnEntities[MBEDGE].size());
1926 }
1927 double *hcurl_edge_n[6], *diff_hcurl_edge_n[6];
1928 for (int ee = 0; ee != 6; ee++) {
1929 if (data.dataOnEntities[MBEDGE][ee].getSense() == 0) {
1930 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1931 "orintation of edges is not set");
1932 }
1933 sense[ee] = data.dataOnEntities[MBEDGE][ee].getSense();
1934 order[ee] = data.dataOnEntities[MBEDGE][ee].getOrder();
1935 int nb_dofs =
1936 NBEDGE_DEMKOWICZ_HCURL(data.dataOnEntities[MBEDGE][ee].getOrder());
1937 data.dataOnEntities[MBEDGE][ee].getN(base).resize(nb_gauss_pts,
1938 3 * nb_dofs, false);
1939 data.dataOnEntities[MBEDGE][ee].getDiffN(base).resize(nb_gauss_pts,
1940 9 * nb_dofs, false);
1941 hcurl_edge_n[ee] =
1942 &*data.dataOnEntities[MBEDGE][ee].getN(base).data().begin();
1943 diff_hcurl_edge_n[ee] =
1944 &*data.dataOnEntities[MBEDGE][ee].getDiffN(base).data().begin();
1945 }
1947 sense, order,
1948 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
1949 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
1950 hcurl_edge_n, diff_hcurl_edge_n, nb_gauss_pts);
1951 } else {
1952 // No DOFs on edges, resize base function matrices, indicating that no
1953 // dofs on them.
1954 for (int ee = 0; ee != 6; ee++) {
1955 data.dataOnEntities[MBEDGE][ee].getN(base).resize(nb_gauss_pts, 0, false);
1956 data.dataOnEntities[MBEDGE][ee].getDiffN(base).resize(nb_gauss_pts, 0,
1957 false);
1958 }
1959 }
1960
1961 // triangles
1962 if (data.spacesOnEntities[MBTRI].test(HCURL)) {
1963 int order[4];
1964 // faces
1965 if (data.dataOnEntities[MBTRI].size() != 4) {
1966 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1967 "data structure for storing face h-curl base have wrong size "
1968 "should be four but is %zu",
1969 data.dataOnEntities[MBTRI].size());
1970 }
1971 double *hcurl_base_n[4], *diff_hcurl_base_n[4];
1972 for (int ff = 0; ff != 4; ff++) {
1973 if (data.dataOnEntities[MBTRI][ff].getSense() == 0) {
1974 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1975 "orintation of face is not set");
1976 }
1977 order[ff] = data.dataOnEntities[MBTRI][ff].getOrder();
1978 int nb_dofs = NBFACETRI_DEMKOWICZ_HCURL(order[ff]);
1979 data.dataOnEntities[MBTRI][ff].getN(base).resize(nb_gauss_pts,
1980 3 * nb_dofs, false);
1981 data.dataOnEntities[MBTRI][ff].getDiffN(base).resize(nb_gauss_pts,
1982 9 * nb_dofs, false);
1983 hcurl_base_n[ff] =
1984 &*data.dataOnEntities[MBTRI][ff].getN(base).data().begin();
1985 diff_hcurl_base_n[ff] =
1986 &*data.dataOnEntities[MBTRI][ff].getDiffN(base).data().begin();
1987 }
1988 if (data.facesNodes.size1() != 4) {
1989 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1990 "data inconsistency, should be four faces");
1991 }
1992 if (data.facesNodes.size2() != 3) {
1993 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1994 "data inconsistency, should be three nodes on face");
1995 }
1997 &*data.facesNodes.data().begin(), order,
1998 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
1999 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
2000 hcurl_base_n, diff_hcurl_base_n, nb_gauss_pts);
2001 } else {
2002 // No DOFs on faces, resize base function matrices, indicating that no
2003 // dofs on them.
2004 for (int ff = 0; ff != 4; ff++) {
2005 data.dataOnEntities[MBTRI][ff].getN(base).resize(nb_gauss_pts, 0, false);
2006 data.dataOnEntities[MBTRI][ff].getDiffN(base).resize(nb_gauss_pts, 0,
2007 false);
2008 }
2009 }
2010
2011 if (data.spacesOnEntities[MBTET].test(HCURL)) {
2012 // volume
2013 int order = data.dataOnEntities[MBTET][0].getOrder();
2014 int nb_vol_dofs = NBVOLUMETET_DEMKOWICZ_HCURL(order);
2015 data.dataOnEntities[MBTET][0].getN(base).resize(nb_gauss_pts,
2016 3 * nb_vol_dofs, false);
2017 data.dataOnEntities[MBTET][0].getDiffN(base).resize(nb_gauss_pts,
2018 9 * nb_vol_dofs, false);
2020 data.dataOnEntities[MBTET][0].getOrder(),
2021 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
2022 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
2023 &*data.dataOnEntities[MBTET][0].getN(base).data().begin(),
2024 &*data.dataOnEntities[MBTET][0].getDiffN(base).data().begin(),
2025 nb_gauss_pts);
2026 } else {
2027 // No DOFs on faces, resize base function matrices, indicating that no
2028 // dofs on them.
2029 data.dataOnEntities[MBTET][0].getN(base).resize(nb_gauss_pts, 0, false);
2030 data.dataOnEntities[MBTET][0].getDiffN(base).resize(nb_gauss_pts, 0, false);
2031 }
2032
2034}
2035
2038
2039 switch (cTx->bAse) {
2043 break;
2046 break;
2047 default:
2048 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not implemented");
2049 }
2050
2052}
2053
2056 boost::shared_ptr<BaseFunctionCtx> ctx_ptr) {
2058
2060
2061 int nb_gauss_pts = pts.size2();
2062 if (!nb_gauss_pts)
2064
2065 if (pts.size1() < 3)
2066 SETERRQ(
2067 PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2068 "Wrong dimension of pts, should be at least 3 rows with coordinates");
2069
2071 const FieldApproximationBase base = cTx->bAse;
2072 EntitiesFieldData &data = cTx->dAta;
2073 if (cTx->copyNodeBase == LASTBASE) {
2074 data.dataOnEntities[MBVERTEX][0].getN(base).resize(nb_gauss_pts, 4,
2075 false);
2077 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
2078 &pts(0, 0), &pts(1, 0), &pts(2, 0), nb_gauss_pts);
2079 } else {
2080 data.dataOnEntities[MBVERTEX][0].getN(base) =
2081 data.dataOnEntities[MBVERTEX][0].getN(cTx->copyNodeBase);
2082 }
2083 if (data.dataOnEntities[MBVERTEX][0].getN(base).size1() !=
2084 (unsigned int)nb_gauss_pts) {
2085 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2086 "Base functions or nodes has wrong number of integration points "
2087 "for base %s",
2089 }
2090 data.dataOnEntities[MBVERTEX][0].getDiffN(base).resize(4, 3, false);
2091 std::copy(Tools::diffShapeFunMBTET.begin(), Tools::diffShapeFunMBTET.end(),
2092 data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin());
2093 }
2094
2095 switch (cTx->spaceContinuity) {
2096 case CONTINUOUS:
2097
2098 switch (cTx->sPace) {
2099 case H1:
2100 CHKERR getValueH1(pts);
2101 break;
2102 case HDIV:
2103 CHKERR getValueHdiv(pts);
2104 break;
2105 case HCURL:
2106 CHKERR getValueHcurl(pts);
2107 break;
2108 case L2:
2109 CHKERR getValueL2(pts);
2110 break;
2111 default:
2112 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Unknown space %s",
2114 }
2115 break;
2116
2117 case DISCONTINUOUS:
2118
2119 switch (cTx->sPace) {
2120 case HDIV:
2121 CHKERR getValueHdiv(pts);
2122 break;
2123 default:
2124 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Unknown space %s",
2126 }
2127 break;
2128
2129 default:
2130 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Unknown continuity");
2131 }
2132
2134}
2135
2137
2138 const FieldSpace space, const FieldContinuity continuity,
2139 const FieldApproximationBase base, DofsSideMap &dofs_side_map
2140
2141) {
2143
2144 switch (continuity) {
2145 case DISCONTINUOUS:
2146
2147 switch (space) {
2148 case HDIV:
2149 CHKERR setDofsSideMapHdiv(continuity, base, dofs_side_map);
2150 break;
2151 default:
2152 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Unknown space %s",
2153 FieldSpaceNames[space]);
2154 }
2155 break;
2156
2157 default:
2158 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
2159 "Unknown (or not implemented) continuity");
2160 }
2161
2163}
2164
2167 const FieldApproximationBase base,
2168 DofsSideMap &dofs_side_map) {
2170
2171 // That has to be consistent with implementation of getValueHdiv for
2172 // particular base functions.
2173
2174 auto set_ainsworth = [&dofs_side_map]() {
2176
2177 dofs_side_map.clear();
2178
2179 int dof = 0;
2180 for (int oo = 0; oo < Field::maxBrokenDofsOrder; oo++) {
2181
2182 // faces-edge (((P) > 0) ? (P) : 0)
2183 for (int dd = NBFACETRI_AINSWORTH_EDGE_HDIV(oo);
2184 dd != NBFACETRI_AINSWORTH_EDGE_HDIV(oo + 1); dd++) {
2185 for (auto ff = 0; ff != 4; ++ff) {
2186 for (int ee = 0; ee != 3; ++ee) {
2187 dofs_side_map.insert(DofsSideMapData{MBTRI, ff, dof});
2188 ++dof;
2189 }
2190 }
2191 }
2192
2193 // face-face (P - 1) * (P - 2) / 2
2194 for (int dd = NBFACETRI_AINSWORTH_FACE_HDIV(oo);
2195 dd != NBFACETRI_AINSWORTH_FACE_HDIV(oo + 1); dd++) {
2196 for (auto ff = 0; ff != 4; ++ff) {
2197 dofs_side_map.insert(DofsSideMapData{MBTRI, ff, dof});
2198 ++dof;
2199 }
2200 }
2201
2202 // volume-edge (P - 1)
2203 for (int dd = NBVOLUMETET_AINSWORTH_EDGE_HDIV(oo);
2204 dd != NBVOLUMETET_AINSWORTH_EDGE_HDIV(oo + 1); dd++) {
2205 for (int ee = 0; ee < 6; ee++) {
2206 dofs_side_map.insert(DofsSideMapData{MBTET, 0, dof});
2207 ++dof;
2208 }
2209 }
2210 // volume-face (P - 1) * (P - 2)
2211 for (int dd = NBVOLUMETET_AINSWORTH_FACE_HDIV(oo);
2212 dd < NBVOLUMETET_AINSWORTH_FACE_HDIV(oo + 1); dd++) {
2213 for (int ff = 0; ff < 4; ff++) {
2214 dofs_side_map.insert(DofsSideMapData{MBTET, 0, dof});
2215 ++dof;
2216 }
2217 }
2218 // volume-bubble (P - 3) * (P - 2) * (P - 1) / 2
2219 for (int dd = NBVOLUMETET_AINSWORTH_VOLUME_HDIV(oo);
2220 dd < NBVOLUMETET_AINSWORTH_VOLUME_HDIV(oo + 1); dd++) {
2221 dofs_side_map.insert(DofsSideMapData{MBTET, 0, dof});
2222 ++dof;
2223 }
2224 }
2225
2227 };
2228
2229 auto set_demkowicz = [&dofs_side_map]() {
2231
2232 dofs_side_map.clear();
2233
2234 int dof = 0;
2235 for (int oo = 0; oo < Field::maxBrokenDofsOrder; oo++) {
2236
2237 // face
2238 for (auto dd = NBFACETRI_DEMKOWICZ_HDIV(oo);
2239 dd != NBFACETRI_DEMKOWICZ_HDIV(oo + 1); ++dd) {
2240 for (auto ff = 0; ff != 4; ++ff) {
2241 dofs_side_map.insert(DofsSideMapData{MBTRI, ff, dof});
2242 ++dof;
2243 }
2244 }
2245 // volume
2246 for (auto dd = NBVOLUMETET_DEMKOWICZ_HDIV(oo);
2247 dd != NBVOLUMETET_DEMKOWICZ_HDIV(oo + 1); ++dd) {
2248 dofs_side_map.insert(DofsSideMapData{MBTET, 0, dof});
2249 ++dof;
2250 }
2251 }
2252
2254 };
2255
2256 switch (continuity) {
2257 case DISCONTINUOUS:
2258 switch (base) {
2261 MoFEMFunctionReturnHot(set_ainsworth());
2263 MoFEMFunctionReturnHot(set_demkowicz());
2264 default:
2265 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not implemented");
2266 }
2267 break;
2268
2269 default:
2270 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
2271 "Unknown (or not implemented) continuity");
2272 }
2273
2275}
2276
2277template <typename T>
2278auto tetCacheSwitch(const void *ptr, T &cache, std::string cache_name) {
2279 auto it = cache.find(ptr);
2280 if (it != cache.end()) {
2281 MOFEM_LOG_CHANNEL("WORLD");
2282 MOFEM_TAG_AND_LOG("WORLD", Sev::noisy, "TetPolynomialBase")
2283 << "Cache off " << cache_name << ": " << it->second.size();
2284 cache.erase(it);
2285 return false;
2286 } else {
2287 MOFEM_LOG_CHANNEL("WORLD");
2288 MOFEM_TAG_AND_LOG("WORLD", Sev::noisy, "TetPolynomialBase")
2289 << "Cache on " << cache_name;
2290 cache[ptr];
2291 return true;
2292 }
2293}
2294
2295template <>
2296bool TetPolynomialBase::switchCacheBaseFace<HDIV>(FieldApproximationBase base,
2297 void *ptr) {
2299 std::string("hDivBaseFace") +
2301}
2302
2303template <>
2304bool TetPolynomialBase::switchCacheBaseInterior<HDIV>(
2305 FieldApproximationBase base, void *ptr) {
2307 std::string("hdivBaseInterior") +
2309}
2310
2311template <>
2312bool TetPolynomialBase::switchCacheBrokenBaseInterior<HDIV>(
2313 FieldApproximationBase base, void *ptr) {
2315 std::string("hdivBrokenBaseInterior") +
2317}
2318
2319template <>
2320void TetPolynomialBase::switchCacheBaseOn<HDIV>(FieldApproximationBase base,
2321 std::vector<void *> v) {
2322 for (auto fe_ptr : v) {
2323 if (!TetPolynomialBase::switchCacheBaseFace<HDIV>(base, fe_ptr)) {
2324 TetPolynomialBase::switchCacheBaseFace<HDIV>(base, fe_ptr);
2325 }
2326 if (!TetPolynomialBase::switchCacheBaseInterior<HDIV>(base, fe_ptr)) {
2327 TetPolynomialBase::switchCacheBaseInterior<HDIV>(base, fe_ptr);
2328 }
2329 if (!TetPolynomialBase::switchCacheBrokenBaseInterior<HDIV>(base, fe_ptr)) {
2330 TetPolynomialBase::switchCacheBrokenBaseInterior<HDIV>(base, fe_ptr);
2331 }
2332 }
2333}
2334
2335template <>
2336void TetPolynomialBase::switchCacheBaseOff<HDIV>(FieldApproximationBase base,
2337 std::vector<void *> v) {
2338 for (auto fe_ptr : v) {
2339 if (TetPolynomialBase::switchCacheBaseFace<HDIV>(base, fe_ptr)) {
2340 TetPolynomialBase::switchCacheBaseFace<HDIV>(base, fe_ptr);
2341 }
2342 if (TetPolynomialBase::switchCacheBaseInterior<HDIV>(base, fe_ptr)) {
2343 TetPolynomialBase::switchCacheBaseInterior<HDIV>(base, fe_ptr);
2344 }
2345 if (TetPolynomialBase::switchCacheBrokenBaseInterior<HDIV>(base, fe_ptr)) {
2346 TetPolynomialBase::switchCacheBrokenBaseInterior<HDIV>(base, fe_ptr);
2347 }
2348 }
2349}
2350
2351template <>
2352void TetPolynomialBase::switchCacheBaseOn<HDIV>(std::vector<void *> v) {
2353 for (auto b = 0; b != LASTBASE; ++b) {
2354 switchCacheBaseOn<HDIV>(static_cast<FieldApproximationBase>(b), v);
2355 }
2356}
2357
2358template <>
2359void TetPolynomialBase::switchCacheBaseOff<HDIV>(std::vector<void *> v) {
2360 for (auto b = 0; b != LASTBASE; ++b) {
2361 switchCacheBaseOff<HDIV>(static_cast<FieldApproximationBase>(b), v);
2362 }
2363}
2364
2365template <>
2366bool TetPolynomialBase::switchCacheBaseInterior<L2>(FieldApproximationBase base,
2367 void *ptr) {
2369 std::string("hdivBaseInterior") +
2371}
2372
2373template <>
2374void TetPolynomialBase::switchCacheBaseOn<L2>(FieldApproximationBase base,
2375 std::vector<void *> v) {
2376 for (auto fe_ptr : v) {
2377 if (!TetPolynomialBase::switchCacheBaseInterior<L2>(base, fe_ptr)) {
2378 TetPolynomialBase::switchCacheBaseInterior<L2>(base, fe_ptr);
2379 }
2380 }
2381}
2382
2383template <>
2384void TetPolynomialBase::switchCacheBaseOff<L2>(FieldApproximationBase base,
2385 std::vector<void *> v) {
2386 for (auto fe_ptr : v) {
2387 if (TetPolynomialBase::switchCacheBaseInterior<L2>(base, fe_ptr)) {
2388 TetPolynomialBase::switchCacheBaseInterior<L2>(base, fe_ptr);
2389 }
2390 }
2391}
2392
2393template <>
2394void TetPolynomialBase::switchCacheBaseOn<L2>(std::vector<void *> v) {
2395 for (auto b = 0; b != LASTBASE; ++b) {
2396 switchCacheBaseOn<L2>(static_cast<FieldApproximationBase>(b), v);
2397 }
2398}
2399
2400template <>
2401void TetPolynomialBase::switchCacheBaseOff<L2>(std::vector<void *> v) {
2402 for (auto b = 0; b != LASTBASE; ++b) {
2403 switchCacheBaseOff<L2>(static_cast<FieldApproximationBase>(b), v);
2404 }
2405}
#define MOFEM_TAG_AND_LOG(channel, severity, tag)
Tag and log in channel.
#define FTENSOR_INDEX(DIM, I)
auto tetCacheSwitch(const void *ptr, T &cache, std::string cache_name)
constexpr double a
FieldApproximationBase
approximation base
Definition definitions.h:58
@ LASTBASE
Definition definitions.h:69
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ AINSWORTH_LOBATTO_BASE
Definition definitions.h:62
@ NOBASE
Definition definitions.h:59
@ DEMKOWICZ_JACOBI_BASE
Definition definitions.h:66
@ AINSWORTH_BERNSTEIN_BEZIER_BASE
Definition definitions.h:64
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
FieldSpace
approximation spaces
Definition definitions.h:82
@ L2
field with C-1 continuity
Definition definitions.h:88
@ H1
continuous field
Definition definitions.h:85
@ HCURL
field with continuous tangents
Definition definitions.h:86
@ HDIV
field with continuous normal traction
Definition definitions.h:87
FieldContinuity
Field continuity.
Definition definitions.h:99
@ CONTINUOUS
Regular field.
@ DISCONTINUOUS
Broken continuity (No effect on L2 space)
static const char *const FieldSpaceNames[]
Definition definitions.h:92
#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
static const char *const ApproximationBaseNames[]
Definition definitions.h:72
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
constexpr int order
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
#define NBVOLUMETET_AINSWORTH_EDGE_HDIV(P)
#define NBEDGE_DEMKOWICZ_HCURL(P)
#define NBVOLUMETET_H1(P)
Number of base functions on tetrahedron for H1 space.
#define NBVOLUMETET_AINSWORTH_HCURL(P)
#define NBFACETRI_AINSWORTH_HCURL(P)
#define NBVOLUMETET_DEMKOWICZ_HDIV(P)
PetscErrorCode H1_EdgeShapeFunctions_MBTET(int *sense, int *p, double *N, double *diffN, double *edgeN[], double *diff_edgeN[], int GDIM, PetscErrorCode(*base_polynomials)(int p, double s, double *diff_s, double *L, double *diffL, const int dim))
Definition h1.c:274
#define NBVOLUMETET_AINSWORTH_FACE_HDIV(P)
#define NBEDGE_H1(P)
Number of base function on edge for H1 space.
#define NBFACETRI_DEMKOWICZ_HDIV(P)
PetscErrorCode L2_Ainsworth_ShapeFunctions_MBTET(int p, double *N, double *diffN, double *L2N, double *diff_L2N, int GDIM, PetscErrorCode(*base_polynomials)(int p, double s, double *diff_s, double *L, double *diffL, const int dim))
Get base functions on tetrahedron for L2 space.
Definition l2.c:74
#define NBVOLUMETET_DEMKOWICZ_HCURL(P)
#define NBFACETRI_DEMKOWICZ_HCURL(P)
#define NBFACETRI_AINSWORTH_FACE_HDIV(P)
#define NBVOLUMETET_AINSWORTH_VOLUME_HDIV(P)
#define NBFACETRI_AINSWORTH_EDGE_HDIV(P)
PetscErrorCode H1_VolumeShapeFunctions_MBTET(int p, double *N, double *diffN, double *volumeN, double *diff_volumeN, int GDIM, PetscErrorCode(*base_polynomials)(int p, double s, double *diff_s, double *L, double *diffL, const int dim))
Definition h1.c:475
#define NBEDGE_AINSWORTH_HCURL(P)
PetscErrorCode H1_FaceShapeFunctions_MBTET(int *faces_nodes, int *p, double *N, double *diffN, double *faceN[], double *diff_faceN[], int GDIM, PetscErrorCode(*base_polynomials)(int p, double s, double *diff_s, double *L, double *diffL, const int dim))
Definition h1.c:373
#define NBFACETRI_H1(P)
Number of base function on triangle for H1 space.
#define NBVOLUMETET_L2(P)
Number of base functions on tetrahedron for L2 space.
FTensor::Index< 'i', SPACE_DIM > i
static double lambda
const double v
phase velocity of light in medium (cm/ns)
const double n
refractive index of diffusive medium
FTensor::Index< 'j', 3 > j
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
UBlasMatrix< double > MatrixDouble
Definition Types.hpp:77
UBlasMatrix< int > MatrixInt
Definition Types.hpp:76
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
MoFEMErrorCode Hdiv_Demkowicz_Face_MBTET_ON_FACE(int *faces_nodes, int p, double *N, double *diffN, double *phi_f, double *diff_phi_f, int gdim, int nb)
Definition Hdiv.cpp:634
MoFEMErrorCode Hdiv_Ainsworth_EdgeFaceShapeFunctions_MBTET_ON_FACE(int *faces_nodes, int p, double *N, double *diffN, double *phi_f_e[3], double *diff_phi_f_e[3], int gdim, int nb, PetscErrorCode(*base_polynomials)(int p, double s, double *diff_s, double *L, double *diffL, const int dim))
Hdiv base functions, Edge-based face functions by Ainsworth .
Definition Hdiv.cpp:47
auto getFTensor2HVecFromPtr< 3, 3 >(double *ptr)
MoFEMErrorCode Hdiv_Demkowicz_Interior_MBTET(int p, double *N, double *diffN, int p_face[], double *phi_f[4], double *diff_phi_f[4], double *phi_v, double *diff_phi_v, int gdim)
Definition Hdiv.cpp:780
MoFEMErrorCode Hcurl_Ainsworth_VolumeFunctions_MBTET(int p, double *N, double *diffN, double *phi_v, double *diff_phi_v, int nb_integration_pts, PetscErrorCode(*base_polynomials)(int p, double s, double *diff_s, double *L, double *diffL, const int dim))
H-curl volume base functions.
Definition Hcurl.cpp:1403
MoFEMErrorCode Hdiv_Ainsworth_FaceBasedVolumeShapeFunctions_MBTET(int p, double *N, double *diffN, double *phi_v_f[], double *diff_phi_v_f[], int gdim, PetscErrorCode(*base_polynomials)(int p, double s, double *diff_s, double *L, double *diffL, const int dim))
Definition Hdiv.cpp:401
MoFEMErrorCode Hdiv_Ainsworth_FaceBubbleShapeFunctions_ON_FACE(int *faces_nodes, int p, double *N, double *diffN, double *phi_f, double *diff_phi_f, int gdim, int nb, PetscErrorCode(*base_polynomials)(int p, double s, double *diff_s, double *L, double *diffL, const int dim))
Face bubble functions by Ainsworth .
Definition Hdiv.cpp:174
MoFEMErrorCode Hcurl_Ainsworth_EdgeBaseFunctions_MBTET(int *sense, int *p, double *N, double *diffN, double *edgeN[], double *diff_edgeN[], int nb_integration_pts, PetscErrorCode(*base_polynomials)(int p, double s, double *diff_s, double *L, double *diffL, const int dim))
Edge based H-curl base functions on tetrahedral.
Definition Hcurl.cpp:16
MoFEMErrorCode Hcurl_Demkowicz_FaceBaseFunctions_MBTET(int *faces_nodes, int *p, double *n, double *diff_n, double *phi[], double *diff_phi[], int nb_integration_pts)
Face base interior function.
Definition Hcurl.cpp:2402
MoFEMErrorCode Hdiv_Ainsworth_EdgeBasedVolumeShapeFunctions_MBTET(int p, double *N, double *diffN, double *phi_v_e[6], double *diff_phi_v_e[6], int gdim, PetscErrorCode(*base_polynomials)(int p, double s, double *diff_s, double *L, double *diffL, const int dim))
Hdiv base function, Edge-based interior (volume) functions by Ainsworth .
Definition Hdiv.cpp:307
MoFEMErrorCode Hcurl_Demkowicz_VolumeBaseFunctions_MBTET(int p, double *n, double *diff_n, double *phi, double *diff_phi, int nb_integration_pts)
Volume base interior function.
Definition Hcurl.cpp:2475
MoFEMErrorCode Hcurl_Demkowicz_EdgeBaseFunctions_MBTET(int *sense, int *p, double *n, double *diff_n, double *phi[], double *diff_phi[], int nb_integration_pts)
Edge based H-curl base functions on tetrahedral.
Definition Hcurl.cpp:2079
MoFEMErrorCode Hcurl_Ainsworth_FaceFunctions_MBTET(int *face_nodes, int *p, double *N, double *diffN, double *phi_f[4], double *diff_phi_f[4], int nb_integration_pts, PetscErrorCode(*base_polynomials)(int p, double s, double *diff_s, double *L, double *diffL, const int dim))
Face H-curl functions.
Definition Hcurl.cpp:1052
MoFEMErrorCode Hdiv_Ainsworth_VolumeBubbleShapeFunctions_MBTET(int p, double *N, double *diffN, double *phi_v, double *diff_phi_v, int gdim, PetscErrorCode(*base_polynomials)(int p, double s, double *diff_s, double *L, double *diffL, const int dim))
Interior bubble functions by Ainsworth .
Definition Hdiv.cpp:507
constexpr auto field_name
constexpr double g
static boost::function< int(int)> broken_nbvolumetet_edge_hdiv
Definition Hdiv.hpp:27
static boost::function< int(int)> broken_nbvolumetet_face_hdiv
Definition Hdiv.hpp:28
static boost::function< int(int)> broken_nbfacetri_face_hdiv
Definition Hdiv.hpp:26
static boost::function< int(int)> broken_nbvolumetet_volume_hdiv
Definition Hdiv.hpp:29
static boost::function< int(int)> broken_nbfacetri_edge_hdiv
Definition Hdiv.hpp:25
multi_index_container< DofsSideMapData, indexed_by< ordered_non_unique< tag< TypeSide_mi_tag >, composite_key< DofsSideMapData, member< DofsSideMapData, EntityType, &DofsSideMapData::type >, member< DofsSideMapData, int, &DofsSideMapData::side > > >, ordered_unique< tag< EntDofIdx_mi_tag >, member< DofsSideMapData, int, &DofsSideMapData::dof > > > > DofsSideMap
Map entity stype and side to element/entity dof index.
static MoFEMErrorCode generateIndicesTriTet(const int N[], int *alpha[])
static MoFEMErrorCode baseFunctionsTet(const int N, const int gdim, const int n_alpha, const int *alpha, const double *lambda, const double *grad_lambda, double *base, double *grad_base)
static MoFEMErrorCode generateIndicesEdgeTet(const int N[], int *alpha[])
static MoFEMErrorCode generateIndicesVertexTet(const int N, int *alpha)
static MoFEMErrorCode generateIndicesTetTet(const int N, int *alpha)
Class used to pass element data to calculate base functions on tet,triangle,edge.
const FieldApproximationBase copyNodeBase
PetscErrorCode(* basePolynomialsType0)(int p, double s, double *diff_s, double *L, double *diffL, const int dim)
const FieldContinuity spaceContinuity
const FieldApproximationBase bAse
data structure for finite element entity
MatrixInt facesNodes
nodes on finite element faces
std::array< std::bitset< LASTSPACE >, MBMAXTYPE > spacesOnEntities
spaces on entity types
std::array< boost::ptr_vector< EntData >, MBMAXTYPE > dataOnEntities
static constexpr int maxBrokenDofsOrder
Maximum order for broken space DOFs.
Calculate base functions on tetrahedral.
ublas::matrix< MatrixDouble > diffN_face_edge
EntPolynomialBaseCtx * cTx
MoFEMErrorCode getValueHdivAinsworthBaseImpl(MatrixDouble &pts, MatrixDouble &shape_functions, MatrixDouble &diff_shape_functions, int volume_order, std::array< int, 4 > &faces_order, std::array< int, 3 *4 > &faces_nodes, boost::function< int(int)> broken_nbfacetri_edge_hdiv, boost::function< int(int)> broken_nbfacetri_face_hdiv, boost::function< int(int)> broken_nbvolumetet_edge_hdiv, boost::function< int(int)> broken_nbvolumetet_face_hdiv, boost::function< int(int)> broken_nbvolumetet_volume_hdiv)
MoFEMErrorCode getValueH1AinsworthBase(MatrixDouble &pts)
MoFEMErrorCode getValueHdivAinsworthBrokenBase(MatrixDouble &pts)
ublas::vector< MatrixDouble > diffN_volume_face
MoFEMErrorCode getValueL2BernsteinBezierBase(MatrixDouble &pts)
MoFEMErrorCode getValueHcurlDemkowiczBase(MatrixDouble &pts)
MoFEMErrorCode getValueHcurl(MatrixDouble &pts)
Get base functions for Hcurl space.
MoFEMErrorCode getValueH1BernsteinBezierBase(MatrixDouble &pts)
static MoFEMErrorCode setDofsSideMap(const FieldSpace space, const FieldContinuity continuity, const FieldApproximationBase base, DofsSideMap &)
Set map of dof to side number.
MoFEMErrorCode getValueH1(MatrixDouble &pts)
Get base functions for H1 space.
ublas::vector< MatrixDouble > diffN_face_bubble
ublas::vector< MatrixDouble > N_volume_edge
ublas::vector< MatrixDouble > N_volume_face
MoFEMErrorCode getValueHdiv(MatrixDouble &pts)
Get base functions for Hdiv space.
MoFEMErrorCode getValueHdivAinsworthBase(MatrixDouble &pts)
MoFEMErrorCode getValueL2AinsworthBase(MatrixDouble &pts)
ublas::vector< MatrixDouble > N_face_bubble
ublas::matrix< MatrixDouble > N_face_edge
MoFEMErrorCode getValueL2(MatrixDouble &pts)
Get base functions for L2 space.
MoFEMErrorCode getValueHdivDemkowiczBase(MatrixDouble &pts)
TetPolynomialBase(const void *ptr=nullptr)
MoFEMErrorCode getValue(MatrixDouble &pts, boost::shared_ptr< BaseFunctionCtx > ctx_ptr)
MoFEMErrorCode getValueHdivDemkowiczBrokenBase(MatrixDouble &pts)
ublas::vector< MatrixDouble > diffN_volume_edge
MoFEMErrorCode getValueHcurlAinsworthBase(MatrixDouble &pts)
static MoFEMErrorCode setDofsSideMapHdiv(const FieldContinuity continuity, const FieldApproximationBase base, DofsSideMap &dofs_side_map)
Set the Dofs Side Map Hdiv object.
static MoFEMErrorCode shapeFunMBTET(double *shape, const double *ksi, const double *eta, const double *zeta, const double nb)
Calculate shape functions on tetrahedron.
Definition Tools.hpp:759
static constexpr std::array< double, 12 > diffShapeFunMBTET
Definition Tools.hpp:271
base class for all interface classes
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.
boost::multi_index_container< BaseCacheItem, boost::multi_index::indexed_by< boost::multi_index::hashed_unique< composite_key< BaseCacheItem, member< BaseCacheItem, int, &BaseCacheItem::order >, member< BaseCacheItem, int, &BaseCacheItem::nb_gauss_pts > > > > > BaseCacheMI
static std::array< std::map< const void *, BaseCacheMI >, LASTBASE > hdivBaseInterior
boost::multi_index_container< HDivBaseCacheItem, boost::multi_index::indexed_by< boost::multi_index::hashed_unique< composite_key< HDivBaseCacheItem, member< HDivBaseCacheItem, int, &HDivBaseCacheItem::order >, member< HDivBaseCacheItem, int, &HDivBaseCacheItem::nb_gauss_pts >, member< HDivBaseCacheItem, int, &HDivBaseCacheItem::n0 >, member< HDivBaseCacheItem, int, &HDivBaseCacheItem::n1 >, member< HDivBaseCacheItem, int, &HDivBaseCacheItem::n2 > > > > > HDivBaseFaceCacheMI
static std::array< std::map< const void *, HDivBaseFaceCacheMI >, LASTBASE > hDivBaseFace
static std::array< std::map< const void *, BaseCacheMI >, LASTBASE > l2BaseInterior
static std::array< std::map< const void *, BaseCacheMI >, LASTBASE > hdivBrokenBaseInterior