v0.16.3
Loading...
Searching...
No Matches
TriPolynomialBase.cpp
Go to the documentation of this file.
1/** \file TriPolynomialBase.cpp
2\brief Implementation of bases on triangle
3
4*/
5
6using namespace MoFEM;
7
9TriPolynomialBase::query_interface(boost::typeindex::type_index type_index,
10 UnknownInterface **iface) const {
12 *iface = const_cast<TriPolynomialBase *>(this);
14}
15
31
35 EntitiesFieldData &data = cTx->dAta;
36 const std::string &field_name = cTx->fieldName;
37 int nb_gauss_pts = pts.size2();
38
39 auto get_alpha = [field_name](auto &data) -> MatrixInt & {
40 auto &ptr = data.getBBAlphaIndicesSharedPtr(field_name);
41 if (!ptr)
42 ptr.reset(new MatrixInt());
43 return *ptr;
44 };
45
46 auto get_base = [field_name](auto &data) -> MatrixDouble & {
47 auto &ptr = data.getBBNSharedPtr(field_name);
48 if (!ptr)
49 ptr.reset(new MatrixDouble());
50 return *ptr;
51 };
52
53 auto get_diff_base = [field_name](auto &data) -> MatrixDouble & {
54 auto &ptr = data.getBBDiffNSharedPtr(field_name);
55 if (!ptr)
56 ptr.reset(new MatrixDouble());
57 return *ptr;
58 };
59
60 auto get_alpha_by_name_ptr =
61 [](auto &data,
62 const std::string &field_name) -> boost::shared_ptr<MatrixInt> & {
63 return data.getBBAlphaIndicesSharedPtr(field_name);
64 };
65
66 auto get_base_by_name_ptr =
67 [](auto &data,
68 const std::string &field_name) -> boost::shared_ptr<MatrixDouble> & {
69 return data.getBBNSharedPtr(field_name);
70 };
71
72 auto get_diff_base_by_name_ptr =
73 [](auto &data,
74 const std::string &field_name) -> boost::shared_ptr<MatrixDouble> & {
75 return data.getBBDiffNSharedPtr(field_name);
76 };
77
78 auto get_alpha_by_order_ptr =
79 [](auto &data, const size_t o) -> boost::shared_ptr<MatrixInt> & {
80 return data.getBBAlphaIndicesByOrderSharedPtr(o);
81 };
82
83 auto get_base_by_order_ptr =
84 [](auto &data, const size_t o) -> boost::shared_ptr<MatrixDouble> & {
85 return data.getBBNByOrderSharedPtr(o);
86 };
87
88 auto get_diff_base_by_order_ptr =
89 [](auto &data, const size_t o) -> boost::shared_ptr<MatrixDouble> & {
90 return data.getBBDiffNByOrderSharedPtr(o);
91 };
92
93 // A field which was given a by-order matrix shared with another field on a
94 // previous element must not write into it here: on this element that matrix
95 // may already hold the other field's base. Detach and allocate own storage.
96 auto make_own = [field_name](auto &ent_data) {
97 auto &n_ptr = ent_data.getBBNSharedPtr(field_name);
98 if (!n_ptr)
99 return;
100 for (auto &ptr : ent_data.getBBNByOrderArray()) {
101 if (ptr && ptr.get() == n_ptr.get()) {
102 ent_data.getBBAlphaIndicesSharedPtr(field_name).reset();
103 ent_data.getBBDiffNSharedPtr(field_name).reset();
104 n_ptr.reset();
105 return;
106 }
107 }
108 };
109
110 // Entity without base functions for this field: no alpha indices and base
111 // matrices with zero columns, consistent with the hierarchical bases.
112 auto set_empty = [&](auto &ent_data) {
113 make_own(ent_data);
114 ent_data.getBBAlphaIndicesSharedPtr(field_name).reset();
115 get_base(ent_data).resize(nb_gauss_pts, 0, false);
116 get_diff_base(ent_data).resize(nb_gauss_pts, 0, false);
117 };
118
119 // The BB base is not hierarchical, so mixing degrees between the entities
120 // of one element loses completeness. H1 requires one order on all entities
121 // which carry DOFs and vertex degrees between one and that order. L2 is
122 // element-local and has no such restriction. See the tetrahedron version
123 // for the full argument.
124 auto check_uniform_order = [&]() {
126 auto &node_order = data.dataOnEntities[MBVERTEX][0].getBBNodeOrder();
127 if (node_order.size() != 3)
128 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
129 "Wrong number of vertex orders for BB base: %d",
130 static_cast<int>(node_order.size()));
131 int order = 0;
132 for (int n = 0; n != 3; ++n)
133 order = std::max(order, node_order[n]);
134 auto max_order_on = [&](const EntityType type) {
135 if (data.spacesOnEntities[type].test(H1))
136 for (auto &ent_data : data.dataOnEntities[type])
137 order = std::max(order, ent_data.getOrder());
138 };
139 max_order_on(MBEDGE);
140 max_order_on(MBTRI);
141 if (order < 1)
142 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
143 "Bernstein-Bezier H1 base requires approximation order >= 1");
144 if (static_cast<size_t>(order) >=
146 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
147 "Bernstein-Bezier order %d exceeds the supported maximum %d",
148 order,
149 static_cast<int>(
151 1);
152 for (int n = 0; n != 3; ++n)
153 if (node_order[n] < 1)
154 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
155 "Bernstein-Bezier H1 base requires vertex order between 1 "
156 "and the element order %d; vertex %d has order %d",
157 order, n, node_order[n]);
158 auto check_type = [&](const EntityType type, const int nb_dofs_at_order) {
160 if (!nb_dofs_at_order || !data.spacesOnEntities[type].test(H1))
162 int side = 0;
163 for (auto &ent_data : data.dataOnEntities[type]) {
164 if (ent_data.getOrder() != order)
165 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
166 "Bernstein-Bezier base in H1 space requires uniform "
167 "approximation order on the element: %s %d has order %d, "
168 "element order is %d. BB functions are not hierarchical, "
169 "so mixed degrees do not span a complete polynomial space. "
170 "Set one order for the whole H1 field (L2 fields are not "
171 "restricted).",
172 moab::CN::EntityTypeName(type), side, ent_data.getOrder(),
173 order);
174 ++side;
175 }
177 };
178 CHKERR check_type(MBEDGE, NBEDGE_H1(order));
179 CHKERR check_type(MBTRI, NBFACETRI_H1(order));
181 };
182 CHKERR check_uniform_order();
183
184 auto &vert_get_n = get_base(data.dataOnEntities[MBVERTEX][0]);
185 auto &vert_get_diff_n = get_diff_base(data.dataOnEntities[MBVERTEX][0]);
186 vert_get_n.resize(nb_gauss_pts, 3, false);
187 vert_get_diff_n.resize(nb_gauss_pts, 6, false);
188
189 if (data.dataOnEntities[MBVERTEX][0].getN(NOBASE).size1() !=
190 (unsigned int)nb_gauss_pts)
191 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
192 "Base functions or nodes has wrong number of integration points "
193 "for base %s",
195 auto &lambda = data.dataOnEntities[MBVERTEX][0].getN(NOBASE);
196
197 auto &vertex_alpha = get_alpha(data.dataOnEntities[MBVERTEX][0]);
198 vertex_alpha.resize(3, 3, false);
199 vertex_alpha.clear();
200 for (int n = 0; n != 3; ++n)
201 vertex_alpha(n, n) = data.dataOnEntities[MBVERTEX][0].getBBNodeOrder()[n];
202
204 1, lambda.size1(), vertex_alpha.size1(), &vertex_alpha(0, 0),
205 &lambda(0, 0), Tools::diffShapeFunMBTRI.data(), &vert_get_n(0, 0),
206 &vert_get_diff_n(0, 0));
207 for (int n = 0; n != 3; ++n) {
208 const int f = boost::math::factorial<double>(
209 data.dataOnEntities[MBVERTEX][0].getBBNodeOrder()[n]);
210 for (int g = 0; g != nb_gauss_pts; ++g) {
211 vert_get_n(g, n) *= f;
212 for (int d = 0; d != 2; ++d)
213 vert_get_diff_n(g, 2 * n + d) *= f;
214 }
215 }
216
217 // edges
218 if (data.spacesOnEntities[MBEDGE].test(H1)) {
219 if (data.dataOnEntities[MBEDGE].size() != 3)
220 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
221 "Wrong size of ent data");
222
223 constexpr int edges_nodes[3][2] = {{0, 1}, {1, 2}, {2, 0}};
224 for (int ee = 0; ee != 3; ++ee) {
225 auto &ent_data = data.dataOnEntities[MBEDGE][ee];
226
227 if (ent_data.getSense() == 0)
228 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
229 "Sense of the edge unknown");
230
231 const int sense = ent_data.getSense();
232 const int order = ent_data.getOrder();
233 const int nb_dofs = NBEDGE_H1(ent_data.getOrder());
234
235 if (nb_dofs) {
236 if (get_alpha_by_order_ptr(ent_data, order)) {
237 get_alpha_by_name_ptr(ent_data, field_name) =
238 get_alpha_by_order_ptr(ent_data, order);
239 get_base_by_name_ptr(ent_data, field_name) =
240 get_base_by_order_ptr(ent_data, order);
241 get_diff_base_by_name_ptr(ent_data, field_name) =
242 get_diff_base_by_order_ptr(ent_data, order);
243 } else {
244 make_own(ent_data);
245 auto &get_n = get_base(ent_data);
246 auto &get_diff_n = get_diff_base(ent_data);
247 get_n.resize(nb_gauss_pts, nb_dofs, false);
248 get_diff_n.resize(nb_gauss_pts, 2 * nb_dofs, false);
249
250 auto &edge_alpha = get_alpha(ent_data);
251 edge_alpha.resize(nb_dofs, 3, false);
253 &edge_alpha(0, 0));
254 if (sense == -1) {
255 for (int i = 0; i != edge_alpha.size1(); ++i) {
256 int a = edge_alpha(i, edges_nodes[ee][0]);
257 edge_alpha(i, edges_nodes[ee][0]) =
258 edge_alpha(i, edges_nodes[ee][1]);
259 edge_alpha(i, edges_nodes[ee][1]) = a;
260 }
261 }
263 order, lambda.size1(), edge_alpha.size1(), &edge_alpha(0, 0),
264 &lambda(0, 0), Tools::diffShapeFunMBTRI.data(), &get_n(0, 0),
265 &get_diff_n(0, 0));
266
267 get_alpha_by_order_ptr(ent_data, order) =
268 get_alpha_by_name_ptr(ent_data, field_name);
269 get_base_by_order_ptr(ent_data, order) =
270 get_base_by_name_ptr(ent_data, field_name);
271 get_diff_base_by_order_ptr(ent_data, order) =
272 get_diff_base_by_name_ptr(ent_data, field_name);
273 }
274 } else {
275 set_empty(ent_data);
276 }
277 }
278 } else {
279 for (int ee = 0; ee != 3; ++ee)
280 set_empty(data.dataOnEntities[MBEDGE][ee]);
281 }
282
283 if (data.spacesOnEntities[MBTRI].test(H1)) {
284 if (data.dataOnEntities[MBTRI].size() != 1)
285 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
286 "Wrong size ent of ent data");
287
288 auto &ent_data = data.dataOnEntities[MBTRI][0];
289 const int order = ent_data.getOrder();
290 const int nb_dofs = NBFACETRI_H1(order);
291 if (get_alpha_by_order_ptr(ent_data, order)) {
292 get_alpha_by_name_ptr(ent_data, field_name) =
293 get_alpha_by_order_ptr(ent_data, order);
294 get_base_by_name_ptr(ent_data, field_name) =
295 get_base_by_order_ptr(ent_data, order);
296 get_diff_base_by_name_ptr(ent_data, field_name) =
297 get_diff_base_by_order_ptr(ent_data, order);
298 } else {
299
300 make_own(ent_data);
301 auto &get_n = get_base(ent_data);
302 auto &get_diff_n = get_diff_base(ent_data);
303 get_n.resize(nb_gauss_pts, nb_dofs, false);
304 get_diff_n.resize(nb_gauss_pts, 2 * nb_dofs, false);
305 if (nb_dofs) {
306 auto &tri_alpha = get_alpha(ent_data);
307 tri_alpha.resize(nb_dofs, 3, false);
308
311 order, lambda.size1(), tri_alpha.size1(), &tri_alpha(0, 0),
312 &lambda(0, 0), Tools::diffShapeFunMBTRI.data(), &get_n(0, 0),
313 &get_diff_n(0, 0));
314
315 get_alpha_by_order_ptr(ent_data, order) =
316 get_alpha_by_name_ptr(ent_data, field_name);
317 get_base_by_order_ptr(ent_data, order) =
318 get_base_by_name_ptr(ent_data, field_name);
319 get_diff_base_by_order_ptr(ent_data, order) =
320 get_diff_base_by_name_ptr(ent_data, field_name);
321 } else {
322 ent_data.getBBAlphaIndicesSharedPtr(field_name).reset();
323 }
324 }
325 } else {
326 set_empty(data.dataOnEntities[MBTRI][0]);
327 }
328
330}
331
334
335 EntitiesFieldData &data = cTx->dAta;
336 const FieldApproximationBase base = cTx->bAse;
337
338 if (cTx->basePolynomialsType0 == NULL)
339 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
340 "Polynomial type not set");
341
342 PetscErrorCode (*base_polynomials)(int p, double s, double *diff_s, double *L,
343 double *diffL, const int dim) =
345
346 int nb_gauss_pts = pts.size2();
347
348 if (data.spacesOnEntities[MBEDGE].test(H1)) {
349 // edges
350 if (data.dataOnEntities[MBEDGE].size() != 3)
351 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
352 "expected size of data.dataOnEntities[MBEDGE] is 3");
353
354 int sense[3], order[3];
355 double *H1edgeN[3], *diffH1edgeN[3];
356 for (int ee = 0; ee < 3; ee++) {
357
358 if (data.dataOnEntities[MBEDGE][ee].getSense() == 0)
359 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
360 "sense of the edge unknown");
361
362 sense[ee] = data.dataOnEntities[MBEDGE][ee].getSense();
363 order[ee] = data.dataOnEntities[MBEDGE][ee].getOrder();
364 int nb_dofs = NBEDGE_H1(data.dataOnEntities[MBEDGE][ee].getOrder());
365 data.dataOnEntities[MBEDGE][ee].getN(base).resize(nb_gauss_pts, nb_dofs,
366 false);
367 data.dataOnEntities[MBEDGE][ee].getDiffN(base).resize(nb_gauss_pts,
368 2 * nb_dofs, false);
369 H1edgeN[ee] = &*data.dataOnEntities[MBEDGE][ee].getN(base).data().begin();
370 diffH1edgeN[ee] =
371 &*data.dataOnEntities[MBEDGE][ee].getDiffN(base).data().begin();
372 }
374 sense, order,
375 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
376 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
377 H1edgeN, diffH1edgeN, nb_gauss_pts, base_polynomials);
378 }
379
380 if (data.spacesOnEntities[MBTRI].test(H1)) {
381 // face
382 if (data.dataOnEntities[MBTRI].size() != 1) {
383 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
384 "expected that size data.dataOnEntities[MBTRI] is one");
385 }
386
387 int nb_dofs = NBFACETRI_H1(data.dataOnEntities[MBTRI][0].getOrder());
388 data.dataOnEntities[MBTRI][0].getN(base).resize(nb_gauss_pts, nb_dofs,
389 false);
390 data.dataOnEntities[MBTRI][0].getDiffN(base).resize(nb_gauss_pts,
391 2 * nb_dofs, false);
392 const int face_nodes[] = {0, 1, 2};
394 face_nodes, data.dataOnEntities[MBTRI][0].getOrder(),
395 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
396 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
397 &*data.dataOnEntities[MBTRI][0].getN(base).data().begin(),
398 &*data.dataOnEntities[MBTRI][0].getDiffN(base).data().begin(),
399 nb_gauss_pts, base_polynomials);
400 }
401
403}
404
407
408 switch (cTx->bAse) {
413 break;
416 break;
417 default:
418 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not implemented");
419 }
420
422}
423
426
427 EntitiesFieldData &data = cTx->dAta;
428 const FieldApproximationBase base = cTx->bAse;
429 if (cTx->basePolynomialsType0 == NULL)
430 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
431 "Polynomial type not set");
432 PetscErrorCode (*base_polynomials)(int p, double s, double *diff_s, double *L,
433 double *diffL, const int dim) =
435
436 int nb_gauss_pts = pts.size2();
437
438 data.dataOnEntities[MBTRI][0].getN(base).resize(
439 nb_gauss_pts, NBFACETRI_L2(data.dataOnEntities[MBTRI][0].getOrder()),
440 false);
441 data.dataOnEntities[MBTRI][0].getDiffN(base).resize(
442 nb_gauss_pts, 2 * NBFACETRI_L2(data.dataOnEntities[MBTRI][0].getOrder()),
443 false);
444
446 data.dataOnEntities[MBTRI][0].getOrder(),
447 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
448 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
449 &*data.dataOnEntities[MBTRI][0].getN(base).data().begin(),
450 &*data.dataOnEntities[MBTRI][0].getDiffN(base).data().begin(),
451 nb_gauss_pts, base_polynomials);
452
454}
455
459
460 EntitiesFieldData &data = cTx->dAta;
461 const std::string &field_name = cTx->fieldName;
462 int nb_gauss_pts = pts.size2();
463
464 auto get_alpha = [field_name](auto &data) -> MatrixInt & {
465 auto &ptr = data.getBBAlphaIndicesSharedPtr(field_name);
466 if (!ptr)
467 ptr.reset(new MatrixInt());
468 return *ptr;
469 };
470
471 auto get_base = [field_name](auto &data) -> MatrixDouble & {
472 auto &ptr = data.getBBNSharedPtr(field_name);
473 if (!ptr)
474 ptr.reset(new MatrixDouble());
475 return *ptr;
476 };
477
478 auto get_diff_base = [field_name](auto &data) -> MatrixDouble & {
479 auto &ptr = data.getBBDiffNSharedPtr(field_name);
480 if (!ptr)
481 ptr.reset(new MatrixDouble());
482 return *ptr;
483 };
484
485 auto get_alpha_by_name_ptr =
486 [](auto &data,
487 const std::string &field_name) -> boost::shared_ptr<MatrixInt> & {
488 return data.getBBAlphaIndicesSharedPtr(field_name);
489 };
490
491 auto get_base_by_name_ptr =
492 [](auto &data,
493 const std::string &field_name) -> boost::shared_ptr<MatrixDouble> & {
494 return data.getBBNSharedPtr(field_name);
495 };
496
497 auto get_diff_base_by_name_ptr =
498 [](auto &data,
499 const std::string &field_name) -> boost::shared_ptr<MatrixDouble> & {
500 return data.getBBDiffNSharedPtr(field_name);
501 };
502
503 auto get_alpha_by_order_ptr =
504 [](auto &data, const size_t o) -> boost::shared_ptr<MatrixInt> & {
505 return data.getBBAlphaIndicesByOrderSharedPtr(o);
506 };
507
508 auto get_base_by_order_ptr =
509 [](auto &data, const size_t o) -> boost::shared_ptr<MatrixDouble> & {
510 return data.getBBNByOrderSharedPtr(o);
511 };
512
513 auto get_diff_base_by_order_ptr =
514 [](auto &data, const size_t o) -> boost::shared_ptr<MatrixDouble> & {
515 return data.getBBDiffNByOrderSharedPtr(o);
516 };
517
518 // See make_own in getValueH1BernsteinBezierBase: detach from a by-order
519 // matrix shared with another field before writing into it.
520 auto make_own = [field_name](auto &ent_data) {
521 auto &n_ptr = ent_data.getBBNSharedPtr(field_name);
522 if (!n_ptr)
523 return;
524 for (auto &ptr : ent_data.getBBNByOrderArray()) {
525 if (ptr && ptr.get() == n_ptr.get()) {
526 ent_data.getBBAlphaIndicesSharedPtr(field_name).reset();
527 ent_data.getBBDiffNSharedPtr(field_name).reset();
528 n_ptr.reset();
529 return;
530 }
531 }
532 };
533
534 if (data.spacesOnEntities[MBTRI].test(L2)) {
535 if (data.dataOnEntities[MBTRI].size() != 1)
536 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
537 "Wrong size ent of ent data");
538
539 if (data.dataOnEntities[MBVERTEX][0].getN(NOBASE).size1() !=
540 (unsigned int)nb_gauss_pts)
541 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
542 "Base functions or nodes has wrong number of integration points "
543 "for base %s",
545 auto &lambda = data.dataOnEntities[MBVERTEX][0].getN(NOBASE);
546
547 auto &ent_data = data.dataOnEntities[MBTRI][0];
548 const int order = ent_data.getOrder();
549 const int nb_dofs = NBFACETRI_L2(order);
550 // L2 is element-local, so the order may differ between elements; only the
551 // storage limit applies.
552 if (order < 0 || static_cast<size_t>(order) >=
554 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
555 "Bernstein-Bezier order %d is outside the supported range "
556 "[0, %d]",
557 order,
558 static_cast<int>(
560 1);
561
562 if (get_alpha_by_order_ptr(ent_data, order)) {
563 get_alpha_by_name_ptr(ent_data, field_name) =
564 get_alpha_by_order_ptr(ent_data, order);
565 get_base_by_name_ptr(ent_data, field_name) =
566 get_base_by_order_ptr(ent_data, order);
567 get_diff_base_by_name_ptr(ent_data, field_name) =
568 get_diff_base_by_order_ptr(ent_data, order);
569 } else {
570
571 make_own(ent_data);
572 auto &get_n = get_base(ent_data);
573 auto &get_diff_n = get_diff_base(ent_data);
574 get_n.resize(nb_gauss_pts, nb_dofs, false);
575 get_diff_n.resize(nb_gauss_pts, 2 * nb_dofs, false);
576 if (nb_dofs) {
577
578 if (order == 0) {
579
580 if (nb_dofs != 1)
581 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
582 "Inconsistent number of DOFs");
583
584 // The single degree-zero function is one at every integration
585 // point, with the zero multi-index.
586 auto &tri_alpha = get_alpha(ent_data);
587 tri_alpha.resize(1, 3, false);
588 tri_alpha.clear();
589 std::fill(get_n.data().begin(), get_n.data().end(), 1.);
590 get_diff_n.clear();
591
592 } else {
593
594 if (nb_dofs != 3 + 3 * NBEDGE_H1(order) + NBFACETRI_H1(order))
595 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
596 "Inconsistent number of DOFs");
597
598 auto &tri_alpha = get_alpha(ent_data);
599 tri_alpha.resize(nb_dofs, 3, false);
600
602 &tri_alpha(0, 0));
603
604 if (order > 1) {
605 std::array<int, 3> face_n{order, order, order};
606 std::array<int *, 3> face_edge_ptr{
607 &tri_alpha(3, 0), &tri_alpha(3 + NBEDGE_H1(order), 0),
608 &tri_alpha(3 + 2 * NBEDGE_H1(order), 0)};
610 face_n.data(), face_edge_ptr.data());
611 if (order > 2)
613 order, &tri_alpha(3 + 3 * NBEDGE_H1(order), 0));
614 }
616 order, lambda.size1(), tri_alpha.size1(), &tri_alpha(0, 0),
617 &lambda(0, 0), Tools::diffShapeFunMBTRI.data(), &get_n(0, 0),
618 &get_diff_n(0, 0));
619 }
620
621 get_alpha_by_order_ptr(ent_data, order) =
622 get_alpha_by_name_ptr(ent_data, field_name);
623 get_base_by_order_ptr(ent_data, order) =
624 get_base_by_name_ptr(ent_data, field_name);
625 get_diff_base_by_order_ptr(ent_data, order) =
626 get_diff_base_by_name_ptr(ent_data, field_name);
627 }
628 }
629 } else {
630 auto &ent_data = data.dataOnEntities[MBTRI][0];
631 make_own(ent_data);
632 ent_data.getBBAlphaIndicesSharedPtr(field_name).reset();
633 get_base(ent_data).resize(nb_gauss_pts, 0, false);
634 get_diff_base(ent_data).resize(nb_gauss_pts, 0, false);
635 }
636
638}
639
642
643 EntitiesFieldData &data = cTx->dAta;
644 const FieldApproximationBase base = cTx->bAse;
645 if (cTx->basePolynomialsType0 == NULL)
646 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
647 "Polynomial type not set");
648 PetscErrorCode (*base_polynomials)(int p, double s, double *diff_s, double *L,
649 double *diffL, const int dim) =
651
652 int nb_gauss_pts = pts.size2();
653
654 double *phi_f_e[3];
655 double *phi_f;
656
657 N_face_edge.resize(1, 3, false);
658 N_face_bubble.resize(1, false);
659 int face_order = data.dataOnEntities[MBTRI][0].getOrder();
660 auto nb_dofs_on_face =
665 if (nb_dofs_on_face) {
666 auto face_edge_dofs = NBFACETRI_AINSWORTH_EDGE_HDIV(
668 // three edges on face
669 for (int ee = 0; ee < 3; ee++) {
670 N_face_edge(0, ee).resize(nb_gauss_pts, 3 * face_edge_dofs, false);
671 phi_f_e[ee] = &((N_face_edge(0, ee))(0, 0));
672 }
673 auto face_bubble_dofs = NBFACETRI_AINSWORTH_FACE_HDIV(
675 N_face_bubble[0].resize(nb_gauss_pts, 3 * face_bubble_dofs, false);
676 phi_f = &*(N_face_bubble[0].data().begin());
677
678 int face_nodes[3] = {0, 1, 2};
679 if (face_edge_dofs)
681 face_nodes,
683 &data.dataOnEntities[MBVERTEX][0].getN(base)(0, 0), NULL, phi_f_e,
684 NULL, nb_gauss_pts, 3, base_polynomials);
685 if (face_bubble_dofs)
687 face_nodes,
689 &data.dataOnEntities[MBVERTEX][0].getN(base)(0, 0), NULL, phi_f, NULL,
690 nb_gauss_pts, 3, base_polynomials);
691
692 // set shape functions into data structure
693 if (data.dataOnEntities[MBTRI].size() != 1) {
694 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
695 }
696 data.dataOnEntities[MBTRI][0].getN(base).resize(
697 nb_gauss_pts, 3 * NBFACETRI_AINSWORTH_HDIV(face_order), false);
698
699 auto max_face_order =
700 std::max(face_order,
702
703 int col = 0;
704 for (int oo = 0; oo < max_face_order; oo++) {
706 for (int ee = 0; ee < 3; ee++) {
707 for (int dd = 3 * NBFACETRI_AINSWORTH_EDGE_HDIV(oo);
708 dd < 3 * NBFACETRI_AINSWORTH_EDGE_HDIV(oo + 1); dd++, col++) {
709 for (int gg = 0; gg < nb_gauss_pts; gg++) {
710 data.dataOnEntities[MBTRI][0].getN(base)(gg, col) =
711 N_face_edge(0, ee)(gg, dd);
712 }
713 }
714 }
715
717 for (int dd = 3 * NBFACETRI_AINSWORTH_FACE_HDIV(oo);
718 dd < 3 * NBFACETRI_AINSWORTH_FACE_HDIV(oo + 1); dd++, col++) {
719 for (int gg = 0; gg < nb_gauss_pts; gg++) {
720 data.dataOnEntities[MBTRI][0].getN(base)(gg, col) =
721 N_face_bubble[0](gg, dd);
722 }
723 }
724 }
725 }
726
728}
729
732
733 EntitiesFieldData &data = cTx->dAta;
734 // set shape functions into data structure
735 if (data.dataOnEntities[MBTRI].size() != 1) {
736 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
737 }
738 const FieldApproximationBase base = cTx->bAse;
739 if (base != DEMKOWICZ_JACOBI_BASE) {
740 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
741 "This should be used only with DEMKOWICZ_JACOBI_BASE "
742 "but base is %s",
744 }
745 int order = data.dataOnEntities[MBTRI][0].getOrder();
746 int nb_gauss_pts = pts.size2();
747 data.dataOnEntities[MBTRI][0].getN(base).resize(
748 nb_gauss_pts, 3 * NBFACETRI_DEMKOWICZ_HDIV(order), false);
749 double *phi_f = &*data.dataOnEntities[MBTRI][0].getN(base).data().begin();
752 int face_nodes[3] = {0, 1, 2};
754 face_nodes, order,
755 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
756 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(), phi_f,
757 NULL, nb_gauss_pts, 3);
758
760}
761
777
781
782 EntitiesFieldData &data = cTx->dAta;
783 const FieldApproximationBase base = cTx->bAse;
784 if (data.dataOnEntities[MBTRI].size() != 1)
785 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
786
787 PetscErrorCode (*base_polynomials)(int p, double s, double *diff_s, double *L,
788 double *diffL, const int dim) =
790
791 int nb_gauss_pts = pts.size2();
792
793 // Calculation H-curl on triangle faces
794 if (data.spacesOnEntities[MBEDGE].test(HCURL)) {
795 if (data.dataOnEntities[MBEDGE].size() != 3) {
796 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
797 }
798 int sense[3], order[3];
799 double *hcurl_edge_n[3];
800 double *diff_hcurl_edge_n[3];
801 for (int ee = 0; ee < 3; ee++) {
802 if (data.dataOnEntities[MBEDGE][ee].getSense() == 0) {
803 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
804 "data inconsistency");
805 }
806 sense[ee] = data.dataOnEntities[MBEDGE][ee].getSense();
807 order[ee] = data.dataOnEntities[MBEDGE][ee].getOrder();
808 int nb_dofs =
809 NBEDGE_AINSWORTH_HCURL(data.dataOnEntities[MBEDGE][ee].getOrder());
810 data.dataOnEntities[MBEDGE][ee].getN(base).resize(nb_gauss_pts,
811 3 * nb_dofs, false);
812 data.dataOnEntities[MBEDGE][ee].getDiffN(base).resize(
813 nb_gauss_pts, 2 * 3 * nb_dofs, false);
814 hcurl_edge_n[ee] =
815 &*data.dataOnEntities[MBEDGE][ee].getN(base).data().begin();
816 diff_hcurl_edge_n[ee] =
817 &*data.dataOnEntities[MBEDGE][ee].getDiffN(base).data().begin();
818 }
820 sense, order,
821 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
822 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
823 hcurl_edge_n, diff_hcurl_edge_n, nb_gauss_pts, base_polynomials);
824 } else {
825 for (int ee = 0; ee < 3; ee++) {
826 data.dataOnEntities[MBEDGE][ee].getN(base).resize(nb_gauss_pts, 0, false);
827 data.dataOnEntities[MBEDGE][ee].getDiffN(base).resize(nb_gauss_pts, 0,
828 false);
829 }
830 }
831
832 if (data.spacesOnEntities[MBTRI].test(HCURL)) {
833
834 // cerr << data.dataOnEntities[MBVERTEX][0].getN(base) << endl;
835 // cerr << data.dataOnEntities[MBVERTEX][0].getDiffN(base) << endl;
836 //
837 // face
838 if (data.dataOnEntities[MBTRI].size() != 1) {
839 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
840 }
841 int order = data.dataOnEntities[MBTRI][0].getOrder();
842 int nb_dofs = NBFACETRI_AINSWORTH_HCURL(order);
843 data.dataOnEntities[MBTRI][0].getN(base).resize(nb_gauss_pts, 3 * nb_dofs,
844 false);
845 data.dataOnEntities[MBTRI][0].getDiffN(base).resize(nb_gauss_pts,
846 3 * 2 * nb_dofs, false);
847 // cerr << data.dataOnEntities[MBVERTEX][0].getDiffN(base) << endl;
848 int face_nodes[] = {0, 1, 2};
850 face_nodes, order,
851 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
852 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
853 &*data.dataOnEntities[MBTRI][0].getN(base).data().begin(),
854 &*data.dataOnEntities[MBTRI][0].getDiffN(base).data().begin(),
855 nb_gauss_pts, base_polynomials);
856 // cerr << data.dataOnEntities[MBTRI][0].getN(base) << endl;
857 } else {
858 data.dataOnEntities[MBTRI][0].getN(base).resize(nb_gauss_pts, 0, false);
859 data.dataOnEntities[MBTRI][0].getDiffN(base).resize(nb_gauss_pts, 0, false);
860 }
861
863}
864
868
869 EntitiesFieldData &data = cTx->dAta;
870 const FieldApproximationBase base = cTx->bAse;
871 if (data.dataOnEntities[MBTRI].size() != 1)
872 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
873
874 PetscErrorCode (*base_polynomials)(int p, double s, double *diff_s, double *L,
875 double *diffL, const int dim) =
877
878 int nb_gauss_pts = pts.size2();
879
880 if (data.spacesOnEntities[MBTRI].test(HCURL)) {
881
882 // face
883 if (data.dataOnEntities[MBTRI].size() != 1) {
884 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
885 }
886
887 int order = data.dataOnEntities[MBTRI][0].getOrder();
888 auto nb_edge_dofs = NBEDGE_AINSWORTH_HCURL(order);
889 int nb_dofs_face = NBFACETRI_AINSWORTH_HCURL(order);
890
891 // three faces on triangle
892 int nb_dofs = 3 * nb_edge_dofs + nb_dofs_face;
893 data.dataOnEntities[MBTRI][0].getN(base).resize(nb_gauss_pts, 3 * nb_dofs,
894 false);
895 data.dataOnEntities[MBTRI][0].getDiffN(base).resize(nb_gauss_pts,
896 3 * 2 * nb_dofs, false);
897
898 MatrixDouble edge_bases[] = {
899 MatrixDouble(nb_gauss_pts, 3 * nb_edge_dofs, false),
900 MatrixDouble(nb_gauss_pts, 3 * nb_edge_dofs, false),
901 MatrixDouble(nb_gauss_pts, 3 * nb_edge_dofs, false)};
902 MatrixDouble diff_edge_bases[] = {
903 MatrixDouble(nb_gauss_pts, 3 * 2 * nb_edge_dofs, false),
904 MatrixDouble(nb_gauss_pts, 3 * 2 * nb_edge_dofs, false),
905 MatrixDouble(nb_gauss_pts, 3 * 2 * nb_edge_dofs, false)};
906
907 std::array<double *, 3> phi{&*edge_bases[0].data().begin(),
908 &*edge_bases[1].data().begin(),
909 &*edge_bases[2].data().begin()};
910 std::array<double *, 3> diff_phi{&*diff_edge_bases[0].data().begin(),
911 &*diff_edge_bases[1].data().begin(),
912 &*diff_edge_bases[2].data().begin()};
913
914 std::array<int, 3> edge_order{order, order, order};
915 std::array<int, 3> edge_sense{1, 1, 1};
917 edge_sense.data(), edge_order.data(),
918 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
919 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
920 phi.data(), diff_phi.data(), nb_gauss_pts, base_polynomials);
921
922 MatrixDouble face_bases(nb_gauss_pts, 3 * nb_dofs_face, false);
923 MatrixDouble diff_face_bases(nb_gauss_pts, 3 * 2 * nb_dofs_face, false);
924 int face_nodes[] = {0, 1, 2};
926 face_nodes, order,
927 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
928 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
929 &*face_bases.data().begin(), &*diff_face_bases.data().begin(),
930 nb_gauss_pts, base_polynomials);
931
932 // edges
933 using Tensor1Ptr3 =
934 decltype(getFTensor1FromPtr<3>(static_cast<double *>(nullptr)));
935 Tensor1Ptr3 t_edge_base[] = {
936 getFTensor1FromPtr<3>(&*edge_bases[0].data().begin()),
937 getFTensor1FromPtr<3>(&*edge_bases[1].data().begin()),
938 getFTensor1FromPtr<3>(&*edge_bases[2].data().begin())};
939 FTensor::Tensor2<FTensor::PackPtr<double *, 6>, 3, 2> t_edge_diff_base[] = {
940 getFTensor2HVecFromPtr<3, 2>(&*diff_edge_bases[0].data().begin()),
941 getFTensor2HVecFromPtr<3, 2>(&*diff_edge_bases[1].data().begin()),
942 getFTensor2HVecFromPtr<3, 2>(&*diff_edge_bases[2].data().begin())};
943
944 // face
945 auto t_vol_base = getFTensor1FromPtr<3>(&*face_bases.data().begin());
946 auto t_vol_diff_base =
947 getFTensor2HVecFromPtr<3, 2>(&*diff_face_bases.data().begin());
948
949 auto t_base = getFTensor1FromPtr<3>(
950 &*data.dataOnEntities[MBTRI][0].getN(base).data().begin());
951 auto t_diff_base = getFTensor2HVecFromPtr<3, 2>(
952 &*data.dataOnEntities[MBTRI][0].getDiffN(base).data().begin());
953
954 FTENSOR_INDEX(3, i);
955 FTENSOR_INDEX(2, j);
956
957 for (int gg = 0; gg != nb_gauss_pts; gg++) {
958 for (int oo = 0; oo < order; oo++) {
959 // edges
960 for (int dd = NBEDGE_AINSWORTH_HCURL(oo);
961 dd != NBEDGE_AINSWORTH_HCURL(oo + 1); ++dd) {
962 for (int ee = 0; ee != 3; ++ee) {
963 t_base(i) = t_edge_base[ee](i);
964 ++t_base;
965 ++t_edge_base[ee];
966 t_diff_base(i, j) = t_edge_diff_base[ee](i, j);
967 ++t_diff_base;
968 ++t_edge_diff_base[ee];
969 }
970 }
971 // face
972 for (int dd = NBFACETRI_AINSWORTH_HCURL(oo);
973 dd != NBFACETRI_AINSWORTH_HCURL(oo + 1); ++dd) {
974 t_base(i) = t_vol_base(i);
975 ++t_base;
976 ++t_vol_base;
977 t_diff_base(i, j) = t_vol_diff_base(i, j);
978 ++t_diff_base;
979 ++t_vol_diff_base;
980 }
981 }
982 }
983
984 } else {
985 data.dataOnEntities[MBTRI][0].getN(base).resize(nb_gauss_pts, 0, false);
986 data.dataOnEntities[MBTRI][0].getDiffN(base).resize(nb_gauss_pts, 0, false);
987 }
988
990}
991
995
996 EntitiesFieldData &data = cTx->dAta;
997 const FieldApproximationBase base = cTx->bAse;
998
999 int nb_gauss_pts = pts.size2();
1000
1001 // Calculation H-curl on triangle faces
1002 if (data.spacesOnEntities[MBEDGE].test(HCURL)) {
1003
1004 if (data.dataOnEntities[MBEDGE].size() != 3)
1005 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1006 "wrong number of data structures on edges, should be three but "
1007 "is %zu",
1008 data.dataOnEntities[MBEDGE].size());
1009
1010 int sense[3], order[3];
1011 double *hcurl_edge_n[3];
1012 double *diff_hcurl_edge_n[3];
1013
1014 for (int ee = 0; ee != 3; ++ee) {
1015
1016 if (data.dataOnEntities[MBEDGE][ee].getSense() == 0)
1017 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1018 "orientation (sense) of edge is not set");
1019
1020 sense[ee] = data.dataOnEntities[MBEDGE][ee].getSense();
1021 order[ee] = data.dataOnEntities[MBEDGE][ee].getOrder();
1022 int nb_dofs =
1023 NBEDGE_DEMKOWICZ_HCURL(data.dataOnEntities[MBEDGE][ee].getOrder());
1024 data.dataOnEntities[MBEDGE][ee].getN(base).resize(nb_gauss_pts,
1025 3 * nb_dofs, false);
1026 data.dataOnEntities[MBEDGE][ee].getDiffN(base).resize(
1027 nb_gauss_pts, 2 * 3 * nb_dofs, false);
1028
1029 hcurl_edge_n[ee] =
1030 &*data.dataOnEntities[MBEDGE][ee].getN(base).data().begin();
1031 diff_hcurl_edge_n[ee] =
1032 &*data.dataOnEntities[MBEDGE][ee].getDiffN(base).data().begin();
1033 }
1034
1036 sense, order,
1037 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
1038 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
1039 hcurl_edge_n, diff_hcurl_edge_n, nb_gauss_pts);
1040
1041 } else {
1042
1043 // No DOFs on faces, resize base function matrices, indicating that no
1044 // dofs on them.
1045 for (int ee = 0; ee != 3; ++ee) {
1046 data.dataOnEntities[MBEDGE][ee].getN(base).resize(nb_gauss_pts, 0, false);
1047 data.dataOnEntities[MBEDGE][ee].getDiffN(base).resize(nb_gauss_pts, 0,
1048 false);
1049 }
1050 }
1051
1052 if (data.spacesOnEntities[MBTRI].test(HCURL)) {
1053
1054 // face
1055 if (data.dataOnEntities[MBTRI].size() != 1)
1056 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1057 "No data struture to keep base functions on face");
1058
1059 int order = data.dataOnEntities[MBTRI][0].getOrder();
1060 int nb_dofs = NBFACETRI_DEMKOWICZ_HCURL(order);
1061 data.dataOnEntities[MBTRI][0].getN(base).resize(nb_gauss_pts, 3 * nb_dofs,
1062 false);
1063 data.dataOnEntities[MBTRI][0].getDiffN(base).resize(nb_gauss_pts,
1064 3 * 2 * nb_dofs, false);
1065
1066 int face_nodes[] = {0, 1, 2};
1068 face_nodes, order,
1069 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
1070 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
1071 &*data.dataOnEntities[MBTRI][0].getN(base).data().begin(),
1072 &*data.dataOnEntities[MBTRI][0].getDiffN(base).data().begin(),
1073 nb_gauss_pts);
1074
1075 } else {
1076
1077 // No DOFs on faces, resize base function matrices, indicating that no
1078 // dofs on them.
1079 data.dataOnEntities[MBTRI][0].getN(base).resize(nb_gauss_pts, 0, false);
1080 data.dataOnEntities[MBTRI][0].getDiffN(base).resize(nb_gauss_pts, 0, false);
1081 }
1082
1084}
1085
1089
1090 EntitiesFieldData &data = cTx->dAta;
1091 const FieldApproximationBase base = cTx->bAse;
1092
1093 int nb_gauss_pts = pts.size2();
1094
1095 if (data.spacesOnEntities[MBTRI].test(HCURL)) {
1096
1097 // face
1098 if (data.dataOnEntities[MBTRI].size() != 1)
1099 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1100 "No data struture to keep base functions on face");
1101
1102 int order = data.dataOnEntities[MBTRI][0].getOrder();
1103 int nb_edge_dofs = NBEDGE_DEMKOWICZ_HCURL(order);
1104 int nb_volume_dofs = NBFACETRI_DEMKOWICZ_HCURL(order);
1105 int nb_dofs = 3 * nb_edge_dofs + nb_volume_dofs;
1106 data.dataOnEntities[MBTRI][0].getN(base).resize(nb_gauss_pts, 3 * nb_dofs,
1107 false);
1108 data.dataOnEntities[MBTRI][0].getDiffN(base).resize(nb_gauss_pts,
1109 3 * 2 * nb_dofs, false);
1110
1111 MatrixDouble edge_bases[] = {
1112 MatrixDouble(nb_gauss_pts, 3 * nb_edge_dofs, false),
1113 MatrixDouble(nb_gauss_pts, 3 * nb_edge_dofs, false),
1114 MatrixDouble(nb_gauss_pts, 3 * nb_edge_dofs, false)};
1115 MatrixDouble diff_edge_bases[] = {
1116 MatrixDouble(nb_gauss_pts, 3 * 2 * nb_edge_dofs, false),
1117 MatrixDouble(nb_gauss_pts, 3 * 2 * nb_edge_dofs, false),
1118 MatrixDouble(nb_gauss_pts, 3 * 2 * nb_edge_dofs, false)};
1119
1120 std::array<int, 3> edge_order{order, order, order};
1121 std::array<int, 3> edge_sense{1, 1, 1};
1122 std::array<double *, 3> phi{&*edge_bases[0].data().begin(),
1123 &*edge_bases[1].data().begin(),
1124 &*edge_bases[2].data().begin()};
1125 std::array<double *, 3> diff_phi{&*diff_edge_bases[0].data().begin(),
1126 &*diff_edge_bases[1].data().begin(),
1127 &*diff_edge_bases[2].data().begin()};
1129 edge_sense.data(), edge_order.data(),
1130 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
1131 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
1132 phi.data(), diff_phi.data(), nb_gauss_pts);
1133
1134 MatrixDouble face_bases(nb_gauss_pts, 3 * nb_volume_dofs, false);
1135 MatrixDouble diff_face_bases(nb_gauss_pts, 3 * 2 * nb_volume_dofs, false);
1136 int face_nodes[] = {0, 1, 2};
1138 face_nodes, order,
1139 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
1140 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin(),
1141 &*face_bases.data().begin(), &*diff_face_bases.data().begin(),
1142 nb_gauss_pts);
1143
1144 // edges
1145 using Tensor1Ptr3 =
1146 decltype(getFTensor1FromPtr<3>(static_cast<double *>(nullptr)));
1147 Tensor1Ptr3 t_edge_base[] = {
1148 getFTensor1FromPtr<3>(&*edge_bases[0].data().begin()),
1149 getFTensor1FromPtr<3>(&*edge_bases[1].data().begin()),
1150 getFTensor1FromPtr<3>(&*edge_bases[2].data().begin())};
1151 FTensor::Tensor2<FTensor::PackPtr<double *, 6>, 3, 2> t_edge_diff_base[] = {
1152 getFTensor2HVecFromPtr<3, 2>(&*diff_edge_bases[0].data().begin()),
1153 getFTensor2HVecFromPtr<3, 2>(&*diff_edge_bases[1].data().begin()),
1154 getFTensor2HVecFromPtr<3, 2>(&*diff_edge_bases[2].data().begin())};
1155 // face
1156 auto t_vol_base = getFTensor1FromPtr<3>(&*face_bases.data().begin());
1157 auto t_vol_diff_base =
1158 getFTensor2HVecFromPtr<3, 2>(&*diff_face_bases.data().begin());
1159
1160 auto t_base = getFTensor1FromPtr<3>(
1161 &*data.dataOnEntities[MBTRI][0].getN(base).data().begin());
1162 auto t_diff_base = getFTensor2HVecFromPtr<3, 2>(
1163 &*data.dataOnEntities[MBTRI][0].getDiffN(base).data().begin());
1164
1165 FTENSOR_INDEX(3, i);
1166 FTENSOR_INDEX(2, j);
1167
1168 // Fill the base functions and their derivatives
1169 for (int gg = 0; gg != nb_gauss_pts; gg++) {
1170 for (int oo = 0; oo < order; oo++) {
1171 // edges
1172 for (int dd = NBEDGE_DEMKOWICZ_HCURL(oo);
1173 dd != NBEDGE_DEMKOWICZ_HCURL(oo + 1); ++dd) {
1174 for (int ee = 0; ee != 3; ++ee) {
1175 t_base(i) = t_edge_base[ee](i);
1176 ++t_base;
1177 ++t_edge_base[ee];
1178 t_diff_base(i, j) = t_edge_diff_base[ee](i, j);
1179 ++t_diff_base;
1180 ++t_edge_diff_base[ee];
1181 }
1182 }
1183 // faces
1184 for (int dd = NBFACETRI_DEMKOWICZ_HCURL(oo);
1185 dd != NBFACETRI_DEMKOWICZ_HCURL(oo + 1); ++dd) {
1186 t_base(i) = t_vol_base(i);
1187 ++t_base;
1188 ++t_vol_base;
1189 t_diff_base(i, j) = t_vol_diff_base(i, j);
1190 ++t_diff_base;
1191 ++t_vol_diff_base;
1192 }
1193 }
1194 }
1195
1196 } else {
1197
1198 // No DOFs on faces, resize base function matrices, indicating that no
1199 // dofs on them.
1200 data.dataOnEntities[MBTRI][0].getN(base).resize(nb_gauss_pts, 0, false);
1201 data.dataOnEntities[MBTRI][0].getDiffN(base).resize(nb_gauss_pts, 0, false);
1202 }
1203
1205}
1206
1209 switch (cTx->spaceContinuity) {
1210 case CONTINUOUS:
1211
1212 switch (cTx->bAse) {
1218 default:
1219 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not implemented");
1220 }
1221
1222 break;
1223
1224 case DISCONTINUOUS:
1225 switch (cTx->bAse) {
1231 default:
1232 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not implemented");
1233 }
1234
1235 default:
1236 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Unknown continuity");
1237 }
1238
1240}
1241
1244 boost::shared_ptr<BaseFunctionCtx> ctx_ptr) {
1246
1248
1249 int nb_gauss_pts = pts.size2();
1250 if (!nb_gauss_pts) {
1252 }
1253
1254 if (pts.size1() < 2)
1255 SETERRQ(
1256 PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1257 "Wrong dimension of pts, should be at least 3 rows with coordinates");
1258
1259 const FieldApproximationBase base = cTx->bAse;
1260 EntitiesFieldData &data = cTx->dAta;
1261
1262 if (base != AINSWORTH_BERNSTEIN_BEZIER_BASE) {
1263 if (cTx->copyNodeBase == LASTBASE) {
1264 data.dataOnEntities[MBVERTEX][0].getN(base).resize(nb_gauss_pts, 3,
1265 false);
1267 &*data.dataOnEntities[MBVERTEX][0].getN(base).data().begin(),
1268 &pts(0, 0), &pts(1, 0), nb_gauss_pts);
1269 data.dataOnEntities[MBVERTEX][0].getDiffN(base).resize(3, 2, false);
1271 &*data.dataOnEntities[MBVERTEX][0].getDiffN(base).data().begin());
1272 } else {
1273 data.dataOnEntities[MBVERTEX][0].getN(base) =
1274 data.dataOnEntities[MBVERTEX][0].getN(cTx->copyNodeBase);
1275 data.dataOnEntities[MBVERTEX][0].getDiffN(base) =
1276 data.dataOnEntities[MBVERTEX][0].getDiffN(cTx->copyNodeBase);
1277 }
1278 if (data.dataOnEntities[MBVERTEX][0].getN(base).size1() !=
1279 (unsigned int)nb_gauss_pts) {
1280 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1281 "Base functions or nodes has wrong number of integration points "
1282 "for base %s",
1284 }
1285 }
1286
1287 auto set_node_derivative_for_all_gauss_pts = [&]() {
1289 // In linear geometry derivatives are constant,
1290 // this in expense of efficiency makes implementation
1291 // consistent between vertices and other types of entities
1292 data.dataOnEntities[MBVERTEX][0].getDiffN(base).resize(nb_gauss_pts, 6,
1293 false);
1294 for (int gg = 0; gg != nb_gauss_pts; ++gg)
1295 std::copy(Tools::diffShapeFunMBTRI.begin(),
1297 &data.dataOnEntities[MBVERTEX][0].getDiffN(base)(gg, 0));
1299 };
1300
1301 CHKERR set_node_derivative_for_all_gauss_pts();
1302
1303 switch (cTx->spaceContinuity) {
1304 case CONTINUOUS:
1305
1306 switch (cTx->sPace) {
1307 case H1:
1309 case HDIV:
1311 case HCURL:
1313 case L2:
1315 default:
1316 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not yet implemented");
1317 }
1318
1319 case DISCONTINUOUS:
1320 switch (cTx->sPace) {
1321 case HCURL:
1323 default:
1324 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not yet implemented");
1325 }
1326
1327 default:
1328 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Unknown continuity");
1329 }
1330
1332}
1333
1335
1336 const FieldSpace space, const FieldContinuity continuity,
1337 const FieldApproximationBase base, DofsSideMap &dofs_side_map
1338
1339) {
1341
1342 switch (continuity) {
1343 case DISCONTINUOUS:
1344
1345 switch (space) {
1346 case HCURL:
1348 setDofsSideMapHcurl(space, continuity, base, dofs_side_map));
1349 default:
1350 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Unknown space %s",
1351 FieldSpaceNames[space]);
1352 }
1353 break;
1354
1355 default:
1356 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
1357 "Unknown (or not implemented) continuity");
1358 }
1359
1361}
1362
1364 const FieldSpace space, const FieldContinuity continuity,
1365 const FieldApproximationBase base, DofsSideMap &dofs_side_map) {
1367
1368 // That has to be consistent with implementation of getValueHdiv for
1369 // particular base functions.
1370
1371 auto set_ainsworth = [&dofs_side_map]() {
1373
1374 dofs_side_map.clear();
1375
1376 int dof = 0;
1377 for (int oo = 0; oo < Field::maxBrokenDofsOrder; oo++) {
1378
1379 // edges
1380 for (int dd = NBEDGE_AINSWORTH_HCURL(oo);
1381 dd != NBEDGE_AINSWORTH_HCURL(oo + 1); ++dd) {
1382 for (int ee = 0; ee != 3; ++ee) {
1383 dofs_side_map.insert(DofsSideMapData{MBEDGE, ee, dof});
1384 ++dof;
1385 }
1386 }
1387 // face
1388 for (int dd = NBFACETRI_AINSWORTH_HCURL(oo);
1389 dd != NBFACETRI_AINSWORTH_HCURL(oo + 1); ++dd) {
1390 dofs_side_map.insert(DofsSideMapData{MBTRI, 0, dof});
1391 ++dof;
1392 }
1393 }
1394
1396 };
1397
1398 auto set_demkowicz = [&dofs_side_map]() {
1400
1401 dofs_side_map.clear();
1402
1403 int dof = 0;
1404 for (int oo = 0; oo < Field::maxBrokenDofsOrder; oo++) {
1405
1406 // edges
1407 for (int dd = NBEDGE_DEMKOWICZ_HCURL(oo);
1408 dd != NBEDGE_DEMKOWICZ_HCURL(oo + 1); ++dd) {
1409 for (int ee = 0; ee != 3; ++ee) {
1410 dofs_side_map.insert(DofsSideMapData{MBEDGE, ee, dof});
1411 ++dof;
1412 }
1413 }
1414 // faces
1415 for (int dd = NBFACETRI_DEMKOWICZ_HCURL(oo);
1416 dd != NBFACETRI_DEMKOWICZ_HCURL(oo + 1); ++dd) {
1417 dofs_side_map.insert(DofsSideMapData{MBTRI, 0, dof});
1418 ++dof;
1419 }
1420 }
1421
1423 };
1424
1425 switch (continuity) {
1426 case DISCONTINUOUS:
1427 switch (base) {
1430 MoFEMFunctionReturnHot(set_ainsworth());
1432 MoFEMFunctionReturnHot(set_demkowicz());
1433 default:
1434 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not implemented");
1435 }
1436 break;
1437
1438 default:
1439 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
1440 "Unknown (or not implemented) continuity");
1441 }
1442
1444}
std::string type
#define FTENSOR_INDEX(DIM, I)
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
PetscErrorCode ShapeDiffMBTRI(double *diffN)
calculate derivatives of shape functions
Definition fem_tools.c:194
PetscErrorCode ShapeMBTRI(double *N, const double *X, const double *Y, const int G_DIM)
calculate shape functions on triangle
Definition fem_tools.c:182
#define NBEDGE_DEMKOWICZ_HCURL(P)
#define NBFACETRI_AINSWORTH_HCURL(P)
#define NBFACETRI_L2(P)
Number of base functions on triangle for L2 space.
#define NBEDGE_H1(P)
Number of base function on edge for H1 space.
#define NBFACETRI_DEMKOWICZ_HDIV(P)
PetscErrorCode L2_Ainsworth_ShapeFunctions_MBTRI(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 triangle for L2 space.
Definition l2.c:19
#define NBFACETRI_DEMKOWICZ_HCURL(P)
PetscErrorCode H1_EdgeShapeFunctions_MBTRI(int *sense, int *p, double *N, double *diffN, double *edgeN[3], double *diff_edgeN[3], int GDIM, PetscErrorCode(*base_polynomials)(int p, double s, double *diff_s, double *L, double *diffL, const int dim))
H1_EdgeShapeFunctions_MBTRI.
Definition h1.c:17
#define NBFACETRI_AINSWORTH_FACE_HDIV(P)
PetscErrorCode H1_FaceShapeFunctions_MBTRI(const int *face_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:191
#define NBFACETRI_AINSWORTH_EDGE_HDIV(P)
#define NBEDGE_AINSWORTH_HCURL(P)
#define NBFACETRI_H1(P)
Number of base function on triangle for H1 space.
#define NBFACETRI_AINSWORTH_HDIV(P)
FTensor::Index< 'i', SPACE_DIM > i
static double lambda
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 Hcurl_Demkowicz_EdgeBaseFunctions_MBTRI(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 teriangle.
Definition Hcurl.cpp:2116
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 Hcurl_Ainsworth_FaceFunctions_MBTET_ON_FACE(int *faces_nodes, int p, double *N, double *diffN, double *phi_f, double *diff_phi_f, 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:1249
auto getFTensor2HVecFromPtr< 3, 2 >(double *ptr)
MoFEMErrorCode Hcurl_Ainsworth_EdgeBaseFunctions_MBTET_ON_FACE(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 face.
Definition Hcurl.cpp:237
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
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_Demkowicz_FaceBaseFunctions_MBTRI(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:2440
static double phi
constexpr auto field_name
constexpr double g
static boost::function< int(int)> broken_nbfacetri_face_hdiv
Definition Hdiv.hpp:26
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 baseFunctionsTri(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 generateIndicesVertexTri(const int N, int *alpha)
static MoFEMErrorCode generateIndicesTriTri(const int N, int *alpha)
static MoFEMErrorCode generateIndicesEdgeTri(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
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.
static constexpr std::array< double, 6 > diffShapeFunMBTRI
Definition Tools.hpp:104
Calculate base functions on triangle.
MoFEMErrorCode getValueH1BernsteinBezierBase(MatrixDouble &pts)
MoFEMErrorCode getValueL2BernsteinBezierBase(MatrixDouble &pts)
MoFEMErrorCode getValueH1(MatrixDouble &pts)
MoFEMErrorCode getValueH1AinsworthBase(MatrixDouble &pts)
MoFEMErrorCode getValueL2(MatrixDouble &pts)
MoFEMErrorCode getValue(MatrixDouble &pts, boost::shared_ptr< BaseFunctionCtx > ctx_ptr)
ublas::matrix< MatrixDouble > N_face_edge
MoFEMErrorCode getValueHdivAinsworthBase(MatrixDouble &pts)
MoFEMErrorCode getValueHdivDemkowiczBase(MatrixDouble &pts)
MoFEMErrorCode query_interface(boost::typeindex::type_index type_index, UnknownInterface **iface) const
ublas::vector< MatrixDouble > N_face_bubble
MoFEMErrorCode getValueHcurlDemkowiczBase(MatrixDouble &pts)
MoFEMErrorCode getValueHcurl(MatrixDouble &pts)
static MoFEMErrorCode setDofsSideMapHcurl(const FieldSpace space, const FieldContinuity continuity, const FieldApproximationBase base, DofsSideMap &dofs_side_map)
static MoFEMErrorCode setDofsSideMap(const FieldSpace space, const FieldContinuity continuity, const FieldApproximationBase base, DofsSideMap &)
Set map of dof to side number.
EntPolynomialBaseCtx * cTx
MoFEMErrorCode getValueHcurlAinsworthBase(MatrixDouble &pts)
MoFEMErrorCode getValueHcurlAinsworthBrokenBase(MatrixDouble &pts)
MoFEMErrorCode getValueHdiv(MatrixDouble &pts)
MoFEMErrorCode getValueL2AinsworthBase(MatrixDouble &pts)
MoFEMErrorCode getValueHcurlDemkowiczBrokenBase(MatrixDouble &pts)
base class for all interface classes
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.