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 // A field which was given a by-order matrix shared with another field on a
313 // previous element must not write into it here: on this element that matrix
314 // may already hold the other field's base. Detach and allocate own storage.
315 auto make_own = [field_name](auto &ent_data) {
316 auto &n_ptr = ent_data.getBBNSharedPtr(field_name);
317 if (!n_ptr)
318 return;
319 for (auto &ptr : ent_data.getBBNByOrderArray()) {
320 if (ptr && ptr.get() == n_ptr.get()) {
321 ent_data.getBBAlphaIndicesSharedPtr(field_name).reset();
322 ent_data.getBBDiffNSharedPtr(field_name).reset();
323 n_ptr.reset();
324 return;
325 }
326 }
327 };
328
329 // Entity without base functions for this field: no alpha indices and base
330 // matrices with zero columns, consistent with the hierarchical bases.
331 auto set_empty = [&](auto &ent_data) {
332 make_own(ent_data);
333 ent_data.getBBAlphaIndicesSharedPtr(field_name).reset();
334 get_base(ent_data).resize(nb_gauss_pts, 0, false);
335 get_diff_base(ent_data).resize(nb_gauss_pts, 0, false);
336 };
337
338 // The BB base is not hierarchical: a degree-p function is not in the span
339 // of the degree-(p+1) functions, so mixing degrees between the entities of
340 // one element loses completeness (with a differing vertex degree even the
341 // constant function is lost). H1 therefore requires one order on all
342 // entities which carry DOFs, and vertex degrees between one and that order.
343 // L2 is element-local and has no such restriction.
344 auto check_uniform_order = [&]() {
346 auto &node_order = data.dataOnEntities[MBVERTEX][0].getBBNodeOrder();
347 if (node_order.size() != 4)
348 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
349 "Wrong number of vertex orders for BB base: %d",
350 static_cast<int>(node_order.size()));
351 int order = 0;
352 for (int n = 0; n != 4; ++n)
353 order = std::max(order, node_order[n]);
354 auto max_order_on = [&](const EntityType type) {
355 if (data.spacesOnEntities[type].test(H1))
356 for (auto &ent_data : data.dataOnEntities[type])
357 order = std::max(order, ent_data.getOrder());
358 };
359 max_order_on(MBEDGE);
360 max_order_on(MBTRI);
361 max_order_on(MBTET);
362 if (order < 1)
363 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
364 "Bernstein-Bezier H1 base requires approximation order >= 1");
365 if (static_cast<size_t>(order) >=
367 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
368 "Bernstein-Bezier order %d exceeds the supported maximum %d",
369 order,
370 static_cast<int>(
372 1);
373 for (int n = 0; n != 4; ++n)
374 if (node_order[n] < 1)
375 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
376 "Bernstein-Bezier H1 base requires vertex order between 1 "
377 "and the element order %d; vertex %d has order %d",
378 order, n, node_order[n]);
379 auto check_type = [&](const EntityType type, const int nb_dofs_at_order) {
381 if (!nb_dofs_at_order || !data.spacesOnEntities[type].test(H1))
383 int side = 0;
384 for (auto &ent_data : data.dataOnEntities[type]) {
385 if (ent_data.getOrder() != order)
386 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
387 "Bernstein-Bezier base in H1 space requires uniform "
388 "approximation order on the element: %s %d has order %d, "
389 "element order is %d. BB functions are not hierarchical, "
390 "so mixed degrees do not span a complete polynomial space. "
391 "Set one order for the whole H1 field (L2 fields are not "
392 "restricted).",
393 moab::CN::EntityTypeName(type), side, ent_data.getOrder(),
394 order);
395 ++side;
396 }
398 };
399 CHKERR check_type(MBEDGE, NBEDGE_H1(order));
400 CHKERR check_type(MBTRI, NBFACETRI_H1(order));
401 CHKERR check_type(MBTET, NBVOLUMETET_H1(order));
403 };
404 CHKERR check_uniform_order();
405
406 auto &vert_ent_data = data.dataOnEntities[MBVERTEX][0];
407 auto &vertex_alpha = get_alpha(vert_ent_data);
408 vertex_alpha.resize(4, 4, false);
409 vertex_alpha.clear();
410 for (int n = 0; n != 4; ++n)
411 vertex_alpha(n, n) = data.dataOnEntities[MBVERTEX][0].getBBNodeOrder()[n];
412
413 auto &vert_get_n = get_base(vert_ent_data);
414 auto &vert_get_diff_n = get_diff_base(vert_ent_data);
415 vert_get_n.resize(nb_gauss_pts, 4, false);
416 vert_get_diff_n.resize(nb_gauss_pts, 12, false);
418 1, lambda.size1(), vertex_alpha.size1(), &vertex_alpha(0, 0),
419 &lambda(0, 0), Tools::diffShapeFunMBTET.data(), &vert_get_n(0, 0),
420 &vert_get_diff_n(0, 0));
421 for (int n = 0; n != 4; ++n) {
422 const double f = boost::math::factorial<double>(
423 data.dataOnEntities[MBVERTEX][0].getBBNodeOrder()[n]);
424 for (int g = 0; g != nb_gauss_pts; ++g) {
425 vert_get_n(g, n) *= f;
426 for (int d = 0; d != 3; ++d)
427 vert_get_diff_n(g, 3 * n + d) *= f;
428 }
429 }
430
431 // edges
432 if (data.spacesOnEntities[MBEDGE].test(H1)) {
433 if (data.dataOnEntities[MBEDGE].size() != 6)
434 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
435 "Wrong size of ent data");
436
437 constexpr int edges_nodes[6][2] = {{0, 1}, {1, 2}, {2, 0},
438 {0, 3}, {1, 3}, {2, 3}};
439 for (int ee = 0; ee != 6; ++ee) {
440 auto &ent_data = data.dataOnEntities[MBEDGE][ee];
441 const int sense = ent_data.getSense();
442 if (sense == 0)
443 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
444 "Sense of the edge unknown");
445 const int order = ent_data.getOrder();
446 const int nb_dofs = NBEDGE_H1(order);
447
448 if (nb_dofs) {
449 if (get_alpha_by_order_ptr(ent_data, order)) {
450 get_alpha_by_name_ptr(ent_data, field_name) =
451 get_alpha_by_order_ptr(ent_data, order);
452 get_base_by_name_ptr(ent_data, field_name) =
453 get_base_by_order_ptr(ent_data, order);
454 get_diff_base_by_name_ptr(ent_data, field_name) =
455 get_diff_base_by_order_ptr(ent_data, order);
456 } else {
457 make_own(ent_data);
458 auto &get_n = get_base(ent_data);
459 auto &get_diff_n = get_diff_base(ent_data);
460 get_n.resize(nb_gauss_pts, nb_dofs, false);
461 get_diff_n.resize(nb_gauss_pts, 3 * nb_dofs, false);
462
463 auto &edge_alpha = get_alpha(ent_data);
464 edge_alpha.resize(nb_dofs, 4, false);
466 &edge_alpha(0, 0));
467 if (sense == -1) {
468 for (int i = 0; i != edge_alpha.size1(); ++i) {
469 int a = edge_alpha(i, edges_nodes[ee][0]);
470 edge_alpha(i, edges_nodes[ee][0]) =
471 edge_alpha(i, edges_nodes[ee][1]);
472 edge_alpha(i, edges_nodes[ee][1]) = a;
473 }
474 }
476 order, lambda.size1(), edge_alpha.size1(), &edge_alpha(0, 0),
477 &lambda(0, 0), Tools::diffShapeFunMBTET.data(), &get_n(0, 0),
478 &get_diff_n(0, 0));
479
480 get_alpha_by_order_ptr(ent_data, order) =
481 get_alpha_by_name_ptr(ent_data, field_name);
482 get_base_by_order_ptr(ent_data, order) =
483 get_base_by_name_ptr(ent_data, field_name);
484 get_diff_base_by_order_ptr(ent_data, order) =
485 get_diff_base_by_name_ptr(ent_data, field_name);
486 }
487 } else {
488 set_empty(ent_data);
489 }
490 }
491 } else {
492 for (int ee = 0; ee != 6; ++ee)
493 set_empty(data.dataOnEntities[MBEDGE][ee]);
494 }
495
496 // face
497 if (data.spacesOnEntities[MBTRI].test(H1)) {
498 if (data.dataOnEntities[MBTRI].size() != 4)
499 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
500 "Wrong size of ent data");
501 if (data.facesNodes.size1() != 4)
502 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
503 if (data.facesNodes.size2() != 3)
504 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
505
506 for (int ff = 0; ff != 4; ++ff) {
507 auto &ent_data = data.dataOnEntities[MBTRI][ff];
508 const int order = ent_data.getOrder();
509 const int nb_dofs = NBFACETRI_H1(order);
510
511 if (nb_dofs) {
512 if (get_alpha_by_order_ptr(ent_data, order)) {
513 get_alpha_by_name_ptr(ent_data, field_name) =
514 get_alpha_by_order_ptr(ent_data, order);
515 get_base_by_name_ptr(ent_data, field_name) =
516 get_base_by_order_ptr(ent_data, order);
517 get_diff_base_by_name_ptr(ent_data, field_name) =
518 get_diff_base_by_order_ptr(ent_data, order);
519 } else {
520
521 make_own(ent_data);
522 auto &get_n = get_base(ent_data);
523 auto &get_diff_n = get_diff_base(ent_data);
524 get_n.resize(nb_gauss_pts, nb_dofs, false);
525 get_diff_n.resize(nb_gauss_pts, 3 * nb_dofs, false);
526
527 auto &face_alpha = get_alpha(ent_data);
528 face_alpha.resize(nb_dofs, 4, false);
529
531 &face_alpha(0, 0));
532 senseFaceAlpha.resize(face_alpha.size1(), face_alpha.size2(), false);
533 senseFaceAlpha.clear();
534 constexpr int tri_nodes[4][3] = {
535 {0, 1, 3}, {1, 2, 3}, {0, 2, 3}, {0, 1, 2}};
536 for (int d = 0; d != nb_dofs; ++d)
537 for (int n = 0; n != 3; ++n)
538 senseFaceAlpha(d, data.facesNodes(ff, n)) =
539 face_alpha(d, tri_nodes[ff][n]);
540 face_alpha.swap(senseFaceAlpha);
542 order, lambda.size1(), face_alpha.size1(), &face_alpha(0, 0),
543 &lambda(0, 0), Tools::diffShapeFunMBTET.data(), &get_n(0, 0),
544 &get_diff_n(0, 0));
545
546 get_alpha_by_order_ptr(ent_data, order) =
547 get_alpha_by_name_ptr(ent_data, field_name);
548 get_base_by_order_ptr(ent_data, order) =
549 get_base_by_name_ptr(ent_data, field_name);
550 get_diff_base_by_order_ptr(ent_data, order) =
551 get_diff_base_by_name_ptr(ent_data, field_name);
552 }
553 } else {
554 set_empty(ent_data);
555 }
556 }
557 } else {
558 for (int ff = 0; ff != 4; ++ff)
559 set_empty(data.dataOnEntities[MBTRI][ff]);
560 }
561
562 if (data.spacesOnEntities[MBTET].test(H1)) {
563 if (data.dataOnEntities[MBTET].size() != 1)
564 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
565 "Wrong size ent of ent data");
566
567 auto &ent_data = data.dataOnEntities[MBTET][0];
568 const int order = ent_data.getOrder();
569 const int nb_dofs = NBVOLUMETET_H1(order);
570 if (get_alpha_by_order_ptr(ent_data, order)) {
571 get_alpha_by_name_ptr(ent_data, field_name) =
572 get_alpha_by_order_ptr(ent_data, order);
573 get_base_by_name_ptr(ent_data, field_name) =
574 get_base_by_order_ptr(ent_data, order);
575 get_diff_base_by_name_ptr(ent_data, field_name) =
576 get_diff_base_by_order_ptr(ent_data, order);
577 } else {
578
579 make_own(ent_data);
580 auto &get_n = get_base(ent_data);
581 auto &get_diff_n = get_diff_base(ent_data);
582 get_n.resize(nb_gauss_pts, nb_dofs, false);
583 get_diff_n.resize(nb_gauss_pts, 3 * nb_dofs, false);
584 if (nb_dofs) {
585 auto &tet_alpha = get_alpha(ent_data);
586 tet_alpha.resize(nb_dofs, 4, false);
587
590 order, lambda.size1(), tet_alpha.size1(), &tet_alpha(0, 0),
591 &lambda(0, 0), Tools::diffShapeFunMBTET.data(), &get_n(0, 0),
592 &get_diff_n(0, 0));
593
594 get_alpha_by_order_ptr(ent_data, order) =
595 get_alpha_by_name_ptr(ent_data, field_name);
596 get_base_by_order_ptr(ent_data, order) =
597 get_base_by_name_ptr(ent_data, field_name);
598 get_diff_base_by_order_ptr(ent_data, order) =
599 get_diff_base_by_name_ptr(ent_data, field_name);
600 } else {
601 ent_data.getBBAlphaIndicesSharedPtr(field_name).reset();
602 }
603 }
604 } else {
605 set_empty(data.dataOnEntities[MBTET][0]);
606 }
607
609}
610
613
614 switch (cTx->bAse) {
619 break;
622 break;
623 default:
624 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not implemented");
625 }
626
628}
629
632
633 EntitiesFieldData &data = cTx->dAta;
634 const FieldApproximationBase base = cTx->bAse;
635 PetscErrorCode (*base_polynomials)(int p, double s, double *diff_s, double *L,
636 double *diffL, const int dim) =
638
639 int nb_gauss_pts = pts.size2();
640 int volume_order = data.dataOnEntities[MBTET][0].getOrder();
641 int nb_dofs = NBVOLUMETET_L2(volume_order);
642
643 data.dataOnEntities[MBTET][0].getN(base).resize(nb_gauss_pts, nb_dofs, false);
644 data.dataOnEntities[MBTET][0].getDiffN(base).resize(nb_gauss_pts, 3 * nb_dofs,
645 false);
646
647 if (!nb_dofs)
649
650 auto get_interior_cache = [this](auto base) -> TetBaseCache::BaseCacheMI * {
651 if (vPtr) {
652 auto it = TetBaseCache::l2BaseInterior[base].find(vPtr);
653 if (it != TetBaseCache::l2BaseInterior[base].end()) {
654 return &it->second;
655 }
656 }
657 return nullptr;
658 };
659
660 auto interior_cache_ptr = get_interior_cache(base);
661
662 if (interior_cache_ptr) {
663 auto it =
664 interior_cache_ptr->find(boost::make_tuple(volume_order, nb_gauss_pts));
665 if (it != interior_cache_ptr->end()) {
666 noalias(data.dataOnEntities[MBTET][0].getN(base)) = it->N;
667 noalias(data.dataOnEntities[MBTET][0].getDiffN(base)) = it->diffN;
669 }
670 }
671
673 data.dataOnEntities[MBTET][0].getOrder(),
674 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
675 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
676 &*data.dataOnEntities[MBTET][0].getN(base).data().begin(),
677 &*data.dataOnEntities[MBTET][0].getDiffN(base).data().begin(),
678 nb_gauss_pts, base_polynomials);
679
680 if (interior_cache_ptr) {
681 auto p = interior_cache_ptr->emplace(
682 TetBaseCache::BaseCacheItem{volume_order, nb_gauss_pts});
683 p.first->N = data.dataOnEntities[MBTET][0].getN(base);
684 p.first->diffN = data.dataOnEntities[MBTET][0].getDiffN(base);
685 }
686
688}
689
693
694 EntitiesFieldData &data = cTx->dAta;
695 const std::string field_name = cTx->fieldName;
696 const int nb_gauss_pts = pts.size2();
697
698 if (data.dataOnEntities[MBVERTEX][0].getN(NOBASE).size1() !=
699 (unsigned int)nb_gauss_pts)
700 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
701 "Base functions or nodes has wrong number of integration points "
702 "for base %s",
704 auto &lambda = data.dataOnEntities[MBVERTEX][0].getN(NOBASE);
705
706 auto get_alpha = [field_name](auto &data) -> MatrixInt & {
707 auto &ptr = data.getBBAlphaIndicesSharedPtr(field_name);
708 if (!ptr)
709 ptr.reset(new MatrixInt());
710 return *ptr;
711 };
712
713 auto get_base = [field_name](auto &data) -> MatrixDouble & {
714 auto &ptr = data.getBBNSharedPtr(field_name);
715 if (!ptr)
716 ptr.reset(new MatrixDouble());
717 return *ptr;
718 };
719
720 auto get_diff_base = [field_name](auto &data) -> MatrixDouble & {
721 auto &ptr = data.getBBDiffNSharedPtr(field_name);
722 if (!ptr)
723 ptr.reset(new MatrixDouble());
724 return *ptr;
725 };
726
727 auto get_alpha_by_name_ptr =
728 [](auto &data,
729 const std::string &field_name) -> boost::shared_ptr<MatrixInt> & {
730 return data.getBBAlphaIndicesSharedPtr(field_name);
731 };
732
733 auto get_base_by_name_ptr =
734 [](auto &data,
735 const std::string &field_name) -> boost::shared_ptr<MatrixDouble> & {
736 return data.getBBNSharedPtr(field_name);
737 };
738
739 auto get_diff_base_by_name_ptr =
740 [](auto &data,
741 const std::string &field_name) -> boost::shared_ptr<MatrixDouble> & {
742 return data.getBBDiffNSharedPtr(field_name);
743 };
744
745 auto get_alpha_by_order_ptr =
746 [](auto &data, const size_t o) -> boost::shared_ptr<MatrixInt> & {
747 return data.getBBAlphaIndicesByOrderSharedPtr(o);
748 };
749
750 auto get_base_by_order_ptr =
751 [](auto &data, const size_t o) -> boost::shared_ptr<MatrixDouble> & {
752 return data.getBBNByOrderSharedPtr(o);
753 };
754
755 auto get_diff_base_by_order_ptr =
756 [](auto &data, const size_t o) -> boost::shared_ptr<MatrixDouble> & {
757 return data.getBBDiffNByOrderSharedPtr(o);
758 };
759
760 // See make_own in getValueH1BernsteinBezierBase: detach from a by-order
761 // matrix shared with another field before writing into it.
762 auto make_own = [field_name](auto &ent_data) {
763 auto &n_ptr = ent_data.getBBNSharedPtr(field_name);
764 if (!n_ptr)
765 return;
766 for (auto &ptr : ent_data.getBBNByOrderArray()) {
767 if (ptr && ptr.get() == n_ptr.get()) {
768 ent_data.getBBAlphaIndicesSharedPtr(field_name).reset();
769 ent_data.getBBDiffNSharedPtr(field_name).reset();
770 n_ptr.reset();
771 return;
772 }
773 }
774 };
775
776 if (data.spacesOnEntities[MBTET].test(L2)) {
777 if (data.dataOnEntities[MBTET].size() != 1)
778 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
779 "Wrong size ent of ent data");
780
781 auto &ent_data = data.dataOnEntities[MBTET][0];
782 const int order = ent_data.getOrder();
783 const int nb_dofs = NBVOLUMETET_L2(order);
784 // L2 is element-local, so the order may differ between elements; only the
785 // storage limit applies.
786 if (order < 0 || static_cast<size_t>(order) >=
788 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
789 "Bernstein-Bezier order %d is outside the supported range "
790 "[0, %d]",
791 order,
792 static_cast<int>(
794 1);
795
796 if (get_alpha_by_order_ptr(ent_data, order)) {
797 get_alpha_by_name_ptr(ent_data, field_name) =
798 get_alpha_by_order_ptr(ent_data, order);
799 get_base_by_name_ptr(ent_data, field_name) =
800 get_base_by_order_ptr(ent_data, order);
801 get_diff_base_by_name_ptr(ent_data, field_name) =
802 get_diff_base_by_order_ptr(ent_data, order);
803 } else {
804
805 make_own(ent_data);
806 auto &get_n = get_base(ent_data);
807 auto &get_diff_n = get_diff_base(ent_data);
808 get_n.resize(nb_gauss_pts, nb_dofs, false);
809 get_diff_n.resize(nb_gauss_pts, 3 * nb_dofs, false);
810
811 if (nb_dofs) {
812
813 if (order == 0) {
814
815 if (nb_dofs != 1)
816 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
817 "Inconsistent number of DOFs");
818
819 // The single degree-zero function is one at every integration
820 // point, with the zero multi-index.
821 auto &tet_alpha = get_alpha(ent_data);
822 tet_alpha.resize(1, 4, false);
823 tet_alpha.clear();
824 std::fill(get_n.data().begin(), get_n.data().end(), 1.);
825 get_diff_n.clear();
826
827 } else {
828
829 if (nb_dofs != 4 + 6 * NBEDGE_H1(order) + 4 * NBFACETRI_H1(order) +
831 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
832 "Inconsistent number of DOFs");
833
834 auto &tet_alpha = get_alpha(ent_data);
835 tet_alpha.resize(nb_dofs, 4, false);
836
838 &tet_alpha(0, 0));
839 if (order > 1) {
840 std::array<int, 6> edge_n{order, order, order, order, order, order};
841 std::array<int *, 6> tet_edge_ptr{
842 &tet_alpha(4, 0),
843 &tet_alpha(4 + 1 * NBEDGE_H1(order), 0),
844 &tet_alpha(4 + 2 * NBEDGE_H1(order), 0),
845 &tet_alpha(4 + 3 * NBEDGE_H1(order), 0),
846 &tet_alpha(4 + 4 * NBEDGE_H1(order), 0),
847 &tet_alpha(4 + 5 * NBEDGE_H1(order), 0)};
849 tet_edge_ptr.data());
850 if (order > 2) {
851 std::array<int, 4> face_n{order, order, order, order};
852 std::array<int *, 4> tet_face_ptr{
853 &tet_alpha(4 + 6 * NBEDGE_H1(order), 0),
854 &tet_alpha(4 + 6 * NBEDGE_H1(order) + 1 * NBFACETRI_H1(order),
855 0),
856 &tet_alpha(4 + 6 * NBEDGE_H1(order) + 2 * NBFACETRI_H1(order),
857 0),
858 &tet_alpha(4 + 6 * NBEDGE_H1(order) + 3 * NBFACETRI_H1(order),
859 0),
860 };
862 face_n.data(), tet_face_ptr.data());
863 if (order > 3)
865 order,
866 &tet_alpha(
867 4 + 6 * NBEDGE_H1(order) + 4 * NBFACETRI_H1(order), 0));
868 }
869 }
870
872 order, lambda.size1(), tet_alpha.size1(), &tet_alpha(0, 0),
873 &lambda(0, 0), Tools::diffShapeFunMBTET.data(), &get_n(0, 0),
874 &get_diff_n(0, 0));
875
876 get_alpha_by_order_ptr(ent_data, order) =
877 get_alpha_by_name_ptr(ent_data, field_name);
878 get_base_by_order_ptr(ent_data, order) =
879 get_base_by_name_ptr(ent_data, field_name);
880 get_diff_base_by_order_ptr(ent_data, order) =
881 get_diff_base_by_name_ptr(ent_data, field_name);
882 }
883 }
884 }
885 } else {
886 auto &ent_data = data.dataOnEntities[MBTET][0];
887 make_own(ent_data);
888 ent_data.getBBAlphaIndicesSharedPtr(field_name).reset();
889 get_base(ent_data).resize(nb_gauss_pts, 0, false);
890 get_diff_base(ent_data).resize(nb_gauss_pts, 0, false);
891 }
892
894}
895
897
898 MatrixDouble &pts,
899
900 MatrixDouble &shape_functions, MatrixDouble &diff_shape_functions,
901
902 int volume_order, std::array<int, 4> &faces_order,
903 std::array<int, 3 * 4> &faces_nodes,
904
905 boost::function<int(int)> broken_nbfacetri_edge_hdiv,
906 boost::function<int(int)> broken_nbfacetri_face_hdiv,
907 boost::function<int(int)> broken_nbvolumetet_edge_hdiv,
908 boost::function<int(int)> broken_nbvolumetet_face_hdiv,
909 boost::function<int(int)> broken_nbvolumetet_volume_hdiv
910
911) {
913
914 PetscErrorCode (*base_polynomials)(int p, double s, double *diff_s, double *L,
915 double *diffL, const int dim) =
917
918 int nb_gauss_pts = pts.size2();
919 auto get_data_ptr = [](MatrixDouble &m) -> double * {
920 return (m.size1() && m.size2()) ? &*m.data().begin() : nullptr;
921 };
922
923 // face shape functions
924
925 double *phi_f_e[4][3];
926 double *phi_f[4];
927 double *diff_phi_f_e[4][3];
928 double *diff_phi_f[4];
929
930 N_face_edge.resize(4, 3, false);
931 N_face_bubble.resize(4, false);
932 diffN_face_edge.resize(4, 3, false);
933 diffN_face_bubble.resize(4, false);
934
935 for (int ff = 0; ff != 4; ++ff) {
936 const auto face_edge_dofs = NBFACETRI_AINSWORTH_EDGE_HDIV(
937 broken_nbfacetri_edge_hdiv(faces_order[ff]));
938 // three edges on face
939 for (int ee = 0; ee < 3; ee++) {
940 N_face_edge(ff, ee).resize(nb_gauss_pts, 3 * face_edge_dofs, false);
941 diffN_face_edge(ff, ee).resize(nb_gauss_pts, 9 * face_edge_dofs, false);
942 phi_f_e[ff][ee] = get_data_ptr(N_face_edge(ff, ee));
943 diff_phi_f_e[ff][ee] = get_data_ptr(diffN_face_edge(ff, ee));
944 }
945 auto face_bubble_dofs = NBFACETRI_AINSWORTH_FACE_HDIV(
946 broken_nbfacetri_face_hdiv(faces_order[ff]));
947 N_face_bubble[ff].resize(nb_gauss_pts, 3 * face_bubble_dofs, false);
948 diffN_face_bubble[ff].resize(nb_gauss_pts, 9 * face_bubble_dofs, false);
949 phi_f[ff] = get_data_ptr(N_face_bubble[ff]);
950 diff_phi_f[ff] = get_data_ptr(diffN_face_bubble[ff]);
951 }
952
953 constexpr int nb_nodes_on_tet = 4;
954
955 for (int ff = 0; ff < 4; ff++) {
957 &faces_nodes[3 * ff], broken_nbfacetri_edge_hdiv(faces_order[ff]),
958 &*shape_functions.data().begin(), &*diff_shape_functions.data().begin(),
959 phi_f_e[ff], diff_phi_f_e[ff], nb_gauss_pts, nb_nodes_on_tet,
960 base_polynomials);
961 }
962
963 for (int ff = 0; ff < 4; ff++) {
965 &faces_nodes[3 * ff], broken_nbfacetri_face_hdiv(faces_order[ff]),
966 &*shape_functions.data().begin(), &*diff_shape_functions.data().begin(),
967 phi_f[ff], diff_phi_f[ff], nb_gauss_pts, nb_nodes_on_tet,
968 base_polynomials);
969 }
970
971 // volume shape functions
972
973 double *phi_v_e[6];
974 double *phi_v_f[4];
975 double *phi_v;
976 double *diff_phi_v_e[6];
977 double *diff_phi_v_f[4];
978 double *diff_phi_v;
979
980 const auto volume_edge_dofs = NBVOLUMETET_AINSWORTH_EDGE_HDIV(
981 broken_nbvolumetet_edge_hdiv(volume_order));
982 N_volume_edge.resize(6, false);
983 diffN_volume_edge.resize(6, false);
984 for (int ee = 0; ee != 6; ++ee) {
985 N_volume_edge[ee].resize(nb_gauss_pts, 3 * volume_edge_dofs, false);
986 diffN_volume_edge[ee].resize(nb_gauss_pts, 9 * volume_edge_dofs, false);
987 phi_v_e[ee] = get_data_ptr(N_volume_edge[ee]);
988 diff_phi_v_e[ee] = get_data_ptr(diffN_volume_edge[ee]);
989 }
990 if (volume_edge_dofs)
992 broken_nbvolumetet_edge_hdiv(volume_order),
993 &*shape_functions.data().begin(), &*diff_shape_functions.data().begin(),
994 phi_v_e, diff_phi_v_e, nb_gauss_pts, base_polynomials);
995
996 const auto volume_face_dofs = NBVOLUMETET_AINSWORTH_FACE_HDIV(
997 broken_nbvolumetet_face_hdiv(volume_order));
998 N_volume_face.resize(4, false);
999 diffN_volume_face.resize(4, false);
1000 for (int ff = 0; ff != 4; ++ff) {
1001 N_volume_face[ff].resize(nb_gauss_pts, 3 * volume_face_dofs, false);
1002 diffN_volume_face[ff].resize(nb_gauss_pts, 9 * volume_face_dofs, false);
1003 phi_v_f[ff] = get_data_ptr(N_volume_face[ff]);
1004 diff_phi_v_f[ff] = get_data_ptr(diffN_volume_face[ff]);
1005 }
1006 if (volume_face_dofs)
1008 broken_nbvolumetet_face_hdiv(volume_order),
1009 &*shape_functions.data().begin(), &*diff_shape_functions.data().begin(),
1010 phi_v_f, diff_phi_v_f, nb_gauss_pts, base_polynomials);
1011
1012 auto volume_bubble_dofs = NBVOLUMETET_AINSWORTH_VOLUME_HDIV(
1013 broken_nbvolumetet_volume_hdiv(volume_order));
1014 N_volume_bubble.resize(nb_gauss_pts, 3 * volume_bubble_dofs, false);
1015 diffN_volume_bubble.resize(nb_gauss_pts, 9 * volume_bubble_dofs, false);
1016 phi_v = get_data_ptr(N_volume_bubble);
1017 diff_phi_v = get_data_ptr(diffN_volume_bubble);
1018 if (volume_bubble_dofs)
1020 broken_nbvolumetet_volume_hdiv(volume_order),
1021 &*shape_functions.data().begin(), &*diff_shape_functions.data().begin(),
1022 phi_v, diff_phi_v, nb_gauss_pts, base_polynomials);
1023
1025}
1026
1029
1030 std::array<int, 4> faces_order;
1031 std::array<int, 4 * 3> faces_nodes;
1032
1034 EntitiesFieldData &data = cTx->dAta;
1035
1036 int volume_order = data.dataOnEntities[MBTET][0].getOrder();
1037 std::copy(data.facesNodes.data().begin(), data.facesNodes.data().end(),
1038 faces_nodes.begin());
1039 for (int ff = 0; ff != 4; ff++) {
1040 faces_order[ff] = cTx->dAta.dataOnEntities[MBTRI][ff].getOrder();
1041 }
1042
1044 pts, data.dataOnEntities[MBVERTEX][0].getN(base),
1045 data.dataOnEntities[MBVERTEX][0].getDiffN(base), volume_order,
1046 faces_order, faces_nodes,
1047
1053
1054 );
1055
1056 // Set shape functions into data structure Shape functions hast to be put
1057 // in arrays in order which guarantee hierarchical series of degrees of
1058 // freedom, i.e. in other words dofs form sub-entities has to be group
1059 // by order.
1060
1061 FTENSOR_INDEX(3, i);
1062 FTENSOR_INDEX(3, j);
1063
1064 int nb_gauss_pts = pts.size2();
1065 auto get_data_ptr = [](MatrixDouble &m) -> double * {
1066 return (m.size1() && m.size2()) ? &*m.data().begin() : nullptr;
1067 };
1068
1069 // faces
1070 if (data.dataOnEntities[MBTRI].size() != 4) {
1071 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
1072 }
1073
1074 // face-face
1075 using Tensor1Ptr3 =
1076 decltype(getFTensor1FromPtr<3>(static_cast<double *>(nullptr)));
1077 Tensor1Ptr3 t_base_f_f[] = {
1078 getFTensor1FromPtr<3>(get_data_ptr(N_face_bubble[0])),
1079 getFTensor1FromPtr<3>(get_data_ptr(N_face_bubble[1])),
1080 getFTensor1FromPtr<3>(get_data_ptr(N_face_bubble[2])),
1081 getFTensor1FromPtr<3>(get_data_ptr(N_face_bubble[3]))};
1082 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_f_f[] = {
1087 // face-edge
1088 Tensor1Ptr3 t_base_f_e[] = {
1089 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(0, 0))),
1090 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(0, 1))),
1091 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(0, 2))),
1092 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(1, 0))),
1093 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(1, 1))),
1094 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(1, 2))),
1095 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(2, 0))),
1096 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(2, 1))),
1097 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(2, 2))),
1098 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(3, 0))),
1099 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(3, 1))),
1100 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(3, 2)))};
1101 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_f_e[] = {
1102 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(0, 0))),
1103 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(0, 1))),
1104 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(0, 2))),
1105 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(1, 0))),
1106 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(1, 1))),
1107 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(1, 2))),
1108 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(2, 0))),
1109 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(2, 1))),
1110 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(2, 2))),
1111 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(3, 0))),
1112 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(3, 1))),
1113 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(3, 2)))};
1114
1115 for (int ff = 0; ff != 4; ff++) {
1116 int face_order = faces_order[ff];
1117 auto face_dofs =
1122 data.dataOnEntities[MBTRI][ff].getN(base).resize(nb_gauss_pts,
1123 3 * face_dofs, false);
1124 data.dataOnEntities[MBTRI][ff].getDiffN(base).resize(nb_gauss_pts,
1125 9 * face_dofs, false);
1126 if (face_dofs) {
1127 double *base_ptr =
1128 &*data.dataOnEntities[MBTRI][ff].getN(base).data().begin();
1129 double *diff_base_ptr =
1130 &*data.dataOnEntities[MBTRI][ff].getDiffN(base).data().begin();
1131 auto t_base = getFTensor1FromPtr<3>(base_ptr);
1132 auto t_diff_base = getFTensor2HVecFromPtr<3, 3>(diff_base_ptr);
1133
1134 auto max_face_order =
1135 std::max(face_order,
1137 max_face_order =
1138 std::max(max_face_order,
1140
1141 for (int gg = 0; gg != nb_gauss_pts; gg++) {
1142 for (int oo = 0; oo != max_face_order; oo++) {
1143
1144 // face-edge
1146 for (int dd = NBFACETRI_AINSWORTH_EDGE_HDIV(oo);
1147 dd != NBFACETRI_AINSWORTH_EDGE_HDIV(oo + 1); dd++) {
1148 for (int ee = 0; ee != 3; ++ee) {
1149 t_base(i) = t_base_f_e[ff * 3 + ee](i);
1150 ++t_base;
1151 ++t_base_f_e[ff * 3 + ee];
1152 }
1153 for (int ee = 0; ee != 3; ++ee) {
1154 t_diff_base(i, j) = t_diff_base_f_e[ff * 3 + ee](i, j);
1155 ++t_diff_base;
1156 ++t_diff_base_f_e[ff * 3 + ee];
1157 }
1158 }
1159
1160 // face-face
1162 for (int dd = NBFACETRI_AINSWORTH_FACE_HDIV(oo);
1163 dd != NBFACETRI_AINSWORTH_FACE_HDIV(oo + 1); dd++) {
1164 t_base(i) = t_base_f_f[ff](i);
1165 ++t_base;
1166 ++t_base_f_f[ff];
1167 t_diff_base(i, j) = t_diff_base_f_f[ff](i, j);
1168 ++t_diff_base;
1169 ++t_diff_base_f_f[ff];
1170 }
1171 }
1172 }
1173 }
1174 }
1175
1176 // volume
1177 int volume_dofs =
1184 data.dataOnEntities[MBTET][0].getN(base).resize(nb_gauss_pts, 3 * volume_dofs,
1185 false);
1186 data.dataOnEntities[MBTET][0].getDiffN(base).resize(nb_gauss_pts,
1187 9 * volume_dofs, false);
1188 if (volume_dofs) {
1189 double *base_ptr =
1190 &*data.dataOnEntities[MBTET][0].getN(base).data().begin();
1191 double *diff_base_ptr =
1192 &*data.dataOnEntities[MBTET][0].getDiffN(base).data().begin();
1193 auto t_base = getFTensor1FromPtr<3>(base_ptr);
1194 auto t_diff_base = getFTensor2HVecFromPtr<3, 3>(diff_base_ptr);
1195
1196 // volume-edge
1197 using Tensor1Ptr3 =
1198 decltype(getFTensor1FromPtr<3>(static_cast<double *>(nullptr)));
1199 Tensor1Ptr3 t_base_v_e[] = {
1200 getFTensor1FromPtr<3>(get_data_ptr(N_volume_edge[0])),
1201 getFTensor1FromPtr<3>(get_data_ptr(N_volume_edge[1])),
1202 getFTensor1FromPtr<3>(get_data_ptr(N_volume_edge[2])),
1203 getFTensor1FromPtr<3>(get_data_ptr(N_volume_edge[3])),
1204 getFTensor1FromPtr<3>(get_data_ptr(N_volume_edge[4])),
1205 getFTensor1FromPtr<3>(get_data_ptr(N_volume_edge[5]))};
1206 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_v_e[] = {
1213
1214 // volume-faces
1215 Tensor1Ptr3 t_base_v_f[] = {
1216 getFTensor1FromPtr<3>(get_data_ptr(N_volume_face[0])),
1217 getFTensor1FromPtr<3>(get_data_ptr(N_volume_face[1])),
1218 getFTensor1FromPtr<3>(get_data_ptr(N_volume_face[2])),
1219 getFTensor1FromPtr<3>(get_data_ptr(N_volume_face[3]))};
1220 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_v_f[] = {
1225
1226 // volume-bubble
1227 base_ptr = get_data_ptr(N_volume_bubble);
1228 diff_base_ptr = get_data_ptr(diffN_volume_bubble);
1229 auto t_base_v = getFTensor1FromPtr<3>(base_ptr);
1230 auto t_diff_base_v = getFTensor2HVecFromPtr<3, 3>(diff_base_ptr);
1231
1232 auto max_volume_order = std::max(
1233 volume_order,
1235 max_volume_order = std::max(
1236 max_volume_order,
1238 max_volume_order = std::max(
1239 max_volume_order,
1241
1242 for (int gg = 0; gg != nb_gauss_pts; gg++) {
1243 for (int oo = 0; oo < max_volume_order; oo++) {
1244
1245 // volume-edge
1246 if (oo <
1248 for (int dd = NBVOLUMETET_AINSWORTH_EDGE_HDIV(oo);
1249 dd != NBVOLUMETET_AINSWORTH_EDGE_HDIV(oo + 1); dd++) {
1250 for (int ee = 0; ee < 6; ee++) {
1251 t_base(i) = t_base_v_e[ee](i);
1252 ++t_base;
1253 ++t_base_v_e[ee];
1254 t_diff_base(i, j) = t_diff_base_v_e[ee](i, j);
1255 ++t_diff_base;
1256 ++t_diff_base_v_e[ee];
1257 }
1258 }
1259
1260 // volume-face
1261 if (oo <
1263 for (int dd = NBVOLUMETET_AINSWORTH_FACE_HDIV(oo);
1264 dd < NBVOLUMETET_AINSWORTH_FACE_HDIV(oo + 1); dd++) {
1265 for (int ff = 0; ff < 4; ff++) {
1266 t_base(i) = t_base_v_f[ff](i);
1267 ++t_base;
1268 ++t_base_v_f[ff];
1269 t_diff_base(i, j) = t_diff_base_v_f[ff](i, j);
1270 ++t_diff_base;
1271 ++t_diff_base_v_f[ff];
1272 }
1273 }
1274
1275 // volume-bubble
1276 if (oo <
1278 for (int dd = NBVOLUMETET_AINSWORTH_VOLUME_HDIV(oo);
1279 dd < NBVOLUMETET_AINSWORTH_VOLUME_HDIV(oo + 1); dd++) {
1280 t_base(i) = t_base_v(i);
1281 ++t_base;
1282 ++t_base_v;
1283 t_diff_base(i, j) = t_diff_base_v(i, j);
1284 ++t_diff_base;
1285 ++t_diff_base_v;
1286 }
1287 }
1288 }
1289 }
1290
1292}
1293
1297
1298 // Set shape functions into data structure Shape functions has to be put
1299 // in arrays in order which guarantee hierarchical series of degrees of
1300 // freedom, i.e. in other words dofs form sub-entities has to be group
1301 // by order.
1302
1304 EntitiesFieldData &data = cTx->dAta;
1305
1306 FTENSOR_INDEX(3, i);
1307 FTENSOR_INDEX(3, j);
1308
1309 int volume_order = data.dataOnEntities[MBTET][0].getOrder();
1310 int nb_gauss_pts = pts.size2();
1311 auto get_data_ptr = [](MatrixDouble &m) -> double * {
1312 return (m.size1() && m.size2()) ? &*m.data().begin() : nullptr;
1313 };
1314 int nb_dofs_face =
1319 int nb_dofs_volume =
1326
1327 int nb_dofs = 4 * nb_dofs_face + nb_dofs_volume;
1328 data.dataOnEntities[MBTET][0].getN(base).resize(nb_gauss_pts, 3 * nb_dofs,
1329 false);
1330 data.dataOnEntities[MBTET][0].getDiffN(base).resize(nb_gauss_pts, 9 * nb_dofs,
1331 false);
1332 if (nb_dofs == 0)
1334
1335 auto get_interior_cache = [this](auto base) -> TetBaseCache::BaseCacheMI * {
1336 if (vPtr) {
1337 auto it = TetBaseCache::hdivBrokenBaseInterior[base].find(vPtr);
1338 if (it != TetBaseCache::hdivBrokenBaseInterior[base].end()) {
1339 return &it->second;
1340 }
1341 }
1342 return nullptr;
1343 };
1344
1345 auto interior_cache_ptr = get_interior_cache(base);
1346
1347 if (interior_cache_ptr) {
1348 auto it =
1349 interior_cache_ptr->find(boost::make_tuple(volume_order, nb_gauss_pts));
1350 if (it != interior_cache_ptr->end()) {
1351 noalias(data.dataOnEntities[MBTET][0].getN(base)) = it->N;
1352 noalias(data.dataOnEntities[MBTET][0].getDiffN(base)) = it->diffN;
1354 }
1355 }
1356
1357 std::array<int, 4 * 3> faces_nodes = {0, 1, 3, 1, 2, 3, 0, 3, 2, 0, 2, 1};
1358 std::array<int, 4> faces_order{volume_order, volume_order, volume_order,
1359 volume_order};
1361 pts, data.dataOnEntities[MBVERTEX][0].getN(base),
1362 data.dataOnEntities[MBVERTEX][0].getDiffN(base), volume_order,
1363 faces_order, faces_nodes,
1364
1370
1371 );
1372
1373 auto *base_ptr = &*data.dataOnEntities[MBTET][0].getN(base).data().begin();
1374 auto *diff_base_ptr =
1375 &*data.dataOnEntities[MBTET][0].getDiffN(base).data().begin();
1376 auto t_base = getFTensor1FromPtr<3>(base_ptr);
1377 auto t_diff_base = getFTensor2HVecFromPtr<3, 3>(diff_base_ptr);
1378
1379 // face-edge
1380 using Tensor1Ptr3 =
1381 decltype(getFTensor1FromPtr<3>(static_cast<double *>(nullptr)));
1382 Tensor1Ptr3 t_base_f_e[] = {
1383 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(0, 0))),
1384 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(0, 1))),
1385 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(0, 2))),
1386 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(1, 0))),
1387 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(1, 1))),
1388 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(1, 2))),
1389 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(2, 0))),
1390 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(2, 1))),
1391 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(2, 2))),
1392 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(3, 0))),
1393 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(3, 1))),
1394 getFTensor1FromPtr<3>(get_data_ptr(N_face_edge(3, 2)))};
1395 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_f_e[] = {
1396 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(0, 0))),
1397 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(0, 1))),
1398 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(0, 2))),
1399 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(1, 0))),
1400 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(1, 1))),
1401 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(1, 2))),
1402 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(2, 0))),
1403 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(2, 1))),
1404 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(2, 2))),
1405 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(3, 0))),
1406 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(3, 1))),
1407 getFTensor2HVecFromPtr<3, 3>(get_data_ptr(diffN_face_edge(3, 2)))};
1408
1409 // face-face
1410 Tensor1Ptr3 t_base_f_f[] = {
1411 getFTensor1FromPtr<3>(get_data_ptr(N_face_bubble[0])),
1412 getFTensor1FromPtr<3>(get_data_ptr(N_face_bubble[1])),
1413 getFTensor1FromPtr<3>(get_data_ptr(N_face_bubble[2])),
1414 getFTensor1FromPtr<3>(get_data_ptr(N_face_bubble[3]))};
1415 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_f_f[] = {
1420
1421 // volume-edge
1422 Tensor1Ptr3 t_base_v_e[] = {
1423 getFTensor1FromPtr<3>(get_data_ptr(N_volume_edge[0])),
1424 getFTensor1FromPtr<3>(get_data_ptr(N_volume_edge[1])),
1425 getFTensor1FromPtr<3>(get_data_ptr(N_volume_edge[2])),
1426 getFTensor1FromPtr<3>(get_data_ptr(N_volume_edge[3])),
1427 getFTensor1FromPtr<3>(get_data_ptr(N_volume_edge[4])),
1428 getFTensor1FromPtr<3>(get_data_ptr(N_volume_edge[5]))};
1429 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_v_e[] = {
1436
1437 // volume-faces
1438 Tensor1Ptr3 t_base_v_f[] = {
1439 getFTensor1FromPtr<3>(get_data_ptr(N_volume_face[0])),
1440 getFTensor1FromPtr<3>(get_data_ptr(N_volume_face[1])),
1441 getFTensor1FromPtr<3>(get_data_ptr(N_volume_face[2])),
1442 getFTensor1FromPtr<3>(get_data_ptr(N_volume_face[3]))};
1443 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_v_f[] = {
1448
1449 // volume-bubble
1450 auto *base_vol_ptr = get_data_ptr(N_volume_bubble);
1451 auto *diff_base_vol_ptr = get_data_ptr(diffN_volume_bubble);
1452 auto t_base_v = getFTensor1FromPtr<3>(base_vol_ptr);
1453 auto t_diff_base_v = getFTensor2HVecFromPtr<3, 3>(diff_base_vol_ptr);
1454
1455 int count_dofs = 0;
1456 int count_dofs_face = 0;
1457 int count_dofs_volume = 0;
1458
1459 auto max_volume_order =
1460 std::max(volume_order,
1462 max_volume_order =
1463 std::max(max_volume_order,
1465 max_volume_order =
1466 std::max(max_volume_order,
1468 max_volume_order =
1469 std::max(max_volume_order,
1471 max_volume_order = std::max(
1472 max_volume_order,
1474
1475 for (int gg = 0; gg != nb_gauss_pts; gg++) {
1476 for (int oo = 0; oo < max_volume_order; oo++) {
1477
1478 // faces-edge (((P) > 0) ? (P) : 0)
1480 for (int dd = NBFACETRI_AINSWORTH_EDGE_HDIV(oo);
1481 dd != NBFACETRI_AINSWORTH_EDGE_HDIV(oo + 1); dd++) {
1482 for (auto ff = 0; ff != 4; ++ff) {
1483 for (int ee = 0; ee != 3; ++ee) {
1484 t_base(i) = t_base_f_e[ff * 3 + ee](i);
1485 ++t_base;
1486 ++t_base_f_e[ff * 3 + ee];
1487 ++count_dofs;
1488 ++count_dofs_face;
1489 }
1490 for (int ee = 0; ee != 3; ++ee) {
1491 t_diff_base(i, j) = t_diff_base_f_e[ff * 3 + ee](i, j);
1492 ++t_diff_base;
1493 ++t_diff_base_f_e[ff * 3 + ee];
1494 }
1495 }
1496 }
1497
1498 // face-face (P - 1) * (P - 2) / 2
1500 for (int dd = NBFACETRI_AINSWORTH_FACE_HDIV(oo);
1501 dd != NBFACETRI_AINSWORTH_FACE_HDIV(oo + 1); dd++) {
1502 for (auto ff = 0; ff != 4; ++ff) {
1503 t_base(i) = t_base_f_f[ff](i);
1504 ++t_base;
1505 ++t_base_f_f[ff];
1506 t_diff_base(i, j) = t_diff_base_f_f[ff](i, j);
1507 ++t_diff_base;
1508 ++t_diff_base_f_f[ff];
1509 ++count_dofs;
1510 ++count_dofs_face;
1511 }
1512 }
1513
1514 // volume-edge (P - 1)
1516 for (int dd = NBVOLUMETET_AINSWORTH_EDGE_HDIV(oo);
1517 dd != NBVOLUMETET_AINSWORTH_EDGE_HDIV(oo + 1); dd++) {
1518 for (int ee = 0; ee < 6; ++ee) {
1519 t_base(i) = t_base_v_e[ee](i);
1520 ++t_base;
1521 ++t_base_v_e[ee];
1522 t_diff_base(i, j) = t_diff_base_v_e[ee](i, j);
1523 ++t_diff_base;
1524 ++t_diff_base_v_e[ee];
1525 ++count_dofs;
1526 ++count_dofs_volume;
1527 }
1528 }
1529
1530 // volume-face (P - 1) * (P - 2)
1532 for (int dd = NBVOLUMETET_AINSWORTH_FACE_HDIV(oo);
1533 dd != NBVOLUMETET_AINSWORTH_FACE_HDIV(oo + 1); dd++) {
1534 for (int ff = 0; ff < 4; ff++) {
1535 t_base(i) = t_base_v_f[ff](i);
1536 ++t_base;
1537 ++t_base_v_f[ff];
1538 t_diff_base(i, j) = t_diff_base_v_f[ff](i, j);
1539 ++t_diff_base;
1540 ++t_diff_base_v_f[ff];
1541 ++count_dofs;
1542 ++count_dofs_volume;
1543 }
1544 }
1545
1546 // volume-bubble (P - 3) * (P - 2) * (P - 1) / 2
1547 if (oo <
1549 for (int dd = NBVOLUMETET_AINSWORTH_VOLUME_HDIV(oo);
1550 dd != NBVOLUMETET_AINSWORTH_VOLUME_HDIV(oo + 1); dd++) {
1551 t_base(i) = t_base_v(i);
1552 ++t_base;
1553 ++t_base_v;
1554 t_diff_base(i, j) = t_diff_base_v(i, j);
1555 ++t_diff_base;
1556 ++t_diff_base_v;
1557 ++count_dofs;
1558 ++count_dofs_volume;
1559 }
1560 }
1561 }
1562
1563#ifndef NDEBUG
1564 if (nb_dofs != count_dofs / nb_gauss_pts) {
1565 MOFEM_LOG_CHANNEL("SELF");
1566 MOFEM_LOG("SELF", Sev::error) << "Nb dofs face: " << 4 * nb_dofs_face
1567 << " -> " << count_dofs_face / nb_gauss_pts;
1568 MOFEM_LOG("SELF", Sev::error) << "Nb dofs volume: " << nb_dofs_volume
1569 << " -> " << count_dofs_volume / nb_gauss_pts;
1570 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1571 "Number of dofs %d is different than expected %d",
1572 count_dofs / nb_gauss_pts, nb_dofs);
1573 }
1574#endif // NDEBUG
1575
1576 if (interior_cache_ptr) {
1577 auto p = interior_cache_ptr->emplace(
1578 TetBaseCache::BaseCacheItem{volume_order, nb_gauss_pts});
1579 p.first->N = data.dataOnEntities[MBTET][0].getN(base);
1580 p.first->diffN = data.dataOnEntities[MBTET][0].getDiffN(base);
1581 }
1582
1584}
1585
1588
1589 EntitiesFieldData &data = cTx->dAta;
1590 const FieldApproximationBase base = cTx->bAse;
1591 if (base != DEMKOWICZ_JACOBI_BASE) {
1592 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1593 "This should be used only with DEMKOWICZ_JACOBI_BASE "
1594 "but base is %s",
1596 }
1597 int nb_gauss_pts = pts.size2();
1598
1599 int volume_order = data.dataOnEntities[MBTET][0].getOrder();
1600
1601 int p_f[4];
1602 double *phi_f[4];
1603 double *diff_phi_f[4];
1604
1605 auto get_face_cache_ptr = [this]() -> TetBaseCache::HDivBaseFaceCacheMI * {
1606 if (vPtr) {
1609 return &it->second;
1610 }
1611 }
1612 return nullptr;
1613 };
1614
1615 auto face_cache_ptr = get_face_cache_ptr();
1616
1617 // Calculate base function on tet faces
1618 for (int ff = 0; ff != 4; ff++) {
1619 int face_order = data.dataOnEntities[MBTRI][ff].getOrder();
1620 int order = volume_order > face_order ? volume_order : face_order;
1621 data.dataOnEntities[MBTRI][ff].getN(base).resize(
1622 nb_gauss_pts, 3 * NBFACETRI_DEMKOWICZ_HDIV(order), false);
1623 data.dataOnEntities[MBTRI][ff].getDiffN(base).resize(
1624 nb_gauss_pts, 9 * NBFACETRI_DEMKOWICZ_HDIV(order), false);
1626 continue;
1627
1628 if (face_cache_ptr) {
1629 auto it = face_cache_ptr->find(boost::make_tuple(
1630
1631 face_order, nb_gauss_pts,
1632
1633 data.facesNodes(ff, 0), data.facesNodes(ff, 1), data.facesNodes(ff, 2)
1634
1635 ));
1636 if (it != face_cache_ptr->end()) {
1637 noalias(data.dataOnEntities[MBTRI][ff].getN(base)) = it->N;
1638 noalias(data.dataOnEntities[MBTRI][ff].getDiffN(base)) = it->diffN;
1639 continue;
1640 }
1641 }
1642
1643 p_f[ff] = order;
1644 phi_f[ff] = &*data.dataOnEntities[MBTRI][ff].getN(base).data().begin();
1645 diff_phi_f[ff] =
1646 &*data.dataOnEntities[MBTRI][ff].getDiffN(base).data().begin();
1647
1649 &data.facesNodes(ff, 0), order,
1650 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
1651 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
1652 phi_f[ff], diff_phi_f[ff], nb_gauss_pts, 4);
1653 if (face_cache_ptr) {
1654 auto p = face_cache_ptr->emplace(TetBaseCache::HDivBaseCacheItem{
1655 face_order, nb_gauss_pts, data.facesNodes(ff, 0),
1656 data.facesNodes(ff, 1), data.facesNodes(ff, 2)});
1657 p.first->N = data.dataOnEntities[MBTRI][ff].getN(base);
1658 p.first->diffN = data.dataOnEntities[MBTRI][ff].getDiffN(base);
1659 }
1660 }
1661
1662 auto get_interior_cache = [this]() -> TetBaseCache::BaseCacheMI * {
1663 if (vPtr) {
1664 auto it =
1667 return &it->second;
1668 }
1669 }
1670 return nullptr;
1671 };
1672
1673 auto interior_cache_ptr = get_interior_cache();
1674
1675 // Calculate base functions in tet interior
1676 if (NBVOLUMETET_DEMKOWICZ_HDIV(volume_order) > 0) {
1677 data.dataOnEntities[MBTET][0].getN(base).resize(
1678 nb_gauss_pts, 3 * NBVOLUMETET_DEMKOWICZ_HDIV(volume_order), false);
1679 data.dataOnEntities[MBTET][0].getDiffN(base).resize(
1680 nb_gauss_pts, 9 * NBVOLUMETET_DEMKOWICZ_HDIV(volume_order), false);
1681
1682 for (int v = 0; v != 1; ++v) {
1683 if (interior_cache_ptr) {
1684 auto it = interior_cache_ptr->find(
1685 boost::make_tuple(volume_order, nb_gauss_pts));
1686 if (it != interior_cache_ptr->end()) {
1687 noalias(data.dataOnEntities[MBTET][0].getN(base)) = it->N;
1688 noalias(data.dataOnEntities[MBTET][0].getDiffN(base)) = it->diffN;
1689 continue;
1690 }
1691 }
1692
1693 double *phi_v = &*data.dataOnEntities[MBTET][0].getN(base).data().begin();
1694 double *diff_phi_v =
1695 &*data.dataOnEntities[MBTET][0].getDiffN(base).data().begin();
1696
1698 volume_order, &data.dataOnEntities[MBVERTEX][0].getN(base)(0, 0),
1699 &data.dataOnEntities[MBVERTEX][0].getDiffN(base)(0, 0), p_f, phi_f,
1700 diff_phi_f, phi_v, diff_phi_v, nb_gauss_pts);
1701 if (interior_cache_ptr) {
1702 auto p = interior_cache_ptr->emplace(
1703 TetBaseCache::BaseCacheItem{volume_order, nb_gauss_pts});
1704 p.first->N = data.dataOnEntities[MBTET][0].getN(base);
1705 p.first->diffN = data.dataOnEntities[MBTET][0].getDiffN(base);
1706 }
1707 }
1708 }
1709
1710 // Set size of face base correctly
1711 for (int ff = 0; ff != 4; ff++) {
1712 int face_order = data.dataOnEntities[MBTRI][ff].getOrder();
1713 data.dataOnEntities[MBTRI][ff].getN(base).resize(
1714 nb_gauss_pts, 3 * NBFACETRI_DEMKOWICZ_HDIV(face_order), true);
1715 data.dataOnEntities[MBTRI][ff].getDiffN(base).resize(
1716 nb_gauss_pts, 9 * NBFACETRI_DEMKOWICZ_HDIV(face_order), true);
1717 }
1718
1720}
1721
1725
1726 EntitiesFieldData &data = cTx->dAta;
1727 const FieldApproximationBase base = cTx->bAse;
1728 if (base != DEMKOWICZ_JACOBI_BASE) {
1729 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1730 "This should be used only with DEMKOWICZ_JACOBI_BASE "
1731 "but base is %s",
1733 }
1734 int nb_gauss_pts = pts.size2();
1735
1736 int volume_order = data.dataOnEntities[MBTET][0].getOrder();
1737 int nb_dofs_face = NBFACETRI_DEMKOWICZ_HDIV(volume_order);
1738 int nb_dofs_volume = NBVOLUMETET_DEMKOWICZ_HDIV(volume_order);
1739 int nb_dofs = 4 * nb_dofs_face + nb_dofs_volume;
1740 data.dataOnEntities[MBTET][0].getN(base).resize(nb_gauss_pts, 3 * nb_dofs,
1741 false);
1742 data.dataOnEntities[MBTET][0].getDiffN(base).resize(nb_gauss_pts, 9 * nb_dofs,
1743 false);
1744 if (nb_dofs == 0)
1746
1747 auto get_interior_cache = [this]() -> TetBaseCache::BaseCacheMI * {
1748 if (vPtr) {
1749 auto it =
1751 vPtr);
1752 if (it !=
1754 return &it->second;
1755 }
1756 }
1757 return nullptr;
1758 };
1759
1760 auto interior_cache_ptr = get_interior_cache();
1761
1762 if (interior_cache_ptr) {
1763 auto it =
1764 interior_cache_ptr->find(boost::make_tuple(volume_order, nb_gauss_pts));
1765 if (it != interior_cache_ptr->end()) {
1766 noalias(data.dataOnEntities[MBTET][0].getN(base)) = it->N;
1767 noalias(data.dataOnEntities[MBTET][0].getDiffN(base)) = it->diffN;
1769 }
1770 }
1771
1772 std::array<MatrixDouble, 4> face_base_fun{
1773 MatrixDouble(nb_gauss_pts, 3 * nb_dofs_face),
1774 MatrixDouble(nb_gauss_pts, 3 * nb_dofs_face),
1775 MatrixDouble(nb_gauss_pts, 3 * nb_dofs_face),
1776 MatrixDouble(nb_gauss_pts, 3 * nb_dofs_face)};
1777 std::array<MatrixDouble, 4> face_diff_base{
1778 MatrixDouble(nb_gauss_pts, 9 * nb_dofs_face),
1779 MatrixDouble(nb_gauss_pts, 9 * nb_dofs_face),
1780 MatrixDouble(nb_gauss_pts, 9 * nb_dofs_face),
1781 MatrixDouble(nb_gauss_pts, 9 * nb_dofs_face)};
1782
1783 int faces_nodes[4][3] = {{0, 1, 3}, {1, 2, 3}, {0, 3, 2}, {0, 2, 1}};
1784
1785 std::array<int, 4> p_f{volume_order, volume_order, volume_order,
1786 volume_order};
1787 std::array<double *, 4> phi_f{
1788 &*face_base_fun[0].data().begin(), &*face_base_fun[1].data().begin(),
1789 &*face_base_fun[2].data().begin(), &*face_base_fun[3].data().begin()};
1790 std::array<double *, 4> diff_phi_f{
1791 &*face_diff_base[0].data().begin(), &*face_diff_base[1].data().begin(),
1792 &*face_diff_base[2].data().begin(), &*face_diff_base[3].data().begin()};
1793
1794 // Calculate base function on tet faces
1795 for (int ff = 0; ff != 4; ff++) {
1797 // &data.facesNodes(ff, 0)
1798 faces_nodes[ff], p_f[ff],
1799 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
1800 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
1801 phi_f[ff], diff_phi_f[ff], nb_gauss_pts, 4);
1802 }
1803
1804 MatrixDouble vol_bases(nb_gauss_pts, 3 * nb_dofs_volume);
1805 MatrixDouble vol_diff_bases(nb_gauss_pts, 9 * nb_dofs_volume);
1806 auto *phi_v = &*vol_bases.data().begin();
1807 auto *diff_phi_v = &*vol_diff_bases.data().begin();
1809 volume_order, &data.dataOnEntities[MBVERTEX][0].getN(base)(0, 0),
1810 &data.dataOnEntities[MBVERTEX][0].getDiffN(base)(0, 0), p_f.data(),
1811 phi_f.data(), diff_phi_f.data(), phi_v, diff_phi_v, nb_gauss_pts);
1812
1813 // faces
1814 using Tensor1Ptr3 =
1815 decltype(getFTensor1FromPtr<3>(static_cast<double *>(nullptr)));
1816 Tensor1Ptr3 t_base_v_f[] = {
1817 getFTensor1FromPtr<3>(phi_f[0]), getFTensor1FromPtr<3>(phi_f[1]),
1818 getFTensor1FromPtr<3>(phi_f[2]), getFTensor1FromPtr<3>(phi_f[3])};
1819 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_diff_base_v_f[] = {
1820 getFTensor2HVecFromPtr<3, 3>(diff_phi_f[0]),
1821 getFTensor2HVecFromPtr<3, 3>(diff_phi_f[1]),
1822 getFTensor2HVecFromPtr<3, 3>(diff_phi_f[2]),
1823 getFTensor2HVecFromPtr<3, 3>(diff_phi_f[3])};
1824
1825 // volumes
1826 auto t_base_v = getFTensor1FromPtr<3>(&*vol_bases.data().begin());
1828 getFTensor2HVecFromPtr<3, 3>(&*vol_diff_bases.data().begin());
1829
1830 auto t_base = getFTensor1FromPtr<3>(
1831 &*data.dataOnEntities[MBTET][0].getN(base).data().begin());
1832 auto t_diff_base = getFTensor2HVecFromPtr<3, 3>(
1833 &*data.dataOnEntities[MBTET][0].getDiffN(base).data().begin());
1834
1835 FTENSOR_INDEX(3, i);
1836 FTENSOR_INDEX(3, j);
1837
1838 for (auto gg = 0; gg != nb_gauss_pts; ++gg) {
1839 for (int oo = 0; oo < volume_order; oo++) {
1840 // face
1841 for (auto dd = NBFACETRI_DEMKOWICZ_HDIV(oo);
1842 dd != NBFACETRI_DEMKOWICZ_HDIV(oo + 1); ++dd) {
1843 for (auto ff = 0; ff != 4; ++ff) {
1844 t_base(i) = t_base_v_f[ff](i);
1845 ++t_base;
1846 ++t_base_v_f[ff];
1847 t_diff_base(i, j) = t_diff_base_v_f[ff](i, j);
1848 ++t_diff_base;
1849 ++t_diff_base_v_f[ff];
1850 }
1851 }
1852 // volume
1853 for (auto dd = NBVOLUMETET_DEMKOWICZ_HDIV(oo);
1854 dd != NBVOLUMETET_DEMKOWICZ_HDIV(oo + 1); ++dd) {
1855 t_base(i) = t_base_v(i);
1856 ++t_base;
1857 ++t_base_v;
1858 t_diff_base(i, j) = t_diff_base_v(i, j);
1859 ++t_diff_base;
1860 ++t_diff_base_v;
1861 }
1862 }
1863 }
1864
1865 if (interior_cache_ptr) {
1866 auto p = interior_cache_ptr->emplace(
1867 TetBaseCache::BaseCacheItem{volume_order, nb_gauss_pts});
1868 p.first->N = data.dataOnEntities[MBTET][0].getN(base);
1869 p.first->diffN = data.dataOnEntities[MBTET][0].getDiffN(base);
1870 }
1871
1873}
1874
1877
1878 switch (cTx->spaceContinuity) {
1879 case CONTINUOUS:
1880 switch (cTx->bAse) {
1886 default:
1887 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not implemented");
1888 }
1889 break;
1890 case DISCONTINUOUS:
1891 switch (cTx->bAse) {
1897 default:
1898 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not implemented");
1899 }
1900 break;
1901
1902 default:
1903 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Unknown continuity");
1904 }
1905
1907}
1908
1912
1913 EntitiesFieldData &data = cTx->dAta;
1914 const FieldApproximationBase base = cTx->bAse;
1915 PetscErrorCode (*base_polynomials)(int p, double s, double *diff_s, double *L,
1916 double *diffL, const int dim) =
1918
1919 int nb_gauss_pts = pts.size2();
1920
1921 // edges
1922 if (data.spacesOnEntities[MBEDGE].test(HCURL)) {
1923 int sense[6], order[6];
1924 if (data.dataOnEntities[MBEDGE].size() != 6) {
1925 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
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 "data inconsistency");
1932 }
1933 sense[ee] = data.dataOnEntities[MBEDGE][ee].getSense();
1934 order[ee] = data.dataOnEntities[MBEDGE][ee].getOrder();
1935 int nb_dofs =
1936 NBEDGE_AINSWORTH_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, base_polynomials);
1951 } else {
1952 for (int ee = 0; ee != 6; ee++) {
1953 data.dataOnEntities[MBEDGE][ee].getN(base).resize(nb_gauss_pts, 0, false);
1954 data.dataOnEntities[MBEDGE][ee].getDiffN(base).resize(nb_gauss_pts, 0,
1955 false);
1956 }
1957 }
1958
1959 // triangles
1960 if (data.spacesOnEntities[MBTRI].test(HCURL)) {
1961 int order[4];
1962 // faces
1963 if (data.dataOnEntities[MBTRI].size() != 4) {
1964 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
1965 }
1966 double *hcurl_base_n[4], *diff_hcurl_base_n[4];
1967 for (int ff = 0; ff != 4; ff++) {
1968 if (data.dataOnEntities[MBTRI][ff].getSense() == 0) {
1969 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1970 "data inconsistency");
1971 }
1972 order[ff] = data.dataOnEntities[MBTRI][ff].getOrder();
1973 int nb_dofs = NBFACETRI_AINSWORTH_HCURL(order[ff]);
1974 data.dataOnEntities[MBTRI][ff].getN(base).resize(nb_gauss_pts,
1975 3 * nb_dofs, false);
1976 data.dataOnEntities[MBTRI][ff].getDiffN(base).resize(nb_gauss_pts,
1977 9 * nb_dofs, false);
1978 hcurl_base_n[ff] =
1979 &*data.dataOnEntities[MBTRI][ff].getN(base).data().begin();
1980 diff_hcurl_base_n[ff] =
1981 &*data.dataOnEntities[MBTRI][ff].getDiffN(base).data().begin();
1982 }
1983 if (data.facesNodes.size1() != 4) {
1984 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
1985 }
1986 if (data.facesNodes.size2() != 3) {
1987 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
1988 }
1990 &*data.facesNodes.data().begin(), order,
1991 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
1992 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
1993 hcurl_base_n, diff_hcurl_base_n, nb_gauss_pts, base_polynomials);
1994 } else {
1995 for (int ff = 0; ff != 4; ff++) {
1996 data.dataOnEntities[MBTRI][ff].getN(base).resize(nb_gauss_pts, 0, false);
1997 data.dataOnEntities[MBTRI][ff].getDiffN(base).resize(nb_gauss_pts, 0,
1998 false);
1999 }
2000 }
2001
2002 if (data.spacesOnEntities[MBTET].test(HCURL)) {
2003
2004 // volume
2005 int order = data.dataOnEntities[MBTET][0].getOrder();
2006 int nb_vol_dofs = NBVOLUMETET_AINSWORTH_HCURL(order);
2007 data.dataOnEntities[MBTET][0].getN(base).resize(nb_gauss_pts,
2008 3 * nb_vol_dofs, false);
2009 data.dataOnEntities[MBTET][0].getDiffN(base).resize(nb_gauss_pts,
2010 9 * nb_vol_dofs, false);
2012 data.dataOnEntities[MBTET][0].getOrder(),
2013 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
2014 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
2015 &*data.dataOnEntities[MBTET][0].getN(base).data().begin(),
2016 &*data.dataOnEntities[MBTET][0].getDiffN(base).data().begin(),
2017 nb_gauss_pts, base_polynomials);
2018
2019 } else {
2020 data.dataOnEntities[MBTET][0].getN(base).resize(nb_gauss_pts, 0, false);
2021 data.dataOnEntities[MBTET][0].getDiffN(base).resize(nb_gauss_pts, 0, false);
2022 }
2023
2025}
2026
2030
2031 EntitiesFieldData &data = cTx->dAta;
2032 const FieldApproximationBase base = cTx->bAse;
2033 if (base != DEMKOWICZ_JACOBI_BASE) {
2034 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2035 "This should be used only with DEMKOWICZ_JACOBI_BASE "
2036 "but base is %s",
2038 }
2039
2040 int nb_gauss_pts = pts.size2();
2041
2042 // edges
2043 if (data.spacesOnEntities[MBEDGE].test(HCURL)) {
2044 int sense[6], order[6];
2045 if (data.dataOnEntities[MBEDGE].size() != 6) {
2046 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2047 "wrong size of data structure, expected space for six edges "
2048 "but is %zu",
2049 data.dataOnEntities[MBEDGE].size());
2050 }
2051 double *hcurl_edge_n[6], *diff_hcurl_edge_n[6];
2052 for (int ee = 0; ee != 6; ee++) {
2053 if (data.dataOnEntities[MBEDGE][ee].getSense() == 0) {
2054 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2055 "orintation of edges is not set");
2056 }
2057 sense[ee] = data.dataOnEntities[MBEDGE][ee].getSense();
2058 order[ee] = data.dataOnEntities[MBEDGE][ee].getOrder();
2059 int nb_dofs =
2060 NBEDGE_DEMKOWICZ_HCURL(data.dataOnEntities[MBEDGE][ee].getOrder());
2061 data.dataOnEntities[MBEDGE][ee].getN(base).resize(nb_gauss_pts,
2062 3 * nb_dofs, false);
2063 data.dataOnEntities[MBEDGE][ee].getDiffN(base).resize(nb_gauss_pts,
2064 9 * nb_dofs, false);
2065 hcurl_edge_n[ee] =
2066 &*data.dataOnEntities[MBEDGE][ee].getN(base).data().begin();
2067 diff_hcurl_edge_n[ee] =
2068 &*data.dataOnEntities[MBEDGE][ee].getDiffN(base).data().begin();
2069 }
2071 sense, order,
2072 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
2073 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
2074 hcurl_edge_n, diff_hcurl_edge_n, nb_gauss_pts);
2075 } else {
2076 // No DOFs on edges, resize base function matrices, indicating that no
2077 // dofs on them.
2078 for (int ee = 0; ee != 6; ee++) {
2079 data.dataOnEntities[MBEDGE][ee].getN(base).resize(nb_gauss_pts, 0, false);
2080 data.dataOnEntities[MBEDGE][ee].getDiffN(base).resize(nb_gauss_pts, 0,
2081 false);
2082 }
2083 }
2084
2085 // triangles
2086 if (data.spacesOnEntities[MBTRI].test(HCURL)) {
2087 int order[4];
2088 // faces
2089 if (data.dataOnEntities[MBTRI].size() != 4) {
2090 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2091 "data structure for storing face h-curl base have wrong size "
2092 "should be four but is %zu",
2093 data.dataOnEntities[MBTRI].size());
2094 }
2095 double *hcurl_base_n[4], *diff_hcurl_base_n[4];
2096 for (int ff = 0; ff != 4; ff++) {
2097 if (data.dataOnEntities[MBTRI][ff].getSense() == 0) {
2098 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2099 "orintation of face is not set");
2100 }
2101 order[ff] = data.dataOnEntities[MBTRI][ff].getOrder();
2102 int nb_dofs = NBFACETRI_DEMKOWICZ_HCURL(order[ff]);
2103 data.dataOnEntities[MBTRI][ff].getN(base).resize(nb_gauss_pts,
2104 3 * nb_dofs, false);
2105 data.dataOnEntities[MBTRI][ff].getDiffN(base).resize(nb_gauss_pts,
2106 9 * nb_dofs, false);
2107 hcurl_base_n[ff] =
2108 &*data.dataOnEntities[MBTRI][ff].getN(base).data().begin();
2109 diff_hcurl_base_n[ff] =
2110 &*data.dataOnEntities[MBTRI][ff].getDiffN(base).data().begin();
2111 }
2112 if (data.facesNodes.size1() != 4) {
2113 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2114 "data inconsistency, should be four faces");
2115 }
2116 if (data.facesNodes.size2() != 3) {
2117 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2118 "data inconsistency, should be three nodes on face");
2119 }
2121 &*data.facesNodes.data().begin(), order,
2122 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
2123 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
2124 hcurl_base_n, diff_hcurl_base_n, nb_gauss_pts);
2125 } else {
2126 // No DOFs on faces, resize base function matrices, indicating that no
2127 // dofs on them.
2128 for (int ff = 0; ff != 4; ff++) {
2129 data.dataOnEntities[MBTRI][ff].getN(base).resize(nb_gauss_pts, 0, false);
2130 data.dataOnEntities[MBTRI][ff].getDiffN(base).resize(nb_gauss_pts, 0,
2131 false);
2132 }
2133 }
2134
2135 if (data.spacesOnEntities[MBTET].test(HCURL)) {
2136 // volume
2137 int order = data.dataOnEntities[MBTET][0].getOrder();
2138 int nb_vol_dofs = NBVOLUMETET_DEMKOWICZ_HCURL(order);
2139 data.dataOnEntities[MBTET][0].getN(base).resize(nb_gauss_pts,
2140 3 * nb_vol_dofs, false);
2141 data.dataOnEntities[MBTET][0].getDiffN(base).resize(nb_gauss_pts,
2142 9 * nb_vol_dofs, false);
2144 data.dataOnEntities[MBTET][0].getOrder(),
2145 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
2146 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
2147 &*data.dataOnEntities[MBTET][0].getN(base).data().begin(),
2148 &*data.dataOnEntities[MBTET][0].getDiffN(base).data().begin(),
2149 nb_gauss_pts);
2150 } else {
2151 // No DOFs on faces, resize base function matrices, indicating that no
2152 // dofs on them.
2153 data.dataOnEntities[MBTET][0].getN(base).resize(nb_gauss_pts, 0, false);
2154 data.dataOnEntities[MBTET][0].getDiffN(base).resize(nb_gauss_pts, 0, false);
2155 }
2156
2158}
2159
2162
2163 switch (cTx->bAse) {
2167 break;
2170 break;
2171 default:
2172 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not implemented");
2173 }
2174
2176}
2177
2180 boost::shared_ptr<BaseFunctionCtx> ctx_ptr) {
2182
2184
2185 int nb_gauss_pts = pts.size2();
2186 if (!nb_gauss_pts)
2188
2189 if (pts.size1() < 3)
2190 SETERRQ(
2191 PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2192 "Wrong dimension of pts, should be at least 3 rows with coordinates");
2193
2195 const FieldApproximationBase base = cTx->bAse;
2196 EntitiesFieldData &data = cTx->dAta;
2197 if (cTx->copyNodeBase == LASTBASE) {
2198 data.dataOnEntities[MBVERTEX][0].getN(base).resize(nb_gauss_pts, 4,
2199 false);
2201 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
2202 &pts(0, 0), &pts(1, 0), &pts(2, 0), nb_gauss_pts);
2203 } else {
2204 data.dataOnEntities[MBVERTEX][0].getN(base) =
2205 data.dataOnEntities[MBVERTEX][0].getN(cTx->copyNodeBase);
2206 }
2207 if (data.dataOnEntities[MBVERTEX][0].getN(base).size1() !=
2208 (unsigned int)nb_gauss_pts) {
2209 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2210 "Base functions or nodes has wrong number of integration points "
2211 "for base %s",
2213 }
2214 data.dataOnEntities[MBVERTEX][0].getDiffN(base).resize(4, 3, false);
2215 std::copy(Tools::diffShapeFunMBTET.begin(), Tools::diffShapeFunMBTET.end(),
2216 data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin());
2217 }
2218
2219 switch (cTx->spaceContinuity) {
2220 case CONTINUOUS:
2221
2222 switch (cTx->sPace) {
2223 case H1:
2224 CHKERR getValueH1(pts);
2225 break;
2226 case HDIV:
2227 CHKERR getValueHdiv(pts);
2228 break;
2229 case HCURL:
2230 CHKERR getValueHcurl(pts);
2231 break;
2232 case L2:
2233 CHKERR getValueL2(pts);
2234 break;
2235 default:
2236 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Unknown space %s",
2238 }
2239 break;
2240
2241 case DISCONTINUOUS:
2242
2243 switch (cTx->sPace) {
2244 case HDIV:
2245 CHKERR getValueHdiv(pts);
2246 break;
2247 default:
2248 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Unknown space %s",
2250 }
2251 break;
2252
2253 default:
2254 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Unknown continuity");
2255 }
2256
2258}
2259
2261
2262 const FieldSpace space, const FieldContinuity continuity,
2263 const FieldApproximationBase base, DofsSideMap &dofs_side_map
2264
2265) {
2267
2268 switch (continuity) {
2269 case DISCONTINUOUS:
2270
2271 switch (space) {
2272 case HDIV:
2273 CHKERR setDofsSideMapHdiv(continuity, base, dofs_side_map);
2274 break;
2275 default:
2276 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Unknown space %s",
2277 FieldSpaceNames[space]);
2278 }
2279 break;
2280
2281 default:
2282 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
2283 "Unknown (or not implemented) continuity");
2284 }
2285
2287}
2288
2291 const FieldApproximationBase base,
2292 DofsSideMap &dofs_side_map) {
2294
2295 // That has to be consistent with implementation of getValueHdiv for
2296 // particular base functions.
2297
2298 auto set_ainsworth = [&dofs_side_map]() {
2300
2301 dofs_side_map.clear();
2302
2303 const auto map_order = Field::maxBrokenDofsOrder;
2304 const auto face_edge_order =
2306 const auto face_face_order =
2308 const auto volume_edge_order =
2310 const auto volume_face_order =
2312 const auto volume_bubble_order =
2314
2315 auto max_order = std::max(map_order, face_edge_order);
2316 max_order = std::max(max_order, face_face_order);
2317 max_order = std::max(max_order, volume_edge_order);
2318 max_order = std::max(max_order, volume_face_order);
2319 max_order = std::max(max_order, volume_bubble_order);
2320
2321 int dof = 0;
2322 for (int oo = 0; oo < max_order; oo++) {
2323
2324 // faces-edge (((P) > 0) ? (P) : 0)
2325 if (oo < face_edge_order)
2326 for (int dd = NBFACETRI_AINSWORTH_EDGE_HDIV(oo);
2327 dd != NBFACETRI_AINSWORTH_EDGE_HDIV(oo + 1); dd++) {
2328 for (auto ff = 0; ff != 4; ++ff) {
2329 for (int ee = 0; ee != 3; ++ee) {
2330 dofs_side_map.insert(DofsSideMapData{MBTRI, ff, dof});
2331 ++dof;
2332 }
2333 }
2334 }
2335
2336 // face-face (P - 1) * (P - 2) / 2
2337 if (oo < face_face_order)
2338 for (int dd = NBFACETRI_AINSWORTH_FACE_HDIV(oo);
2339 dd != NBFACETRI_AINSWORTH_FACE_HDIV(oo + 1); dd++) {
2340 for (auto ff = 0; ff != 4; ++ff) {
2341 dofs_side_map.insert(DofsSideMapData{MBTRI, ff, dof});
2342 ++dof;
2343 }
2344 }
2345
2346 // volume-edge (P - 1)
2347 if (oo < volume_edge_order)
2348 for (int dd = NBVOLUMETET_AINSWORTH_EDGE_HDIV(oo);
2349 dd != NBVOLUMETET_AINSWORTH_EDGE_HDIV(oo + 1); dd++) {
2350 for (int ee = 0; ee < 6; ee++) {
2351 dofs_side_map.insert(DofsSideMapData{MBTET, 0, dof});
2352 ++dof;
2353 }
2354 }
2355
2356 // volume-face (P - 1) * (P - 2)
2357 if (oo < volume_face_order)
2358 for (int dd = NBVOLUMETET_AINSWORTH_FACE_HDIV(oo);
2359 dd < NBVOLUMETET_AINSWORTH_FACE_HDIV(oo + 1); dd++) {
2360 for (int ff = 0; ff < 4; ff++) {
2361 dofs_side_map.insert(DofsSideMapData{MBTET, 0, dof});
2362 ++dof;
2363 }
2364 }
2365
2366 // volume-bubble (P - 3) * (P - 2) * (P - 1) / 2
2367 if (oo < volume_bubble_order)
2368 for (int dd = NBVOLUMETET_AINSWORTH_VOLUME_HDIV(oo);
2369 dd < NBVOLUMETET_AINSWORTH_VOLUME_HDIV(oo + 1); dd++) {
2370 dofs_side_map.insert(DofsSideMapData{MBTET, 0, dof});
2371 ++dof;
2372 }
2373 }
2374
2376 };
2377
2378 auto set_demkowicz = [&dofs_side_map]() {
2380
2381 dofs_side_map.clear();
2382
2383 int dof = 0;
2384 for (int oo = 0; oo < Field::maxBrokenDofsOrder; oo++) {
2385
2386 // face
2387 for (auto dd = NBFACETRI_DEMKOWICZ_HDIV(oo);
2388 dd != NBFACETRI_DEMKOWICZ_HDIV(oo + 1); ++dd) {
2389 for (auto ff = 0; ff != 4; ++ff) {
2390 dofs_side_map.insert(DofsSideMapData{MBTRI, ff, dof});
2391 ++dof;
2392 }
2393 }
2394 // volume
2395 for (auto dd = NBVOLUMETET_DEMKOWICZ_HDIV(oo);
2396 dd != NBVOLUMETET_DEMKOWICZ_HDIV(oo + 1); ++dd) {
2397 dofs_side_map.insert(DofsSideMapData{MBTET, 0, dof});
2398 ++dof;
2399 }
2400 }
2401
2403 };
2404
2405 switch (continuity) {
2406 case DISCONTINUOUS:
2407 switch (base) {
2410 MoFEMFunctionReturnHot(set_ainsworth());
2412 MoFEMFunctionReturnHot(set_demkowicz());
2413 default:
2414 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not implemented");
2415 }
2416 break;
2417
2418 default:
2419 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
2420 "Unknown (or not implemented) continuity");
2421 }
2422
2424}
2425
2426template <typename T>
2427auto tetCacheSwitch(const void *ptr, T &cache, std::string cache_name) {
2428 auto it = cache.find(ptr);
2429 if (it != cache.end()) {
2430 MOFEM_LOG_CHANNEL("WORLD");
2431 MOFEM_TAG_AND_LOG("WORLD", Sev::noisy, "TetPolynomialBase")
2432 << "Cache off " << cache_name << ": " << it->second.size();
2433 cache.erase(it);
2434 return false;
2435 } else {
2436 MOFEM_LOG_CHANNEL("WORLD");
2437 MOFEM_TAG_AND_LOG("WORLD", Sev::noisy, "TetPolynomialBase")
2438 << "Cache on " << cache_name;
2439 cache[ptr];
2440 return true;
2441 }
2442}
2443
2444template <>
2445bool TetPolynomialBase::switchCacheBaseFace<HDIV>(FieldApproximationBase base,
2446 void *ptr) {
2448 std::string("hDivBaseFace") +
2450}
2451
2452template <>
2453bool TetPolynomialBase::switchCacheBaseInterior<HDIV>(
2454 FieldApproximationBase base, void *ptr) {
2456 std::string("hdivBaseInterior") +
2458}
2459
2460template <>
2461bool TetPolynomialBase::switchCacheBrokenBaseInterior<HDIV>(
2462 FieldApproximationBase base, void *ptr) {
2464 std::string("hdivBrokenBaseInterior") +
2466}
2467
2468template <>
2469void TetPolynomialBase::switchCacheBaseOn<HDIV>(FieldApproximationBase base,
2470 std::vector<void *> v) {
2471 for (auto fe_ptr : v) {
2472 if (!TetPolynomialBase::switchCacheBaseFace<HDIV>(base, fe_ptr)) {
2473 TetPolynomialBase::switchCacheBaseFace<HDIV>(base, fe_ptr);
2474 }
2475 if (!TetPolynomialBase::switchCacheBaseInterior<HDIV>(base, fe_ptr)) {
2476 TetPolynomialBase::switchCacheBaseInterior<HDIV>(base, fe_ptr);
2477 }
2478 if (!TetPolynomialBase::switchCacheBrokenBaseInterior<HDIV>(base, fe_ptr)) {
2479 TetPolynomialBase::switchCacheBrokenBaseInterior<HDIV>(base, fe_ptr);
2480 }
2481 }
2482}
2483
2484template <>
2485void TetPolynomialBase::switchCacheBaseOff<HDIV>(FieldApproximationBase base,
2486 std::vector<void *> v) {
2487 for (auto fe_ptr : v) {
2488 if (TetPolynomialBase::switchCacheBaseFace<HDIV>(base, fe_ptr)) {
2489 TetPolynomialBase::switchCacheBaseFace<HDIV>(base, fe_ptr);
2490 }
2491 if (TetPolynomialBase::switchCacheBaseInterior<HDIV>(base, fe_ptr)) {
2492 TetPolynomialBase::switchCacheBaseInterior<HDIV>(base, fe_ptr);
2493 }
2494 if (TetPolynomialBase::switchCacheBrokenBaseInterior<HDIV>(base, fe_ptr)) {
2495 TetPolynomialBase::switchCacheBrokenBaseInterior<HDIV>(base, fe_ptr);
2496 }
2497 }
2498}
2499
2500template <>
2501void TetPolynomialBase::switchCacheBaseOn<HDIV>(std::vector<void *> v) {
2502 for (auto b = 0; b != LASTBASE; ++b) {
2503 switchCacheBaseOn<HDIV>(static_cast<FieldApproximationBase>(b), v);
2504 }
2505}
2506
2507template <>
2508void TetPolynomialBase::switchCacheBaseOff<HDIV>(std::vector<void *> v) {
2509 for (auto b = 0; b != LASTBASE; ++b) {
2510 switchCacheBaseOff<HDIV>(static_cast<FieldApproximationBase>(b), v);
2511 }
2512}
2513
2514template <>
2515bool TetPolynomialBase::switchCacheBaseInterior<L2>(FieldApproximationBase base,
2516 void *ptr) {
2518 std::string("hdivBaseInterior") +
2520}
2521
2522template <>
2523void TetPolynomialBase::switchCacheBaseOn<L2>(FieldApproximationBase base,
2524 std::vector<void *> v) {
2525 for (auto fe_ptr : v) {
2526 if (!TetPolynomialBase::switchCacheBaseInterior<L2>(base, fe_ptr)) {
2527 TetPolynomialBase::switchCacheBaseInterior<L2>(base, fe_ptr);
2528 }
2529 }
2530}
2531
2532template <>
2533void TetPolynomialBase::switchCacheBaseOff<L2>(FieldApproximationBase base,
2534 std::vector<void *> v) {
2535 for (auto fe_ptr : v) {
2536 if (TetPolynomialBase::switchCacheBaseInterior<L2>(base, fe_ptr)) {
2537 TetPolynomialBase::switchCacheBaseInterior<L2>(base, fe_ptr);
2538 }
2539 }
2540}
2541
2542template <>
2543void TetPolynomialBase::switchCacheBaseOn<L2>(std::vector<void *> v) {
2544 for (auto b = 0; b != LASTBASE; ++b) {
2545 switchCacheBaseOn<L2>(static_cast<FieldApproximationBase>(b), v);
2546 }
2547}
2548
2549template <>
2550void TetPolynomialBase::switchCacheBaseOff<L2>(std::vector<void *> v) {
2551 for (auto b = 0; b != LASTBASE; ++b) {
2552 switchCacheBaseOff<L2>(static_cast<FieldApproximationBase>(b), v);
2553 }
2554}
std::string type
#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:683
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:97
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:829
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:450
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:224
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:357
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:556
constexpr auto field_name
constexpr double g
FTensor::Index< 'm', 3 > m
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
static constexpr size_t MaxBernsteinBezierOrder
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 query_interface(boost::typeindex::type_index type_index, UnknownInterface **iface) const
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:767
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