v0.15.0
Loading...
Searching...
No Matches
HODataOperators.cpp
Go to the documentation of this file.
1/** \file HODataOperators.cpp
2
3\brief Set of operators for high-order geometry approximation.
4
5*/
6
7namespace MoFEM {
8
10 boost::shared_ptr<MatrixDouble> jac_ptr)
12 jacPtr(jac_ptr) {
13
14 for (auto t = MBEDGE; t != MBMAXTYPE; ++t)
15 doEntities[t] = false;
16
17 if (!jacPtr)
18 THROW_MESSAGE("Jac pointer not allocated");
19}
20
22OpCalculateHOJacForVolume::doWork(int side, EntityType type,
25
26 const auto nb_base_functions = data.getN(NOBASE).size2();
27 if (nb_base_functions) {
28
29 const auto nb_gauss_pts = getGaussPts().size2();
30 auto t_diff_base = data.getFTensor1DiffN<3>(NOBASE);
31 auto &coords = getCoords();
32
33#ifndef NDEBUG
34 if (nb_gauss_pts != data.getDiffN().size1())
35 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
36 "Inconsistent number base functions and gauss points");
37 if (nb_base_functions != data.getDiffN().size2() / 3)
38 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
39 "Inconsistent number of base functions");
40 if (coords.size() != 3 * nb_base_functions)
41 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
42 "Number of vertex coordinates and base functions is inconsistent "
43 "%ld != %ld",
44 coords.size() / 3, nb_base_functions);
45#endif
46
47 jacPtr->resize(9, nb_gauss_pts, false);
48 jacPtr->clear();
49 auto t_jac = getFTensor2FromMat<3, 3>(*jacPtr);
50 auto t_vol_inv_jac = getInvJac();
51
52 FTensor::Index<'i', 3> i;
53 FTensor::Index<'j', 3> j;
54 FTensor::Index<'k', 3> k;
55
56 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
58 &coords[0], &coords[1], &coords[2]);
59 for (size_t bb = 0; bb != nb_base_functions; ++bb) {
60 t_jac(i, j) += t_coords(i) * (t_vol_inv_jac(k, j) * t_diff_base(k));
61 ++t_diff_base;
62 ++t_coords;
63 }
64 ++t_jac;
65 }
66 }
67
69}
70
75
76 if (getFEDim() == 3) {
77
78 auto transform_base = [&](MatrixDouble &diff_n) {
79 return applyTransform<3, 3, 3, 3>(diff_n);
80 };
81
82 for (int b = AINSWORTH_LEGENDRE_BASE; b != LASTBASE; b++) {
84 CHKERR transform_base(data.getDiffN(base));
85 }
86
87 switch (type) {
88 case MBVERTEX:
89 for (auto &m : data.getBBDiffNMap())
90 CHKERR transform_base(*(m.second));
91 break;
92 default:
93 for (auto &ptr : data.getBBDiffNByOrderArray())
94 if (ptr)
95 CHKERR transform_base(*ptr);
96 }
97
98 } else {
99 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Use different operator");
100 }
101
103}
104
106OpSetHOInvJacVectorBase::doWork(int side, EntityType type,
109
110 FTensor::Index<'i', 3> i;
111 FTensor::Index<'j', 3> j;
112 FTensor::Index<'k', 3> k;
113
114 for (int b = AINSWORTH_LEGENDRE_BASE; b != LASTBASE; b++) {
115
116 FieldApproximationBase base = static_cast<FieldApproximationBase>(b);
117
118 diffHdivInvJac.resize(data.getDiffN(base).size1(),
119 data.getDiffN(base).size2(), false);
120
121 unsigned int nb_gauss_pts = data.getDiffN(base).size1();
122 unsigned int nb_base_functions = data.getDiffN(base).size2() / 9;
123 if (nb_base_functions == 0)
124 continue;
125
126 auto t_diff_n = data.getFTensor2DiffN<3, 3>(base);
127 double *t_inv_diff_n_ptr = &*diffHdivInvJac.data().begin();
129 t_inv_diff_n_ptr, &t_inv_diff_n_ptr[HVEC0_1],
130 &t_inv_diff_n_ptr[HVEC0_2], &t_inv_diff_n_ptr[HVEC1_0],
131 &t_inv_diff_n_ptr[HVEC1_1], &t_inv_diff_n_ptr[HVEC1_2],
132 &t_inv_diff_n_ptr[HVEC2_0], &t_inv_diff_n_ptr[HVEC2_1],
133 &t_inv_diff_n_ptr[HVEC2_2]);
134 auto t_inv_jac = getFTensor2FromMat<3, 3>(*invJacPtr);
135 for (unsigned int gg = 0; gg != nb_gauss_pts; ++gg) {
136 for (unsigned int bb = 0; bb != nb_base_functions; ++bb) {
137 t_inv_diff_n(i, j) = t_inv_jac(k, j) * t_diff_n(i, k);
138 ++t_diff_n;
139 ++t_inv_diff_n;
140 }
141 ++t_inv_jac;
142 }
143
144 data.getDiffN(base).swap(diffHdivInvJac);
145 }
146
148}
149
153 const size_t nb_int_pts = getGaussPts().size2();
154 if (getNormalsAtGaussPts().size1()) {
155 if (getNormalsAtGaussPts().size1() == nb_int_pts) {
156 double a = getMeasure();
157 if (getNumeredEntFiniteElementPtr()->getEntType() == MBTRI)
158 a *= 2;
159 auto t_w = getFTensor0IntegrationWeight();
160 auto t_normal = getFTensor1NormalsAtGaussPts();
161 FTensor::Index<'i', 3> i;
162 for (size_t gg = 0; gg != nb_int_pts; ++gg) {
163 t_w *= sqrt(t_normal(i) * t_normal(i)) / a;
164 ++t_w;
165 ++t_normal;
166 }
167 } else {
168 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE,
169 "Number of rows in getNormalsAtGaussPts should be equal to "
170 "number of integration points, but is not, i.e. %ld != %ld",
171 getNormalsAtGaussPts().size1(), nb_int_pts);
172 }
173 }
175}
176
180 const size_t nb_int_pts = getGaussPts().size2();
181 if (getTangentAtGaussPts().size1()) {
182 if (getTangentAtGaussPts().size1() == nb_int_pts) {
183 double a = getMeasure();
184 auto t_w = getFTensor0IntegrationWeight();
185 auto t_tangent = getFTensor1TangentAtGaussPts();
186 FTensor::Index<'i', 3> i;
187 for (size_t gg = 0; gg != nb_int_pts; ++gg) {
188 t_w *= sqrt(t_tangent(i) * t_tangent(i)) / a;
189 ++t_w;
190 ++t_tangent;
191 }
192 } else {
193 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE,
194 "Number of rows in getTangentAtGaussPts should be equal to "
195 "number of integration points, but is not, i.e. %ld != %ld",
196 getTangentAtGaussPts().size1(), nb_int_pts);
197 }
198 }
200}
201
202MoFEMErrorCode OpSetHOWeights::doWork(int side, EntityType type,
205
206 const auto nb_integration_pts = detPtr->size();
207
208#ifndef NDEBUG
209 if (nb_integration_pts != getGaussPts().size2())
210 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
211 "Inconsistent number of data points");
212#endif
213
214 auto t_w = getFTensor0IntegrationWeight();
215 auto t_det = getFTensor0FromVec(*detPtr);
216 for (size_t gg = 0; gg != nb_integration_pts; ++gg) {
217 t_w *= t_det;
218 ++t_w;
219 ++t_det;
220 }
221
223}
224
229
230 FTensor::Index<'i', 3> i;
231 FTensor::Index<'j', 3> j;
232 FTensor::Index<'k', 3> k;
233
234#ifndef NDEBUG
235 if (!detPtr)
236 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
237 "Pointer for detPtr not allocated");
238 if (!jacPtr)
239 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
240 "Pointer for jacPtr not allocated");
241#endif
242
243 for (int b = AINSWORTH_LEGENDRE_BASE; b != LASTBASE; ++b) {
244
245 FieldApproximationBase base = static_cast<FieldApproximationBase>(b);
246
247 auto nb_gauss_pts = data.getNSharedPtr(base) ? data.getN(base).size1() : 0;
248 auto nb_base_functions =
249 data.getNSharedPtr(base) ? data.getN(base).size2() / 3 : 0;
250 auto nb_diff_base_functions =
251 data.getDiffNSharedPtr(base) ? data.getDiffN(base).size2() / 9 : 0;
252
253#ifndef NDEBUG
254 if (nb_diff_base_functions) {
255 if (nb_diff_base_functions != nb_base_functions)
256 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
257 "Wrong number base functions %ld != %ld",
258 nb_diff_base_functions, nb_base_functions);
259 if (data.getDiffN(base).size1() != nb_gauss_pts)
260 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
261 "Wrong number integration points");
262 }
263#endif
264
265 if (nb_gauss_pts && nb_base_functions) {
266
267 piolaN.resize(nb_gauss_pts, data.getN(base).size2(), false);
268
269 auto t_n = data.getFTensor1N<3>(base);
270 double *t_transformed_n_ptr = &*piolaN.data().begin();
272 t_transformed_n_ptr, // HVEC0
273 &t_transformed_n_ptr[HVEC1], &t_transformed_n_ptr[HVEC2]);
274
275 auto t_det = getFTensor0FromVec(*detPtr);
276 auto t_jac = getFTensor2FromMat<3, 3>(*jacPtr);
277
278 for (unsigned int gg = 0; gg != nb_gauss_pts; ++gg) {
279 for (unsigned int bb = 0; bb != nb_base_functions; ++bb) {
280 const double a = 1. / t_det;
281 t_transformed_n(i) = a * (t_jac(i, k) * t_n(k));
282 ++t_n;
283 ++t_transformed_n;
284 }
285 ++t_det;
286 ++t_jac;
287 }
288
289 data.getN(base).swap(piolaN);
290 }
291
292 if (nb_gauss_pts && nb_diff_base_functions) {
293
294 piolaDiffN.resize(nb_gauss_pts, data.getDiffN(base).size2(), false);
295
296 auto t_diff_n = data.getFTensor2DiffN<3, 3>(base);
297 double *t_transformed_diff_n_ptr = &*piolaDiffN.data().begin();
299 t_transformed_diff_n(t_transformed_diff_n_ptr,
300 &t_transformed_diff_n_ptr[HVEC0_1],
301 &t_transformed_diff_n_ptr[HVEC0_2],
302 &t_transformed_diff_n_ptr[HVEC1_0],
303 &t_transformed_diff_n_ptr[HVEC1_1],
304 &t_transformed_diff_n_ptr[HVEC1_2],
305 &t_transformed_diff_n_ptr[HVEC2_0],
306 &t_transformed_diff_n_ptr[HVEC2_1],
307 &t_transformed_diff_n_ptr[HVEC2_2]);
308
309 auto t_det = getFTensor0FromVec(*detPtr);
310 for (unsigned int gg = 0; gg != nb_gauss_pts; ++gg) {
311 for (unsigned int bb = 0; bb != nb_diff_base_functions; ++bb) {
312 const double a = 1. / t_det;
313 t_transformed_diff_n(i, k) = a * t_diff_n(i, k);
314 ++t_diff_n;
315 ++t_transformed_diff_n;
316 }
317 ++t_det;
318 }
319
320 data.getDiffN(base).swap(piolaDiffN);
321 }
322 }
323
325}
326
331
332 FTensor::Index<'i', 3> i;
333 FTensor::Index<'j', 3> j;
334 FTensor::Index<'k', 3> k;
335
336 for (int b = AINSWORTH_LEGENDRE_BASE; b != LASTBASE; b++) {
337
338 FieldApproximationBase base = static_cast<FieldApproximationBase>(b);
339
340 unsigned int nb_gauss_pts = data.getN(base).size1();
341 unsigned int nb_base_functions = data.getN(base).size2() / 3;
342 piolaN.resize(nb_gauss_pts, data.getN(base).size2(), false);
343 piolaDiffN.resize(nb_gauss_pts, data.getDiffN(base).size2(), false);
344
345 auto t_n = data.getFTensor1N<3>(base);
346 double *t_transformed_n_ptr = &*piolaN.data().begin();
348 t_transformed_n_ptr, // HVEC0
349 &t_transformed_n_ptr[HVEC1], &t_transformed_n_ptr[HVEC2]);
350 auto t_diff_n = data.getFTensor2DiffN<3, 3>(base);
351 double *t_transformed_diff_n_ptr = &*piolaDiffN.data().begin();
352 FTensor::Tensor2<FTensor::PackPtr<double *, 9>, 3, 3> t_transformed_diff_n(
353 t_transformed_diff_n_ptr, &t_transformed_diff_n_ptr[HVEC0_1],
354 &t_transformed_diff_n_ptr[HVEC0_2], &t_transformed_diff_n_ptr[HVEC1_0],
355 &t_transformed_diff_n_ptr[HVEC1_1], &t_transformed_diff_n_ptr[HVEC1_2],
356 &t_transformed_diff_n_ptr[HVEC2_0], &t_transformed_diff_n_ptr[HVEC2_1],
357 &t_transformed_diff_n_ptr[HVEC2_2]);
358
359 auto t_inv_jac = getFTensor2FromMat<3, 3>(*jacInvPtr);
360
361 for (unsigned int gg = 0; gg != nb_gauss_pts; ++gg) {
362 for (unsigned int bb = 0; bb != nb_base_functions; ++bb) {
363 t_transformed_n(i) = t_inv_jac(k, i) * t_n(k);
364 t_transformed_diff_n(i, k) = t_inv_jac(j, i) * t_diff_n(j, k);
365 ++t_n;
366 ++t_transformed_n;
367 ++t_diff_n;
368 ++t_transformed_diff_n;
369 }
370 ++t_inv_jac;
371 }
372
373 data.getN(base).swap(piolaN);
374 data.getDiffN(base).swap(piolaDiffN);
375 }
376
378}
379
381 boost::shared_ptr<MatrixDouble> jac_ptr)
383 jacPtr(jac_ptr) {}
384
388
390
391 const auto nb_gauss_pts = getGaussPts().size2();
392
393 jacPtr->resize(4, nb_gauss_pts, false);
394 auto t_jac = getFTensor2FromMat<2, 2>(*jacPtr);
395
396 FTensor::Index<'i', 2> i;
397 FTensor::Index<'j', 2> j;
398
399 auto t_t1 = getFTensor1Tangent1AtGaussPts();
400 auto t_t2 = getFTensor1Tangent2AtGaussPts();
403
404 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
405 t_jac(i, N0) = t_t1(i);
406 t_jac(i, N1) = t_t2(i);
407 ++t_t1;
408 ++t_t2;
409 ++t_jac;
410 }
411
413};
414
419
420 FTensor::Index<'i', 3> i;
421 FTensor::Index<'j', 3> j;
422 FTensor::Index<'k', 3> k;
423
424 size_t nb_gauss_pts = getGaussPts().size2();
425 jacPtr->resize(9, nb_gauss_pts, false);
426
427 auto t_t1 = getFTensor1Tangent1AtGaussPts();
428 auto t_t2 = getFTensor1Tangent2AtGaussPts();
429 auto t_normal = getFTensor1NormalsAtGaussPts();
430
434
435 auto t_jac = getFTensor2FromMat<3, 3>(*jacPtr);
436 for (size_t gg = 0; gg != nb_gauss_pts; ++gg, ++t_jac) {
437
438 t_jac(i, N0) = t_t1(i);
439 t_jac(i, N1) = t_t2(i);
440
441 const double l = sqrt(t_normal(j) * t_normal(j));
442
443 t_jac(i, N2) = t_normal(i) / l;
444
445 ++t_t1;
446 ++t_t2;
447 ++t_normal;
448 }
449
451}
452
454 int side, EntityType type, EntitiesFieldData::EntData &data) {
455 FTensor::Index<'i', 3> i;
457
458 if (moab::CN::Dimension(type) != 2)
460
461 auto get_normals_ptr = [&]() {
463 return &*normalsAtGaussPts->data().begin();
464 else
465 return &*getNormalsAtGaussPts().data().begin();
466 };
467
468 auto apply_transform_nonlinear_geometry = [&](auto base, auto nb_gauss_pts,
469 auto nb_base_functions) {
471
472 auto ptr = get_normals_ptr();
474 &ptr[0], &ptr[1], &ptr[2]);
475
476 auto t_base = data.getFTensor1N<3>(base);
477 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
478 const auto l2 = t_normal(i) * t_normal(i);
479 for (int bb = 0; bb != nb_base_functions; ++bb) {
480 const auto v = t_base(0);
481 t_base(i) = (v / l2) * t_normal(i);
482 ++t_base;
483 }
484 ++t_normal;
485 }
487 };
488
489 for (int b = AINSWORTH_LEGENDRE_BASE; b != LASTBASE; b++) {
490
491 FieldApproximationBase base = static_cast<FieldApproximationBase>(b);
492 const auto &base_functions = data.getN(base);
493 const auto nb_gauss_pts = base_functions.size1();
494
495 if (nb_gauss_pts) {
496
497 const auto nb_base_functions = base_functions.size2() / 3;
498 CHKERR apply_transform_nonlinear_geometry(base, nb_gauss_pts,
499 nb_base_functions);
500 }
501 }
502
504}
505
507 int side, EntityType type, EntitiesFieldData::EntData &data) {
509
510 const auto type_dim = moab::CN::Dimension(type);
511 if (type_dim != 1 && type_dim != 2)
513
514 FTensor::Index<'i', 3> i;
515 FTensor::Index<'j', 3> j;
516 FTensor::Index<'k', 2> k;
517
518 auto get_jac = [&]() {
520 double *ptr_n = &*normalsAtPts->data().begin();
521 double *ptr_t1 = &*tangent1AtPts->data().begin();
522 double *ptr_t2 = &*tangent2AtPts->data().begin();
524 &ptr_t1[0], &ptr_t2[0], &ptr_n[0],
525
526 &ptr_t1[1], &ptr_t2[1], &ptr_n[1],
527
528 &ptr_t1[2], &ptr_t2[2], &ptr_n[2]);
529 } else {
530 double *ptr_n = &*getNormalsAtGaussPts().data().begin();
531 double *ptr_t1 = &*getTangent1AtGaussPts().data().begin();
532 double *ptr_t2 = &*getTangent2AtGaussPts().data().begin();
534 &ptr_t1[0], &ptr_t2[0], &ptr_n[0],
535
536 &ptr_t1[1], &ptr_t2[1], &ptr_n[1],
537
538 &ptr_t1[2], &ptr_t2[2], &ptr_n[2]);
539 }
540 };
541
542 for (int b = AINSWORTH_LEGENDRE_BASE; b != LASTBASE; ++b) {
543
544 FieldApproximationBase base = static_cast<FieldApproximationBase>(b);
545
546 auto &baseN = data.getN(base);
547 auto &diffBaseN = data.getDiffN(base);
548
549 int nb_dofs = baseN.size2() / 3;
550 int nb_gauss_pts = baseN.size1();
551
552 piolaN.resize(baseN.size1(), baseN.size2());
553 diffPiolaN.resize(diffBaseN.size1(), diffBaseN.size2());
554
555 if (nb_dofs > 0 && nb_gauss_pts > 0) {
556
557 auto t_h_curl = data.getFTensor1N<3>(base);
558 auto t_diff_h_curl = data.getFTensor2DiffN<3, 2>(base);
559
560 FTensor::Tensor1<FTensor::PackPtr<double *, 3>, 3> t_transformed_h_curl(
561 &piolaN(0, HVEC0), &piolaN(0, HVEC1), &piolaN(0, HVEC2));
562
564 t_transformed_diff_h_curl(
568
569 int cc = 0;
570 double det;
572
573 // HO geometry is set, so jacobian is different at each gauss point
574 auto t_m_at_pts = get_jac();
575 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
576 CHKERR determinantTensor3by3(t_m_at_pts, det);
577 CHKERR invertTensor3by3(t_m_at_pts, det, t_inv_m);
578 for (int ll = 0; ll != nb_dofs; ll++) {
579 t_transformed_h_curl(i) = t_inv_m(j, i) * t_h_curl(j);
580 t_transformed_diff_h_curl(i, k) = t_inv_m(j, i) * t_diff_h_curl(j, k);
581 ++t_h_curl;
582 ++t_transformed_h_curl;
583 ++t_diff_h_curl;
584 ++t_transformed_diff_h_curl;
585 ++cc;
586 }
587 ++t_m_at_pts;
588 }
589
590#ifndef NDEBUG
591 if (cc != nb_gauss_pts * nb_dofs)
592 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "Data inconsistency");
593#endif
594
595 baseN.swap(piolaN);
596 diffBaseN.swap(diffPiolaN);
597 }
598 }
599
601}
602
604 int side, EntityType type, EntitiesFieldData::EntData &data) {
605 FTensor::Index<'i', 3> i;
607
608 if (type != MBEDGE)
610
611 const auto nb_gauss_pts = getGaussPts().size2();
612
614 if (tangentAtGaussPts->size1() != nb_gauss_pts)
615 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
616 "Wrong number of integration points %ld!=%ld",
617 tangentAtGaussPts->size1(), nb_gauss_pts);
618
619 auto get_base_at_pts = [&](auto base) {
621 &data.getN(base)(0, HVEC0), &data.getN(base)(0, HVEC1),
622 &data.getN(base)(0, HVEC2));
623 return t_h_curl;
624 };
625
626 auto get_tangent_ptr = [&]() {
627 if (tangentAtGaussPts) {
628 return &*tangentAtGaussPts->data().begin();
629 } else {
630 return &*getTangentAtGaussPts().data().begin();
631 }
632 };
633
634 auto get_tangent_at_pts = [&]() {
635 auto ptr = get_tangent_ptr();
637 &ptr[0], &ptr[1], &ptr[2]);
638 return t_m_at_pts;
639 };
640
641 auto calculate_squared_edge_length = [&]() {
642 std::vector<double> l1;
643 if (nb_gauss_pts) {
644 l1.resize(nb_gauss_pts);
645 auto t_m_at_pts = get_tangent_at_pts();
646 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
647 l1[gg] = t_m_at_pts(i) * t_m_at_pts(i);
648 ++t_m_at_pts;
649 }
650 }
651 return l1;
652 };
653
654 auto l1 = calculate_squared_edge_length();
655
656 for (int b = AINSWORTH_LEGENDRE_BASE; b != LASTBASE; b++) {
657
658 FieldApproximationBase base = static_cast<FieldApproximationBase>(b);
659 const auto nb_dofs = data.getN(base).size2() / 3;
660
661 if (nb_gauss_pts && nb_dofs) {
662 auto t_h_curl = get_base_at_pts(base);
663 int cc = 0;
664 auto t_m_at_pts = get_tangent_at_pts();
665 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
666 const double l0 = l1[gg];
667 for (int ll = 0; ll != nb_dofs; ++ll) {
668 const double val = t_h_curl(0);
669 const double a = val / l0;
670 t_h_curl(i) = t_m_at_pts(i) * a;
671 ++t_h_curl;
672 ++cc;
673 }
674 ++t_m_at_pts;
675 }
676
677#ifndef NDEBUG
678 if (cc != nb_gauss_pts * nb_dofs)
679 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "Data inconsistency");
680#endif
681 }
682 }
683
685}
686
688 const FieldSpace space, const FieldApproximationBase base,
689 boost::shared_ptr<VectorDouble> det_jac_ptr,
690 boost::shared_ptr<double> scale_det_ptr)
691 : OP(space), fieldSpace(space), fieldBase(base), detJacPtr(det_jac_ptr),
692 scaleDetPtr(scale_det_ptr) {
693 if (!detJacPtr) {
694 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "detJacPtr not set");
695 }
696}
697
702
703 double scale_det = 1.0;
704 if (scaleDetPtr)
705 scale_det = *scaleDetPtr;
706
707 auto scale = [&](auto base) {
709 auto &base_fun = data.getN(base);
710 if (base_fun.size2()) {
711
712 auto &det_vec = *detJacPtr;
713 const auto nb_int_pts = base_fun.size1();
714
715 if (nb_int_pts != det_vec.size())
716 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
717 "Number of integration pts in detJacPtr does not mush "
718 "number of integration pts in base function");
719
720 for (auto gg = 0; gg != nb_int_pts; ++gg) {
721 auto row = ublas::matrix_row<MatrixDouble>(base_fun, gg);
722 row *= scale_det / det_vec[gg];
723 }
724
725 auto &diff_base_fun = data.getDiffN(base);
726 if (diff_base_fun.size2()) {
727 for (auto gg = 0; gg != nb_int_pts; ++gg) {
728 auto row = ublas::matrix_row<MatrixDouble>(diff_base_fun, gg);
729 row *= scale_det / det_vec[gg];
730 }
731 }
732 }
734 };
735
736 if (this->getFEDim() == 3) {
737 switch (fieldSpace) {
738 case L2:
739 if (type >= MBTET)
741 break;
742 default:
743 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "space not handled");
744 }
745 } else if (this->getFEDim() == 2) {
746 switch (fieldSpace) {
747 case L2:
748 if (type >= MBTRI)
750 break;
751 default:
752 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "space not handled");
753 }
754 } else if (this->getFEDim() == 1) {
755 switch (fieldSpace) {
756 case L2:
757 if (type >= MBEDGE)
759 break;
760 default:
761 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "space not handled");
762 }
763 } else {
764 SETERRQ(PETSC_COMM_SELF, MOFEM_IMPOSSIBLE_CASE, "dimension not handled");
765 }
766
768}
769
771 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
772 std::vector<FieldSpace> spaces, std::string geom_field_name,
773 boost::shared_ptr<MatrixDouble> jac_ptr,
774 boost::shared_ptr<VectorDouble> det_ptr,
775 boost::shared_ptr<MatrixDouble> inv_jac_ptr) {
777
778 if (!jac_ptr)
779 jac_ptr = boost::make_shared<MatrixDouble>();
780 if (!det_ptr)
781 det_ptr = boost::make_shared<VectorDouble>();
782 if (!inv_jac_ptr)
783 inv_jac_ptr = boost::make_shared<MatrixDouble>();
784
785 if (geom_field_name.empty()) {
786
787 pipeline.push_back(new OpCalculateHOJac<2>(jac_ptr));
788
789 } else {
790
791 pipeline.push_back(new OpCalculateHOCoords<2>(geom_field_name));
792 pipeline.push_back(
793 new OpCalculateVectorFieldGradient<2, 2>(geom_field_name, jac_ptr));
794 pipeline.push_back(new OpGetHONormalsOnFace<2>(geom_field_name));
795 }
796
797 pipeline.push_back(new OpInvertMatrix<2>(jac_ptr, det_ptr, inv_jac_ptr));
798 pipeline.push_back(new OpSetHOWeightsOnFace());
799
800 for (auto s : spaces) {
801 switch (s) {
802 case NOSPACE:
803 break;
804 case H1:
805 case L2:
806 pipeline.push_back(new OpSetHOInvJacToScalarBases<2>(s, inv_jac_ptr));
807 break;
808 case HCURL:
809 pipeline.push_back(new OpSetCovariantPiolaTransformOnFace2D(inv_jac_ptr));
810 pipeline.push_back(new OpSetInvJacHcurlFace(inv_jac_ptr));
811 break;
812 case HDIV:
813 pipeline.push_back(new OpMakeHdivFromHcurl());
814 pipeline.push_back(new OpSetContravariantPiolaTransformOnFace2D(jac_ptr));
815 pipeline.push_back(new OpSetInvJacHcurlFace(inv_jac_ptr));
816 break;
817 default:
818 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
819 "Space %s not yet implemented", FieldSpaceNames[s]);
820 }
821 }
822
824}
825
827 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
828 std::vector<FieldSpace> spaces, std::string geom_field_name,
829 boost::shared_ptr<MatrixDouble> jac_ptr,
830 boost::shared_ptr<VectorDouble> det_ptr,
831 boost::shared_ptr<MatrixDouble> inv_jac_ptr) {
833
834 if (!jac_ptr)
835 jac_ptr = boost::make_shared<MatrixDouble>();
836 if (!det_ptr)
837 det_ptr = boost::make_shared<VectorDouble>();
838 if (!inv_jac_ptr)
839 inv_jac_ptr = boost::make_shared<MatrixDouble>();
840
841 if (geom_field_name.empty()) {
842
843 } else {
844
845 pipeline.push_back(new OpCalculateHOCoords<3>(geom_field_name));
846 pipeline.push_back(new OpGetHONormalsOnFace<3>(geom_field_name));
847 }
848
849 pipeline.push_back(new OpCalculateHOJacForFaceEmbeddedIn3DSpace(jac_ptr));
850 pipeline.push_back(new OpInvertMatrix<3>(jac_ptr, det_ptr, inv_jac_ptr));
851 pipeline.push_back(new OpSetHOWeightsOnFace());
852
853 for (auto s : spaces) {
854 switch (s) {
855 case NOSPACE:
856 break;
857 case H1:
858 pipeline.push_back(
860 break;
861 case HDIV:
862 pipeline.push_back(new OpMakeHdivFromHcurl());
863 pipeline.push_back(
865 jac_ptr));
866 pipeline.push_back(
868 break;
869 case L2:
870 pipeline.push_back(
872 break;
873 default:
874 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
875 "Space %s not yet implemented", FieldSpaceNames[s]);
876 }
877 }
878
880}
881
883 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
884 std::vector<FieldSpace> spaces, std::string geom_field_name) {
886
887 if (geom_field_name.empty()) {
888
889 } else {
890
891 pipeline.push_back(new OpCalculateHOCoords<2>(geom_field_name));
892 pipeline.push_back(new OpGetHOTangentsOnEdge<2>(geom_field_name));
893 }
894
895 for (auto s : spaces) {
896 switch (s) {
897 case NOSPACE:
898 break;
899 case HCURL:
900 pipeline.push_back(new OpHOSetContravariantPiolaTransformOnEdge3D(HCURL));
901 break;
902 case HDIV:
903 pipeline.push_back(new OpSetContravariantPiolaTransformOnEdge2D());
904 break;
905 default:
906 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
907 "Space %s not yet implemented", FieldSpaceNames[s]);
908 }
909 }
910
912}
913
915 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
916 std::vector<FieldSpace> spaces, std::string geom_field_name) {
918
919 if (geom_field_name.empty()) {
920
921 } else {
922
923 pipeline.push_back(new OpCalculateHOCoords<3>(geom_field_name));
924 pipeline.push_back(new OpGetHOTangentsOnEdge<3>(geom_field_name));
925 }
926
927 for (auto s : spaces) {
928 switch (s) {
929 case HCURL:
930 pipeline.push_back(new OpHOSetContravariantPiolaTransformOnEdge3D(HCURL));
931 break;
932 default:
933 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
934 "Space %s not yet implemented", FieldSpaceNames[s]);
935 }
936 }
937
939}
940
942 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
943 std::vector<FieldSpace> spaces, std::string geom_field_name) {
945
946 if (geom_field_name.empty()) {
947 } else {
948
949 pipeline.push_back(new OpCalculateHOCoords<3>(geom_field_name));
950 pipeline.push_back(new OpGetHONormalsOnFace<3>(geom_field_name));
951 }
952
953 for (auto s : spaces) {
954 switch (s) {
955 case NOSPACE:
956 break;
957 case HCURL:
958 pipeline.push_back(new OpHOSetCovariantPiolaTransformOnFace3D(HCURL));
959 break;
960 case HDIV:
961 pipeline.push_back(new OpHOSetContravariantPiolaTransformOnFace3D(HDIV));
962 break;
963 case L2:
964 break;
965 default:
966 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
967 "Space %s not yet implemented", FieldSpaceNames[s]);
968 break;
969 }
970 }
971
973}
974
976 boost::ptr_deque<ForcesAndSourcesCore::UserDataOperator> &pipeline,
977 std::vector<FieldSpace> spaces, std::string geom_field_name,
978 boost::shared_ptr<MatrixDouble> jac, boost::shared_ptr<VectorDouble> det,
979 boost::shared_ptr<MatrixDouble> inv_jac) {
981
982 if (!jac)
983 jac = boost::make_shared<MatrixDouble>();
984 if (!det)
985 det = boost::make_shared<VectorDouble>();
986 if (!inv_jac)
987 inv_jac = boost::make_shared<MatrixDouble>();
988
989 if (geom_field_name.empty()) {
990
991 pipeline.push_back(new OpCalculateHOJac<3>(jac));
992
993 } else {
994
995 pipeline.push_back(new OpCalculateHOCoords<3>(geom_field_name));
996 pipeline.push_back(
997 new OpCalculateVectorFieldGradient<3, 3>(geom_field_name, jac));
998 }
999
1000 pipeline.push_back(new OpInvertMatrix<3>(jac, det, inv_jac));
1001 pipeline.push_back(new OpSetHOWeights(det));
1002
1003 for (auto s : spaces) {
1004 switch (s) {
1005 case NOSPACE:
1006 break;
1007 case H1:
1008 pipeline.push_back(new OpSetHOInvJacToScalarBases<3>(H1, inv_jac));
1009 break;
1010 case HCURL:
1011 pipeline.push_back(new OpSetHOCovariantPiolaTransform(HCURL, inv_jac));
1012 pipeline.push_back(new OpSetHOInvJacVectorBase(HCURL, inv_jac));
1013 break;
1014 case HDIV:
1015 pipeline.push_back(
1017 break;
1018 case L2:
1019 pipeline.push_back(new OpSetHOInvJacToScalarBases<3>(L2, inv_jac));
1020 break;
1021 default:
1022 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
1023 "Space %s not yet implemented", FieldSpaceNames[s]);
1024 break;
1025 }
1026 }
1027
1029}
1030
1031} // namespace MoFEM
ForcesAndSourcesCore::UserDataOperator UserDataOperator
static MoFEMErrorCode get_jac(EntitiesFieldData::EntData &col_data, int gg, MatrixDouble &jac_stress, MatrixDouble &jac)
constexpr double a
T data[Tensor_Dim]
FieldApproximationBase
approximation base
Definition definitions.h:58
@ LASTBASE
Definition definitions.h:69
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
Definition definitions.h:60
@ NOBASE
Definition definitions.h:59
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
#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
@ NOSPACE
Definition definitions.h:83
@ HCURL
field with continuous tangents
Definition definitions.h:86
@ HDIV
field with continuous normal traction
Definition definitions.h:87
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 ...
@ HVEC0
@ HVEC1
@ HVEC2
@ MOFEM_IMPOSSIBLE_CASE
Definition definitions.h:35
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
@ MOFEM_NOT_IMPLEMENTED
Definition definitions.h:32
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ HVEC1_1
@ HVEC0_1
@ HVEC1_0
@ HVEC2_1
@ HVEC1_2
@ HVEC2_2
@ HVEC2_0
@ HVEC0_2
@ HVEC0_0
#define CHKERR
Inline error check.
#define MoFEMFunctionBeginHot
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define THROW_MESSAGE(msg)
Throw MoFEM exception.
FTensor::Index< 'i', SPACE_DIM > i
const double v
phase velocity of light in medium (cm/ns)
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
OpSetInvJacHcurlFaceImpl< 2 > OpSetInvJacHcurlFace
OpSetContravariantPiolaTransformOnFace2DImpl< 3 > OpSetContravariantPiolaTransformOnFace2DEmbeddedIn3DSpace
OpSetInvJacHcurlFaceImpl< 3 > OpSetInvJacHcurlFaceEmbeddedIn3DSpace
MoFEMErrorCode invertTensor3by3(ublas::matrix< T, L, A > &jac_data, ublas::vector< T, A > &det_data, ublas::matrix< T, L, A > &inv_jac_data)
Calculate inverse of tensor rank 2 at integration points.
OpSetCovariantPiolaTransformOnFace2DImpl< 2 > OpSetCovariantPiolaTransformOnFace2D
OpSetContravariantPiolaTransformOnFace2DImpl< 2 > OpSetContravariantPiolaTransformOnFace2D
static auto getFTensor0FromVec(ublas::vector< T, A > &data)
Get tensor rank 0 (scalar) form data vector.
OpCalculateHOJacForFaceImpl< 3 > OpCalculateHOJacForFaceEmbeddedIn3DSpace
static auto determinantTensor3by3(T &t)
Calculate the determinant of a 3x3 matrix or a tensor of rank 2.
double scale
Definition plastic.cpp:123
constexpr double t
plate stiffness
Definition plate.cpp:58
FTensor::Index< 'm', 3 > m
Add operators pushing bases from local to physical configuration.
std::array< bool, MBMAXTYPE > doEntities
If true operator is executed for entity.
MatrixDouble & getTangentAtGaussPts()
get tangent vector to edge curve at integration points
FTensor::Tensor1< FTensor::PackPtr< double *, 3 >, DIM > getFTensor1TangentAtGaussPts()
Get tangent vector at integration points.
Data on single entity (This is passed as argument to DataOperator::doWork)
FTensor::Tensor2< FTensor::PackPtr< double *, Tensor_Dim0 *Tensor_Dim1 >, Tensor_Dim0, Tensor_Dim1 > getFTensor2DiffN(FieldApproximationBase base)
Get derivatives of base functions for Hdiv space.
FTensor::Tensor1< FTensor::PackPtr< double *, Tensor_Dim >, Tensor_Dim > getFTensor1DiffN(const FieldApproximationBase base)
Get derivatives of base functions.
virtual std::array< boost::shared_ptr< MatrixDouble >, MaxBernsteinBezierOrder > & getBBDiffNByOrderArray()
MatrixDouble & getDiffN(const FieldApproximationBase base)
get derivatives of base functions
MatrixDouble & getN(const FieldApproximationBase base)
get base functions this return matrix (nb. of rows is equal to nb. of Gauss pts, nb....
virtual std::map< std::string, boost::shared_ptr< MatrixDouble > > & getBBDiffNMap()
get hash map of derivatives base function for BB base, key is a field name
FTensor::Tensor1< FTensor::PackPtr< double *, Tensor_Dim >, Tensor_Dim > getFTensor1N(FieldApproximationBase base)
Get base functions for Hdiv/Hcurl spaces.
virtual boost::shared_ptr< MatrixDouble > & getDiffNSharedPtr(const FieldApproximationBase base)
virtual boost::shared_ptr< MatrixDouble > & getNSharedPtr(const FieldApproximationBase base, const BaseDerivatives direvatie)
MatrixDouble & getNormalsAtGaussPts()
if higher order geometry return normals at Gauss pts.
MatrixDouble & getTangent2AtGaussPts()
if higher order geometry return tangent vector to triangle at Gauss pts.
MatrixDouble & getTangent1AtGaussPts()
if higher order geometry return tangent vector to triangle at Gauss pts.
auto getFTensor0IntegrationWeight()
Get integration weights.
double getMeasure() const
get measure of element
boost::shared_ptr< const NumeredEntFiniteElement > getNumeredEntFiniteElementPtr() const
Return raw pointer to NumeredEntFiniteElement.
int getFEDim() const
Get dimension of finite element.
MatrixDouble & getGaussPts()
matrix of integration (Gauss) points for Volume Element
Calculate HO coordinates at gauss points.
Calculate jacobian for face element.
boost::shared_ptr< MatrixDouble > jacPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpCalculateHOJacForVolume(boost::shared_ptr< MatrixDouble > jac_ptr)
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Calculate normals at Gauss points of triangle element.
Calculate tangent vector on edge form HO geometry approximation.
transform Hcurl base fluxes from reference element to physical edge
boost::shared_ptr< MatrixDouble > tangentAtGaussPts
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
transform Hdiv base fluxes from reference element to physical triangle
boost::shared_ptr< MatrixDouble > normalsAtGaussPts
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
transform Hcurl base fluxes from reference element to physical triangle
boost::shared_ptr< MatrixDouble > normalsAtPts
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
boost::shared_ptr< MatrixDouble > tangent2AtPts
boost::shared_ptr< MatrixDouble > tangent1AtPts
Make Hdiv space from Hcurl space in 2d.
boost::shared_ptr< VectorDouble > detJacPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpScaleBaseBySpaceInverseOfMeasure(const FieldSpace space, const FieldApproximationBase base, boost::shared_ptr< VectorDouble > det_jac_ptr, boost::shared_ptr< double > scale_det_ptr=nullptr)
Apply contravariant (Piola) transfer to Hdiv space for HO geometry.
boost::shared_ptr< VectorDouble > detPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
boost::shared_ptr< MatrixDouble > jacPtr
Apply covariant (Piola) transfer to Hcurl space for HO geometry.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
boost::shared_ptr< MatrixDouble > jacInvPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Set inverse jacobian to base functions.
transform local reference derivatives of shape function to global derivatives if higher order geometr...
boost::shared_ptr< MatrixDouble > invJacPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Modify integration weights on face to take in account higher-order geometry.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Set inverse jacobian to base functions.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
boost::shared_ptr< VectorDouble > detPtr
FTensor::Tensor2< double *, 3, 3 > & getInvJac()
get element inverse Jacobian