26 doEntities{
true,
true,
true,
true,
true,
true,
27 true,
true,
true,
true,
true,
true},
29 doVertices(doEntities[MBVERTEX]), doEdges(doEntities[MBEDGE]),
30 doQuads(doEntities[MBQUAD]), doTris(doEntities[MBTRI]),
31 doTets(doEntities[MBTET]), doPrisms(doEntities[MBPRISM]) {
34 doEntities[MBPOLYGON] =
false;
35 doEntities[MBPYRAMID] =
false;
36 doEntities[MBKNIFE] =
false;
37 doEntities[MBPOLYHEDRON] =
false;
46 [&](boost::ptr_vector<EntitiesFieldData::EntData> &row_ent_data,
47 const int ss,
const EntityType row_type,
const EntityType low_type,
48 const EntityType hi_type) {
50 for (EntityType col_type = low_type; col_type != hi_type; ++col_type) {
52 for (
size_t SS = 0; SS != col_ent_data.size(); SS++) {
53 if (col_ent_data[SS].getFieldData().size())
54 CHKERR doWork(ss, SS, row_type, col_type, row_ent_data[ss],
61 auto do_row_entity = [&](
const EntityType
type) {
64 for (
size_t ss = 0; ss != row_ent_data.size(); ++ss) {
75 static_cast<EntityType
>(
type + 1), MBMAXTYPE);
80 for (EntityType row_type = MBVERTEX; row_type != MBMAXTYPE; ++row_type) {
82 CHKERR do_row_entity(row_type);
93 return opLhs<true>(row_data, col_data);
95 return opLhs<false>(row_data, col_data);
98 template <
bool ErrorIfNoBase>
101 const std::array<bool, MBMAXTYPE> &do_entities) {
104 auto do_entity = [&](
auto type) {
108 const size_t size = ent_data.size();
109 for (
size_t ss = 0; ss != size; ++ss) {
111 auto &side_data = ent_data[ss];
114 if (side_data.getFieldData().size() &&
115 (side_data.getBase() ==
NOBASE ||
117 for (VectorDofs::iterator it = side_data.getFieldDofs().begin();
118 it != side_data.getFieldDofs().end(); it++)
119 if ((*it) && (*it)->getActive())
130 for (EntityType row_type = MBVERTEX; row_type != MBMAXTYPE; ++row_type) {
131 if (do_entities[row_type]) {
132 CHKERR do_entity(row_type);
141 const bool error_if_no_base) {
142 if (error_if_no_base)
153 auto A = getFTensor2FromMat<3, 3>(jac_data);
154 int nb_gauss_pts = jac_data.size2();
155 det_data.resize(nb_gauss_pts,
false);
156 inv_jac_data.resize(3, nb_gauss_pts,
false);
158 auto I = getFTensor2FromMat<3, 3>(inv_jac_data);
159 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
176 if (diff_n.data().size()) {
177 const int nb_base_functions = diff_n.size2() / 3;
178 const int nb_gauss_pts = diff_n.size1();
179 diffNinvJac.resize(diff_n.size1(), diff_n.size2(),
false);
181 double *t_diff_n_ptr = &*diff_n.data().begin();
183 t_diff_n_ptr, &t_diff_n_ptr[1], &t_diff_n_ptr[2]);
184 double *t_inv_n_ptr = &*
diffNinvJac.data().begin();
186 t_inv_n_ptr, &t_inv_n_ptr[1], &t_inv_n_ptr[2]);
188 for (
unsigned int gg = 0; gg != nb_gauss_pts; ++gg) {
189 for (
unsigned int bb = 0; bb != nb_base_functions; ++bb) {
210 CHKERR transform_base(*(
m.second));
215 CHKERR transform_base(*ptr);
226 if (
type == MBVERTEX)
233 const unsigned int nb_gauss_pts = data.
getDiffN(base).size1();
234 const unsigned int nb_base_functions = data.
getDiffN(base).size2() / 9;
235 if (!nb_base_functions)
243 inv_diff_n_ptr, &inv_diff_n_ptr[
HVEC0_1], &inv_diff_n_ptr[
HVEC0_2],
251 for (
unsigned int gg = 0; gg != nb_gauss_pts; ++gg) {
252 for (
unsigned int bb = 0; bb != nb_base_functions; ++bb) {
269 if (CN::Dimension(
type) > 1) {
275 const unsigned int nb_base_functions = data.
getN(base).size2() / 3;
276 if (!nb_base_functions)
279 const unsigned int nb_gauss_pts = data.
getN(base).size1();
282 piolaN.resize(nb_gauss_pts, data.
getN(base).size2(),
false);
283 if (data.
getN(base).size2() > 0) {
285 double *t_transformed_n_ptr = &*
piolaN.data().begin();
288 &t_transformed_n_ptr[
HVEC1], &t_transformed_n_ptr[
HVEC2]);
289 for (
unsigned int gg = 0; gg != nb_gauss_pts; ++gg) {
290 for (
unsigned int bb = 0; bb != nb_base_functions; ++bb) {
291 t_transformed_n(
i) =
a * (
tJac(
i,
k) * t_n(
k));
300 if (data.
getDiffN(base).size2() > 0) {
302 double *t_transformed_diff_n_ptr = &*
piolaDiffN.data().begin();
304 t_transformed_diff_n(t_transformed_diff_n_ptr,
305 &t_transformed_diff_n_ptr[
HVEC0_1],
306 &t_transformed_diff_n_ptr[
HVEC0_2],
307 &t_transformed_diff_n_ptr[
HVEC1_0],
308 &t_transformed_diff_n_ptr[
HVEC1_1],
309 &t_transformed_diff_n_ptr[
HVEC1_2],
310 &t_transformed_diff_n_ptr[
HVEC2_0],
311 &t_transformed_diff_n_ptr[
HVEC2_1],
312 &t_transformed_diff_n_ptr[
HVEC2_2]);
313 for (
unsigned int gg = 0; gg != nb_gauss_pts; ++gg) {
314 for (
unsigned int bb = 0; bb != nb_base_functions; ++bb) {
315 t_transformed_diff_n(
i,
k) =
a *
tJac(
i,
j) * t_diff_n(
j,
k);
317 ++t_transformed_diff_n;
333 if (
type == MBVERTEX)
340 const unsigned int nb_base_functions = data.
getN(base).size2() / 3;
341 if (!nb_base_functions)
344 const unsigned int nb_gauss_pts = data.
getN(base).size1();
345 piolaN.resize(nb_gauss_pts, data.
getN(base).size2(),
false);
349 double *t_transformed_n_ptr = &*
piolaN.data().begin();
351 t_transformed_n_ptr, &t_transformed_n_ptr[
HVEC1],
352 &t_transformed_n_ptr[
HVEC2]);
354 double *t_transformed_diff_n_ptr = &*
piolaDiffN.data().begin();
356 t_transformed_diff_n_ptr, &t_transformed_diff_n_ptr[
HVEC0_1],
357 &t_transformed_diff_n_ptr[
HVEC0_2], &t_transformed_diff_n_ptr[
HVEC1_0],
358 &t_transformed_diff_n_ptr[
HVEC1_1], &t_transformed_diff_n_ptr[
HVEC1_2],
359 &t_transformed_diff_n_ptr[
HVEC2_0], &t_transformed_diff_n_ptr[
HVEC2_1],
360 &t_transformed_diff_n_ptr[
HVEC2_2]);
362 for (
unsigned int gg = 0; gg != nb_gauss_pts; ++gg) {
363 for (
unsigned int bb = 0; bb != nb_base_functions; ++bb) {
370 for (
unsigned int gg = 0; gg != nb_gauss_pts; ++gg) {
371 for (
unsigned int bb = 0; bb != nb_base_functions; ++bb) {
374 ++t_transformed_diff_n;
394 const int valid_edges3[] = {1, 1, 1, 0, 0, 0, 0, 0, 0};
395 const int valid_faces3[] = {0, 0, 0, 1, 0, 0, 0, 0, 0};
396 const int valid_edges4[] = {0, 0, 0, 0, 0, 0, 1, 1, 1};
397 const int valid_faces4[] = {0, 0, 0, 0, 1, 0, 0, 0, 0};
399 if (
type == MBEDGE) {
400 if (!valid_edges3[side] || valid_edges4[side])
402 }
else if (
type == MBTRI) {
403 if (!valid_faces3[side] || valid_faces4[side])
409 for (
unsigned int gg = 0; gg < data.
getN().size1(); ++gg) {
410 for (
int dd = 0;
dd < 3;
dd++) {
428 if (2 * data.
getN().size2() != data.
getDiffN().size2()) {
432 if (nb_dofs % 3 != 0) {
435 if (nb_dofs > 3 * data.
getN().size2()) {
437 "data inconsistency, side %d type %d", side,
type);
439 for (
unsigned int gg = 0; gg < data.
getN().size1(); ++gg) {
440 for (
int dd = 0;
dd < 3;
dd++) {
441 if ((
type == MBTRI && valid_faces3[side]) ||
442 (
type == MBEDGE && valid_edges3[side])) {
446 cblas_ddot(nb_dofs / 3, &data.
getDiffN()(gg, 0), 2,
449 cblas_ddot(nb_dofs / 3, &data.
getDiffN()(gg, 1), 2,
451 }
else if ((
type == MBTRI && valid_faces4[side]) ||
452 (
type == MBEDGE && valid_edges4[side])) {
456 cblas_ddot(nb_dofs / 3, &data.
getDiffN()(gg, 0), 2,
459 cblas_ddot(nb_dofs / 3, &data.
getDiffN()(gg, 1), 2,
481 cblas_dgemv(CblasRowMajor, CblasNoTrans, 3, 3, 1., &*
sPin.data().begin(), 3,
490 cblas_dgemv(CblasRowMajor, CblasNoTrans, 3, 3, 1., &*
sPin.data().begin(), 3,
502 if (moab::CN::Dimension(
type) != 2)
507 "Pointer to normal/normals not set");
510 if (normal_is_at_gauss_pts)
513 auto apply_transform_linear_geometry = [&](
auto base,
auto nb_gauss_pts,
514 auto nb_base_functions) {
520 const auto l02 = t_normal(
i) * t_normal(
i);
522 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
523 for (
int bb = 0; bb != nb_base_functions; ++bb) {
524 const auto v = t_base(0);
525 t_base(
i) = (
v / l02) * t_normal(
i);
532 auto apply_transform_nonlinear_geometry = [&](
auto base,
auto nb_gauss_pts,
533 auto nb_base_functions) {
537 &normals_at_pts(0, 0), &normals_at_pts(0, 1), &normals_at_pts(0, 2));
540 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
541 const auto l2 = t_normal(
i) * t_normal(
i);
542 for (
int bb = 0; bb != nb_base_functions; ++bb) {
543 const auto v = t_base(0);
544 t_base(
i) = (
v / l2) * t_normal(
i);
552 if (normal_is_at_gauss_pts) {
556 const auto &base_functions = data.
getN(base);
557 const auto nb_gauss_pts = base_functions.size1();
563 "normalsAtGaussPtsRawPtr has inconsistent number of "
567 const auto nb_base_functions = base_functions.size2() / 3;
568 CHKERR apply_transform_nonlinear_geometry(base, nb_gauss_pts,
576 const auto &base_functions = data.
getN(base);
577 const auto nb_gauss_pts = base_functions.size1();
580 const auto nb_base_functions = base_functions.size2() / 3;
581 CHKERR apply_transform_linear_geometry(base, nb_gauss_pts,
594 const auto type_dim = moab::CN::Dimension(
type);
595 if (type_dim != 1 && type_dim != 2)
617 auto &baseN = data.
getN(base);
618 auto &diffBaseN = data.
getDiffN(base);
620 int nb_dofs = baseN.size2() / 3;
621 int nb_gauss_pts = baseN.size1();
624 MatrixDouble diff_piola_n(diffBaseN.size1(), diffBaseN.size2());
626 if (nb_dofs > 0 && nb_gauss_pts > 0) {
637 t_transformed_diff_h_curl(
651 for (
int gg = 0; gg < nb_gauss_pts; ++gg) {
654 for (
int ll = 0; ll != nb_dofs; ll++) {
655 t_transformed_h_curl(
i) = t_inv_m(
j,
i) * t_h_curl(
j);
656 t_transformed_diff_h_curl(
i,
k) =
657 t_inv_m(
j,
i) * t_diff_h_curl(
j,
k);
659 ++t_transformed_h_curl;
661 ++t_transformed_diff_h_curl;
667 for (
int gg = 0; gg < nb_gauss_pts; ++gg) {
668 for (
int ll = 0; ll != nb_dofs; ll++) {
669 t_transformed_h_curl(
i) = t_inv_m(
j,
i) * t_h_curl(
j);
670 t_transformed_diff_h_curl(
i,
k) =
671 t_inv_m(
j,
i) * t_diff_h_curl(
j,
k);
673 ++t_transformed_h_curl;
675 ++t_transformed_diff_h_curl;
680 if (cc != nb_gauss_pts * nb_dofs)
684 diffBaseN.swap(diff_piola_n);
700 int nb_gauss_pts = data.
getN().size1();
701 tAngent.resize(nb_gauss_pts, 3,
false);
703 int nb_approx_fun = data.
getN().size2();
704 double *diff = &*data.
getDiffN().data().begin();
708 tAngent.resize(nb_gauss_pts, 3,
false);
712 for (
int dd = 0;
dd != 3;
dd++) {
713 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
714 tAngent(gg,
dd) = cblas_ddot(2, diff, 1, dofs[
dd], 3);
721 "Approximated field should be rank 3, i.e. vector in 3d space");
723 for (
int dd = 0;
dd != 3;
dd++) {
724 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
726 cblas_ddot(nb_dofs / 3, &diff[gg * nb_approx_fun], 1, dofs[
dd], 3);
732 "This operator can calculate tangent vector only on edge");
748 const double l0 = t_m(
i) * t_m(
i);
750 auto get_base_at_pts = [&](
auto base) {
757 auto get_tangent_at_pts = [&]() {
764 auto calculate_squared_edge_length = [&]() {
765 std::vector<double> l1;
768 l1.resize(nb_gauss_pts);
769 auto t_m_at_pts = get_tangent_at_pts();
770 for (
size_t gg = 0; gg != nb_gauss_pts; ++gg) {
771 l1[gg] = t_m_at_pts(
i) * t_m_at_pts(
i);
778 auto l1 = calculate_squared_edge_length();
783 const size_t nb_gauss_pts = data.
getN(base).size1();
784 const size_t nb_dofs = data.
getN(base).size2() / 3;
785 if (nb_gauss_pts && nb_dofs) {
786 auto t_h_curl = get_base_at_pts(base);
789 auto t_m_at_pts = get_tangent_at_pts();
790 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
791 const double l0 = l1[gg];
792 for (
int ll = 0; ll != nb_dofs; ll++) {
793 const double val = t_h_curl(0);
794 const double a = val / l0;
795 t_h_curl(
i) = t_m_at_pts(
i) *
a;
802 for (
int gg = 0; gg != nb_gauss_pts; ++gg) {
803 for (
int ll = 0; ll != nb_dofs; ll++) {
804 const double val = t_h_curl(0);
805 const double a = val / l0;
806 t_h_curl(
i) = t_m(
i) *
a;
813 if (cc != nb_gauss_pts * nb_dofs)
825 double *ptr = &*data.data().begin();
833 double *ptr = &*data.data().begin();
835 &ptr[4], &ptr[5], &ptr[6], &ptr[7],
845 const unsigned int nb_gauss_pts = data.
getN().size1();
846 const unsigned int nb_base_functions = data.
getN().size2();
847 const unsigned int nb_dofs = data.
getFieldData().size();
851 auto t_val = getValAtGaussPtsTensor<3>(dataAtGaussPts);
852 auto t_grad = getGradAtGaussPtsTensor<3, 3>(dataGradAtGaussPts);
855 if (
type == MBVERTEX &&
856 data.
getDiffN().data().size() == 3 * nb_base_functions) {
857 for (
unsigned int gg = 0; gg != nb_gauss_pts; ++gg) {
861 for (; bb != nb_dofs / 3; ++bb) {
862 t_val(
i) += t_data(
i) * t_n;
863 t_grad(
i,
j) += t_data(
i) * t_diff_n(
j);
870 for (; bb != nb_base_functions; ++bb) {
876 for (
unsigned int gg = 0; gg != nb_gauss_pts; ++gg) {
879 for (; bb != nb_dofs / 3; ++bb) {
880 t_val(
i) += t_data(
i) * t_n;
881 t_grad(
i,
j) += t_data(
i) * t_diff_n(
j);
888 for (; bb != nb_base_functions; ++bb) {
901 const unsigned int nb_gauss_pts = data.
getN().size1();
902 const unsigned int nb_base_functions = data.
getN().size2();
904 const unsigned int nb_dofs = data.
getFieldData().size();
908 double *ptr = &*dataGradAtGaussPts.data().begin();
912 if (
type == MBVERTEX &&
913 data.
getDiffN().data().size() == 3 * nb_base_functions) {
914 for (
unsigned int gg = 0; gg != nb_gauss_pts; ++gg) {
918 for (; bb != nb_dofs / 3; ++bb) {
919 t_val += t_data * t_n;
920 t_grad(
i) += t_data * t_diff_n(
i);
927 for (; bb != nb_base_functions; ++bb) {
933 for (
unsigned int gg = 0; gg != nb_gauss_pts; ++gg) {
936 for (; bb != nb_dofs / 3; ++bb) {
937 t_val = t_data * t_n;
938 t_grad(
i) += t_data * t_diff_n(
i);
945 for (; bb != nb_base_functions; ++bb) {