v0.15.5
Loading...
Searching...
No Matches
UserDataOperators.hpp
Go to the documentation of this file.
1/** \file UserDataOperators.hpp
2 * \brief User data operators for finite element computations
3 *
4 * This file contains a comprehensive collection of user data operators used in
5 * MoFEM finite element computations. These operators provide functionality for
6 * calculating, transforming, and manipulating field values at integration points.
7 *
8 * ## Main Categories of Operators:
9 *
10 * ### Field Value Calculation Operators
11 * - **Scalar Field Operators**: Calculate scalar field values at integration points
12 * - OpCalculateScalarFieldValues: General scalar field value calculation
13 * - OpCalculateScalarFieldValuesFromPetscVecImpl: PETSc vector-based scalar values
14 * - **Vector Field Operators**: Calculate vector field values at integration points
15 * - OpCalculateVectorFieldValues: General vector field value calculation
16 * - OpCalculateDivergenceVectorFieldValues: Divergence calculation for vector fields
17 * - **Tensor Field Operators**: Calculate tensor field values at integration points
18 * - OpCalculateTensor2FieldValues: Second-rank tensor field calculations
19 * - OpCalculateTensor2SymmetricFieldValues: Symmetric tensor field calculations
20 *
21 * ### Field Gradient Calculation Operators
22 * - **Scalar Gradient Operators**:
23 * - OpCalculateScalarFieldGradient: Gradient of scalar fields
24 * - OpCalculateScalarFieldHessian: Hessian (second derivatives) of scalar fields
25 * - **Vector Gradient Operators**:
26 * - OpCalculateVectorFieldGradient: Gradient of vector fields
27 *
28 * ### Matrix and Tensor Operations
29 * - **Matrix Manipulation**:
30 * - OpInvertMatrix: Matrix inversion at integration points
31 * - OpScaleMatrix: Element-wise matrix scaling operations
32 * - OpCalculateTraceFromMat: Trace calculation for matrices
33 * - **Tensor Operations**:
34 * - OpSymmetrizeTensor: Tensor symmetrization operations
35 * - OpTensorTimesSymmetricTensor: Tensor multiplication operations
36 *
37 * @see ForcesAndSourcesCore::UserDataOperator for base class documentation
38 * @see EntitiesFieldData for field data management
39 * @see PipelineManager for operator pipeline management
40 */
41
42#ifndef __USER_DATA_OPERATORS_HPP__
43 #define __USER_DATA_OPERATORS_HPP__
44
45namespace MoFEM {
46
47/** \name Get values at Gauss pts */
48
49/**@{*/
50
51/** \name Scalar values */
52
53/**@{*/
54
55/** \brief Scalar field values at integration points
56 *
57 */
58
59/**
60 * @brief Operator for calculating scalar field values at integration points
61 *
62 * This template structure calculates scalar field values at integration points
63 * and stores them in a provided data container. It supports different storage
64 * types through template parameters and can optionally work with PETSc vectors.
65 *
66 * @tparam T Data type for the scalar field values (e.g., double, float)
67 * @tparam A Allocator type for the ublas vector storage
68 */
69template <class T, class A>
72
73 /**
74 * @brief Constructor for scalar field values calculation operator
75 *
76 * @param field_name Name of the scalar field to calculate values for
77 * @param data_ptr Shared pointer to ublas vector for storing calculated values
78 * @param zero_type Entity type for zero-level entities (default: MBVERTEX)
79 */
81 const std::string field_name,
82 boost::shared_ptr<ublas::vector<T, A>> data_ptr,
83 const EntityType zero_type = MBVERTEX)
85 dataPtr(data_ptr), zeroType(zero_type) {
86 if (!dataPtr)
87 THROW_MESSAGE("Pointer is not set");
88 }
89
90 /**
91 * @brief Constructor with PETSc vector support
92 *
93 * @param field_name Name of the scalar field to calculate values for
94 * @param data_ptr Shared pointer to ublas vector for storing calculated values
95 * @param data_vec Smart PETSc vector object for additional data storage
96 * @param zero_type Entity type for zero-level entities (default: MBVERTEX)
97 */
99 const std::string field_name,
100 boost::shared_ptr<ublas::vector<T, A>> data_ptr,
101 SmartPetscObj<Vec> data_vec, const EntityType zero_type = MBVERTEX)
103 dataPtr(data_ptr), zeroType(zero_type), dataVec(data_vec) {
104 if (!dataPtr)
105 THROW_MESSAGE("Pointer is not set");
106 }
107
108 /**
109 * \brief calculate values of scalar field at integration points
110 * @param side side entity number
111 * @param type side entity type
112 * @param data entity data
113 * @return error code
114 */
115 MoFEMErrorCode doWork(int side, EntityType type,
117
118protected:
119 boost::shared_ptr<ublas::vector<T, A>> dataPtr;
123};
124
125/**
126 * \brief Specialization of member function
127 *
128 */
129template <class T, class A>
131 int side, EntityType type, EntitiesFieldData::EntData &data) {
133 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not implemented for T = %s",
134 typeid(T).name() // boost::core::demangle(typeid(T).name()).c_str()
135 );
137}
138
139/**
140 * @brief Specialization for double precision scalar field values calculation
141 *
142 * This structure is a specialization of OpCalculateScalarFieldValues_General
143 * for double precision scalar fields using DoubleAllocator. It provides
144 * concrete implementation for calculating scalar field values at integration
145 * points and storing them in double precision format.
146 *
147 * @ingroup mofem_forces_and_sources_user_data_operators
148 */
150 : public OpCalculateScalarFieldValues_General<double, DoubleAllocator> {
151
153 double, DoubleAllocator>::OpCalculateScalarFieldValues_General;
154
155 /**
156 * \brief calculate values of scalar field at integration points
157 * @param side side entity number
158 * @param type side entity type
159 * @param data entity data
160 * @return error code
161 */
162 MoFEMErrorCode doWork(int side, EntityType type,
165 VectorDouble &vec = *dataPtr;
166 const size_t nb_gauss_pts = getGaussPts().size2();
167 if (type == zeroType || vec.size() != nb_gauss_pts) {
168 vec.resize(nb_gauss_pts, false);
169 vec.clear();
170 }
171
172 const size_t nb_dofs = data.getFieldData().size();
173
174 if (nb_dofs) {
175
176 if (dataVec.use_count()) {
177 dotVector.resize(nb_dofs, false);
178 const double *array;
179 CHKERR VecGetArrayRead(dataVec, &array);
180 const auto &local_indices = data.getLocalIndices();
181 for (int i = 0; i != local_indices.size(); ++i)
182 if (local_indices[i] != -1)
183 dotVector[i] = array[local_indices[i]];
184 else
185 dotVector[i] = 0;
186 CHKERR VecRestoreArrayRead(dataVec, &array);
187 data.getFieldData().swap(dotVector);
188 }
189
190 const size_t nb_base_functions = data.getN().size2();
191 auto base_function = data.getFTensor0N();
192 auto values_at_gauss_pts = getFTensor0FromVec(vec);
193 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
194 auto field_data = data.getFTensor0FieldData();
195 size_t bb = 0;
196 for (; bb != nb_dofs; ++bb) {
197 values_at_gauss_pts += field_data * base_function;
198 ++field_data;
199 ++base_function;
200 }
201 // It is possible to have more base functions than dofs
202 for (; bb < nb_base_functions; ++bb)
203 ++base_function;
204 ++values_at_gauss_pts;
205 }
206
207 if (dataVec.use_count()) {
208 data.getFieldData().swap(dotVector);
209 }
210 }
211
213 }
214};
215
216/**
217 * @brief Calculate scalar field values from PETSc vector at integration points
218 *
219 * This template structure extracts scalar field values from a PETSc vector
220 * and calculates them at integration points. It supports different data contexts
221 * through the template parameter and can handle various entity types.
222 *
223 * @tparam CTX PETSc data context type specifying how data is accessed
224 *
225 * @ingroup mofem_forces_and_sources_user_data_operators
226 */
227template <PetscData::DataContext CTX>
230
231 /**
232 * @brief Constructor for PETSc vector-based scalar field calculation
233 *
234 * @param field_name Name of the scalar field to extract values from
235 * @param data_ptr Shared pointer to VectorDouble for storing calculated values
236 * @param zero_at_type Entity type where values should be zeroed (default: MBVERTEX)
237 */
239 const std::string field_name, boost::shared_ptr<VectorDouble> data_ptr,
240 const EntityType zero_at_type = MBVERTEX)
243 dataPtr(data_ptr), zeroAtType(zero_at_type) {
244 if (!dataPtr)
245 THROW_MESSAGE("Pointer is not set");
246 }
247
248 MoFEMErrorCode doWork(int side, EntityType type,
251
252 const size_t nb_gauss_pts = getGaussPts().size2();
253
254 VectorDouble &vec = *dataPtr;
255 if (type == zeroAtType || vec.size() != nb_gauss_pts) {
256 vec.resize(nb_gauss_pts, false);
257 vec.clear();
258 }
259
260 auto &local_indices = data.getLocalIndices();
261 const size_t nb_dofs = local_indices.size();
262 if (nb_dofs) {
263
264 const double *array;
265
266 auto get_array = [&](const auto ctx, auto vec) {
268 #ifndef NDEBUG
269 if ((getFEMethod()->data_ctx & ctx).none()) {
270 MOFEM_LOG_CHANNEL("SELF");
271 MOFEM_LOG("SELF", Sev::error)
272 << "In this case field degrees of freedom are read from vector. "
273 "That usually happens when time solver is used, and acces to "
274 "first or second rates is needed. You probably not set ts_u, "
275 "ts_u_t, or ts_u_tt and associated data structure, i.e. "
276 "data_ctx to CTX_SET_X, CTX_SET_X_T, or CTX_SET_X_TT "
277 "respectively";
278 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Vector not set!");
279 }
280 #endif
281 CHKERR VecGetArrayRead(vec, &array);
283 };
284
285 auto restore_array = [&](auto vec) {
286 return VecRestoreArrayRead(vec, &array);
287 };
288
289 switch (CTX) {
291 CHKERR get_array(PetscData::CtxSetX, getFEMethod()->ts_u);
292 break;
294 CHKERR get_array(PetscData::CtxSetX_T, getFEMethod()->ts_u_t);
295 break;
297 CHKERR get_array(PetscData::CtxSetX_TT, getFEMethod()->ts_u_tt);
298 break;
299 default:
300 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
301 "That case is not implemented");
302 }
303
304 std::array<double, MAX_DOFS_ON_ENTITY> dot_dofs_vector;
305 for (int i = 0; i != local_indices.size(); ++i)
306 if (local_indices[i] != -1)
307 dot_dofs_vector[i] = array[local_indices[i]];
308 else
309 dot_dofs_vector[i] = 0;
310
311 switch (CTX) {
313 CHKERR restore_array(getFEMethod()->ts_u);
314 break;
316 CHKERR restore_array(getFEMethod()->ts_u_t);
317 break;
319 CHKERR restore_array(getFEMethod()->ts_u_tt);
320 break;
321 default:
322 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
323 "That case is not implemented");
324 }
325
326 const size_t nb_base_functions = data.getN().size2();
327 auto base_function = data.getFTensor0N();
328 auto values_at_gauss_pts = getFTensor0FromVec(vec);
329
330 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
331 size_t bb = 0;
332 for (; bb != nb_dofs; ++bb) {
333 values_at_gauss_pts += dot_dofs_vector[bb] * base_function;
334 ++base_function;
335 }
336 // Number of dofs can be smaller than number of Tensor_Dim x base
337 // functions
338 for (; bb < nb_base_functions; ++bb)
339 ++base_function;
340 ++values_at_gauss_pts;
341 }
342 }
344 }
345
346private:
347 boost::shared_ptr<VectorDouble> dataPtr;
349};
350
355
356/**
357 * \deprecated Name inconsistent with other operators
358 *
359 */
361
362/**@}*/
363
364/** \name Vector field values at integration points */
365
366/**@{*/
367
368/**
369 * @brief Calculate field values for tensor field rank 1, i.e. vector field
370 *
371 * This template structure calculates vector field values at integration points
372 * and stores them in a matrix container. It supports various tensor dimensions,
373 * data types, and storage layouts through template parameters.
374 *
375 * @tparam Tensor_Dim Dimension of the vector field (e.g., 2 for 2D, 3 for 3D)
376 * @tparam T Data type for the field values (e.g., double, float)
377 * @tparam L Layout type for the ublas matrix storage
378 * @tparam A Allocator type for the ublas matrix storage
379 */
380template <int Tensor_Dim, class T, class L, class A>
383
384 /**
385 * @brief Constructor for vector field values calculation operator
386 *
387 * @param field_name Name of the vector field to calculate values for
388 * @param data_ptr Shared pointer to ublas matrix for storing calculated values
389 * @param zero_type Entity type for zero-level entities (default: MBVERTEX)
390 */
392 const std::string field_name,
393 boost::shared_ptr<ublas::matrix<T, L, A>> data_ptr,
394 const EntityType zero_type = MBVERTEX)
397 dataPtr(data_ptr), zeroType(zero_type) {
398 if (!dataPtr)
399 THROW_MESSAGE("Pointer is not set");
400 }
401
402 /**
403 * \brief calculate values of vector field at integration points
404 * @param side side entity number
405 * @param type side entity type
406 * @param data entity data
407 * @return error code
408 */
409 MoFEMErrorCode doWork(int side, EntityType type,
411
412protected:
413 boost::shared_ptr<ublas::matrix<T, L, A>> dataPtr;
415};
416
417template <int Tensor_Dim, class T, class L, class A>
420 int side, EntityType type, EntitiesFieldData::EntData &data) {
422 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
423 "Not implemented for T = %s and dim = %d",
424 typeid(T).name(), // boost::core::demangle(typeid(T).name()),
425 Tensor_Dim);
427}
428
429/** \brief Calculate field values (template specialization) for tensor field
430 * rank 1, i.e. vector field
431 *
432 */
433template <int Tensor_Dim>
435 ublas::row_major, DoubleAllocator>
437
439 boost::shared_ptr<MatrixDouble> data_ptr,
440 const EntityType zero_type = MBVERTEX)
443 dataPtr(data_ptr), zeroType(zero_type) {
444 if (!dataPtr)
445 THROW_MESSAGE("Pointer is not set");
446 }
447
449 boost::shared_ptr<MatrixDouble> data_ptr,
450 SmartPetscObj<Vec> data_vec,
451 const EntityType zero_type = MBVERTEX)
454 dataPtr(data_ptr), dataVec(data_vec), zeroType(zero_type) {
455 if (!dataPtr)
456 THROW_MESSAGE("Pointer is not set");
457 }
458
459 MoFEMErrorCode doWork(int side, EntityType type,
461
462protected:
463 boost::shared_ptr<MatrixDouble> dataPtr;
467};
468
469/**
470 * \brief Member function specialization calculating values for tenor field rank
471 *
472 */
473template <int Tensor_Dim>
475 Tensor_Dim, double, ublas::row_major,
476 DoubleAllocator>::doWork(int side, EntityType type,
479
480 const size_t nb_gauss_pts = getGaussPts().size2();
481 auto &mat = *dataPtr;
482 if (type == zeroType || mat.size2() != nb_gauss_pts) {
483 mat.resize(Tensor_Dim, nb_gauss_pts, false);
484 mat.clear();
485 }
486
487 const size_t nb_dofs = data.getFieldData().size();
488 if (nb_dofs) {
489
490 if (dataVec.use_count()) {
491 dotVector.resize(nb_dofs, false);
492 const double *array;
493 CHKERR VecGetArrayRead(dataVec, &array);
494 const auto &local_indices = data.getLocalIndices();
495 for (int i = 0; i != local_indices.size(); ++i)
496 if (local_indices[i] != -1)
497 dotVector[i] = array[local_indices[i]];
498 else
499 dotVector[i] = 0;
500 CHKERR VecRestoreArrayRead(dataVec, &array);
501 data.getFieldData().swap(dotVector);
502 }
503
504 if (nb_gauss_pts) {
505 const size_t nb_base_functions = data.getN().size2();
506 auto base_function = data.getFTensor0N();
507 auto values_at_gauss_pts = getFTensor1FromMat<Tensor_Dim>(mat);
508 FTensor::Index<'I', Tensor_Dim> I;
509 const size_t size = nb_dofs / Tensor_Dim;
510 if (nb_dofs % Tensor_Dim) {
511 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
512 "Nb. of DOFs is inconsistent with Tensor_Dim");
513 }
514 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
515 auto field_data = data.getFTensor1FieldData<Tensor_Dim>();
516
517 #ifndef NDEBUG
518 if (field_data.l2() != field_data.l2()) {
519 MOFEM_LOG("SELF", Sev::error) << "field data: " << field_data;
520 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
521 "Wrong number in coefficients");
522 }
523 #endif
524
525 size_t bb = 0;
526 for (; bb != size; ++bb) {
527
528 #ifndef SINGULARITY
529 #ifndef NDEBUG
530 if (base_function != base_function) {
531 MOFEM_LOG("SELF", Sev::error) << "base function: " << base_function;
532 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
533 "Wrong number number in base functions");
534 }
535 #endif
536 #endif
537
538 values_at_gauss_pts(I) += field_data(I) * base_function;
539 ++field_data;
540 ++base_function;
541 }
542 // Number of dofs can be smaller than number of Tensor_Dim x base
543 // functions
544 for (; bb < nb_base_functions; ++bb)
545 ++base_function;
546 ++values_at_gauss_pts;
547 }
548 }
549
550 if (dataVec.use_count()) {
551 data.getFieldData().swap(dotVector);
552 }
553 }
555}
556
557/**
558 * @brief Specialization for double precision vector field values calculation
559 *
560 * This structure is a specialization of OpCalculateVectorFieldValues_General
561 * for double precision vector fields using row_major layout and DoubleAllocator.
562 * It provides a convenient interface for calculating vector field values at
563 * integration points.
564 *
565 * @tparam Tensor_Dim Dimension of the vector field (e.g., 2 for 2D, 3 for 3D)
566 *
567 * @ingroup mofem_forces_and_sources_user_data_operators
568 */
569template <int Tensor_Dim>
572 Tensor_Dim, double, ublas::row_major, DoubleAllocator> {
573
575 Tensor_Dim, double, ublas::row_major,
576 DoubleAllocator>::OpCalculateVectorFieldValues_General;
577};
578
579/**@}*/
580
581/** \name Vector field values at integration points */
582
583/**@{*/
584
585/**
586 * @brief Calculate divergence of vector field at integration points
587 *
588 * This template structure calculates the divergence of a vector field at
589 * integration points. It supports different coordinate systems and tensor
590 * dimensions, making it suitable for various physical applications.
591 *
592 * @tparam Tensor_Dim Dimension of the vector field (e.g., 2 for 2D, 3 for 3D)
593 * @tparam COORDINATE_SYSTEM Coordinate system type (default: CARTESIAN)
594 */
595template <int Tensor_Dim, CoordinateTypes COORDINATE_SYSTEM = CARTESIAN>
598
599 /**
600 * @brief Constructor for vector field divergence calculation operator
601 *
602 * @param field_name Name of the vector field to calculate divergence for
603 * @param data_ptr Shared pointer to VectorDouble for storing calculated divergence values
604 * @param zero_type Entity type for zero-level entities (default: MBVERTEX)
605 */
607 const std::string field_name, boost::shared_ptr<VectorDouble> data_ptr,
608 const EntityType zero_type = MBVERTEX)
611 dataPtr(data_ptr), zeroType(zero_type) {
612 if (!dataPtr)
613 THROW_MESSAGE("Pointer is not set");
614 }
615
616 MoFEMErrorCode doWork(int side, EntityType type,
619
620 // When we move to C++17 add if constexpr()
621 if constexpr (COORDINATE_SYSTEM == POLAR || COORDINATE_SYSTEM == SPHERICAL)
622 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
623 "%s coordiante not implemented",
624 CoordinateTypesNames[COORDINATE_SYSTEM]);
625
626 const size_t nb_gauss_pts = getGaussPts().size2();
627 auto &vec = *dataPtr;
628 if (type == zeroType) {
629 vec.resize(nb_gauss_pts, false);
630 vec.clear();
631 }
632
633 const size_t nb_dofs = data.getFieldData().size();
634 if (nb_dofs) {
635
636 if (nb_gauss_pts) {
637 const size_t nb_base_functions = data.getN().size2();
638 auto values_at_gauss_pts = getFTensor0FromVec(vec);
639 FTensor::Index<'I', Tensor_Dim> I;
640 const size_t size = nb_dofs / Tensor_Dim;
641 #ifndef NDEBUG
642 if (nb_dofs % Tensor_Dim) {
643 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
644 "Number of dofs should multiple of dimensions");
645 }
646 #endif
647
648 // When we move to C++17 add if constexpr()
649 if constexpr (COORDINATE_SYSTEM == CARTESIAN) {
650 auto diff_base_function = data.getFTensor1DiffN<Tensor_Dim>();
651 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
652 auto field_data = data.getFTensor1FieldData<Tensor_Dim>();
653 size_t bb = 0;
654 for (; bb != size; ++bb) {
655 values_at_gauss_pts += field_data(I) * diff_base_function(I);
656 ++field_data;
657 ++diff_base_function;
658 }
659 // Number of dofs can be smaller than number of Tensor_Dim x base
660 // functions
661 for (; bb < nb_base_functions; ++bb)
662 ++diff_base_function;
663 ++values_at_gauss_pts;
664 }
665 }
666
667 // When we move to C++17 add if constexpr()
668 if constexpr (COORDINATE_SYSTEM == CYLINDRICAL) {
669 auto t_coords = getFTensor1CoordsAtGaussPts();
670 auto values_at_gauss_pts = getFTensor0FromVec(vec);
671 auto base_function = data.getFTensor0N();
672 auto diff_base_function = data.getFTensor1DiffN<Tensor_Dim>();
673 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
674 auto field_data = data.getFTensor1FieldData<Tensor_Dim>();
675 size_t bb = 0;
676 for (; bb != size; ++bb) {
677 values_at_gauss_pts += field_data(I) * diff_base_function(I);
678 values_at_gauss_pts +=
679 base_function * (field_data(0) / t_coords(0));
680 ++field_data;
681 ++base_function;
682 ++diff_base_function;
683 }
684 // Number of dofs can be smaller than number of Tensor_Dim x base
685 // functions
686 for (; bb < nb_base_functions; ++bb) {
687 ++base_function;
688 ++diff_base_function;
689 }
690 ++values_at_gauss_pts;
691 ++t_coords;
692 }
693 }
694 }
695 }
697 }
698
699protected:
700 boost::shared_ptr<VectorDouble> dataPtr;
702};
703
704/** \brief Approximate field values for given petsc vector
705 *
706 * \note Look at PetscData to see what vectors could be extracted with that user
707 * data operator.
708 *
709 * \ingroup mofem_forces_and_sources_user_data_operators
710 */
711template <int Tensor_Dim, PetscData::DataContext CTX>
714
716 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
717 const EntityType zero_at_type = MBVERTEX, bool throw_error = true)
720 dataPtr(data_ptr), zeroAtType(zero_at_type), throwError(throw_error) {
721 if (!dataPtr)
722 THROW_MESSAGE("Pointer is not set");
723 }
724
725 MoFEMErrorCode doWork(int side, EntityType type,
728
729 auto &local_indices = data.getLocalIndices();
730 const size_t nb_dofs = local_indices.size();
731 const size_t nb_gauss_pts = getGaussPts().size2();
732
733 MatrixDouble &mat = *dataPtr;
734 if (type == zeroAtType) {
735 mat.resize(Tensor_Dim, nb_gauss_pts, false);
736 mat.clear();
737 }
738 if (!nb_dofs)
740
741 if (!throwError) {
742 if ((getFEMethod()->data_ctx & PetscData::Switches(CTX)).none()) {
744 }
745 }
746
747 const double *array;
748
749 auto get_array = [&](const auto ctx, auto vec) {
751 #ifndef NDEBUG
752 if ((getFEMethod()->data_ctx & ctx).none()) {
753 MOFEM_LOG_CHANNEL("SELF");
754 MOFEM_LOG("SELF", Sev::error)
755 << "In this case field degrees of freedom are read from vector. "
756 "That usually happens when time solver is used, and access to "
757 "first or second rates is needed. You probably not set ts_u, "
758 "ts_u_t, or ts_u_tt and associated data structure, i.e. "
759 "data_ctx to CTX_SET_X, CTX_SET_DX, CTX_SET_X_T, or "
760 "CTX_SET_X_TT respectively";
761 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Vector not set");
762 }
763 #endif
764 CHKERR VecGetArrayRead(vec, &array);
766 };
767
768 auto restore_array = [&](auto vec) {
769 return VecRestoreArrayRead(vec, &array);
770 };
771
772 switch (CTX) {
774 CHKERR get_array(PetscData::CtxSetX, getFEMethod()->ts_u);
775 break;
777 CHKERR get_array(PetscData::CtxSetX, getFEMethod()->dx);
778 break;
780 CHKERR get_array(PetscData::CtxSetX_T, getFEMethod()->ts_u_t);
781 break;
783 CHKERR get_array(PetscData::CtxSetX_TT, getFEMethod()->ts_u_tt);
784 break;
785 default:
786 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
787 "That case is not implemented");
788 }
789
790 dotVector.resize(local_indices.size());
791 for (int i = 0; i != local_indices.size(); ++i)
792 if (local_indices[i] != -1)
793 dotVector[i] = array[local_indices[i]];
794 else
795 dotVector[i] = 0;
796
797 switch (CTX) {
799 CHKERR restore_array(getFEMethod()->ts_u);
800 break;
802 CHKERR restore_array(getFEMethod()->dx);
803 break;
805 CHKERR restore_array(getFEMethod()->ts_u_t);
806 break;
808 CHKERR restore_array(getFEMethod()->ts_u_tt);
809 break;
810 default:
811 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
812 "That case is not implemented");
813 }
814
815 const size_t nb_base_functions = data.getN().size2();
816 auto base_function = data.getFTensor0N();
817 auto values_at_gauss_pts = getFTensor1FromMat<Tensor_Dim>(mat);
818
819 FTensor::Index<'I', Tensor_Dim> I;
820 const size_t size = nb_dofs / Tensor_Dim;
821 if (nb_dofs % Tensor_Dim) {
822 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Data inconsistency");
823 }
824 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
825 auto field_data = getFTensor1FromArray<Tensor_Dim, Tensor_Dim>(dotVector);
826 size_t bb = 0;
827 for (; bb != size; ++bb) {
828 values_at_gauss_pts(I) += field_data(I) * base_function;
829 ++field_data;
830 ++base_function;
831 }
832 // Number of dofs can be smaller than number of Tensor_Dim x base
833 // functions
834 for (; bb < nb_base_functions; ++bb)
835 ++base_function;
836 ++values_at_gauss_pts;
837 }
839 }
840
841protected:
842 boost::shared_ptr<MatrixDouble> dataPtr;
846};
847
848/** \brief Get rate of values at integration pts for tensor field
849 * rank 1, i.e. vector field
850 *
851 * \ingroup mofem_forces_and_sources_user_data_operators
852 */
853template <int Tensor_Dim>
857
858/** \brief Get second rate of values at integration pts for tensor
859 * field rank 1, i.e. vector field
860 *
861 * \ingroup mofem_forces_and_sources_user_data_operators
862 */
863template <int Tensor_Dim>
867
868/** \brief Get second time second update vector at integration pts for tensor
869 * field rank 1, i.e. vector field
870 *
871 * \ingroup mofem_forces_and_sources_user_data_operators
872 */
873template <int Tensor_Dim>
877
878/**@}*/
879
880/** \name Tensor field values at integration points */
881
882/**@{*/
883
884/** \brief Calculate field values for tenor field rank 2.
885 *
886 */
887template <int Tensor_Dim0, int Tensor_Dim1, class T, class L, class A>
890
892 const std::string field_name,
893 boost::shared_ptr<ublas::matrix<T, L, A>> data_ptr,
894 const EntityType zero_type = MBVERTEX)
897 dataPtr(data_ptr), zeroType(zero_type) {
898 if (!dataPtr)
899 THROW_MESSAGE("Pointer is not set");
900 }
901
902 MoFEMErrorCode doWork(int side, EntityType type,
904
905protected:
906 boost::shared_ptr<ublas::matrix<T, L, A>> dataPtr;
908};
909
910template <int Tensor_Dim0, int Tensor_Dim1, class T, class L, class A>
913 doWork(int side, EntityType type, EntitiesFieldData::EntData &data) {
915 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
916 "Not implemented for T = %s, dim0 = %d and dim1 = %d",
917 typeid(T).name(), // boost::core::demangle(typeid(T).name()),
918 Tensor_Dim0, Tensor_Dim1);
920}
921
922template <int Tensor_Dim0, int Tensor_Dim1>
923struct OpCalculateTensor2FieldValues_General<Tensor_Dim0, Tensor_Dim1, double,
924 ublas::row_major, DoubleAllocator>
926
928 const std::string field_name,
929 boost::shared_ptr<
930 ublas::matrix<double, ublas::row_major, DoubleAllocator>>
931 data_ptr,
932 const EntityType zero_type = MBVERTEX)
935 dataPtr(data_ptr), zeroType(zero_type) {
936 if (!dataPtr)
937 THROW_MESSAGE("Pointer is not set");
938 }
939
941 const std::string field_name,
942 boost::shared_ptr<
943 ublas::matrix<double, ublas::row_major, DoubleAllocator>>
944 data_ptr,
945 SmartPetscObj<Vec> data_vec, const EntityType zero_type = MBVERTEX)
948 dataPtr(data_ptr), zeroType(zero_type), dataVec(data_vec) {
949 if (!dataPtr)
950 THROW_MESSAGE("Pointer is not set");
951 }
952
953 MoFEMErrorCode doWork(int side, EntityType type,
955
956protected:
957 boost::shared_ptr<ublas::matrix<double, ublas::row_major, DoubleAllocator>>
962};
963
964template <int Tensor_Dim0, int Tensor_Dim1>
966 Tensor_Dim0, Tensor_Dim1, double, ublas::row_major,
967 DoubleAllocator>::doWork(int side, EntityType type,
970
971 MatrixDouble &mat = *dataPtr;
972 const size_t nb_gauss_pts = data.getN().size1();
973 if (type == zeroType) {
974 mat.resize(Tensor_Dim0 * Tensor_Dim1, nb_gauss_pts, false);
975 mat.clear();
976 }
977
978 const size_t nb_dofs = data.getFieldData().size();
979
980 if (dataVec.use_count()) {
981 dotVector.resize(nb_dofs, false);
982 const double *array;
983 CHKERR VecGetArrayRead(dataVec, &array);
984 const auto &local_indices = data.getLocalIndices();
985 for (int i = 0; i != local_indices.size(); ++i)
986 if (local_indices[i] != -1)
987 dotVector[i] = array[local_indices[i]];
988 else
989 dotVector[i] = 0;
990 CHKERR VecRestoreArrayRead(dataVec, &array);
991 data.getFieldData().swap(dotVector);
992 }
993
994 if (nb_dofs) {
995 const size_t nb_base_functions = data.getN().size2();
996 auto base_function = data.getFTensor0N();
997 auto values_at_gauss_pts =
998 getFTensor2FromMat<Tensor_Dim0, Tensor_Dim1>(mat);
999 FTensor::Index<'i', Tensor_Dim0> i;
1000 FTensor::Index<'j', Tensor_Dim1> j;
1001 const size_t size = nb_dofs / (Tensor_Dim0 * Tensor_Dim1);
1002 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
1003 auto field_data = data.getFTensor2FieldData<Tensor_Dim0, Tensor_Dim1>();
1004 size_t bb = 0;
1005 for (; bb != size; ++bb) {
1006 values_at_gauss_pts(i, j) += field_data(i, j) * base_function;
1007 ++field_data;
1008 ++base_function;
1009 }
1010 for (; bb < nb_base_functions; ++bb)
1011 ++base_function;
1012 ++values_at_gauss_pts;
1013 }
1014
1015 if (dataVec.use_count()) {
1016 data.getFieldData().swap(dotVector);
1017 }
1018 }
1020}
1021
1022/** \brief Get values at integration pts for tensor field rank 2, i.e. matrix
1023 * field
1024 *
1025 * \ingroup mofem_forces_and_sources_user_data_operators
1026 */
1027template <int Tensor_Dim0, int Tensor_Dim1>
1030 Tensor_Dim0, Tensor_Dim1, double, ublas::row_major, DoubleAllocator> {
1031
1033 Tensor_Dim0, Tensor_Dim1, double, ublas::row_major,
1034 DoubleAllocator>::OpCalculateTensor2FieldValues_General;
1035};
1036
1037/** \brief Get time direvarive values at integration pts for tensor field rank
1038 * 2, i.e. matrix field
1039 *
1040 * \ingroup mofem_forces_and_sources_user_data_operators
1041 */
1042template <int Tensor_Dim0, int Tensor_Dim1>
1045
1047 boost::shared_ptr<MatrixDouble> data_ptr,
1048 const EntityType zero_at_type = MBVERTEX)
1051 dataPtr(data_ptr), zeroAtType(zero_at_type) {
1052 if (!dataPtr)
1053 THROW_MESSAGE("Pointer is not set");
1054 }
1055
1056 MoFEMErrorCode doWork(int side, EntityType type,
1059
1060 const size_t nb_gauss_pts = getGaussPts().size2();
1061 MatrixDouble &mat = *dataPtr;
1062 if (type == zeroAtType) {
1063 mat.resize(Tensor_Dim0 * Tensor_Dim1, nb_gauss_pts, false);
1064 mat.clear();
1065 }
1066 const auto &local_indices = data.getLocalIndices();
1067 const size_t nb_dofs = local_indices.size();
1068 if (nb_dofs) {
1069 dotVector.resize(nb_dofs, false);
1070 const double *array;
1071 CHKERR VecGetArrayRead(getFEMethod()->ts_u_t, &array);
1072 for (size_t i = 0; i != local_indices.size(); ++i)
1073 if (local_indices[i] != -1)
1074 dotVector[i] = array[local_indices[i]];
1075 else
1076 dotVector[i] = 0;
1077 CHKERR VecRestoreArrayRead(getFEMethod()->ts_u_t, &array);
1078
1079 const size_t nb_base_functions = data.getN().size2();
1080
1081 auto base_function = data.getFTensor0N();
1082 auto values_at_gauss_pts =
1083 getFTensor2FromMat<Tensor_Dim0, Tensor_Dim1>(mat);
1084 FTensor::Index<'i', Tensor_Dim0> i;
1085 FTensor::Index<'j', Tensor_Dim1> j;
1086 const size_t size = nb_dofs / (Tensor_Dim0 * Tensor_Dim1);
1087 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
1088 auto field_data =
1089 getFTensor2FromPtr<Tensor_Dim0, Tensor_Dim1>(&*dotVector.begin());
1090 size_t bb = 0;
1091 for (; bb != size; ++bb) {
1092 values_at_gauss_pts(i, j) += field_data(i, j) * base_function;
1093 ++field_data;
1094 ++base_function;
1095 }
1096 for (; bb < nb_base_functions; ++bb)
1097 ++base_function;
1098 ++values_at_gauss_pts;
1099 }
1100 }
1102 }
1103
1104protected:
1105 boost::shared_ptr<MatrixDouble> dataPtr; ///< Data computed into this matrix
1106 EntityType zeroAtType; ///< Zero values at Gauss point at this type
1107 VectorDouble dotVector; ///< Keeps temporary values of time derivatives
1108};
1109
1110/**
1111 * @brief Calculate symmetric tensor field values at integration pts.
1112 *
1113 * @tparam Tensor_Dim
1114
1115 * \ingroup mofem_forces_and_sources_user_data_operators
1116 */
1117template <int Tensor_Dim>
1120
1122 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
1123 const EntityType zero_type = MBEDGE, const int zero_side = 0)
1126 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
1127 if (!dataPtr)
1128 THROW_MESSAGE("Pointer is not set");
1129 }
1130
1132 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
1133 SmartPetscObj<Vec> data_vec, const EntityType zero_type = MBEDGE,
1134 const int zero_side = 0)
1137 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side),
1138 dataVec(data_vec) {
1139 if (!dataPtr)
1140 THROW_MESSAGE("Pointer is not set");
1141 }
1142
1143 MoFEMErrorCode doWork(int side, EntityType type,
1146 MatrixDouble &mat = *dataPtr;
1147 const int nb_gauss_pts = getGaussPts().size2();
1148 if (type == this->zeroType && side == zeroSide) {
1149 mat.resize((Tensor_Dim * (Tensor_Dim + 1)) / 2, nb_gauss_pts, false);
1150 mat.clear();
1151 }
1152 const int nb_dofs = data.getFieldData().size();
1153 if (!nb_dofs)
1155
1156 if (dataVec.use_count()) {
1157 dotVector.resize(nb_dofs, false);
1158 const double *array;
1159 CHKERR VecGetArrayRead(dataVec, &array);
1160 const auto &local_indices = data.getLocalIndices();
1161 for (int i = 0; i != local_indices.size(); ++i)
1162 if (local_indices[i] != -1)
1163 dotVector[i] = array[local_indices[i]];
1164 else
1165 dotVector[i] = 0;
1166 CHKERR VecRestoreArrayRead(dataVec, &array);
1167 data.getFieldData().swap(dotVector);
1168 }
1169
1170 const int nb_base_functions = data.getN().size2();
1171 auto base_function = data.getFTensor0N();
1172 auto values_at_gauss_pts = getFTensor2SymmetricFromMat<Tensor_Dim>(mat);
1173 FTensor::Index<'i', Tensor_Dim> i;
1174 FTensor::Index<'j', Tensor_Dim> j;
1175 const int size = nb_dofs / ((Tensor_Dim * (Tensor_Dim + 1)) / 2);
1176 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
1177 auto field_data = data.getFTensor2SymmetricFieldData<Tensor_Dim>();
1178 int bb = 0;
1179 for (; bb != size; ++bb) {
1180 values_at_gauss_pts(i, j) += field_data(i, j) * base_function;
1181 ++field_data;
1182 ++base_function;
1183 }
1184 for (; bb < nb_base_functions; ++bb)
1185 ++base_function;
1186 ++values_at_gauss_pts;
1187 }
1188
1189 if (dataVec.use_count()) {
1190 data.getFieldData().swap(dotVector);
1191 }
1192
1194 }
1195
1196protected:
1197 boost::shared_ptr<MatrixDouble> dataPtr;
1199 const int zeroSide;
1202};
1203
1204/**
1205 * @brief Calculate symmetric tensor field rates ant integratio pts.
1206 *
1207 * @tparam Tensor_Dim
1208 *
1209 * \ingroup mofem_forces_and_sources_user_data_operators
1210 */
1211template <int Tensor_Dim>
1214
1216 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
1217 const EntityType zero_type = MBEDGE, const int zero_side = 0)
1220 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
1221 if (!dataPtr)
1222 THROW_MESSAGE("Pointer is not set");
1223 }
1224
1225 MoFEMErrorCode doWork(int side, EntityType type,
1228 const int nb_gauss_pts = getGaussPts().size2();
1229 MatrixDouble &mat = *dataPtr;
1230 constexpr auto symm_size = (Tensor_Dim * (Tensor_Dim + 1)) / 2;
1231 if (type == zeroType && side == zeroSide) {
1232 mat.resize(symm_size, nb_gauss_pts, false);
1233 mat.clear();
1234 }
1235 auto &local_indices = data.getLocalIndices();
1236 const int nb_dofs = local_indices.size();
1237 if (!nb_dofs)
1239
1240 #ifndef NDEBUG
1241 if ((getFEMethod()->data_ctx & PetscData::CtxSetX_T).none()) {
1242 MOFEM_LOG_CHANNEL("SELF");
1243 MOFEM_LOG("SELF", Sev::error)
1244 << "In this case field degrees of freedom are read from vector. "
1245 "That usually happens when time solver is used, and acces to "
1246 "first rates is needed. You probably not set "
1247 "ts_u_t and associated data structure data_ctx to CTX_SET_X_T "
1248 "respectively";
1249 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Vector not set!");
1250 }
1251 #endif
1252
1253 dotVector.resize(nb_dofs, false);
1254 const double *array;
1255 CHKERR VecGetArrayRead(getFEMethod()->ts_u_t, &array);
1256 for (int i = 0; i != local_indices.size(); ++i)
1257 if (local_indices[i] != -1)
1258 dotVector[i] = array[local_indices[i]];
1259 else
1260 dotVector[i] = 0;
1261 CHKERR VecRestoreArrayRead(getFEMethod()->ts_u_t, &array);
1262
1263 const int nb_base_functions = data.getN().size2();
1264
1265 auto base_function = data.getFTensor0N();
1266 auto values_at_gauss_pts = getFTensor2SymmetricFromMat<Tensor_Dim>(mat);
1267 FTensor::Index<'i', Tensor_Dim> i;
1268 FTensor::Index<'j', Tensor_Dim> j;
1269 const int size = nb_dofs / symm_size;
1270 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
1271 auto field_data = getFTensorDotData<Tensor_Dim>();
1272 int bb = 0;
1273 for (; bb != size; ++bb) {
1274 values_at_gauss_pts(i, j) += field_data(i, j) * base_function;
1275 ++field_data;
1276 ++base_function;
1277 }
1278 for (; bb < nb_base_functions; ++bb)
1279 ++base_function;
1280 ++values_at_gauss_pts;
1281 }
1282
1284 }
1285
1286protected:
1287 boost::shared_ptr<MatrixDouble> dataPtr;
1289 const int zeroSide;
1291
1292 template <int Dim> inline auto getFTensorDotData() {
1293 static_assert(Dim || !Dim, "not implemented");
1294 }
1295};
1296
1297template <>
1298template <>
1299inline auto
1302 &dotVector[0], &dotVector[1], &dotVector[2], &dotVector[3], &dotVector[4],
1303 &dotVector[5]);
1304}
1305
1306template <>
1307template <>
1308inline auto
1311 &dotVector[0], &dotVector[1], &dotVector[2]);
1312}
1313
1314/**@}*/
1315
1316/** \name Gradients and Hessian of scalar fields at integration points */
1317
1318/**@{*/
1319
1320/**
1321 * \brief Evaluate field gradient values for scalar field, i.e. gradient is
1322 * tensor rank 1 (vector)
1323 *
1324 */
1325template <int Tensor_Dim, class T, class L, class A>
1327 : public OpCalculateVectorFieldValues_General<Tensor_Dim, T, L, A> {
1328
1330 Tensor_Dim, T, L, A>::OpCalculateVectorFieldValues_General;
1331};
1332
1333/** \brief Evaluate field gradient values for scalar field, i.e. gradient is
1334 * tensor rank 1 (vector), specialization
1335 *
1336 */
1337template <int Tensor_Dim>
1339 ublas::row_major, DoubleAllocator>
1341 Tensor_Dim, double, ublas::row_major, DoubleAllocator> {
1342
1344 Tensor_Dim, double, ublas::row_major,
1345 DoubleAllocator>::OpCalculateVectorFieldValues_General;
1346
1347 /**
1348 * \brief calculate gradient values of scalar field at integration points
1349 * @param side side entity number
1350 * @param type side entity type
1351 * @param data entity data
1352 * @return error code
1353 */
1354 MoFEMErrorCode doWork(int side, EntityType type,
1356};
1357
1358/**
1359 * \brief Member function specialization calculating scalar field gradients for
1360 * tenor field rank 1
1361 *
1362 */
1363template <int Tensor_Dim>
1365 Tensor_Dim, double, ublas::row_major,
1366 DoubleAllocator>::doWork(int side, EntityType type,
1369
1370 const size_t nb_gauss_pts = this->getGaussPts().size2();
1371 auto &mat = *this->dataPtr;
1372 if (type == this->zeroType) {
1373 mat.resize(Tensor_Dim, nb_gauss_pts, false);
1374 mat.clear();
1375 }
1376
1377 const int nb_dofs = data.getFieldData().size();
1378 if (nb_dofs) {
1379
1380 if (nb_gauss_pts) {
1381 const int nb_base_functions = data.getN().size2();
1382 auto diff_base_function = data.getFTensor1DiffN<Tensor_Dim>();
1383 auto gradients_at_gauss_pts = getFTensor1FromMat<Tensor_Dim>(mat);
1384
1385 #ifndef NDEBUG
1386 if (nb_dofs > nb_base_functions)
1387 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1388 "Number of base functions inconsistent with number of DOFs "
1389 "(%d > %d)",
1390 nb_dofs, nb_base_functions);
1391
1392 if (data.getDiffN().size2() != nb_base_functions * Tensor_Dim)
1393 SETERRQ(
1394 PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1395 "Number of base functions inconsistent with number of derivatives "
1396 "(%lu != %d)",
1397 data.getDiffN().size2(), nb_base_functions);
1398
1399 if (data.getDiffN().size1() != nb_gauss_pts)
1400 SETERRQ(
1401 PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1402 "Number of base functions inconsistent with number of integration "
1403 "pts (%lu != %lu)",
1404 data.getDiffN().size2(), nb_gauss_pts);
1405
1406 #endif
1407
1408 FTensor::Index<'I', Tensor_Dim> I;
1409 for (int gg = 0; gg < nb_gauss_pts; ++gg) {
1410 auto field_data = data.getFTensor0FieldData();
1411 int bb = 0;
1412 for (; bb != nb_dofs; ++bb) {
1413 gradients_at_gauss_pts(I) += field_data * diff_base_function(I);
1414 ++field_data;
1415 ++diff_base_function;
1416 }
1417 // Number of dofs can be smaller than number of base functions
1418 for (; bb < nb_base_functions; ++bb)
1419 ++diff_base_function;
1420 ++gradients_at_gauss_pts;
1421 }
1422 }
1423 }
1424
1426}
1427
1428/** \brief Get field gradients at integration pts for scalar field rank 0, i.e.
1429 * vector field
1430 *
1431 * \ingroup mofem_forces_and_sources_user_data_operators
1432 */
1433template <int Tensor_Dim>
1436 Tensor_Dim, double, ublas::row_major, DoubleAllocator> {
1438 Tensor_Dim, double, ublas::row_major,
1439 DoubleAllocator>::OpCalculateScalarFieldGradient_General;
1440};
1441
1442/** \brief Evaluate field gradient values for scalar field, i.e. gradient is
1443 * tensor rank 1 (vector), specialization
1444 *
1445 */
1446template <int Tensor_Dim>
1449 Tensor_Dim, double, ublas::row_major, DoubleAllocator> {
1450
1452 Tensor_Dim, double, ublas::row_major,
1453 DoubleAllocator>::OpCalculateVectorFieldValues_General;
1454
1455 /**
1456 * \brief calculate gradient values of scalar field at integration points
1457 * @param side side entity number
1458 * @param type side entity type
1459 * @param data entity data
1460 * @return error code
1461 */
1462 MoFEMErrorCode doWork(int side, EntityType type,
1464};
1465
1466template <int Tensor_Dim>
1468 int side, EntityType type, EntitiesFieldData::EntData &data) {
1470
1471 const size_t nb_gauss_pts = this->getGaussPts().size2();
1472 auto &mat = *this->dataPtr;
1473 if (type == this->zeroType) {
1474 mat.resize(Tensor_Dim * Tensor_Dim, nb_gauss_pts, false);
1475 mat.clear();
1476 }
1477
1478 const int nb_dofs = data.getFieldData().size();
1479 if (nb_dofs) {
1480
1481 if (nb_gauss_pts) {
1482 const int nb_base_functions = data.getN().size2();
1483
1484 auto &hessian_base = data.getN(BaseDerivatives::SecondDerivative);
1485 #ifndef NDEBUG
1486 if (hessian_base.size1() != nb_gauss_pts) {
1487 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1488 "Wrong number of integration pts (%ld != %d)",
1489 hessian_base.size1(), nb_gauss_pts);
1490 }
1491 if (hessian_base.size2() != nb_base_functions * Tensor_Dim * Tensor_Dim) {
1492 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1493 "Wrong number of base functions (%ld != %d)",
1494 hessian_base.size2() / (Tensor_Dim * Tensor_Dim),
1495 nb_base_functions);
1496 }
1497 if (hessian_base.size2() < nb_dofs * Tensor_Dim * Tensor_Dim) {
1498 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1499 "Wrong number of base functions (%ld < %d)",
1500 hessian_base.size2(), nb_dofs * Tensor_Dim * Tensor_Dim);
1501 }
1502 #endif
1503
1504 auto t_diff2_base_function = getFTensor2FromPtr<Tensor_Dim, Tensor_Dim>(
1505 &*hessian_base.data().begin());
1506
1507 auto hessian_at_gauss_pts =
1508 getFTensor2FromMat<Tensor_Dim, Tensor_Dim>(mat);
1509
1510 FTensor::Index<'I', Tensor_Dim> I;
1511 FTensor::Index<'J', Tensor_Dim> J;
1512 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
1513 auto field_data = data.getFTensor0FieldData();
1514 int bb = 0;
1515 for (; bb != nb_dofs; ++bb) {
1516 hessian_at_gauss_pts(I, J) +=
1517 field_data * t_diff2_base_function(I, J);
1518 ++field_data;
1519 ++t_diff2_base_function;
1520 }
1521 // Number of dofs can be smaller than number of base functions
1522 for (; bb < nb_base_functions; ++bb) {
1523 ++t_diff2_base_function;
1524 }
1525
1526 ++hessian_at_gauss_pts;
1527 }
1528 }
1529 }
1530
1532}
1533
1534/**}*/
1535
1536/** \name Gradients and hessian of tensor fields at integration points */
1537
1538/**@{*/
1539
1540/**
1541 * \brief Evaluate field gradient values for vector field, i.e. gradient is
1542 * tensor rank 2
1543 *
1544 * \tparam Tensor_Dim0 Dimension of the vector field
1545 * \tparam Tensor_Dim1 Dimension of the gradient (usually spatial dimension)
1546 * \tparam S Storage order for the field data
1547 * \tparam T Data type
1548 * \tparam L Layout type
1549 * \tparam A Allocator type
1550 *
1551 */
1552template <int Tensor_Dim0, int Tensor_Dim1, int S, class T, class L, class A>
1554 : public OpCalculateTensor2FieldValues_General<Tensor_Dim0, Tensor_Dim1, T,
1555 L, A> {
1556
1558 Tensor_Dim0, Tensor_Dim1, T, L, A>::OpCalculateTensor2FieldValues_General;
1559};
1560
1561template <int Tensor_Dim0, int Tensor_Dim1, int S>
1563 Tensor_Dim0, Tensor_Dim1, S, double, ublas::row_major, DoubleAllocator>
1565 Tensor_Dim0, Tensor_Dim1, double, ublas::row_major, DoubleAllocator> {
1566
1568 Tensor_Dim0, Tensor_Dim1, double, ublas::row_major,
1569 DoubleAllocator>::OpCalculateTensor2FieldValues_General;
1570
1571 /**
1572 * \brief calculate values of vector field at integration points
1573 * @param side side entity number
1574 * @param type side entity type
1575 * @param data entity data
1576 * @return error code
1577 */
1578 MoFEMErrorCode doWork(int side, EntityType type,
1580};
1581
1582/**
1583 * \brief Member function specialization calculating vector field gradients for
1584 * tenor field rank 2
1585 *
1586 */
1587template <int Tensor_Dim0, int Tensor_Dim1, int S>
1589 Tensor_Dim0, Tensor_Dim1, S, double, ublas::row_major,
1590 DoubleAllocator>::doWork(int side, EntityType type,
1593 if (!this->dataPtr)
1594 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1595 "Data pointer not allocated");
1596
1597 const size_t nb_gauss_pts = this->getGaussPts().size2();
1598 auto &mat = *this->dataPtr;
1599 if (type == this->zeroType) {
1600 mat.resize(Tensor_Dim0 * Tensor_Dim1, nb_gauss_pts, false);
1601 mat.clear();
1602 }
1603
1604 if (nb_gauss_pts) {
1605 const size_t nb_dofs = data.getFieldData().size();
1606
1607 if (nb_dofs) {
1608
1609 if (this->dataVec.use_count()) {
1610 this->dotVector.resize(nb_dofs, false);
1611 const double *array;
1612 CHKERR VecGetArrayRead(this->dataVec, &array);
1613 const auto &local_indices = data.getLocalIndices();
1614 for (int i = 0; i != local_indices.size(); ++i)
1615 if (local_indices[i] != -1)
1616 this->dotVector[i] = array[local_indices[i]];
1617 else
1618 this->dotVector[i] = 0;
1619 CHKERR VecRestoreArrayRead(this->dataVec, &array);
1620 data.getFieldData().swap(this->dotVector);
1621 }
1622
1623 const int nb_base_functions = data.getN().size2();
1624 auto diff_base_function = data.getFTensor1DiffN<Tensor_Dim1>();
1625 auto gradients_at_gauss_pts =
1626 getFTensor2FromMat<Tensor_Dim0, Tensor_Dim1>(mat);
1627 FTensor::Index<'I', Tensor_Dim0> I;
1628 FTensor::Index<'J', Tensor_Dim1> J;
1629 int size = nb_dofs / Tensor_Dim0;
1630 if (nb_dofs % Tensor_Dim0) {
1631 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1632 "Data inconsistency");
1633 }
1634 for (int gg = 0; gg < nb_gauss_pts; ++gg) {
1635 auto field_data = getFTensor1FromPtr<Tensor_Dim0, S>(
1636 data.getFieldData().data().data());
1637
1638 #ifndef NDEBUG
1639 if (field_data.l2() != field_data.l2()) {
1640 MOFEM_LOG("SELF", Sev::error) << "field data " << field_data;
1641 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1642 "Wrong number in coefficients");
1643 }
1644 #endif
1645
1646 int bb = 0;
1647 for (; bb < size; ++bb) {
1648 #ifndef SINGULARITY
1649 #ifndef NDEBUG
1650 if (diff_base_function.l2() != diff_base_function.l2()) {
1651 MOFEM_LOG("SELF", Sev::error)
1652 << "diff_base_function: " << diff_base_function;
1653 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1654 "Wrong number number in base functions");
1655 }
1656 #endif
1657 #endif
1658
1659 gradients_at_gauss_pts(I, J) += field_data(I) * diff_base_function(J);
1660 ++field_data;
1661 ++diff_base_function;
1662 }
1663 // Number of dofs can be smaller than number of Tensor_Dim0 x base
1664 // functions
1665 for (; bb != nb_base_functions; ++bb)
1666 ++diff_base_function;
1667 ++gradients_at_gauss_pts;
1668 }
1669
1670 if (this->dataVec.use_count()) {
1671 data.getFieldData().swap(this->dotVector);
1672 }
1673 }
1674 }
1676}
1677
1678/** \brief Get field gradients at integration pts for scalar field rank 0, i.e.
1679 * vector field
1680 *
1681 * \tparam Tensor_Dim0 Dimension of the vector field
1682 * \tparam Tensor_Dim1 Dimension of the gradient (usually spatial dimension)
1683 * \tparam S Stride in the storage of the vector field, default is Tensor_Dim0
1684 *
1685 * \ingroup mofem_forces_and_sources_user_data_operators
1686 */
1687template <int Tensor_Dim0, int Tensor_Dim1, int S = Tensor_Dim0>
1689 : public OpCalculateVectorFieldGradient_General<Tensor_Dim0, Tensor_Dim1, S,
1690 double, ublas::row_major,
1691 DoubleAllocator> {
1692
1694 Tensor_Dim0, Tensor_Dim1, S, double, ublas::row_major,
1695 DoubleAllocator>::OpCalculateVectorFieldGradient_General;
1696};
1697
1698/** \brief Get field gradients time derivative at integration pts for scalar
1699 * field rank 0, i.e. vector field
1700 *
1701 * \ingroup mofem_forces_and_sources_user_data_operators
1702 */
1703template <int Tensor_Dim0, int Tensor_Dim1>
1706
1708 boost::shared_ptr<MatrixDouble> data_ptr,
1709 const EntityType zero_at_type = MBVERTEX)
1712 dataPtr(data_ptr), zeroAtType(zero_at_type) {
1713 if (!dataPtr)
1714 THROW_MESSAGE("Pointer is not set");
1715 }
1716
1717 MoFEMErrorCode doWork(int side, EntityType type,
1720
1721 const auto &local_indices = data.getLocalIndices();
1722 const int nb_dofs = local_indices.size();
1723 const int nb_gauss_pts = this->getGaussPts().size2();
1724
1725 auto &mat = *this->dataPtr;
1726 if (type == this->zeroAtType) {
1727 mat.resize(Tensor_Dim0 * Tensor_Dim1, nb_gauss_pts, false);
1728 mat.clear();
1729 }
1730 if (!nb_dofs)
1732
1733 dotVector.resize(nb_dofs, false);
1734 const double *array;
1735 CHKERR VecGetArrayRead(getFEMethod()->ts_u_t, &array);
1736 for (int i = 0; i != local_indices.size(); ++i)
1737 if (local_indices[i] != -1)
1738 dotVector[i] = array[local_indices[i]];
1739 else
1740 dotVector[i] = 0;
1741 CHKERR VecRestoreArrayRead(getFEMethod()->ts_u_t, &array);
1742
1743 const int nb_base_functions = data.getN().size2();
1744 auto diff_base_function = data.getFTensor1DiffN<Tensor_Dim1>();
1745 auto gradients_at_gauss_pts =
1746 getFTensor2FromMat<Tensor_Dim0, Tensor_Dim1>(mat);
1747 FTensor::Index<'I', Tensor_Dim0> I;
1748 FTensor::Index<'J', Tensor_Dim1> J;
1749 int size = nb_dofs / Tensor_Dim0;
1750 if (nb_dofs % Tensor_Dim0) {
1751 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Data inconsistency");
1752 }
1753
1754 for (int gg = 0; gg < nb_gauss_pts; ++gg) {
1755 auto field_data = getFTensor1FromPtr<Tensor_Dim0>(&*dotVector.begin());
1756 int bb = 0;
1757 for (; bb < size; ++bb) {
1758 gradients_at_gauss_pts(I, J) += field_data(I) * diff_base_function(J);
1759 ++field_data;
1760 ++diff_base_function;
1761 }
1762 // Number of dofs can be smaller than number of Tensor_Dim0 x base
1763 // functions
1764 for (; bb != nb_base_functions; ++bb)
1765 ++diff_base_function;
1766 ++gradients_at_gauss_pts;
1767 }
1769 }
1770
1771private:
1772 boost::shared_ptr<MatrixDouble> dataPtr; ///< Data computed into this matrix
1773 EntityType zeroAtType; ///< Zero values at Gauss point at this type
1774 VectorDouble dotVector; ///< Keeps temporary values of time derivatives
1775};
1776
1777/**
1778 * \brief Evaluate field gradient values for symmetric 2nd order tensor field,
1779 * i.e. gradient is tensor rank 3
1780 *
1781 */
1782template <int Tensor_Dim0, int Tensor_Dim1, class T, class L, class A>
1784 : public OpCalculateTensor2FieldValues_General<Tensor_Dim0, Tensor_Dim1, T,
1785 L, A> {
1786
1788 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
1789 const EntityType zero_type = MBVERTEX)
1790 : OpCalculateTensor2FieldValues_General<Tensor_Dim0, Tensor_Dim1, T, L,
1791 A>(field_name, data_ptr,
1792 zero_type) {}
1793};
1794
1795template <int Tensor_Dim0, int Tensor_Dim1>
1797 Tensor_Dim0, Tensor_Dim1, double, ublas::row_major, DoubleAllocator>
1799 Tensor_Dim0, Tensor_Dim1, double, ublas::row_major, DoubleAllocator> {
1800
1802 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
1803 const EntityType zero_type = MBVERTEX)
1804 : OpCalculateTensor2FieldValues_General<Tensor_Dim0, Tensor_Dim1, double,
1805 ublas::row_major,
1807 field_name, data_ptr, zero_type) {}
1808
1809 /**
1810 * \brief calculate values of vector field at integration points
1811 * @param side side entity number
1812 * @param type side entity type
1813 * @param data entity data
1814 * @return error code
1815 */
1816 MoFEMErrorCode doWork(int side, EntityType type,
1818};
1819
1820/**
1821 * \brief Member function specialization calculating tensor field gradients for
1822 * symmetric tensor field rank 2
1823 *
1824 */
1825template <int Tensor_Dim0, int Tensor_Dim1>
1826MoFEMErrorCode OpCalculateTensor2SymmetricFieldGradient_General<
1827 Tensor_Dim0, Tensor_Dim1, double, ublas::row_major,
1828 DoubleAllocator>::doWork(int side, EntityType type,
1831 if (!this->dataPtr)
1832 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1833 "Data pointer not allocated");
1834
1835 const size_t nb_gauss_pts = this->getGaussPts().size2();
1836 constexpr size_t msize = (Tensor_Dim0 * (Tensor_Dim0 + 1)) / 2;
1837 auto &mat = *this->dataPtr;
1838 if (type == this->zeroType) {
1839 mat.resize(msize * Tensor_Dim1, nb_gauss_pts, false);
1840 mat.clear();
1841 }
1842
1843 if (nb_gauss_pts) {
1844 const size_t nb_dofs = data.getFieldData().size();
1845
1846 if (nb_dofs) {
1847
1848 const int nb_base_functions = data.getN().size2();
1849 auto diff_base_function = data.getFTensor1DiffN<Tensor_Dim1>();
1850 auto gradients_at_gauss_pts =
1851 getFTensor3DgFromMat<Tensor_Dim0, Tensor_Dim1>(mat);
1852 FTensor::Index<'I', Tensor_Dim0> I;
1853 FTensor::Index<'J', Tensor_Dim0> J;
1854 FTensor::Index<'K', Tensor_Dim1> K;
1855 int size = nb_dofs / msize;
1856 if (nb_dofs % msize) {
1857 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1858 "Data inconsistency");
1859 }
1860 for (int gg = 0; gg < nb_gauss_pts; ++gg) {
1861 auto field_data = data.getFTensor2SymmetricFieldData<Tensor_Dim0>();
1862 int bb = 0;
1863 for (; bb < size; ++bb) {
1864 gradients_at_gauss_pts(I, J, K) +=
1865 field_data(I, J) * diff_base_function(K);
1866 ++field_data;
1867 ++diff_base_function;
1868 }
1869 // Number of dofs can be smaller than number of Tensor_Dim0 x base
1870 // functions
1871 for (; bb != nb_base_functions; ++bb)
1872 ++diff_base_function;
1873 ++gradients_at_gauss_pts;
1874 }
1875 }
1876 }
1878}
1879
1880/** \brief Get field gradients at integration pts for symmetric tensorial field
1881 * rank 2
1882 *
1883 * \ingroup mofem_forces_and_sources_user_data_operators
1884 */
1885template <int Tensor_Dim0, int Tensor_Dim1>
1888 Tensor_Dim0, Tensor_Dim1, double, ublas::row_major, DoubleAllocator> {
1889
1891 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
1892 const EntityType zero_type = MBVERTEX)
1894 Tensor_Dim0, Tensor_Dim1, double, ublas::row_major,
1895 DoubleAllocator>(field_name, data_ptr, zero_type) {}
1896};
1897
1898template <int Tensor_Dim0, int Tensor_Dim1>
1901 Tensor_Dim0, Tensor_Dim1, double, ublas::row_major, DoubleAllocator> {
1902
1904 Tensor_Dim0, Tensor_Dim1, double, ublas::row_major,
1905 DoubleAllocator>::OpCalculateTensor2FieldValues_General;
1906
1907 /**
1908 * \brief calculate values of vector field at integration points
1909 * @param side side entity number
1910 * @param type side entity type
1911 * @param data entity data
1912 * @return error code
1913 */
1914 MoFEMErrorCode doWork(int side, EntityType type,
1916};
1917
1918/**
1919 * \brief Member function specialization calculating vector field gradients for
1920 * tenor field rank 2
1921 *
1922 */
1923template <int Tensor_Dim0, int Tensor_Dim1>
1925 int side, EntityType type, EntitiesFieldData::EntData &data) {
1927 if (!this->dataPtr)
1928 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1929 "Data pointer not allocated");
1930
1931 const size_t nb_gauss_pts = this->getGaussPts().size2();
1932 auto &mat = *this->dataPtr;
1933 if (type == this->zeroType) {
1934 mat.resize(Tensor_Dim0 * Tensor_Dim1 * Tensor_Dim1, nb_gauss_pts, false);
1935 mat.clear();
1936 }
1937
1938 if (nb_gauss_pts) {
1939 const size_t nb_dofs = data.getFieldData().size();
1940
1941 if (nb_dofs) {
1942
1943 if (this->dataVec.use_count()) {
1944 this->dotVector.resize(nb_dofs, false);
1945 const double *array;
1946 CHKERR VecGetArrayRead(this->dataVec, &array);
1947 const auto &local_indices = data.getLocalIndices();
1948 for (int i = 0; i != local_indices.size(); ++i)
1949 if (local_indices[i] != -1)
1950 this->dotVector[i] = array[local_indices[i]];
1951 else
1952 this->dotVector[i] = 0;
1953 CHKERR VecRestoreArrayRead(this->dataVec, &array);
1954 data.getFieldData().swap(this->dotVector);
1955 }
1956
1957 const int nb_base_functions = data.getN().size2();
1958
1959 auto &hessian_base = data.getN(BaseDerivatives::SecondDerivative);
1960 #ifndef NDEBUG
1961 if (hessian_base.size1() != nb_gauss_pts) {
1962 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1963 "Wrong number of integration pts (%d != %d)",
1964 hessian_base.size1(), nb_gauss_pts);
1965 }
1966 if (hessian_base.size2() !=
1967 nb_base_functions * Tensor_Dim1 * Tensor_Dim1) {
1968 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1969 "Wrong number of base functions (%d != %d)",
1970 hessian_base.size2() / (Tensor_Dim1 * Tensor_Dim1),
1971 nb_base_functions);
1972 }
1973 if (hessian_base.size2() < nb_dofs * Tensor_Dim1 * Tensor_Dim1) {
1974 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1975 "Wrong number of base functions (%d < %d)",
1976 hessian_base.size2(), nb_dofs * Tensor_Dim1 * Tensor_Dim1);
1977 }
1978 #endif
1979
1980 auto t_diff2_base_function = getFTensor2FromPtr<Tensor_Dim1, Tensor_Dim1>(
1981 &*hessian_base.data().begin());
1982
1983 auto t_hessian_at_gauss_pts =
1984 getFTensor3FromMat<Tensor_Dim0, Tensor_Dim1, Tensor_Dim1>(mat);
1985
1986 FTensor::Index<'I', Tensor_Dim0> I;
1987 FTensor::Index<'J', Tensor_Dim1> J;
1988 FTensor::Index<'K', Tensor_Dim1> K;
1989
1990 int size = nb_dofs / Tensor_Dim0;
1991 #ifndef NDEBUG
1992 if (nb_dofs % Tensor_Dim0) {
1993 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1994 "Data inconsistency");
1995 }
1996 #endif
1997
1998 for (int gg = 0; gg < nb_gauss_pts; ++gg) {
1999 auto field_data = data.getFTensor1FieldData<Tensor_Dim0>();
2000 int bb = 0;
2001 for (; bb < size; ++bb) {
2002 t_hessian_at_gauss_pts(I, J, K) +=
2003 field_data(I) * t_diff2_base_function(J, K);
2004 ++field_data;
2005 ++t_diff2_base_function;
2006 }
2007 // Number of dofs can be smaller than number of Tensor_Dim0 x base
2008 // functions
2009 for (; bb != nb_base_functions; ++bb)
2010 ++t_diff2_base_function;
2011 ++t_hessian_at_gauss_pts;
2012 }
2013
2014 if (this->dataVec.use_count()) {
2015 data.getFieldData().swap(this->dotVector);
2016 }
2017 }
2018 }
2020}
2021
2022/**@}*/
2023
2024/** \name Transform tensors and vectors */
2025
2026/**@{*/
2027
2028/**
2029 * @brief Calculate \f$ \pmb\sigma_{ij} = \mathbf{D}_{ijkl} \pmb\varepsilon_{kl}
2030 * \f$
2031 *
2032 * @tparam DIM
2033 *
2034 * \ingroup mofem_forces_and_sources_user_data_operators
2035 */
2036template <int DIM_01, int DIM_23, int S = 0>
2039
2042
2043 /**
2044 * @deprecated Do not use this constructor
2045 */
2048 boost::shared_ptr<MatrixDouble> in_mat,
2049 boost::shared_ptr<MatrixDouble> out_mat,
2050 boost::shared_ptr<MatrixDouble> d_mat)
2051 : UserOp(field_name, OPROW), inMat(in_mat), outMat(out_mat), dMat(d_mat) {
2052 // Only is run for vertices
2053 std::fill(&doEntities[MBEDGE], &doEntities[MBMAXTYPE], false);
2054 if (!inMat)
2055 THROW_MESSAGE("Pointer for in mat is null");
2056 if (!outMat)
2057 THROW_MESSAGE("Pointer for out mat is null");
2058 if (!dMat)
2059 THROW_MESSAGE("Pointer for tensor mat is null");
2060 }
2061
2062 OpTensorTimesSymmetricTensor(boost::shared_ptr<MatrixDouble> in_mat,
2063 boost::shared_ptr<MatrixDouble> out_mat,
2064 boost::shared_ptr<MatrixDouble> d_mat)
2065 : UserOp(NOSPACE, OPSPACE), inMat(in_mat), outMat(out_mat), dMat(d_mat) {
2066 // Only is run for vertices
2067 if (!inMat)
2068 THROW_MESSAGE("Pointer for in mat is null");
2069 if (!outMat)
2070 THROW_MESSAGE("Pointer for out mat is null");
2071 if (!dMat)
2072 THROW_MESSAGE("Pointer for tensor mat is null");
2073 }
2074
2075 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
2077 const size_t nb_gauss_pts = getGaussPts().size2();
2078 auto t_D = getFTensor4DdgFromMat<DIM_01, DIM_23, S>(*(dMat));
2079 auto t_in = getFTensor2SymmetricFromMat<DIM_01>(*(inMat));
2080 outMat->resize((DIM_23 * (DIM_23 + 1)) / 2, nb_gauss_pts, false);
2081 auto t_out = getFTensor2SymmetricFromMat<DIM_23>(*(outMat));
2082 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
2083 t_out(i, j) = t_D(i, j, k, l) * t_in(k, l);
2084 ++t_in;
2085 ++t_out;
2086 }
2088 }
2089
2090private:
2091 FTensor::Index<'i', DIM_01> i;
2092 FTensor::Index<'j', DIM_01> j;
2093 FTensor::Index<'k', DIM_23> k;
2094 FTensor::Index<'l', DIM_23> l;
2095
2096 boost::shared_ptr<MatrixDouble> inMat;
2097 boost::shared_ptr<MatrixDouble> outMat;
2098 boost::shared_ptr<MatrixDouble> dMat;
2099};
2100
2101/**
2102 * @brief Operator for symmetrizing tensor fields
2103 *
2104 * This template structure symmetrizes tensor fields by computing the symmetric
2105 * part of an input tensor and storing the result in an output matrix. It's
2106 * commonly used in mechanics where symmetric tensors (like stress and strain)
2107 * are required.
2108 *
2109 * @tparam DIM Dimension of the tensor field
2110 */
2111template <int DIM>
2113
2116
2117 /**
2118 * @deprecated Do not use this constructor
2119 */
2121 boost::shared_ptr<MatrixDouble> in_mat,
2122 boost::shared_ptr<MatrixDouble> out_mat)
2123 : UserOp(field_name, OPROW), inMat(in_mat), outMat(out_mat) {
2124 // Only is run for vertices
2125 std::fill(&doEntities[MBEDGE], &doEntities[MBMAXTYPE], false);
2126 if (!inMat)
2127 THROW_MESSAGE("Pointer not set for in matrix");
2128 if (!outMat)
2129 THROW_MESSAGE("Pointer not set for in matrix");
2130 }
2131
2132 /**
2133 * @brief Constructor for tensor symmetrization operator
2134 *
2135 * @param in_mat Shared pointer to input matrix containing asymmetric tensor
2136 * @param out_mat Shared pointer to output matrix for storing symmetric tensor
2137 */
2138 OpSymmetrizeTensor(boost::shared_ptr<MatrixDouble> in_mat,
2139 boost::shared_ptr<MatrixDouble> out_mat)
2140 : UserOp(NOSPACE, OPSPACE), inMat(in_mat), outMat(out_mat) {
2141 // Only is run for vertices
2142 if (!inMat)
2143 THROW_MESSAGE("Pointer not set for in matrix");
2144 if (!outMat)
2145 THROW_MESSAGE("Pointer not set for in matrix");
2146 }
2147
2148 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
2150 const size_t nb_gauss_pts = getGaussPts().size2();
2151 auto t_in = getFTensor2FromMat<DIM, DIM>(*(inMat));
2152 outMat->resize((DIM * (DIM + 1)) / 2, nb_gauss_pts, false);
2153 auto t_out = getFTensor2SymmetricFromMat<DIM>(*(outMat));
2154 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
2155 t_out(i, j) = (t_in(i, j) || t_in(j, i)) / 2;
2156 ++t_in;
2157 ++t_out;
2158 }
2160 }
2161
2162private:
2165 boost::shared_ptr<MatrixDouble> inMat;
2166 boost::shared_ptr<MatrixDouble> outMat;
2167};
2168
2169/**
2170 * @brief Operator for scaling matrix values by a scalar factor
2171 *
2172 * This structure performs element-wise scaling of matrix data by multiplying
2173 * all elements by a scalar value. It's useful for applying material properties,
2174 * coordinate transformations, or other scaling operations in finite element
2175 * computations.
2176 */
2178
2181
2182 /**
2183 * @deprecated Do not use this constructor
2184 */
2185 DEPRECATED OpScaleMatrix(const std::string field_name, const double scale,
2186 boost::shared_ptr<MatrixDouble> in_mat,
2187 boost::shared_ptr<MatrixDouble> out_mat)
2188 : UserOp(field_name, OPROW), inMat(in_mat), outMat(out_mat) {
2189 scalePtr = boost::make_shared<double>(scale);
2190 // Only is run for vertices
2191 std::fill(&doEntities[MBEDGE], &doEntities[MBMAXTYPE], false);
2192 if (!inMat)
2193 THROW_MESSAGE("Pointer not set for in matrix");
2194 if (!outMat)
2195 THROW_MESSAGE("Pointer not set for in matrix");
2196 }
2197
2198 /**
2199 * @brief Constructor for matrix scaling operator
2200 *
2201 * @param scale_ptr Shared pointer to scalar value for scaling matrix elements
2202 * @param in_mat Shared pointer to input matrix to be scaled
2203 * @param out_mat Shared pointer to output matrix for storing scaled results
2204 */
2205 OpScaleMatrix(boost::shared_ptr<double> scale_ptr,
2206 boost::shared_ptr<MatrixDouble> in_mat,
2207 boost::shared_ptr<MatrixDouble> out_mat)
2208 : UserOp(NOSPACE, OPSPACE), scalePtr(scale_ptr), inMat(in_mat),
2209 outMat(out_mat) {
2210 if (!scalePtr)
2211 THROW_MESSAGE("Pointer not set for scale");
2212 if (!inMat)
2213 THROW_MESSAGE("Pointer not set for in matrix");
2214 if (!outMat)
2215 THROW_MESSAGE("Pointer not set for in matrix");
2216 }
2217
2218 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
2220 outMat->resize(inMat->size1(), inMat->size2(), false);
2221 noalias(*outMat) = (*scalePtr) * (*inMat);
2223 }
2224
2225private:
2226 boost::shared_ptr<double> scalePtr;
2227 boost::shared_ptr<MatrixDouble> inMat;
2228 boost::shared_ptr<MatrixDouble> outMat;
2229};
2230
2231/**@}*/
2232
2233/** \name H-div/H-curls (Vectorial bases) values at integration points */
2234
2235/**@{*/
2236
2237/** \brief Get vector field for H-div approximation
2238 * \ingroup mofem_forces_and_sources_user_data_operators
2239 */
2240template <int Base_Dim, int Field_Dim, class T, class L, class A>
2242
2243/** \brief Get vector field for H-div approximation
2244 * \ingroup mofem_forces_and_sources_user_data_operators
2245 */
2246template <int Field_Dim>
2248 ublas::row_major, DoubleAllocator>
2250
2252 boost::shared_ptr<MatrixDouble> data_ptr,
2253 SmartPetscObj<Vec> data_vec,
2254 const EntityType zero_type = MBEDGE,
2255 const int zero_side = 0)
2258 dataPtr(data_ptr), dataVec(data_vec), zeroType(zero_type),
2259 zeroSide(zero_side) {
2260 if (!dataPtr)
2261 THROW_MESSAGE("Pointer is not set");
2262 }
2263
2265 boost::shared_ptr<MatrixDouble> data_ptr,
2266 const EntityType zero_type = MBEDGE,
2267 const int zero_side = 0)
2269 field_name, data_ptr, SmartPetscObj<Vec>(), zero_type, zero_side) {}
2270
2271 /**
2272 * \brief Calculate values of vector field at integration points
2273 * @param side side entity number
2274 * @param type side entity type
2275 * @param data entity data
2276 * @return error code
2277 */
2278 MoFEMErrorCode doWork(int side, EntityType type,
2280
2281private:
2282 boost::shared_ptr<MatrixDouble> dataPtr;
2285 const int zeroSide;
2287};
2288
2289template <int Field_Dim>
2291 3, Field_Dim, double, ublas::row_major,
2292 DoubleAllocator>::doWork(int side, EntityType type,
2295 const size_t nb_integration_points = this->getGaussPts().size2();
2296 if (type == zeroType && side == zeroSide) {
2297 dataPtr->resize(Field_Dim, nb_integration_points, false);
2298 dataPtr->clear();
2299 }
2300 const size_t nb_dofs = data.getFieldData().size();
2301 if (!nb_dofs)
2303
2304 if (dataVec.use_count()) {
2305 dotVector.resize(nb_dofs, false);
2306 const double *array;
2307 CHKERR VecGetArrayRead(dataVec, &array);
2308 const auto &local_indices = data.getLocalIndices();
2309 for (int i = 0; i != local_indices.size(); ++i)
2310 if (local_indices[i] != -1)
2311 dotVector[i] = array[local_indices[i]];
2312 else
2313 dotVector[i] = 0;
2314 CHKERR VecRestoreArrayRead(dataVec, &array);
2315 data.getFieldData().swap(dotVector);
2316 }
2317
2318 const size_t nb_base_functions = data.getN().size2() / 3;
2319 FTensor::Index<'i', Field_Dim> i;
2320 auto t_n_hdiv = data.getFTensor1N<3>();
2321 auto t_data = getFTensor1FromMat<Field_Dim>(*dataPtr);
2322 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2323 auto t_dof = data.getFTensor0FieldData();
2324 int bb = 0;
2325 for (; bb != nb_dofs; ++bb) {
2326 t_data(i) += t_n_hdiv(i) * t_dof;
2327 ++t_n_hdiv;
2328 ++t_dof;
2329 }
2330 for (; bb != nb_base_functions; ++bb)
2331 ++t_n_hdiv;
2332 ++t_data;
2333 }
2334
2335 if (dataVec.use_count()) {
2336 data.getFieldData().swap(dotVector);
2337 }
2339}
2340
2341/** \brief Get vector field for H-div approximation
2342 *
2343 * \ingroup mofem_forces_and_sources_user_data_operators
2344 */
2345template <int Base_Dim, int Field_Dim = Base_Dim>
2348 Base_Dim, Field_Dim, double, ublas::row_major, DoubleAllocator> {
2350 Base_Dim, Field_Dim, double, ublas::row_major,
2351 DoubleAllocator>::OpCalculateHVecVectorField_General;
2352};
2353
2354/** \brief Get vector field for H-div approximation
2355 * \ingroup mofem_forces_and_sources_user_data_operators
2356 */
2357template <int Base_Dim, int Field_Dim = Base_Dim>
2359
2360template <int Field_Dim>
2363
2365 boost::shared_ptr<MatrixDouble> data_ptr,
2366 const EntityType zero_type = MBEDGE,
2367 const int zero_side = 0)
2370 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2371 if (!dataPtr)
2372 THROW_MESSAGE("Pointer is not set");
2373 }
2374
2375 /**
2376 * \brief Calculate values of vector field at integration points
2377 * @param side side entity number
2378 * @param type side entity type
2379 * @param data entity data
2380 * @return error code
2381 */
2382 MoFEMErrorCode doWork(int side, EntityType type,
2384
2385private:
2386 boost::shared_ptr<MatrixDouble> dataPtr;
2388 const int zeroSide;
2389};
2390
2391template <int Field_Dim>
2393 int side, EntityType type, EntitiesFieldData::EntData &data) {
2395
2396 const size_t nb_integration_points = this->getGaussPts().size2();
2397 if (type == zeroType && side == zeroSide) {
2398 dataPtr->resize(Field_Dim, nb_integration_points, false);
2399 dataPtr->clear();
2400 }
2401
2402 auto &local_indices = data.getIndices();
2403 const size_t nb_dofs = local_indices.size();
2404 if (nb_dofs) {
2405
2406 std::array<double, MAX_DOFS_ON_ENTITY> dot_dofs_vector;
2407 const double *array;
2408 CHKERR VecGetArrayRead(getFEMethod()->ts_u_t, &array);
2409 for (size_t i = 0; i != nb_dofs; ++i)
2410 if (local_indices[i] != -1)
2411 dot_dofs_vector[i] = array[local_indices[i]];
2412 else
2413 dot_dofs_vector[i] = 0;
2414 CHKERR VecRestoreArrayRead(getFEMethod()->ts_u_t, &array);
2415
2416 const size_t nb_base_functions = data.getN().size2() / 3;
2417 FTensor::Index<'i', Field_Dim> i;
2418 auto t_n_hdiv = data.getFTensor1N<3>();
2419 auto t_data = getFTensor1FromMat<Field_Dim>(*dataPtr);
2420 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2421 int bb = 0;
2422 for (; bb != nb_dofs; ++bb) {
2423 t_data(i) += t_n_hdiv(i) * dot_dofs_vector[bb];
2424 ++t_n_hdiv;
2425 }
2426 for (; bb != nb_base_functions; ++bb)
2427 ++t_n_hdiv;
2428 ++t_data;
2429 }
2430 }
2431
2433}
2434
2435/**
2436 * @brief Calculate divergence of vector field
2437 * @ingroup mofem_forces_and_sources_user_data_operators
2438 *
2439 * @tparam BASE_DIM
2440 * @tparam SPACE_DIM
2441 */
2442template <int BASE_DIM, int SPACE_DIM>
2445
2447 boost::shared_ptr<VectorDouble> data_ptr,
2448 const EntityType zero_type = MBEDGE,
2449 const int zero_side = 0)
2452 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2453 if (!dataPtr)
2454 THROW_MESSAGE("Pointer is not set");
2455 }
2456
2457 MoFEMErrorCode doWork(int side, EntityType type,
2460 const size_t nb_integration_points = getGaussPts().size2();
2461 if (type == zeroType && side == zeroSide) {
2462 dataPtr->resize(nb_integration_points, false);
2463 dataPtr->clear();
2464 }
2465 const size_t nb_dofs = data.getFieldData().size();
2466 if (!nb_dofs)
2468 const size_t nb_base_functions = data.getN().size2() / BASE_DIM;
2471 auto t_n_diff_hdiv = data.getFTensor2DiffN<BASE_DIM, SPACE_DIM>();
2472 auto t_data = getFTensor0FromVec(*dataPtr);
2473 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2474 auto t_dof = data.getFTensor0FieldData();
2475 int bb = 0;
2476 for (; bb != nb_dofs; ++bb) {
2477 t_data += t_dof * t_n_diff_hdiv(j, j);
2478 ++t_n_diff_hdiv;
2479 ++t_dof;
2480 }
2481 for (; bb != nb_base_functions; ++bb)
2482 ++t_n_diff_hdiv;
2483 ++t_data;
2484 }
2486 }
2487
2488private:
2489 boost::shared_ptr<VectorDouble> dataPtr;
2491 const int zeroSide;
2492};
2493
2494/**
2495 * @brief Calculate gradient of vector field
2496 * @ingroup mofem_forces_and_sources_user_data_operators
2497 *
2498 * @tparam BASE_DIM
2499 * @tparam SPACE_DIM
2500 */
2501template <int BASE_DIM, int SPACE_DIM>
2504
2506 boost::shared_ptr<MatrixDouble> data_ptr,
2507 const EntityType zero_type = MBEDGE,
2508 const int zero_side = 0)
2511 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2512 if (!dataPtr)
2513 THROW_MESSAGE("Pointer is not set");
2514 }
2515
2516 MoFEMErrorCode doWork(int side, EntityType type,
2519 const size_t nb_integration_points = getGaussPts().size2();
2520 if (type == zeroType && side == zeroSide) {
2521 dataPtr->resize(BASE_DIM * SPACE_DIM, nb_integration_points, false);
2522 dataPtr->clear();
2523 }
2524 const size_t nb_dofs = data.getFieldData().size();
2525 if (!nb_dofs)
2527 const size_t nb_base_functions = data.getN().size2() / BASE_DIM;
2530 auto t_base_diff = data.getFTensor2DiffN<BASE_DIM, SPACE_DIM>();
2531 auto t_data = getFTensor2FromMat<BASE_DIM, SPACE_DIM>(*dataPtr);
2532 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2533 auto t_dof = data.getFTensor0FieldData();
2534 int bb = 0;
2535 for (; bb != nb_dofs; ++bb) {
2536 t_data(i, j) += t_dof * t_base_diff(i, j);
2537 ++t_base_diff;
2538 ++t_dof;
2539 }
2540 for (; bb != nb_base_functions; ++bb)
2541 ++t_base_diff;
2542 ++t_data;
2543 }
2545 }
2546
2547private:
2548 boost::shared_ptr<MatrixDouble> dataPtr;
2550 const int zeroSide;
2551};
2552
2553/**
2554 * @brief Calculate gradient of tensor field
2555 * @ingroup mofem_forces_and_sources_user_data_operators
2556 *
2557 * @tparam BASE_DIM
2558 * @tparam FIELD_DIM
2559 * @tparam SPACE_DIM
2560 */
2561template <int BASE_DIM, int FIELD_DIM, int SPACE_DIM>
2563
2564/**
2565 * @brief Specialisation for 3D tensor field gradient calculation
2566 * @ingroup mofem_forces_and_sources_user_data_operators
2567 *
2568 */
2569template <>
2572
2574 boost::shared_ptr<MatrixDouble> data_ptr,
2575 const EntityType zero_type = MBEDGE,
2576 const int zero_side = 0)
2579 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2580 if (!dataPtr)
2581 THROW_MESSAGE("Pointer is not set");
2582 }
2583
2584 MoFEMErrorCode doWork(int side, EntityType type,
2587
2588 const size_t nb_integration_points = getGaussPts().size2();
2589 if (type == zeroType && side == zeroSide) {
2590 dataPtr->resize(27, nb_integration_points,
2591 false);
2592 dataPtr->clear();
2593 }
2594
2595 #ifndef NDEBUG
2596 if (data.getFieldData().size() % 3) {
2597 SETERRQ(
2598 PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2599 "Data inconsistency, nb_dofs %% COEFF_DIM != 0, that is %ld %% %d "
2600 "!= 0",
2601 data.getFieldData().size(), 3);
2602 }
2603 #endif
2604
2605 const auto nb_dofs = data.getFieldData().size() / 3;
2606 if (!nb_dofs)
2608
2609 const size_t nb_base_functions = data.getN().size2() / 3;
2610 FTensor::Index<'i', 3> i;
2611 FTensor::Index<'j', 3> j;
2612 FTensor::Index<'k', 3> k;
2613
2614 auto t_base_diff = data.getFTensor2DiffN<3, 3>();
2615 auto t_data = getFTensor3FromMat<3, 3, 3>(*dataPtr);
2616 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2617 auto t_dof = data.getFTensor1FieldData<3>();
2618 int bb = 0;
2619 for (; bb != nb_dofs; ++bb) {
2620 t_data(k, i, j) += t_base_diff(i, j) * t_dof(k);
2621 ++t_base_diff;
2622 ++t_dof;
2623 }
2624 for (; bb != nb_base_functions; ++bb)
2625 ++t_base_diff;
2626 ++t_data;
2627 }
2629 }
2630
2631private:
2632 boost::shared_ptr<MatrixDouble> dataPtr;
2634 const int zeroSide;
2635};
2636
2637template <>
2640
2642 boost::shared_ptr<MatrixDouble> data_ptr,
2643 const EntityType zero_type = MBEDGE,
2644 const int zero_side = 0)
2647 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2648 if (!dataPtr)
2649 THROW_MESSAGE("Pointer is not set");
2650 }
2651
2652 MoFEMErrorCode doWork(int side, EntityType type,
2655
2656 const size_t nb_integration_points = getGaussPts().size2();
2657 if (type == zeroType && side == zeroSide) {
2658 dataPtr->resize(27, nb_integration_points, false);
2659 dataPtr->clear();
2660 }
2661
2662 const auto nb_dofs = data.getFieldData().size();
2663 if (!nb_dofs)
2665
2666 const size_t nb_base_functions = data.getN().size2() / 9;
2667
2668 #ifndef NDEBUG
2669 if (data.getDiffN().size1() != nb_integration_points) {
2670 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2671 "Wrong number of integration pts (%ld != %ld)",
2672 data.getDiffN().size1(), nb_integration_points);
2673 }
2674 if (data.getDiffN().size2() != nb_base_functions * 27) {
2675 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2676 "Wrong number of base functions (%ld != %ld)",
2677 data.getDiffN().size2() / 27, nb_base_functions);
2678 }
2679 if (nb_base_functions < nb_dofs) {
2680 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2681 "Wrong number of base functions (%ld < %ld)", nb_base_functions,
2682 nb_dofs);
2683 }
2684 #endif
2685
2686 FTensor::Index<'i', 3> i;
2687 FTensor::Index<'j', 3> j;
2688 FTensor::Index<'k', 3> k;
2689
2690 auto t_base_diff = data.getFTensor3DiffN<3, 3, 3>();
2691 auto t_data = getFTensor3FromMat<3, 3, 3>(*dataPtr);
2692 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2693 auto t_dof = data.getFTensor0FieldData();
2694 int bb = 0;
2695 for (; bb != nb_dofs; ++bb) {
2696 t_data(k, i, j) += t_base_diff(k, i, j) * t_dof;
2697 ++t_base_diff;
2698 ++t_dof;
2699 }
2700 for (; bb != nb_base_functions; ++bb)
2701 ++t_base_diff;
2702 ++t_data;
2703 }
2704
2705
2707 }
2708
2709private:
2710 boost::shared_ptr<MatrixDouble> dataPtr;
2712 const int zeroSide;
2713};
2714
2715/**
2716 * @brief Calculate gradient of vector field
2717 * @ingroup mofem_forces_and_sources_user_data_operators
2718 *
2719 * @tparam BASE_DIM
2720 * @tparam SPACE_DIM
2721 */
2722template <int BASE_DIM, int SPACE_DIM>
2725
2727 boost::shared_ptr<MatrixDouble> data_ptr,
2728 const EntityType zero_type = MBEDGE,
2729 const int zero_side = 0)
2732 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2733 if (!dataPtr)
2734 THROW_MESSAGE("Pointer is not set");
2735 }
2736
2737 MoFEMErrorCode doWork(int side, EntityType type,
2740 const size_t nb_integration_points = getGaussPts().size2();
2741 if (type == zeroType && side == zeroSide) {
2742 dataPtr->resize(BASE_DIM * SPACE_DIM * SPACE_DIM, nb_integration_points,
2743 false);
2744 dataPtr->clear();
2745 }
2746 const size_t nb_dofs = data.getFieldData().size();
2747 if (!nb_dofs)
2749
2750 const int nb_base_functions = data.getN().size2() / BASE_DIM;
2751
2752 #ifndef NDEBUG
2753 auto &hessian_base = data.getN(BaseDerivatives::SecondDerivative);
2754 if (hessian_base.size1() != nb_integration_points) {
2755 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2756 "Wrong number of integration pts (%d != %d)",
2757 hessian_base.size1(), nb_integration_points);
2758 }
2759 if (hessian_base.size2() !=
2760 BASE_DIM * nb_base_functions * SPACE_DIM * SPACE_DIM) {
2761 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2762 "Wrong number of base functions (%d != %d)",
2763 hessian_base.size2() / (BASE_DIM * SPACE_DIM * SPACE_DIM),
2764 nb_base_functions);
2765 }
2766 if (hessian_base.size2() < BASE_DIM * nb_dofs * SPACE_DIM * SPACE_DIM) {
2767 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2768 "Wrong number of base functions (%d < %d)", hessian_base.size2(),
2769 BASE_DIM * nb_dofs * SPACE_DIM * SPACE_DIM);
2770 }
2771 #endif
2772
2776
2777 auto t_base_diff2 =
2779 auto t_data = getFTensor3FromMat<BASE_DIM, SPACE_DIM, SPACE_DIM>(*dataPtr);
2780 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2781 auto t_dof = data.getFTensor0FieldData();
2782 int bb = 0;
2783 for (; bb != nb_dofs; ++bb) {
2784 t_data(i, j, k) += t_dof * t_base_diff2(i, j, k);
2785
2786 ++t_base_diff2;
2787 ++t_dof;
2788 }
2789 for (; bb != nb_base_functions; ++bb)
2790 ++t_base_diff2;
2791 ++t_data;
2792 }
2794 }
2795
2796private:
2797 boost::shared_ptr<MatrixDouble> dataPtr;
2799 const int zeroSide;
2800};
2801
2802/**
2803 * @brief Calculate divergence of vector field dot
2804 * @ingroup mofem_forces_and_sources_user_data_operators
2805 *
2806 * @tparam Tensor_Dim dimension of space
2807 */
2808template <int Tensor_Dim1, int Tensor_Dim2>
2811
2813 boost::shared_ptr<VectorDouble> data_ptr,
2814 const EntityType zero_type = MBEDGE,
2815 const int zero_side = 0)
2818 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2819 if (!dataPtr)
2820 THROW_MESSAGE("Pointer is not set");
2821 }
2822
2823 MoFEMErrorCode doWork(int side, EntityType type,
2826 const size_t nb_integration_points = getGaussPts().size2();
2827 if (type == zeroType && side == zeroSide) {
2828 dataPtr->resize(nb_integration_points, false);
2829 dataPtr->clear();
2830 }
2831
2832 const auto &local_indices = data.getLocalIndices();
2833 const int nb_dofs = local_indices.size();
2834 if (nb_dofs) {
2835
2836 std::array<double, MAX_DOFS_ON_ENTITY> dot_dofs_vector;
2837 const double *array;
2838 CHKERR VecGetArrayRead(getFEMethod()->ts_u_t, &array);
2839 for (size_t i = 0; i != local_indices.size(); ++i)
2840 if (local_indices[i] != -1)
2841 dot_dofs_vector[i] = array[local_indices[i]];
2842 else
2843 dot_dofs_vector[i] = 0;
2844 CHKERR VecRestoreArrayRead(getFEMethod()->ts_u_t, &array);
2845
2846 const size_t nb_base_functions = data.getN().size2() / Tensor_Dim1;
2847 FTensor::Index<'i', Tensor_Dim1> i;
2848 auto t_n_diff_hdiv = data.getFTensor2DiffN<Tensor_Dim1, Tensor_Dim2>();
2849 auto t_data = getFTensor0FromVec(*dataPtr);
2850 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2851 int bb = 0;
2852 for (; bb != nb_dofs; ++bb) {
2853 double div = 0;
2854 for (auto ii = 0; ii != Tensor_Dim2; ++ii)
2855 div += t_n_diff_hdiv(ii, ii);
2856 t_data += dot_dofs_vector[bb] * div;
2857 ++t_n_diff_hdiv;
2858 }
2859 for (; bb != nb_base_functions; ++bb)
2860 ++t_n_diff_hdiv;
2861 ++t_data;
2862 }
2863 }
2865 }
2866
2867private:
2868 boost::shared_ptr<VectorDouble> dataPtr;
2870 const int zeroSide;
2871};
2872
2873/**
2874 * @brief Calculate curl of vector field
2875 * @ingroup mofem_forces_and_sources_user_data_operators
2876 *
2877 * @tparam Base_Dim base function dimension
2878 * @tparam Space_Dim dimension of space
2879 * @tparam Hcurl field dimension
2880 */
2881template <int Base_Dim, int Space_Dim> struct OpCalculateHcurlVectorCurl;
2882
2883/**
2884 * @brief Calculate curl of vector field
2885 * @ingroup mofem_forces_and_sources_user_data_operators
2886 *
2887 * @tparam Base_Dim base function dimension
2888 * @tparam Space_Dim dimension of space
2889 * @tparam Hcurl field dimension
2890 */
2891template <>
2894 OpCalculateHcurlVectorCurl(const std::string field_name,
2895 boost::shared_ptr<MatrixDouble> data_ptr,
2896 const EntityType zero_type = MBEDGE,
2897 const int zero_side = 0);
2898 MoFEMErrorCode doWork(int side, EntityType type,
2900
2901private:
2902 boost::shared_ptr<MatrixDouble> dataPtr;
2904 const int zeroSide;
2905};
2906
2907/**
2908 * @brief Calculate curl of vector field
2909 * @ingroup mofem_forces_and_sources_user_data_operators
2910 *
2911 * @tparam Field_Dim dimension of field
2912 * @tparam Space_Dim dimension of space
2913 */
2914template <>
2917
2918 OpCalculateHcurlVectorCurl(const std::string field_name,
2919 boost::shared_ptr<MatrixDouble> data_ptr,
2920 const EntityType zero_type = MBVERTEX,
2921 const int zero_side = 0);
2922
2923 MoFEMErrorCode doWork(int side, EntityType type,
2925
2926private:
2927 boost::shared_ptr<MatrixDouble> dataPtr;
2929 const int zeroSide;
2930};
2931
2932/**
2933 * @brief Calculate curl of vector field
2934 * @ingroup mofem_forces_and_sources_user_data_operators
2935 *
2936 * @tparam Field_Dim dimension of field
2937 * @tparam Space_Dim dimension of space
2938 */
2939template <>
2942
2943 OpCalculateHcurlVectorCurl(const std::string field_name,
2944 boost::shared_ptr<MatrixDouble> data_ptr,
2945 const EntityType zero_type = MBVERTEX,
2946 const int zero_side = 0);
2947
2948 MoFEMErrorCode doWork(int side, EntityType type,
2950
2951private:
2952 boost::shared_ptr<MatrixDouble> dataPtr;
2954 const int zeroSide;
2955};
2956
2957/**
2958 * @brief Calculate tenor field using vectorial base, i.e. Hdiv/Hcurl
2959 * \ingroup mofem_forces_and_sources_user_data_operators
2960 *
2961 * @tparam Tensor_Dim0 rank of the field
2962 * @tparam Tensor_Dim1 dimension of space
2963 */
2964template <int Tensor_Dim0, int Tensor_Dim1>
2967
2969 boost::shared_ptr<MatrixDouble> data_ptr,
2970 boost::shared_ptr<double> scale_ptr,
2972 const EntityType zero_type = MBEDGE,
2973 const int zero_side = 0)
2976 dataPtr(data_ptr), scalePtr(scale_ptr), dataVec(data_vec),
2977 zeroType(zero_type), zeroSide(zero_side) {
2978 if (!dataPtr)
2979 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Pointer is not set");
2980 }
2981
2983 boost::shared_ptr<MatrixDouble> data_ptr,
2984 const EntityType zero_type = MBEDGE,
2985 const int zero_side = 0)
2986 : OpCalculateHVecTensorField(field_name, data_ptr, nullptr,
2987 SmartPetscObj<Vec>(), zero_type, zero_side) {
2988 }
2989
2990 MoFEMErrorCode doWork(int side, EntityType type,
2993 const size_t nb_integration_points = getGaussPts().size2();
2994 if (type == zeroType && side == zeroSide) {
2995 dataPtr->resize(Tensor_Dim0 * Tensor_Dim1, nb_integration_points, false);
2996 dataPtr->clear();
2997 }
2998 const size_t nb_dofs = data.getFieldData().size();
2999 if (nb_dofs) {
3000
3001 if (dataVec.use_count()) {
3002 dotVector.resize(nb_dofs, false);
3003 const double *array;
3004 CHKERR VecGetArrayRead(dataVec, &array);
3005 const auto &local_indices = data.getLocalIndices();
3006 for (int i = 0; i != local_indices.size(); ++i)
3007 if (local_indices[i] != -1)
3008 dotVector[i] = array[local_indices[i]];
3009 else
3010 dotVector[i] = 0;
3011 CHKERR VecRestoreArrayRead(dataVec, &array);
3012 data.getFieldData().swap(dotVector);
3013 }
3014
3015 double scale = (scalePtr) ? *scalePtr : 1.0;
3016 const size_t nb_base_functions = data.getN().size2() / 3;
3017 FTensor::Index<'i', Tensor_Dim0> i;
3018 FTensor::Index<'j', Tensor_Dim1> j;
3019 auto t_n_hvec = data.getFTensor1N<3>();
3020 auto t_data = getFTensor2FromMat<Tensor_Dim0, Tensor_Dim1>(*dataPtr);
3021 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3022 auto t_dof = data.getFTensor1FieldData<Tensor_Dim0>();
3023 size_t bb = 0;
3024 for (; bb != nb_dofs / Tensor_Dim0; ++bb) {
3025 t_data(i, j) += (scale * t_dof(i)) * t_n_hvec(j);
3026 ++t_n_hvec;
3027 ++t_dof;
3028 }
3029 for (; bb < nb_base_functions; ++bb)
3030 ++t_n_hvec;
3031 ++t_data;
3032 }
3033
3034 if (dataVec.use_count()) {
3035 data.getFieldData().swap(dotVector);
3036 }
3037 }
3039 }
3040
3041private:
3042 boost::shared_ptr<MatrixDouble> dataPtr;
3043 boost::shared_ptr<double> scalePtr;
3046 const int zeroSide;
3047 VectorDouble dotVector; ///< Keeps temporary values of time derivatives
3048};
3049
3050/** \brief Get tensor field for H-div approximation
3051 * \ingroup mofem_forces_and_sources_user_data_operators
3052 *
3053 * \warning This operator is not tested
3054 */
3055template <int Tensor_Dim0, int Tensor_Dim1>
3058
3060
3062 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
3063 SmartPetscObj<Vec> data_vec, EntityType broken_type,
3064 boost::shared_ptr<Range> broken_range_ptr = nullptr,
3065 boost::shared_ptr<double> scale_ptr = nullptr,
3066 const EntityType zero_type = MBEDGE, const int zero_side = 0)
3068 dataPtr(data_ptr), dataVec(data_vec), brokenType(broken_type),
3069 brokenRangePtr(broken_range_ptr), zeroType(zero_type) {
3070 if (!dataPtr)
3071 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Pointer is not set");
3072 }
3073
3074 /**
3075 * \brief Calculate values of vector field at integration points
3076 * @param side side entity number
3077 * @param type side entity type
3078 * @param data entity data
3079 * @return error code
3080 */
3081 MoFEMErrorCode doWork(int side, EntityType type,
3083
3084private:
3085 boost::shared_ptr<MatrixDouble> dataPtr;
3087 EntityType brokenType;
3088 boost::shared_ptr<Range> brokenRangePtr;
3089 boost::shared_ptr<double> scalePtr;
3092};
3093
3094template <int Tensor_Dim0, int Tensor_Dim1>
3097 int side, EntityType type, EntitiesFieldData::EntData &data) {
3099 const size_t nb_integration_points = OP::getGaussPts().size2();
3100 if (type == zeroType) {
3101 dataPtr->resize(Tensor_Dim0 * Tensor_Dim1, nb_integration_points, false);
3102 dataPtr->clear();
3103 }
3104 const size_t nb_dofs = data.getFieldData().size();
3105 if (!nb_dofs)
3107
3108 if (dataVec.use_count()) {
3109 dotVector.resize(nb_dofs, false);
3110 const double *array;
3111 CHKERR VecGetArrayRead(dataVec, &array);
3112 const auto &local_indices = data.getLocalIndices();
3113 for (int i = 0; i != local_indices.size(); ++i)
3114 if (local_indices[i] != -1)
3115 dotVector[i] = array[local_indices[i]];
3116 else
3117 dotVector[i] = 0;
3118 CHKERR VecRestoreArrayRead(dataVec, &array);
3119 data.getFieldData().swap(dotVector);
3120 }
3121
3122 /**
3123 * @brief Get side face dofs
3124 *
3125 * Find which base functions on borken space have adjacent given entity type
3126 * and are in the range ptr if given.
3127 *
3128 */
3129 auto get_get_side_face_dofs = [&]() {
3130 auto fe_type = OP::getFEType();
3131
3132 BaseFunction::DofsSideMap &side_dof_map =
3133 data.getFieldEntities()[0]->getDofSideMap().at(fe_type);
3134 std::vector<int> side_face_dofs;
3135 side_face_dofs.reserve(data.getIndices().size() / Tensor_Dim0);
3136
3137 for (
3138
3139 auto it = side_dof_map.get<1>().begin();
3140 it != side_dof_map.get<1>().end(); ++it
3141
3142 ) {
3143 if ((Tensor_Dim0 * it->dof) >= data.getIndices().size()) {
3144 break;
3145 }
3146 if (it->type == brokenType) {
3147 if (brokenRangePtr) {
3148 auto ent = OP::getSideEntity(it->side, brokenType);
3149 if (brokenRangePtr->find(ent) != brokenRangePtr->end()) {
3150 side_face_dofs.push_back(it->dof);
3151 }
3152 } else {
3153 side_face_dofs.push_back(it->dof);
3154 }
3155 }
3156 }
3157
3158 return side_face_dofs;
3159 };
3160
3161 auto side_face_dofs = get_get_side_face_dofs();
3162
3163 FTensor::Index<'i', Tensor_Dim0> i;
3164 FTensor::Index<'j', Tensor_Dim1> j;
3165 auto t_data = getFTensor2FromMat<Tensor_Dim0, Tensor_Dim1>(*dataPtr);
3166 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3167 for (auto b : side_face_dofs) {
3168 auto t_row_base = data.getFTensor1N<3>(gg, b);
3169 auto t_dof = getFTensor1FromPtr<Tensor_Dim0>(data.getFieldData().data() +
3170 b * Tensor_Dim0);
3171 t_data(i, j) += t_dof(i) * t_row_base(j);
3172 }
3173 ++t_data;
3174 }
3175 *dataPtr *= (scalePtr) ? *scalePtr : 1.0;
3176
3177 if (dataVec.use_count()) {
3178 data.getFieldData().swap(dotVector);
3179 }
3180
3182}
3183
3184/**
3185 * @brief Calculate tenor field using tensor base, i.e. Hdiv/Hcurl
3186 * \ingroup mofem_forces_and_sources_user_data_operators
3187 *
3188 * @tparam Tensor_Dim0 rank of the field
3189 * @tparam Tensor_Dim1 dimension of space
3190 */
3191template <int Tensor_Dim0, int Tensor_Dim1>
3194
3196 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
3197 boost::shared_ptr<double> scale_ptr,
3199 const EntityType zero_type = MBEDGE, const int zero_side = 0)
3202 dataPtr(data_ptr), scalePtr(scale_ptr), dataVec(data_vec),
3203 zeroType(zero_type), zeroSide(zero_side) {
3204 if (!dataPtr)
3205 THROW_MESSAGE("Pointer is not set");
3206 }
3207
3209 boost::shared_ptr<MatrixDouble> data_ptr,
3210 const EntityType zero_type = MBEDGE,
3211 const int zero_side = 0)
3212 : OpCalculateHTensorTensorField(field_name, data_ptr, nullptr,
3213 SmartPetscObj<Vec>(), zero_type,
3214 zero_side) {}
3215
3216 MoFEMErrorCode doWork(int side, EntityType type,
3219 const size_t nb_integration_points = getGaussPts().size2();
3220 if (type == zeroType && side == zeroSide) {
3221 dataPtr->resize(Tensor_Dim0 * Tensor_Dim1, nb_integration_points, false);
3222 dataPtr->clear();
3223 }
3224 const size_t nb_dofs = data.getFieldData().size();
3225 if (!nb_dofs)
3227
3228 if (dataVec.use_count()) {
3229 dotVector.resize(nb_dofs, false);
3230 const double *array;
3231 CHKERR VecGetArrayRead(dataVec, &array);
3232 const auto &local_indices = data.getLocalIndices();
3233 for (int i = 0; i != local_indices.size(); ++i)
3234 if (local_indices[i] != -1)
3235 dotVector[i] = array[local_indices[i]];
3236 else
3237 dotVector[i] = 0;
3238 CHKERR VecRestoreArrayRead(dataVec, &array);
3239 data.getFieldData().swap(dotVector);
3240 }
3241
3242 double scale = (scalePtr) ? *scalePtr : 1.0;
3243 const size_t nb_base_functions =
3244 data.getN().size2() / (Tensor_Dim0 * Tensor_Dim1);
3245 FTensor::Index<'i', Tensor_Dim0> i;
3246 FTensor::Index<'j', Tensor_Dim1> j;
3247 auto t_n_hten = data.getFTensor2N<Tensor_Dim0, Tensor_Dim1>();
3248 auto t_data = getFTensor2FromMat<Tensor_Dim0, Tensor_Dim1>(*dataPtr);
3249 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3250 auto t_dof = data.getFTensor0FieldData();
3251 size_t bb = 0;
3252 for (; bb != nb_dofs; ++bb) {
3253 t_data(i, j) += (scale * t_dof) * t_n_hten(i, j);
3254 ++t_n_hten;
3255 ++t_dof;
3256 }
3257 for (; bb < nb_base_functions; ++bb)
3258 ++t_n_hten;
3259 ++t_data;
3260 }
3261
3262 if (dataVec.use_count()) {
3263 data.getFieldData().swap(dotVector);
3264 }
3265
3267 }
3268
3269private:
3270 boost::shared_ptr<MatrixDouble> dataPtr;
3271 boost::shared_ptr<double> scalePtr;
3274 const int zeroSide;
3275 VectorDouble dotVector; ///< Keeps temporary values of time derivatives
3276};
3277
3278/**
3279 * @brief Calculate divergence of tonsorial field using vectorial base
3280 * \ingroup mofem_forces_and_sources_user_data_operators
3281 *
3282 * @tparam Tensor_Dim0 rank of the field
3283 * @tparam Tensor_Dim1 dimension of space
3284 */
3285template <int Tensor_Dim0, int Tensor_Dim1,
3286 CoordinateTypes CoordSys = CARTESIAN>
3289
3291 boost::shared_ptr<MatrixDouble> data_ptr,
3292 SmartPetscObj<Vec> data_vec,
3293 const EntityType zero_type = MBEDGE,
3294 const int zero_side = 0)
3297 dataPtr(data_ptr), dataVec(data_vec), zeroType(zero_type),
3298 zeroSide(zero_side) {
3299 if (!dataPtr)
3300 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Pointer is not set");
3301 }
3302
3304 boost::shared_ptr<MatrixDouble> data_ptr,
3305 const EntityType zero_type = MBEDGE,
3306 const int zero_side = 0)
3308 field_name, data_ptr, SmartPetscObj<Vec>(), zero_type, zero_side) {}
3309
3310 MoFEMErrorCode doWork(int side, EntityType type,
3313 const size_t nb_integration_points = getGaussPts().size2();
3314 if (type == zeroType && side == zeroSide) {
3315 dataPtr->resize(Tensor_Dim0, nb_integration_points, false);
3316 dataPtr->clear();
3317 }
3318 const size_t nb_dofs = data.getFieldData().size();
3319 if (nb_dofs) {
3320
3321 if (dataVec.use_count()) {
3322 dotVector.resize(nb_dofs, false);
3323 const double *array;
3324 CHKERR VecGetArrayRead(dataVec, &array);
3325 const auto &local_indices = data.getLocalIndices();
3326 for (int i = 0; i != local_indices.size(); ++i)
3327 if (local_indices[i] != -1)
3328 dotVector[i] = array[local_indices[i]];
3329 else
3330 dotVector[i] = 0;
3331 CHKERR VecRestoreArrayRead(dataVec, &array);
3332 data.getFieldData().swap(dotVector);
3333 }
3334
3335 const size_t nb_base_functions = data.getN().size2() / 3;
3336 FTensor::Index<'i', Tensor_Dim0> i;
3337 FTensor::Index<'j', Tensor_Dim1> j;
3338 auto t_n_diff_hvec = data.getFTensor2DiffN<3, Tensor_Dim1>();
3339 auto t_data = getFTensor1FromMat<Tensor_Dim0>(*dataPtr);
3340 auto t_base = data.getFTensor1N<3>();
3341 auto t_coords = getFTensor1CoordsAtGaussPts();
3342 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3343 auto t_dof = data.getFTensor1FieldData<Tensor_Dim0>();
3344 size_t bb = 0;
3345 for (; bb != nb_dofs / Tensor_Dim0; ++bb) {
3346 double div = t_n_diff_hvec(j, j);
3347 t_data(i) += t_dof(i) * div;
3348 if constexpr (CoordSys == CYLINDRICAL) {
3349 t_data(i) += t_base(0) * (t_dof(i) / t_coords(0));
3350 }
3351 ++t_n_diff_hvec;
3352 ++t_dof;
3353 ++t_base;
3354 }
3355 for (; bb < nb_base_functions; ++bb) {
3356 ++t_base;
3357 ++t_n_diff_hvec;
3358 }
3359 ++t_data;
3360 ++t_coords;
3361 }
3362
3363 if (dataVec.use_count()) {
3364 data.getFieldData().swap(dotVector);
3365 }
3366 }
3368 }
3369
3370private:
3371 boost::shared_ptr<MatrixDouble> dataPtr;
3374 const int zeroSide;
3375
3376 VectorDouble dotVector; ///< Keeps temporary values of time derivatives
3377};
3378
3379/**
3380 * @brief Calculate divergence of tonsorial field using vectorial base
3381 * \ingroup mofem_forces_and_sources_user_data_operators
3382 *
3383 * \warning This operator is not tested
3384 *
3385 * @tparam Tensor_Dim0 rank of the field
3386 * @tparam Tensor_Dim1 dimension of space
3387 */
3388template <int Tensor_Dim0, int Tensor_Dim1,
3389 CoordinateTypes CoordSys = CARTESIAN>
3392
3394
3396 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
3397 SmartPetscObj<Vec> data_vec, EntityType broken_type,
3398 boost::shared_ptr<Range> broken_range_ptr = nullptr,
3399 boost::shared_ptr<double> scale_ptr = nullptr,
3400 const EntityType zero_type = MBEDGE)
3402 dataPtr(data_ptr), dataVec(data_vec), brokenType(broken_type),
3403 brokenRangePtr(broken_range_ptr), scalePtr(scale_ptr),
3404 zeroType(zero_type) {
3405 if (!dataPtr)
3406 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Pointer is not set");
3407 }
3408
3409 MoFEMErrorCode doWork(int side, EntityType type,
3412 const size_t nb_integration_points = getGaussPts().size2();
3413 if (type == zeroType && side == 0) {
3414 dataPtr->resize(Tensor_Dim0, nb_integration_points, false);
3415 dataPtr->clear();
3416 }
3417
3418 const size_t nb_dofs = data.getFieldData().size();
3419 if (nb_dofs) {
3420
3421 if (dataVec.use_count()) {
3422 dotVector.resize(nb_dofs, false);
3423 const double *array;
3424 CHKERR VecGetArrayRead(dataVec, &array);
3425 const auto &local_indices = data.getLocalIndices();
3426 for (int i = 0; i != local_indices.size(); ++i)
3427 if (local_indices[i] != -1)
3428 dotVector[i] = array[local_indices[i]];
3429 else
3430 dotVector[i] = 0;
3431 CHKERR VecRestoreArrayRead(dataVec, &array);
3432 data.getFieldData().swap(dotVector);
3433 }
3434
3435 /**
3436 * @brief Get side face dofs
3437 *
3438 * Find which base functions on borken space have adjacent given entity
3439 * type and are in the range ptr if given.
3440 *
3441 */
3442 auto get_get_side_face_dofs = [&]() {
3443 auto fe_type = OP::getFEType();
3444
3445 BaseFunction::DofsSideMap &side_dof_map =
3446 data.getFieldEntities()[0]->getDofSideMap().at(fe_type);
3447 std::vector<int> side_face_dofs;
3448 side_face_dofs.reserve(data.getIndices().size() / Tensor_Dim0);
3449
3450 for (
3451
3452 auto it = side_dof_map.get<1>().begin();
3453 it != side_dof_map.get<1>().end(); ++it
3454
3455 ) {
3456 if ((Tensor_Dim0 * it->dof) >= data.getIndices().size()) {
3457 break;
3458 }
3459 if (it->type == brokenType) {
3460 if (brokenRangePtr) {
3461 auto ent = OP::getSideEntity(it->side, brokenType);
3462 if (brokenRangePtr->find(ent) != brokenRangePtr->end()) {
3463 side_face_dofs.push_back(it->dof);
3464 }
3465 } else {
3466 side_face_dofs.push_back(it->dof);
3467 }
3468 }
3469 }
3470
3471 return side_face_dofs;
3472 };
3473
3474 auto side_face_dofs = get_get_side_face_dofs();
3475
3476 FTensor::Index<'i', Tensor_Dim0> i;
3477 FTensor::Index<'j', Tensor_Dim1> j;
3478 auto t_data = getFTensor1FromMat<Tensor_Dim0>(*dataPtr);
3479 auto t_coords = getFTensor1CoordsAtGaussPts();
3480 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3481 for (auto b : side_face_dofs) {
3482 auto t_dof = getFTensor1FromPtr<Tensor_Dim0>(
3483 data.getFieldData().data() + b * Tensor_Dim0);
3484 auto t_base = data.getFTensor1N<3>(gg, b);
3485 auto t_diff_base = data.getFTensor2DiffN<3, Tensor_Dim1>(gg, b);
3486 double div = t_diff_base(j, j);
3487 t_data(i) += t_dof(i) * div;
3488 if constexpr (CoordSys == CYLINDRICAL) {
3489 t_data(i) += t_base(0) * (t_dof(i) / t_coords(0));
3490 }
3491 }
3492 ++t_data;
3493 ++t_coords;
3494 }
3495 }
3496
3497 if (dataVec.use_count()) {
3498 data.getFieldData().swap(dotVector);
3499 }
3500
3502 }
3503
3504private:
3505 boost::shared_ptr<MatrixDouble> dataPtr;
3507 EntityType brokenType;
3508 boost::shared_ptr<Range> brokenRangePtr;
3509 boost::shared_ptr<double> scalePtr;
3512};
3513
3514/**
3515 * @brief Calculate trace of vector (Hdiv/Hcurl) space
3516 *
3517 * @tparam Tensor_Dim
3518 * @tparam OpBase
3519 */
3520template <int Tensor_Dim, typename OpBase>
3522
3524 boost::shared_ptr<MatrixDouble> data_ptr,
3525 boost::shared_ptr<double> scale_ptr,
3526 const EntityType zero_type = MBEDGE,
3527 const int zero_side = 0)
3528 : OpBase(field_name, OpBase::OPROW), dataPtr(data_ptr),
3529 scalePtr(scale_ptr), zeroType(zero_type), zeroSide(zero_side) {
3530 if (!dataPtr)
3531 THROW_MESSAGE("Pointer is not set");
3532 }
3533
3535 boost::shared_ptr<MatrixDouble> data_ptr,
3536 const EntityType zero_type = MBEDGE,
3537 const int zero_side = 0)
3538 : OpCalculateHVecTensorTrace(field_name, data_ptr, nullptr, zero_type,
3539 zero_side) {}
3540
3541 MoFEMErrorCode doWork(int side, EntityType type,
3544 const size_t nb_integration_points = OpBase::getGaussPts().size2();
3545 if (type == zeroType && side == 0) {
3546 dataPtr->resize(Tensor_Dim, nb_integration_points, false);
3547 dataPtr->clear();
3548 }
3549 const size_t nb_dofs = data.getFieldData().size();
3550 if (nb_dofs) {
3551 double scale_val = (scalePtr) ? *scalePtr : 1.0;
3552 auto t_normal = OpBase::getFTensor1NormalsAtGaussPts();
3553 const size_t nb_base_functions = data.getN().size2() / 3;
3554 auto t_base = data.getFTensor1N<3>();
3555 auto t_data = getFTensor1FromMat<Tensor_Dim>(*dataPtr);
3556 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3557 FTensor::Tensor1<double, Tensor_Dim> t_normalized_normal;
3558 t_normalized_normal(j) = t_normal(j);
3559 t_normalized_normal.normalize();
3560 auto t_dof = data.getFTensor1FieldData<Tensor_Dim>();
3561 size_t bb = 0;
3562 for (; bb != nb_dofs / Tensor_Dim; ++bb) {
3563 t_data(i) +=
3564 (scale_val * t_dof(i)) * (t_base(j) * t_normalized_normal(j));
3565 ++t_base;
3566 ++t_dof;
3567 }
3568 for (; bb < nb_base_functions; ++bb) {
3569 ++t_base;
3570 }
3571 ++t_data;
3572 ++t_normal;
3573 }
3574 }
3576 }
3577
3578private:
3579 boost::shared_ptr<MatrixDouble> dataPtr;
3580 boost::shared_ptr<double> scalePtr;
3582 const int zeroSide;
3583 FTensor::Index<'i', Tensor_Dim> i;
3584 FTensor::Index<'j', Tensor_Dim> j;
3585};
3586
3587/**@}*/
3588
3589/** \name Other operators */
3590
3591/**@{*/
3592
3593/**@}*/
3594
3595/** \name Operators for faces */
3596
3597/**@{*/
3598
3599/** \brief Transform local reference derivatives of shape functions to global
3600derivatives
3601
3602\ingroup mofem_forces_and_sources_tri_element
3603
3604*/
3605template <int DIM, int DERIVATIVE = 1> struct OpSetInvJacSpaceForFaceImpl;
3606
3609
3611 boost::shared_ptr<MatrixDouble> inv_jac_ptr);
3612
3613protected:
3614
3615 /**
3616 * @brief Apply transformation to the input matrix
3617 *
3618 * @tparam D1 dimension of the derivative of base functions in input
3619 * @tparam D2 dimension of the derivative of base functions in output
3620 * @tparam J1 nb of rows in jacobian (= dimension of space)
3621 * @tparam J2 nb of columns in jacobian (= dimension of reference element)
3622 * @param diff_n
3623 * @return MoFEMErrorCode
3624 */
3625 template <int D1, int D2, int J1, int J2>
3628
3629 static_assert(D2 == J2, "Dimension of jacobian and dimension of <out> "
3630 "directive does not match");
3631
3632 size_t nb_functions = diff_n.size2() / D1;
3633 if (nb_functions) {
3634 size_t nb_gauss_pts = diff_n.size1();
3635
3636 #ifndef NDEBUG
3637 if (nb_gauss_pts != getGaussPts().size2())
3638 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3639 "Wrong number of Gauss Pts");
3640 if (diff_n.size2() % D1)
3641 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3642 "Number of directives of base functions and D1 dimension does "
3643 "not match");
3644 #endif
3645
3646 diffNinvJac.resize(diff_n.size1(), D2 * nb_functions, false);
3647
3648 FTensor::Index<'i', D2> i;
3649 FTensor::Index<'k', D1> k;
3650 auto t_diff_n = getFTensor1FromPtr<D2>(&*diffNinvJac.data().begin());
3651 auto t_diff_n_ref = getFTensor1FromPtr<D1>(&*diff_n.data().begin());
3652 auto t_inv_jac = getFTensor2FromMat<J1, J2>(*invJacPtr);
3653 for (size_t gg = 0; gg != nb_gauss_pts; ++gg, ++t_inv_jac) {
3654 for (size_t dd = 0; dd != nb_functions; ++dd) {
3655 t_diff_n(i) = t_inv_jac(k, i) * t_diff_n_ref(k);
3656 ++t_diff_n;
3657 ++t_diff_n_ref;
3658 }
3659 }
3660
3661 diff_n.swap(diffNinvJac);
3662 }
3664 }
3665
3666 boost::shared_ptr<MatrixDouble> invJacPtr;
3668};
3669
3670template <>
3673
3675
3676 MoFEMErrorCode doWork(int side, EntityType type,
3678};
3679
3680template <>
3682 : public OpSetInvJacSpaceForFaceImpl<2, 1> {
3683
3684 using OpSetInvJacSpaceForFaceImpl<2, 1>::OpSetInvJacSpaceForFaceImpl;
3685
3686 MoFEMErrorCode doWork(int side, EntityType type,
3688};
3689
3690template <>
3692 : public OpSetInvJacSpaceForFaceImpl<2, 1> {
3693
3694 using OpSetInvJacSpaceForFaceImpl<2, 1>::OpSetInvJacSpaceForFaceImpl;
3695
3696 MoFEMErrorCode doWork(int side, EntityType type,
3698};
3699
3700template <int DERIVARIVE = 1>
3702 : public OpSetInvJacSpaceForFaceImpl<2, DERIVARIVE> {
3703 OpSetInvJacH1ForFace(boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3704 : OpSetInvJacSpaceForFaceImpl<2, DERIVARIVE>(H1, inv_jac_ptr) {}
3705};
3706
3707template <int DERIVARIVE = 1>
3709 : public OpSetInvJacSpaceForFaceImpl<2, DERIVARIVE> {
3710 OpSetInvJacL2ForFace(boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3711 : OpSetInvJacSpaceForFaceImpl<2, DERIVARIVE>(L2, inv_jac_ptr) {}
3712};
3713
3714template <int DERIVARIVE = 1>
3716 : public OpSetInvJacSpaceForFaceImpl<3, DERIVARIVE> {
3718 boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3719 : OpSetInvJacSpaceForFaceImpl<3, DERIVARIVE>(H1, inv_jac_ptr) {}
3720};
3721
3722template <int DERIVARIVE = 1>
3724 : public OpSetInvJacSpaceForFaceImpl<3, DERIVARIVE> {
3726 boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3727 : OpSetInvJacSpaceForFaceImpl<3, DERIVARIVE>(L2, inv_jac_ptr) {}
3728};
3729
3730/**
3731 * \brief Transform local reference derivatives of shape function to
3732 global derivatives for face
3733
3734 * \ingroup mofem_forces_and_sources_tri_element
3735 */
3736template <int DIM> struct OpSetInvJacHcurlFaceImpl;
3737
3738template <>
3741
3742 OpSetInvJacHcurlFaceImpl(boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3744 invJacPtr(inv_jac_ptr) {}
3745
3746 MoFEMErrorCode doWork(int side, EntityType type,
3748
3749protected:
3750 boost::shared_ptr<MatrixDouble> invJacPtr;
3752};
3753
3754template <>
3756 using OpSetInvJacHcurlFaceImpl<2>::OpSetInvJacHcurlFaceImpl;
3757 MoFEMErrorCode doWork(int side, EntityType type,
3759};
3760
3763
3764/**
3765 * @brief Make Hdiv space from Hcurl space in 2d
3766 * @ingroup mofem_forces_and_sources_tri_element
3767 */
3777
3778/** \brief Transform Hcurl base fluxes from reference element to physical
3779 * triangle
3780 */
3782
3783/** \brief Apply contravariant (Piola) transfer to Hdiv space on face
3784 *
3785 * Covariant Piola transformation
3786 \f[
3787 \psi_i|_t = J^{-1}_{ij}\hat{\psi}_j\\
3788 \left.\frac{\partial \psi_i}{\partial \xi_j}\right|_t
3789 = J^{-1}_{ik}\frac{\partial \hat{\psi}_k}{\partial \xi_j}
3790 \f]
3791
3792 */
3793template <>
3796
3798 boost::shared_ptr<MatrixDouble> inv_jac_ptr);
3799
3800 MoFEMErrorCode doWork(int side, EntityType type,
3802
3803private:
3804 boost::shared_ptr<MatrixDouble> invJacPtr;
3805
3808};
3809
3812
3813/** \brief Apply contravariant (Piola) transfer to Hdiv space on face
3814 *
3815 * \note Hdiv space is generated by Hcurl space in 2d.
3816 *
3817 * Contravariant Piola transformation
3818 * \f[
3819 * \psi_i|_t = \frac{1}{\textrm{det}(J)}J_{ij}\hat{\psi}_j\\
3820 * \left.\frac{\partial \psi_i}{\partial \xi_j}\right|_t
3821 * =
3822 * \frac{1}{\textrm{det}(J)}J_{ik}\frac{\partial \hat{\psi}_k}{\partial \xi_j}
3823 * \f]
3824 *
3825 * \ingroup mofem_forces_and_sources
3826 *
3827 */
3829
3830template <>
3833
3835 boost::shared_ptr<MatrixDouble> jac_ptr)
3837 jacPtr(jac_ptr) {}
3838
3839 MoFEMErrorCode doWork(int side, EntityType type,
3841
3842protected:
3843 boost::shared_ptr<MatrixDouble> jacPtr;
3846};
3847
3848template <>
3852 2>::OpSetContravariantPiolaTransformOnFace2DImpl;
3853
3854 MoFEMErrorCode doWork(int side, EntityType type,
3856};
3857
3862
3863/**@}*/
3864
3865/** \name Operators for edges */
3866
3867/**@{*/
3868
3878
3879/**
3880 * @deprecated Name is deprecated and this is added for backward compatibility
3881 */
3884
3885/**@}*/
3886
3887/** \name Operator for fat prisms */
3888
3889/**@{*/
3890
3891/**
3892 * @brief Operator for fat prism element updating integration weights in the
3893 * volume.
3894 *
3895 * Jacobian on the distorted element is nonconstant. This operator updates
3896 * integration weight on prism to take into account nonconstat jacobian.
3897 *
3898 * \f[
3899 * W_i = w_i \left( \frac{1}{2V} \left\| \frac{\partial \mathbf{x}}{\partial
3900 * \pmb\xi} \right\| \right)
3901 * \f]
3902 * where \f$w_i\f$ is integration weight at integration point \f$i\f$,
3903 * \f$\mathbf{x}\f$ is physical coordinate, and \f$\pmb\xi\f$ is reference
3904 * element coordinate.
3905 *
3906 */
3916
3917/** \brief Calculate inverse of jacobian for face element
3918
3919 It is assumed that face element is XY plane. Applied
3920 only for 2d problems.
3921
3922 FIXME Generalize function for arbitrary face orientation in 3d space
3923 FIXME Calculate to Jacobins for two faces
3924
3925 \ingroup mofem_forces_and_sources_prism_element
3926
3927*/
3930
3931 OpCalculateInvJacForFatPrism(boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3933 invJacPtr(inv_jac_ptr), invJac(*invJacPtr) {}
3934
3938 MoFEMErrorCode doWork(int side, EntityType type,
3940
3941private:
3942 const boost::shared_ptr<MatrixDouble> invJacPtr;
3944};
3945
3946/** \brief Transform local reference derivatives of shape functions to global
3947derivatives
3948
3949FIXME Generalize to curved shapes
3950FIXME Generalize to case that top and bottom face has different shape
3951
3952\ingroup mofem_forces_and_sources_prism_element
3953
3954*/
3957
3958 OpSetInvJacH1ForFatPrism(boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3960 invJacPtr(inv_jac_ptr), invJac(*invJacPtr) {}
3961
3965
3966 MoFEMErrorCode doWork(int side, EntityType type,
3968
3969private:
3970 const boost::shared_ptr<MatrixDouble> invJacPtr;
3973};
3974
3975// Flat prism
3976
3977/** \brief Calculate inverse of jacobian for face element
3978
3979 It is assumed that face element is XY plane. Applied
3980 only for 2d problems.
3981
3982 FIXME Generalize function for arbitrary face orientation in 3d space
3983 FIXME Calculate to Jacobins for two faces
3984
3985 \ingroup mofem_forces_and_sources_prism_element
3986
3987*/
4000
4001/** \brief Transform local reference derivatives of shape functions to global
4002derivatives
4003
4004FIXME Generalize to curved shapes
4005FIXME Generalize to case that top and bottom face has different shape
4006
4007\ingroup mofem_forces_and_sources_prism_element
4008
4009*/
4024
4025/**@}*/
4026
4027/** \name Operation on matrices at integration points */
4028
4029/**@{*/
4030
4031/**
4032 * @brief Operator for inverting matrices at integration points
4033 *
4034 * This template structure computes the inverse of square matrices and their
4035 * determinants at integration points. It's commonly used in finite element
4036 * methods for coordinate transformations, constitutive relations, and other
4037 * matrix operations requiring matrix inversion.
4038 *
4039 * @tparam DIM Dimension of the square matrix to be inverted
4040 */
4041template <int DIM>
4043
4044 /**
4045 * @brief Constructor for matrix inversion operator
4046 *
4047 * @param in_ptr Shared pointer to input matrix to be inverted
4048 * @param det_ptr Shared pointer to vector for storing matrix determinants
4049 * @param out_ptr Shared pointer to output matrix for storing inverted matrices
4050 */
4051 OpInvertMatrix(boost::shared_ptr<MatrixDouble> in_ptr,
4052 boost::shared_ptr<VectorDouble> det_ptr,
4053 boost::shared_ptr<MatrixDouble> out_ptr)
4055 outPtr(out_ptr), detPtr(det_ptr) {}
4056
4057 MoFEMErrorCode doWork(int side, EntityType type,
4059
4060private:
4061 boost::shared_ptr<MatrixDouble> inPtr;
4062 boost::shared_ptr<MatrixDouble> outPtr;
4063 boost::shared_ptr<VectorDouble> detPtr;
4064};
4065
4066template <int DIM>
4070
4071 if (!inPtr)
4072 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4073 "Pointer for inPtr matrix not allocated");
4074 if (!detPtr)
4075 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4076 "Pointer for detPtr matrix not allocated");
4077
4078 const auto nb_rows = inPtr->size1();
4079 const auto nb_integration_pts = inPtr->size2();
4080
4081 // Calculate determinant
4082 {
4083 detPtr->resize(nb_integration_pts, false);
4084 auto t_in = getFTensor2FromMat<DIM, DIM>(*inPtr);
4085 auto t_det = getFTensor0FromVec(*detPtr);
4086 for (size_t gg = 0; gg != nb_integration_pts; ++gg) {
4087 t_det = determinantTensor(t_in);
4088 ++t_in;
4089 ++t_det;
4090 }
4091 }
4092
4093 // Invert jacobian
4094 if (outPtr) {
4095 outPtr->resize(nb_rows, nb_integration_pts, false);
4096 auto t_in = getFTensor2FromMat<DIM, DIM>(*inPtr);
4097 auto t_out = getFTensor2FromMat<DIM, DIM>(*outPtr);
4098 auto t_det = getFTensor0FromVec(*detPtr);
4099 for (size_t gg = 0; gg != nb_integration_pts; ++gg) {
4100 CHKERR invertTensor(t_in, t_det, t_out);
4101 ++t_in;
4102 ++t_out;
4103 ++t_det;
4104 }
4105 }
4106
4108}
4109
4110/**@}*/
4111
4112/**
4113 * @brief Operator for calculating the trace of matrices at integration points
4114 *
4115 * This template structure computes the trace (sum of diagonal elements) of
4116 * square matrices at integration points. The trace is commonly used in
4117 * mechanics for calculating volumetric strain, pressure, and other scalar
4118 * quantities derived from tensors.
4119 *
4120 * @tparam DIM Dimension of the square matrix
4121 *
4122 * @ingroup mofem_forces_and_sources
4123 */
4124template <int DIM>
4126
4127 /**
4128 * @brief Constructor for matrix trace calculation operator
4129 *
4130 * @param in_ptr Shared pointer to input matrix for trace calculation
4131 * @param out_ptr Shared pointer to output vector for storing calculated traces
4132 */
4133 OpCalculateTraceFromMat(boost::shared_ptr<MatrixDouble> in_ptr,
4134 boost::shared_ptr<VectorDouble> out_ptr)
4136 outPtr(out_ptr) {}
4137
4138 MoFEMErrorCode doWork(int side, EntityType type,
4140
4141private:
4143 boost::shared_ptr<MatrixDouble> inPtr;
4144 boost::shared_ptr<VectorDouble> outPtr;
4145};
4146
4147template <int DIM>
4152
4153 if (!inPtr)
4154 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4155 "Pointer for inPtr matrix not allocated");
4156
4157 const auto nb_integration_pts = inPtr->size2();
4158 // Invert jacobian
4159 if (outPtr) {
4160 outPtr->resize(nb_integration_pts, false);
4161 auto t_in = getFTensor2FromMat<DIM, DIM>(*inPtr);
4162 auto t_out = getFTensor0FromVec(*outPtr);
4163
4164 for (size_t gg = 0; gg != nb_integration_pts; ++gg) {
4165 t_out = t_in(i, i);
4166 ++t_in;
4167 ++t_out;
4168 }
4169 }
4170
4172}
4173
4174/**@}*/
4175
4176/** \brief Calculates the trace of an input matrix
4177
4178\ingroup mofem_forces_and_sources
4179
4180*/
4181
4182template <int DIM>
4185
4186 OpCalculateTraceFromSymmMat(boost::shared_ptr<MatrixDouble> in_ptr,
4187 boost::shared_ptr<VectorDouble> out_ptr)
4189 outPtr(out_ptr) {}
4190
4191 MoFEMErrorCode doWork(int side, EntityType type,
4193
4194private:
4196 boost::shared_ptr<MatrixDouble> inPtr;
4197 boost::shared_ptr<VectorDouble> outPtr;
4198};
4199
4200template <int DIM>
4205
4206 if (!inPtr)
4207 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4208 "Pointer for inPtr matrix not allocated");
4209
4210 const auto nb_integration_pts = inPtr->size2();
4211 // Invert jacobian
4212 if (outPtr) {
4213 outPtr->resize(nb_integration_pts, false);
4214 auto t_in = getFTensor2SymmetricFromMat<DIM>(*inPtr);
4215 auto t_out = getFTensor0FromVec(*outPtr);
4216
4217 for (size_t gg = 0; gg != nb_integration_pts; ++gg) {
4218 t_out = t_in(i, i);
4219 ++t_in;
4220 ++t_out;
4221 }
4222 }
4223
4225}
4226
4227} // namespace MoFEM
4228
4229#endif // __USER_DATA_OPERATORS_HPP__
4230
4231/**
4232 * \defgroup mofem_forces_and_sources_user_data_operators Users Operators
4233 *
4234 * \brief Classes and functions used to evaluate fields at integration pts,
4235 *jacobians, etc..
4236 *
4237 * \ingroup mofem_forces_and_sources
4238 **/
constexpr int SPACE_DIM
Tensor1< T, Tensor_Dim > normalize()
static const char *const CoordinateTypesNames[]
Coordinate system names.
#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
#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
CoordinateTypes
Coodinate system.
@ CYLINDRICAL
@ POLAR
@ CARTESIAN
@ SPHERICAL
#define DEPRECATED
Definition definitions.h:17
#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 ...
#define THROW_MESSAGE(msg)
Throw MoFEM exception.
constexpr int BASE_DIM
#define MOFEM_LOG(channel, severity)
Log.
#define MOFEM_LOG_CHANNEL(channel)
Set and reset channel.
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'J', DIM1 > J
Definition level_set.cpp:30
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
VecAllocator< double > DoubleAllocator
Definition Types.hpp:62
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
static MoFEMErrorCode invertTensor(FTensor::Tensor2< T1, DIM, DIM > &t, T2 &det, FTensor::Tensor2< T3, DIM, DIM > &inv_t)
static auto determinantTensor(FTensor::Tensor2< T, DIM, DIM > &t)
Calculate the determinant of a tensor of rank DIM.
static auto getFTensor0FromVec(ublas::vector< T, A > &data)
Get tensor rank 0 (scalar) form data vector.
OpCalculateScalarFieldValuesFromPetscVecImpl< PetscData::CTX_SET_X_T > OpCalculateScalarFieldValuesDot
constexpr IntegrationType I
constexpr AssemblyType A
constexpr auto field_name
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.
std::array< bool, MBMAXTYPE > doEntities
If true operator is executed for entity.
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.
FTensor::Tensor2< FTensor::PackPtr< double *, Tensor_Dim0 *Tensor_Dim1 >, Tensor_Dim0, Tensor_Dim1 > getFTensor2N(FieldApproximationBase base)
Get base functions for Hdiv/Hcurl spaces.
FTensor::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0N(const FieldApproximationBase base)
Get base function as Tensor0.
MatrixDouble & getDiffN(const FieldApproximationBase base)
get derivatives of base functions
const VectorFieldEntities & getFieldEntities() const
Get field entities (const version)
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.
FTensor::Tensor3< FTensor::PackPtr< double *, Tensor_Dim0 *Tensor_Dim1 *Tensor_Dim2 >, Tensor_Dim0, Tensor_Dim1, Tensor_Dim2 > getFTensor3Diff2N(FieldApproximationBase base)
Get second derivatives of base functions for Hvec space.
const VectorInt & getLocalIndices() const
Get local indices of degrees of freedom on entity.
FTensor::Tensor1< FTensor::PackPtr< double *, Tensor_Dim >, Tensor_Dim > getFTensor1FieldData()
Return FTensor of rank 1, i.e. vector from field data coefficients.
FTensor::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0FieldData()
Return scalar files as a FTensor of rank 0.
FTensor::Tensor1< FTensor::PackPtr< double *, Tensor_Dim >, Tensor_Dim > getFTensor1N(FieldApproximationBase base)
Get base functions for Hdiv/Hcurl spaces.
FTensor::Tensor2_symmetric< FTensor::PackPtr< double *,(Tensor_Dim *(Tensor_Dim+1))/2 >, Tensor_Dim > getFTensor2SymmetricFieldData()
Return symmetric FTensor rank 2, i.e. matrix from field data coefficients.
FTensor::Tensor2< FTensor::PackPtr< double *, Tensor_Dim0 *Tensor_Dim1 >, Tensor_Dim0, Tensor_Dim1 > getFTensor2FieldData()
Return FTensor rank 2, i.e. matrix from field data coefficients.
const VectorInt & getIndices() const
Get global indices of degrees of freedom on entity.
FTensor::Tensor3< FTensor::PackPtr< double *, Tensor_Dim0 *Tensor_Dim1 *Tensor_Dim2 >, Tensor_Dim0, Tensor_Dim1, Tensor_Dim2 > getFTensor3DiffN(FieldApproximationBase base)
Get derivatives of base functions for tonsorial Hdiv space.
EntityType getFEType() const
Get dimension of finite element.
auto getFTensor1CoordsAtGaussPts()
Get coordinates at integration points assuming linear geometry.
EntityHandle getSideEntity(const int side_number, const EntityType type)
Get the side entity.
@ OPROW
operator doWork function is executed on FE rows
@ OPSPACE
operator do Work is execute on space data
const FEMethod * getFEMethod() const
Return raw pointer to Finite Element Method object.
MatrixDouble & getGaussPts()
matrix of integration (Gauss) points for Volume Element
structure to get information from mofem into EntitiesFieldData
Calculate divergence of tonsorial field using vectorial base.
OpCalculateBrokenHVecTensorDivergence(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, SmartPetscObj< Vec > data_vec, EntityType broken_type, boost::shared_ptr< Range > broken_range_ptr=nullptr, boost::shared_ptr< double > scale_ptr=nullptr, const EntityType zero_type=MBEDGE)
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Get tensor field for H-div approximation.
boost::shared_ptr< MatrixDouble > dataPtr
OpCalculateBrokenHVecTensorField(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, SmartPetscObj< Vec > data_vec, EntityType broken_type, boost::shared_ptr< Range > broken_range_ptr=nullptr, boost::shared_ptr< double > scale_ptr=nullptr, const EntityType zero_type=MBEDGE, const int zero_side=0)
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Calculate values of vector field at integration points.
Calculate divergence of vector field at integration points.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpCalculateDivergenceVectorFieldValues(const std::string field_name, boost::shared_ptr< VectorDouble > data_ptr, const EntityType zero_type=MBVERTEX)
Constructor for vector field divergence calculation operator.
Calculate tenor field using tensor base, i.e. Hdiv/Hcurl.
VectorDouble dotVector
Keeps temporary values of time derivatives.
OpCalculateHTensorTensorField(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, boost::shared_ptr< double > scale_ptr, SmartPetscObj< Vec > data_vec=SmartPetscObj< Vec >(), const EntityType zero_type=MBEDGE, const int zero_side=0)
boost::shared_ptr< MatrixDouble > dataPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpCalculateHTensorTensorField(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_type=MBEDGE, const int zero_side=0)
Calculate divergence of tonsorial field using vectorial base.
boost::shared_ptr< MatrixDouble > dataPtr
VectorDouble dotVector
Keeps temporary values of time derivatives.
OpCalculateHVecTensorDivergence(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, SmartPetscObj< Vec > data_vec, const EntityType zero_type=MBEDGE, const int zero_side=0)
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpCalculateHVecTensorDivergence(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_type=MBEDGE, const int zero_side=0)
Calculate tenor field using vectorial base, i.e. Hdiv/Hcurl.
OpCalculateHVecTensorField(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, boost::shared_ptr< double > scale_ptr, SmartPetscObj< Vec > data_vec=SmartPetscObj< Vec >(), const EntityType zero_type=MBEDGE, const int zero_side=0)
boost::shared_ptr< MatrixDouble > dataPtr
OpCalculateHVecTensorField(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_type=MBEDGE, const int zero_side=0)
VectorDouble dotVector
Keeps temporary values of time derivatives.
boost::shared_ptr< double > scalePtr
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.
OpCalculateHVecTensorGradient(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_type=MBEDGE, const int zero_side=0)
OpCalculateHVecTensorGradient(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_type=MBEDGE, const int zero_side=0)
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Calculate gradient of tensor field.
Calculate trace of vector (Hdiv/Hcurl) space.
boost::shared_ptr< MatrixDouble > dataPtr
boost::shared_ptr< double > scalePtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
OpCalculateHVecTensorTrace(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_type=MBEDGE, const int zero_side=0)
FTensor::Index< 'j', Tensor_Dim > j
FTensor::Index< 'i', Tensor_Dim > i
OpCalculateHVecTensorTrace(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, boost::shared_ptr< double > scale_ptr, const EntityType zero_type=MBEDGE, const int zero_side=0)
OpCalculateHVecVectorFieldDot(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_type=MBEDGE, const int zero_side=0)
Get vector field for H-div approximation.
OpCalculateHVecVectorField_General(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, SmartPetscObj< Vec > data_vec, const EntityType zero_type=MBEDGE, const int zero_side=0)
OpCalculateHVecVectorField_General(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_type=MBEDGE, const int zero_side=0)
Get vector field for H-div approximation.
Get vector field for H-div approximation.
Calculate gradient of vector field.
boost::shared_ptr< MatrixDouble > dataPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpCalculateHVecVectorGradient(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_type=MBEDGE, const int zero_side=0)
Calculate gradient of vector field.
boost::shared_ptr< MatrixDouble > dataPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpCalculateHVecVectorHessian(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_type=MBEDGE, const int zero_side=0)
boost::shared_ptr< MatrixDouble > dataPtr
boost::shared_ptr< MatrixDouble > dataPtr
boost::shared_ptr< MatrixDouble > dataPtr
Calculate curl of vector field.
Calculate divergence of vector field dot.
boost::shared_ptr< VectorDouble > dataPtr
OpCalculateHdivVectorDivergenceDot(const std::string field_name, boost::shared_ptr< VectorDouble > data_ptr, const EntityType zero_type=MBEDGE, const int zero_side=0)
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Calculate divergence of vector field.
boost::shared_ptr< VectorDouble > dataPtr
OpCalculateHdivVectorDivergence(const std::string field_name, boost::shared_ptr< VectorDouble > data_ptr, const EntityType zero_type=MBEDGE, const int zero_side=0)
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Calculate inverse of jacobian for face element.
OpCalculateInvJacForFatPrism(MatrixDouble &inv_jac)
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpCalculateInvJacForFatPrism(boost::shared_ptr< MatrixDouble > inv_jac_ptr)
const boost::shared_ptr< MatrixDouble > invJacPtr
Calculate inverse of jacobian for face element.
OpCalculateInvJacForFlatPrism(MatrixDouble &inv_jac_f3)
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Evaluate field gradient values for scalar field, i.e. gradient is tensor rank 1 (vector)
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
Evaluate field gradient values for scalar field, i.e. gradient is tensor rank 1 (vector),...
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
calculate gradient values of scalar field at integration points
Calculate scalar field values from PETSc vector at integration points.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpCalculateScalarFieldValuesFromPetscVecImpl(const std::string field_name, boost::shared_ptr< VectorDouble > data_ptr, const EntityType zero_at_type=MBVERTEX)
Constructor for PETSc vector-based scalar field calculation.
Scalar field values at integration points.
OpCalculateScalarFieldValues_General(const std::string field_name, boost::shared_ptr< ublas::vector< T, A > > data_ptr, SmartPetscObj< Vec > data_vec, const EntityType zero_type=MBVERTEX)
Constructor with PETSc vector support.
boost::shared_ptr< ublas::vector< T, A > > dataPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
calculate values of scalar field at integration points
OpCalculateScalarFieldValues_General(const std::string field_name, boost::shared_ptr< ublas::vector< T, A > > data_ptr, const EntityType zero_type=MBVERTEX)
Constructor for scalar field values calculation operator.
Specialization for double precision scalar field values calculation.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
calculate values of scalar field at integration points
Get time direvarive values at integration pts for tensor field rank 2, i.e. matrix field.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpCalculateTensor2FieldValuesDot(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_at_type=MBVERTEX)
EntityType zeroAtType
Zero values at Gauss point at this type.
VectorDouble dotVector
Keeps temporary values of time derivatives.
boost::shared_ptr< MatrixDouble > dataPtr
Data computed into this matrix.
OpCalculateTensor2FieldValues_General(const std::string field_name, boost::shared_ptr< ublas::matrix< double, ublas::row_major, DoubleAllocator > > data_ptr, SmartPetscObj< Vec > data_vec, const EntityType zero_type=MBVERTEX)
OpCalculateTensor2FieldValues_General(const std::string field_name, boost::shared_ptr< ublas::matrix< double, ublas::row_major, DoubleAllocator > > data_ptr, const EntityType zero_type=MBVERTEX)
Calculate field values for tenor field rank 2.
OpCalculateTensor2FieldValues_General(const std::string field_name, boost::shared_ptr< ublas::matrix< T, L, A > > data_ptr, const EntityType zero_type=MBVERTEX)
boost::shared_ptr< ublas::matrix< T, L, A > > dataPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Get values at integration pts for tensor field rank 2, i.e. matrix field.
OpCalculateTensor2SymmetricFieldGradient_General(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_type=MBVERTEX)
Evaluate field gradient values for symmetric 2nd order tensor field, i.e. gradient is tensor rank 3.
OpCalculateTensor2SymmetricFieldGradient_General(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_type=MBVERTEX)
Get field gradients at integration pts for symmetric tensorial field rank 2.
OpCalculateTensor2SymmetricFieldGradient(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_type=MBVERTEX)
Calculate symmetric tensor field rates ant integratio pts.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpCalculateTensor2SymmetricFieldValuesDot(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_type=MBEDGE, const int zero_side=0)
Calculate symmetric tensor field values at integration pts.
OpCalculateTensor2SymmetricFieldValues(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, SmartPetscObj< Vec > data_vec, const EntityType zero_type=MBEDGE, const int zero_side=0)
OpCalculateTensor2SymmetricFieldValues(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_type=MBEDGE, const int zero_side=0)
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Operator for calculating the trace of matrices at integration points.
boost::shared_ptr< MatrixDouble > inPtr
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 > outPtr
OpCalculateTraceFromMat(boost::shared_ptr< MatrixDouble > in_ptr, boost::shared_ptr< VectorDouble > out_ptr)
Constructor for matrix trace calculation operator.
Calculates the trace of an input matrix.
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 > outPtr
boost::shared_ptr< MatrixDouble > inPtr
OpCalculateTraceFromSymmMat(boost::shared_ptr< MatrixDouble > in_ptr, boost::shared_ptr< VectorDouble > out_ptr)
Get field gradients time derivative at integration pts for scalar field rank 0, i....
boost::shared_ptr< MatrixDouble > dataPtr
Data computed into this matrix.
OpCalculateVectorFieldGradientDot(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_at_type=MBVERTEX)
EntityType zeroAtType
Zero values at Gauss point at this type.
VectorDouble dotVector
Keeps temporary values of time derivatives.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Evaluate field gradient values for vector field, i.e. gradient is tensor rank 2.
Get field gradients at integration pts for scalar field rank 0, i.e. vector field.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
calculate values of vector field at integration points
Approximate field values for given petsc vector.
OpCalculateVectorFieldValuesFromPetscVecImpl(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_at_type=MBVERTEX, bool throw_error=true)
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpCalculateVectorFieldValues_General(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, const EntityType zero_type=MBVERTEX)
OpCalculateVectorFieldValues_General(const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, SmartPetscObj< Vec > data_vec, const EntityType zero_type=MBVERTEX)
Calculate field values for tensor field rank 1, i.e. vector field.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
calculate values of vector field at integration points
OpCalculateVectorFieldValues_General(const std::string field_name, boost::shared_ptr< ublas::matrix< T, L, A > > data_ptr, const EntityType zero_type=MBVERTEX)
Constructor for vector field values calculation operator.
boost::shared_ptr< ublas::matrix< T, L, A > > dataPtr
Specialization for double precision vector field values calculation.
Operator for inverting matrices at integration points.
boost::shared_ptr< VectorDouble > detPtr
OpInvertMatrix(boost::shared_ptr< MatrixDouble > in_ptr, boost::shared_ptr< VectorDouble > det_ptr, boost::shared_ptr< MatrixDouble > out_ptr)
Constructor for matrix inversion operator.
boost::shared_ptr< MatrixDouble > outPtr
boost::shared_ptr< MatrixDouble > inPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Make Hdiv space from Hcurl space in 2d.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Operator for fat prism element updating integration weights in the volume.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
Operator for scaling matrix values by a scalar factor.
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
Operator for linear form, usually to calculate values on right hand side.
boost::shared_ptr< MatrixDouble > outMat
DEPRECATED OpScaleMatrix(const std::string field_name, const double scale, boost::shared_ptr< MatrixDouble > in_mat, boost::shared_ptr< MatrixDouble > out_mat)
boost::shared_ptr< double > scalePtr
OpScaleMatrix(boost::shared_ptr< double > scale_ptr, boost::shared_ptr< MatrixDouble > in_mat, boost::shared_ptr< MatrixDouble > out_mat)
Constructor for matrix scaling operator.
boost::shared_ptr< MatrixDouble > inMat
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpSetContravariantPiolaTransformOnEdge2D(const FieldSpace space=HCURL)
OpSetContravariantPiolaTransformOnFace2DImpl(boost::shared_ptr< MatrixDouble > jac_ptr)
Apply contravariant (Piola) transfer to Hdiv space on face.
Apply contravariant (Piola) transfer to Hdiv space on face.
Transform Hcurl base fluxes from reference element to physical triangle.
OpSetInvJacH1ForFaceEmbeddedIn3DSpace(boost::shared_ptr< MatrixDouble > inv_jac_ptr)
OpSetInvJacH1ForFace(boost::shared_ptr< MatrixDouble > inv_jac_ptr)
Transform local reference derivatives of shape functions to global derivatives.
const boost::shared_ptr< MatrixDouble > invJacPtr
OpSetInvJacH1ForFatPrism(MatrixDouble &inv_jac)
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpSetInvJacH1ForFatPrism(boost::shared_ptr< MatrixDouble > inv_jac_ptr)
Transform local reference derivatives of shape functions to global derivatives.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpSetInvJacH1ForFlatPrism(MatrixDouble &inv_jac_f3)
boost::shared_ptr< MatrixDouble > invJacPtr
OpSetInvJacHcurlFaceImpl(boost::shared_ptr< MatrixDouble > inv_jac_ptr)
Transform local reference derivatives of shape function to global derivatives for face.
OpSetInvJacL2ForFaceEmbeddedIn3DSpace(boost::shared_ptr< MatrixDouble > inv_jac_ptr)
OpSetInvJacL2ForFace(boost::shared_ptr< MatrixDouble > inv_jac_ptr)
Transform local reference derivatives of shape functions to global derivatives.
MoFEMErrorCode applyTransform(MatrixDouble &diff_n)
Apply transformation to the input matrix.
OpSetInvJacToScalarBasesBasic(FieldSpace space, boost::shared_ptr< MatrixDouble > inv_jac_ptr)
boost::shared_ptr< MatrixDouble > invJacPtr
Operator for symmetrizing tensor fields.
FTensor::Index< 'i', DIM > i
boost::shared_ptr< MatrixDouble > outMat
OpSymmetrizeTensor(boost::shared_ptr< MatrixDouble > in_mat, boost::shared_ptr< MatrixDouble > out_mat)
Constructor for tensor symmetrization operator.
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
Operator for linear form, usually to calculate values on right hand side.
FTensor::Index< 'j', DIM > j
DEPRECATED OpSymmetrizeTensor(const std::string field_name, boost::shared_ptr< MatrixDouble > in_mat, boost::shared_ptr< MatrixDouble > out_mat)
boost::shared_ptr< MatrixDouble > inMat
MoFEMErrorCode doWork(int side, EntityType type, EntData &data)
Operator for linear form, usually to calculate values on right hand side.
boost::shared_ptr< MatrixDouble > dMat
OpTensorTimesSymmetricTensor(boost::shared_ptr< MatrixDouble > in_mat, boost::shared_ptr< MatrixDouble > out_mat, boost::shared_ptr< MatrixDouble > d_mat)
boost::shared_ptr< MatrixDouble > inMat
DEPRECATED OpTensorTimesSymmetricTensor(const std::string field_name, boost::shared_ptr< MatrixDouble > in_mat, boost::shared_ptr< MatrixDouble > out_mat, boost::shared_ptr< MatrixDouble > d_mat)
boost::shared_ptr< MatrixDouble > outMat
static constexpr Switches CtxSetX
Solution vector switch.
static constexpr Switches CtxSetX_TT
Second time derivative switch.
std::bitset< 8 > Switches
Bitset type for context switches.
static constexpr Switches CtxSetX_T
First time derivative switch.
@ CTX_SET_X_T
Time derivative X_t is set.
@ CTX_SET_DX
Solution increment DX is set.
@ CTX_SET_X
Solution vector X is set.
@ CTX_SET_X_TT
Second time derivative X_tt is set.
intrusive_ptr for managing petsc objects
double scale
Definition plastic.cpp:123