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]) {
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);
98template <
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];
113 if constexpr (ErrorIfNoBase) {
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.size1();
155 det_data.resize(nb_gauss_pts,
false);
156 inv_jac_data.resize(nb_gauss_pts, 9,
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();
832OpGetDataAndGradient<3, 3>::getGradAtGaussPtsTensor<3, 3>(
MatrixDouble &data) {
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) {
FieldApproximationBase
approximation base
@ AINSWORTH_LEGENDRE_BASE
Ainsworth Cole (Legendre) approx. base .
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
#define CHKERRG(n)
Check error code of MoFEM/MOAB/PETSc function.
@ MOFEM_DATA_INCONSISTENCY
#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 ...
FTensor::Index< 'i', SPACE_DIM > i
const double v
phase velocity of light in medium (cm/ns)
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
static MoFEMErrorCodeGeneric< PetscErrorCode > ierr
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
UBlasMatrix< double > MatrixDouble
UBlasVector< double > VectorDouble
implementation of Data Operators for Forces and Sources
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.
MoFEMErrorCode invertTensor3by3< 3, double, ublas::row_major, DoubleAllocator >(MatrixDouble &jac_data, VectorDouble &det_data, MatrixDouble &inv_jac_data)
static auto getFTensor0FromVec(V &data)
Get tensor rank 0 (scalar) form data vector.
static auto determinantTensor3by3(T &t)
Calculate the determinant of a 3x3 matrix or a tensor of rank 2.
constexpr IntegrationType I
FTensor::Index< 'm', 3 > m
std::array< bool, MBMAXTYPE > doEntities
If true operator is executed for entity.
virtual MoFEMErrorCode opLhs(EntitiesFieldData &row_data, EntitiesFieldData &col_data)
virtual MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type, EntityType col_type, EntitiesFieldData::EntData &row_data, EntitiesFieldData::EntData &col_data)
Operator for bi-linear form, usually to calculate values on left hand side.
virtual MoFEMErrorCode opRhs(EntitiesFieldData &data, const bool error_if_no_base=false)
bool getSymm() const
Get if operator uses symmetry of DOFs or not.
DataOperator(const bool symm=true)
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.
virtual std::array< boost::shared_ptr< MatrixDouble >, MaxBernsteinBezierOrder > & getBBDiffNByOrderArray()
FTensor::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0N(const FieldApproximationBase base)
Get base function as Tensor0.
FieldApproximationBase & getBase()
Get approximation base.
MatrixDouble & getDiffN(const FieldApproximationBase base)
get derivatives of base functions
auto getFTensor1FieldData()
Return FTensor of rank 1, i.e. vector from field data coefficients.
auto getFTensor1DiffN(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....
const VectorDouble & getFieldData() const
Get DOF values on entity.
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
auto getFTensor1N(FieldApproximationBase base)
Get base functions for Hdiv/Hcurl spaces.
FTensor::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0FieldData()
Return scalar files as a FTensor of rank 0.
data structure for finite element entity
std::array< boost::ptr_vector< EntData >, MBMAXTYPE > dataOnEntities
MatrixDouble & tAngent2_at_GaussPtF3
MatrixDouble & tAngent1_at_GaussPtF3
MatrixDouble & nOrmals_at_GaussPtF3
MatrixDouble & cOords_at_GaussPtF3
MatrixDouble & nOrmals_at_GaussPtF4
MatrixDouble & cOords_at_GaussPtF4
MoFEMErrorCode calculateNormals()
MatrixDouble & tAngent2_at_GaussPtF4
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data) override
Operator for linear form, usually to calculate values on right hand side.
MatrixDouble & tAngent1_at_GaussPtF4
Get field values and gradients at Gauss points.
MoFEMErrorCode calculateValAndGrad(int side, EntityType type, EntitiesFieldData::EntData &data)
Calculate gradient and values at integration points.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data) override
Operator for linear form, usually to calculate values on right hand side.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data) override
Operator for linear form, usually to calculate values on right hand side.
FTensor::Index< 'j', 3 > j
FTensor::Index< 'i', 3 > i
FTensor::Tensor2< double *, 3, 3 > tInvJac
FTensor::Index< 'j', 3 > j
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data) override
Operator for linear form, usually to calculate values on right hand side.
FTensor::Tensor2< double *, 3, 3 > tInvJac
FTensor::Index< 'i', 3 > i
FTensor::Index< 'k', 3 > k
MatrixDouble diffHdivInvJac