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 (%ld != %ld)",
1964 static_cast<long>(hessian_base.size1()),
1965 static_cast<long>(nb_gauss_pts));
1966 }
1967 if (hessian_base.size2() !=
1968 nb_base_functions * Tensor_Dim1 * Tensor_Dim1) {
1969 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1970 "Wrong number of base functions (%ld != %ld)",
1971 static_cast<long>(hessian_base.size2() /
1972 (Tensor_Dim1 * Tensor_Dim1)),
1973 static_cast<long>(nb_base_functions));
1974 }
1975 if (hessian_base.size2() <
1976 (nb_dofs / Tensor_Dim0) * Tensor_Dim1 * Tensor_Dim1) {
1977 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1978 "Wrong number of base functions (%ld < %ld)",
1979 static_cast<long>(hessian_base.size2()),
1980 static_cast<long>((nb_dofs / Tensor_Dim0) * Tensor_Dim1 *
1981 Tensor_Dim1));
1982 }
1983 #endif
1984
1985 auto t_diff2_base_function = getFTensor2FromPtr<Tensor_Dim1, Tensor_Dim1>(
1986 &*hessian_base.data().begin());
1987
1988 auto t_hessian_at_gauss_pts =
1989 getFTensor3FromMat<Tensor_Dim0, Tensor_Dim1, Tensor_Dim1>(mat);
1990
1991 FTensor::Index<'I', Tensor_Dim0> I;
1992 FTensor::Index<'J', Tensor_Dim1> J;
1993 FTensor::Index<'K', Tensor_Dim1> K;
1994
1995 int size = nb_dofs / Tensor_Dim0;
1996 #ifndef NDEBUG
1997 if (nb_dofs % Tensor_Dim0) {
1998 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1999 "Data inconsistency");
2000 }
2001 #endif
2002
2003 for (int gg = 0; gg < nb_gauss_pts; ++gg) {
2004 auto field_data = data.getFTensor1FieldData<Tensor_Dim0>();
2005 int bb = 0;
2006 for (; bb < size; ++bb) {
2007 t_hessian_at_gauss_pts(I, J, K) +=
2008 field_data(I) * t_diff2_base_function(J, K);
2009 ++field_data;
2010 ++t_diff2_base_function;
2011 }
2012 // Number of dofs can be smaller than number of Tensor_Dim0 x base
2013 // functions
2014 for (; bb != nb_base_functions; ++bb)
2015 ++t_diff2_base_function;
2016 ++t_hessian_at_gauss_pts;
2017 }
2018
2019 if (this->dataVec.use_count()) {
2020 data.getFieldData().swap(this->dotVector);
2021 }
2022 }
2023 }
2025}
2026
2027/**@}*/
2028
2029/** \name Transform tensors and vectors */
2030
2031/**@{*/
2032
2033/**
2034 * @brief Calculate \f$ \pmb\sigma_{ij} = \mathbf{D}_{ijkl} \pmb\varepsilon_{kl}
2035 * \f$
2036 *
2037 * @tparam DIM
2038 *
2039 * \ingroup mofem_forces_and_sources_user_data_operators
2040 */
2041template <int DIM_01, int DIM_23, int S = 0>
2044
2047
2048 /**
2049 * @deprecated Do not use this constructor
2050 */
2053 boost::shared_ptr<MatrixDouble> in_mat,
2054 boost::shared_ptr<MatrixDouble> out_mat,
2055 boost::shared_ptr<MatrixDouble> d_mat)
2056 : UserOp(field_name, OPCOL), inMat(in_mat), outMat(out_mat), dMat(d_mat) {
2057 // Only is run for vertices
2058 std::fill(&doEntities[MBEDGE], &doEntities[MBMAXTYPE], false);
2059 if (!inMat)
2060 THROW_MESSAGE("Pointer for in mat is null");
2061 if (!outMat)
2062 THROW_MESSAGE("Pointer for out mat is null");
2063 if (!dMat)
2064 THROW_MESSAGE("Pointer for tensor mat is null");
2065 }
2066
2067 OpTensorTimesSymmetricTensor(boost::shared_ptr<MatrixDouble> in_mat,
2068 boost::shared_ptr<MatrixDouble> out_mat,
2069 boost::shared_ptr<MatrixDouble> d_mat)
2070 : UserOp(NOSPACE, OPSPACE), inMat(in_mat), outMat(out_mat), dMat(d_mat) {
2071 // Only is run for vertices
2072 if (!inMat)
2073 THROW_MESSAGE("Pointer for in mat is null");
2074 if (!outMat)
2075 THROW_MESSAGE("Pointer for out mat is null");
2076 if (!dMat)
2077 THROW_MESSAGE("Pointer for tensor mat is null");
2078 }
2079
2080 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
2082 const size_t nb_gauss_pts = getGaussPts().size2();
2083 auto t_D = getFTensor4DdgFromMat<DIM_01, DIM_23, S>(*(dMat));
2084 auto t_in = getFTensor2SymmetricFromMat<DIM_01>(*(inMat));
2085 outMat->resize((DIM_23 * (DIM_23 + 1)) / 2, nb_gauss_pts, false);
2086 auto t_out = getFTensor2SymmetricFromMat<DIM_23>(*(outMat));
2087 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
2088 t_out(i, j) = t_D(i, j, k, l) * t_in(k, l);
2089 ++t_in;
2090 ++t_out;
2091 }
2093 }
2094
2095private:
2096 FTensor::Index<'i', DIM_01> i;
2097 FTensor::Index<'j', DIM_01> j;
2098 FTensor::Index<'k', DIM_23> k;
2099 FTensor::Index<'l', DIM_23> l;
2100
2101 boost::shared_ptr<MatrixDouble> inMat;
2102 boost::shared_ptr<MatrixDouble> outMat;
2103 boost::shared_ptr<MatrixDouble> dMat;
2104};
2105
2106/**
2107 * @brief Operator for symmetrizing tensor fields
2108 *
2109 * This template structure symmetrizes tensor fields by computing the symmetric
2110 * part of an input tensor and storing the result in an output matrix. It's
2111 * commonly used in mechanics where symmetric tensors (like stress and strain)
2112 * are required.
2113 *
2114 * @tparam DIM Dimension of the tensor field
2115 */
2116template <int DIM>
2118
2121
2122 /**
2123 * @deprecated Do not use this constructor
2124 */
2126 boost::shared_ptr<MatrixDouble> in_mat,
2127 boost::shared_ptr<MatrixDouble> out_mat)
2128 : UserOp(field_name, OPCOL), inMat(in_mat), outMat(out_mat) {
2129 // Only is run for vertices
2130 std::fill(&doEntities[MBEDGE], &doEntities[MBMAXTYPE], false);
2131 if (!inMat)
2132 THROW_MESSAGE("Pointer not set for in matrix");
2133 if (!outMat)
2134 THROW_MESSAGE("Pointer not set for in matrix");
2135 }
2136
2137 /**
2138 * @brief Constructor for tensor symmetrization operator
2139 *
2140 * @param in_mat Shared pointer to input matrix containing asymmetric tensor
2141 * @param out_mat Shared pointer to output matrix for storing symmetric tensor
2142 */
2143 OpSymmetrizeTensor(boost::shared_ptr<MatrixDouble> in_mat,
2144 boost::shared_ptr<MatrixDouble> out_mat)
2145 : UserOp(NOSPACE, OPSPACE), inMat(in_mat), outMat(out_mat) {
2146 // Only is run for vertices
2147 if (!inMat)
2148 THROW_MESSAGE("Pointer not set for in matrix");
2149 if (!outMat)
2150 THROW_MESSAGE("Pointer not set for in matrix");
2151 }
2152
2153 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
2155 const size_t nb_gauss_pts = getGaussPts().size2();
2156 auto t_in = getFTensor2FromMat<DIM, DIM>(*(inMat));
2157 outMat->resize((DIM * (DIM + 1)) / 2, nb_gauss_pts, false);
2158 auto t_out = getFTensor2SymmetricFromMat<DIM>(*(outMat));
2159 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
2160 t_out(i, j) = (t_in(i, j) || t_in(j, i)) / 2;
2161 ++t_in;
2162 ++t_out;
2163 }
2165 }
2166
2167private:
2170 boost::shared_ptr<MatrixDouble> inMat;
2171 boost::shared_ptr<MatrixDouble> outMat;
2172};
2173
2174/**
2175 * @brief Operator for scaling matrix values by a scalar factor
2176 *
2177 * This structure performs element-wise scaling of matrix data by multiplying
2178 * all elements by a scalar value. It's useful for applying material properties,
2179 * coordinate transformations, or other scaling operations in finite element
2180 * computations.
2181 */
2183
2186
2187 /**
2188 * @deprecated Do not use this constructor
2189 */
2190 DEPRECATED OpScaleMatrix(const std::string field_name, const double scale,
2191 boost::shared_ptr<MatrixDouble> in_mat,
2192 boost::shared_ptr<MatrixDouble> out_mat)
2193 : UserOp(field_name, OPCOL), inMat(in_mat), outMat(out_mat) {
2194 scalePtr = boost::make_shared<double>(scale);
2195 // Only is run for vertices
2196 std::fill(&doEntities[MBEDGE], &doEntities[MBMAXTYPE], false);
2197 if (!inMat)
2198 THROW_MESSAGE("Pointer not set for in matrix");
2199 if (!outMat)
2200 THROW_MESSAGE("Pointer not set for in matrix");
2201 }
2202
2203 /**
2204 * @brief Constructor for matrix scaling operator
2205 *
2206 * @param scale_ptr Shared pointer to scalar value for scaling matrix elements
2207 * @param in_mat Shared pointer to input matrix to be scaled
2208 * @param out_mat Shared pointer to output matrix for storing scaled results
2209 */
2210 OpScaleMatrix(boost::shared_ptr<double> scale_ptr,
2211 boost::shared_ptr<MatrixDouble> in_mat,
2212 boost::shared_ptr<MatrixDouble> out_mat)
2213 : UserOp(NOSPACE, OPSPACE), scalePtr(scale_ptr), inMat(in_mat),
2214 outMat(out_mat) {
2215 if (!scalePtr)
2216 THROW_MESSAGE("Pointer not set for scale");
2217 if (!inMat)
2218 THROW_MESSAGE("Pointer not set for in matrix");
2219 if (!outMat)
2220 THROW_MESSAGE("Pointer not set for in matrix");
2221 }
2222
2223 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
2225 outMat->resize(inMat->size1(), inMat->size2(), false);
2226 noalias(*outMat) = (*scalePtr) * (*inMat);
2228 }
2229
2230private:
2231 boost::shared_ptr<double> scalePtr;
2232 boost::shared_ptr<MatrixDouble> inMat;
2233 boost::shared_ptr<MatrixDouble> outMat;
2234};
2235
2236/**@}*/
2237
2238/** \name H-div/H-curls (Vectorial bases) values at integration points */
2239
2240/**@{*/
2241
2242/** \brief Get vector field for H-div approximation
2243 * \ingroup mofem_forces_and_sources_user_data_operators
2244 */
2245template <int Base_Dim, int Field_Dim, class T, class L, class A>
2247
2248/** \brief Get vector field for H-div approximation
2249 * \ingroup mofem_forces_and_sources_user_data_operators
2250 */
2251template <int Field_Dim>
2253 ublas::row_major, DoubleAllocator>
2255
2257 boost::shared_ptr<MatrixDouble> data_ptr,
2258 SmartPetscObj<Vec> data_vec,
2259 const EntityType zero_type = MBEDGE,
2260 const int zero_side = 0)
2263 dataPtr(data_ptr), dataVec(data_vec), zeroType(zero_type),
2264 zeroSide(zero_side) {
2265 if (!dataPtr)
2266 THROW_MESSAGE("Pointer is not set");
2267 }
2268
2270 boost::shared_ptr<MatrixDouble> data_ptr,
2271 const EntityType zero_type = MBEDGE,
2272 const int zero_side = 0)
2274 field_name, data_ptr, SmartPetscObj<Vec>(), zero_type, zero_side) {}
2275
2276 /**
2277 * \brief Calculate values of vector field at integration points
2278 * @param side side entity number
2279 * @param type side entity type
2280 * @param data entity data
2281 * @return error code
2282 */
2283 MoFEMErrorCode doWork(int side, EntityType type,
2285
2286private:
2287 boost::shared_ptr<MatrixDouble> dataPtr;
2290 const int zeroSide;
2292};
2293
2294template <int Field_Dim>
2296 3, Field_Dim, double, ublas::row_major,
2297 DoubleAllocator>::doWork(int side, EntityType type,
2300 const size_t nb_integration_points = this->getGaussPts().size2();
2301 if (type == zeroType && side == zeroSide) {
2302 dataPtr->resize(Field_Dim, nb_integration_points, false);
2303 dataPtr->clear();
2304 }
2305 const size_t nb_dofs = data.getFieldData().size();
2306 if (!nb_dofs)
2308
2309 if (dataVec.use_count()) {
2310 dotVector.resize(nb_dofs, false);
2311 const double *array;
2312 CHKERR VecGetArrayRead(dataVec, &array);
2313 const auto &local_indices = data.getLocalIndices();
2314 for (int i = 0; i != local_indices.size(); ++i)
2315 if (local_indices[i] != -1)
2316 dotVector[i] = array[local_indices[i]];
2317 else
2318 dotVector[i] = 0;
2319 CHKERR VecRestoreArrayRead(dataVec, &array);
2320 data.getFieldData().swap(dotVector);
2321 }
2322
2323 const size_t nb_base_functions = data.getN().size2() / 3;
2324 FTensor::Index<'i', Field_Dim> i;
2325 auto t_n_hdiv = data.getFTensor1N<3>();
2326 auto t_data = getFTensor1FromMat<Field_Dim>(*dataPtr);
2327 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2328 auto t_dof = data.getFTensor0FieldData();
2329 int bb = 0;
2330 for (; bb != nb_dofs; ++bb) {
2331 t_data(i) += t_n_hdiv(i) * t_dof;
2332 ++t_n_hdiv;
2333 ++t_dof;
2334 }
2335 for (; bb != nb_base_functions; ++bb)
2336 ++t_n_hdiv;
2337 ++t_data;
2338 }
2339
2340 if (dataVec.use_count()) {
2341 data.getFieldData().swap(dotVector);
2342 }
2344}
2345
2346/** \brief Get vector field for H-div approximation
2347 *
2348 * \ingroup mofem_forces_and_sources_user_data_operators
2349 */
2350template <int Base_Dim, int Field_Dim = Base_Dim>
2353 Base_Dim, Field_Dim, double, ublas::row_major, DoubleAllocator> {
2355 Base_Dim, Field_Dim, double, ublas::row_major,
2356 DoubleAllocator>::OpCalculateHVecVectorField_General;
2357};
2358
2359/** \brief Get vector field for H-div approximation
2360 * \ingroup mofem_forces_and_sources_user_data_operators
2361 */
2362template <int Base_Dim, int Field_Dim = Base_Dim>
2364
2365template <int Field_Dim>
2368
2370 boost::shared_ptr<MatrixDouble> data_ptr,
2371 const EntityType zero_type = MBEDGE,
2372 const int zero_side = 0)
2375 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2376 if (!dataPtr)
2377 THROW_MESSAGE("Pointer is not set");
2378 }
2379
2380 /**
2381 * \brief Calculate values of vector field at integration points
2382 * @param side side entity number
2383 * @param type side entity type
2384 * @param data entity data
2385 * @return error code
2386 */
2387 MoFEMErrorCode doWork(int side, EntityType type,
2389
2390private:
2391 boost::shared_ptr<MatrixDouble> dataPtr;
2393 const int zeroSide;
2394};
2395
2396template <int Field_Dim>
2398 int side, EntityType type, EntitiesFieldData::EntData &data) {
2400
2401 const size_t nb_integration_points = this->getGaussPts().size2();
2402 if (type == zeroType && side == zeroSide) {
2403 dataPtr->resize(Field_Dim, nb_integration_points, false);
2404 dataPtr->clear();
2405 }
2406
2407 auto &local_indices = data.getIndices();
2408 const size_t nb_dofs = local_indices.size();
2409 if (nb_dofs) {
2410
2411 std::array<double, MAX_DOFS_ON_ENTITY> dot_dofs_vector;
2412 const double *array;
2413 CHKERR VecGetArrayRead(getFEMethod()->ts_u_t, &array);
2414 for (size_t i = 0; i != nb_dofs; ++i)
2415 if (local_indices[i] != -1)
2416 dot_dofs_vector[i] = array[local_indices[i]];
2417 else
2418 dot_dofs_vector[i] = 0;
2419 CHKERR VecRestoreArrayRead(getFEMethod()->ts_u_t, &array);
2420
2421 const size_t nb_base_functions = data.getN().size2() / 3;
2422 FTensor::Index<'i', Field_Dim> i;
2423 auto t_n_hdiv = data.getFTensor1N<3>();
2424 auto t_data = getFTensor1FromMat<Field_Dim>(*dataPtr);
2425 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2426 int bb = 0;
2427 for (; bb != nb_dofs; ++bb) {
2428 t_data(i) += t_n_hdiv(i) * dot_dofs_vector[bb];
2429 ++t_n_hdiv;
2430 }
2431 for (; bb != nb_base_functions; ++bb)
2432 ++t_n_hdiv;
2433 ++t_data;
2434 }
2435 }
2436
2438}
2439
2440/**
2441 * @brief Calculate divergence of vector field
2442 * @ingroup mofem_forces_and_sources_user_data_operators
2443 *
2444 * @tparam BASE_DIM
2445 * @tparam SPACE_DIM
2446 */
2447template <int BASE_DIM, int SPACE_DIM>
2450
2452 boost::shared_ptr<VectorDouble> data_ptr,
2453 const EntityType zero_type = MBEDGE,
2454 const int zero_side = 0)
2457 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2458 if (!dataPtr)
2459 THROW_MESSAGE("Pointer is not set");
2460 }
2461
2462 MoFEMErrorCode doWork(int side, EntityType type,
2465 const size_t nb_integration_points = getGaussPts().size2();
2466 if (type == zeroType && side == zeroSide) {
2467 dataPtr->resize(nb_integration_points, false);
2468 dataPtr->clear();
2469 }
2470 const size_t nb_dofs = data.getFieldData().size();
2471 if (!nb_dofs)
2473 const size_t nb_base_functions = data.getN().size2() / BASE_DIM;
2476 auto t_n_diff_hdiv = data.getFTensor2DiffN<BASE_DIM, SPACE_DIM>();
2477 auto t_data = getFTensor0FromVec(*dataPtr);
2478 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2479 auto t_dof = data.getFTensor0FieldData();
2480 int bb = 0;
2481 for (; bb != nb_dofs; ++bb) {
2482 t_data += t_dof * t_n_diff_hdiv(j, j);
2483 ++t_n_diff_hdiv;
2484 ++t_dof;
2485 }
2486 for (; bb != nb_base_functions; ++bb)
2487 ++t_n_diff_hdiv;
2488 ++t_data;
2489 }
2491 }
2492
2493private:
2494 boost::shared_ptr<VectorDouble> dataPtr;
2496 const int zeroSide;
2497};
2498
2499/**
2500 * @brief Calculate gradient of vector field
2501 * @ingroup mofem_forces_and_sources_user_data_operators
2502 *
2503 * @tparam BASE_DIM
2504 * @tparam SPACE_DIM
2505 */
2506template <int BASE_DIM, int SPACE_DIM>
2509
2511 boost::shared_ptr<MatrixDouble> data_ptr,
2512 const EntityType zero_type = MBEDGE,
2513 const int zero_side = 0)
2516 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2517 if (!dataPtr)
2518 THROW_MESSAGE("Pointer is not set");
2519 }
2520
2521 MoFEMErrorCode doWork(int side, EntityType type,
2524 const size_t nb_integration_points = getGaussPts().size2();
2525 if (type == zeroType && side == zeroSide) {
2526 dataPtr->resize(BASE_DIM * SPACE_DIM, nb_integration_points, false);
2527 dataPtr->clear();
2528 }
2529 const size_t nb_dofs = data.getFieldData().size();
2530 if (!nb_dofs)
2532 const size_t nb_base_functions = data.getN().size2() / BASE_DIM;
2535 auto t_base_diff = data.getFTensor2DiffN<BASE_DIM, SPACE_DIM>();
2536 auto t_data = getFTensor2FromMat<BASE_DIM, SPACE_DIM>(*dataPtr);
2537 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2538 auto t_dof = data.getFTensor0FieldData();
2539 int bb = 0;
2540 for (; bb != nb_dofs; ++bb) {
2541 t_data(i, j) += t_dof * t_base_diff(i, j);
2542 ++t_base_diff;
2543 ++t_dof;
2544 }
2545 for (; bb != nb_base_functions; ++bb)
2546 ++t_base_diff;
2547 ++t_data;
2548 }
2550 }
2551
2552private:
2553 boost::shared_ptr<MatrixDouble> dataPtr;
2555 const int zeroSide;
2556};
2557
2558/**
2559 * @brief Calculate gradient of tensor field
2560 * @ingroup mofem_forces_and_sources_user_data_operators
2561 *
2562 * @tparam BASE_DIM
2563 * @tparam FIELD_DIM
2564 * @tparam SPACE_DIM
2565 */
2566template <int BASE_DIM, int FIELD_DIM, int SPACE_DIM>
2568
2569/**
2570 * @brief Specialisation for 3D tensor field gradient calculation
2571 * @ingroup mofem_forces_and_sources_user_data_operators
2572 *
2573 */
2574template <>
2577
2579 boost::shared_ptr<MatrixDouble> data_ptr,
2580 const EntityType zero_type = MBEDGE,
2581 const int zero_side = 0)
2584 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2585 if (!dataPtr)
2586 THROW_MESSAGE("Pointer is not set");
2587 }
2588
2589 MoFEMErrorCode doWork(int side, EntityType type,
2592
2593 const size_t nb_integration_points = getGaussPts().size2();
2594 if (type == zeroType && side == zeroSide) {
2595 dataPtr->resize(27, nb_integration_points, false);
2596 dataPtr->clear();
2597 }
2598
2599 #ifndef NDEBUG
2600 if (data.getFieldData().size() % 3) {
2601 SETERRQ(
2602 PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2603 "Data inconsistency, nb_dofs %% COEFF_DIM != 0, that is %ld %% %d "
2604 "!= 0",
2605 data.getFieldData().size(), 3);
2606 }
2607 #endif
2608
2609 const auto nb_dofs = data.getFieldData().size() / 3;
2610 if (!nb_dofs)
2612
2613 const size_t nb_base_functions = data.getN().size2() / 3;
2614 FTensor::Index<'i', 3> i;
2615 FTensor::Index<'j', 3> j;
2616 FTensor::Index<'k', 3> k;
2617
2618 auto t_base_diff = data.getFTensor2DiffN<3, 3>();
2619 auto t_data = getFTensor3FromMat<3, 3, 3>(*dataPtr);
2620 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2621 auto t_dof = data.getFTensor1FieldData<3>();
2622 int bb = 0;
2623 for (; bb != nb_dofs; ++bb) {
2624 t_data(k, i, j) += t_base_diff(i, j) * t_dof(k);
2625 ++t_base_diff;
2626 ++t_dof;
2627 }
2628 for (; bb != nb_base_functions; ++bb)
2629 ++t_base_diff;
2630 ++t_data;
2631 }
2633 }
2634
2635private:
2636 boost::shared_ptr<MatrixDouble> dataPtr;
2638 const int zeroSide;
2639};
2640
2641template <>
2644
2646 boost::shared_ptr<MatrixDouble> data_ptr,
2647 const EntityType zero_type = MBEDGE,
2648 const int zero_side = 0)
2651 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2652 if (!dataPtr)
2653 THROW_MESSAGE("Pointer is not set");
2654 }
2655
2656 MoFEMErrorCode doWork(int side, EntityType type,
2659
2660 const size_t nb_integration_points = getGaussPts().size2();
2661 if (type == zeroType && side == zeroSide) {
2662 dataPtr->resize(27, nb_integration_points, false);
2663 dataPtr->clear();
2664 }
2665
2666 const auto nb_dofs = data.getFieldData().size();
2667 if (!nb_dofs)
2669
2670 const size_t nb_base_functions = data.getN().size2() / 9;
2671
2672 #ifndef NDEBUG
2673 if (data.getDiffN().size1() != nb_integration_points) {
2674 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2675 "Wrong number of integration pts (%ld != %ld)",
2676 data.getDiffN().size1(), nb_integration_points);
2677 }
2678 if (data.getDiffN().size2() != nb_base_functions * 27) {
2679 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2680 "Wrong number of base functions (%ld != %ld)",
2681 data.getDiffN().size2() / 27, nb_base_functions);
2682 }
2683 if (nb_base_functions < nb_dofs) {
2684 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2685 "Wrong number of base functions (%ld < %ld)", nb_base_functions,
2686 nb_dofs);
2687 }
2688 #endif
2689
2690 FTensor::Index<'i', 3> i;
2691 FTensor::Index<'j', 3> j;
2692 FTensor::Index<'k', 3> k;
2693
2694 auto t_base_diff = data.getFTensor3DiffN<3, 3, 3>();
2695 auto t_data = getFTensor3FromMat<3, 3, 3>(*dataPtr);
2696 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2697 auto t_dof = data.getFTensor0FieldData();
2698 int bb = 0;
2699 for (; bb != nb_dofs; ++bb) {
2700 t_data(k, i, j) += t_base_diff(k, i, j) * t_dof;
2701 ++t_base_diff;
2702 ++t_dof;
2703 }
2704 for (; bb != nb_base_functions; ++bb)
2705 ++t_base_diff;
2706 ++t_data;
2707 }
2708
2710 }
2711
2712private:
2713 boost::shared_ptr<MatrixDouble> dataPtr;
2715 const int zeroSide;
2716};
2717
2718/**
2719 * @brief Calculate gradient of vector field
2720 * @ingroup mofem_forces_and_sources_user_data_operators
2721 *
2722 * @tparam BASE_DIM
2723 * @tparam SPACE_DIM
2724 */
2725template <int BASE_DIM, int SPACE_DIM>
2728
2730 boost::shared_ptr<MatrixDouble> data_ptr,
2731 const EntityType zero_type = MBEDGE,
2732 const int zero_side = 0)
2735 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2736 if (!dataPtr)
2737 THROW_MESSAGE("Pointer is not set");
2738 }
2739
2740 MoFEMErrorCode doWork(int side, EntityType type,
2743 const size_t nb_integration_points = getGaussPts().size2();
2744 if (type == zeroType && side == zeroSide) {
2745 dataPtr->resize(BASE_DIM * SPACE_DIM * SPACE_DIM, nb_integration_points,
2746 false);
2747 dataPtr->clear();
2748 }
2749 const size_t nb_dofs = data.getFieldData().size();
2750 if (!nb_dofs)
2752
2753 const int nb_base_functions = data.getN().size2() / BASE_DIM;
2754
2755 #ifndef NDEBUG
2756 auto &hessian_base = data.getN(BaseDerivatives::SecondDerivative);
2757 if (hessian_base.size1() != nb_integration_points) {
2758 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2759 "Wrong number of integration pts (%ld != %ld)",
2760 static_cast<long>(hessian_base.size1()),
2761 static_cast<long>(nb_integration_points));
2762 }
2763 if (hessian_base.size2() !=
2764 BASE_DIM * nb_base_functions * SPACE_DIM * SPACE_DIM) {
2765 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2766 "Wrong number of base functions (%ld != %ld)",
2767 static_cast<long>(hessian_base.size2() /
2769 static_cast<long>(nb_base_functions));
2770 }
2771 if (hessian_base.size2() < BASE_DIM * nb_dofs * SPACE_DIM * SPACE_DIM) {
2772 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2773 "Wrong number of base functions (%ld < %ld)",
2774 static_cast<long>(hessian_base.size2()),
2775 static_cast<long>(BASE_DIM * nb_dofs * SPACE_DIM * SPACE_DIM));
2776 }
2777 #endif
2778
2782
2783 auto t_base_diff2 =
2785 auto t_data = getFTensor3FromMat<BASE_DIM, SPACE_DIM, SPACE_DIM>(*dataPtr);
2786 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2787 auto t_dof = data.getFTensor0FieldData();
2788 int bb = 0;
2789 for (; bb != nb_dofs; ++bb) {
2790 t_data(i, j, k) += t_dof * t_base_diff2(i, j, k);
2791
2792 ++t_base_diff2;
2793 ++t_dof;
2794 }
2795 for (; bb != nb_base_functions; ++bb)
2796 ++t_base_diff2;
2797 ++t_data;
2798 }
2800 }
2801
2802private:
2803 boost::shared_ptr<MatrixDouble> dataPtr;
2805 const int zeroSide;
2806};
2807
2808/**
2809 * @brief Calculate divergence of vector field dot
2810 * @ingroup mofem_forces_and_sources_user_data_operators
2811 *
2812 * @tparam Tensor_Dim dimension of space
2813 */
2814template <int Tensor_Dim1, int Tensor_Dim2>
2817
2819 boost::shared_ptr<VectorDouble> data_ptr,
2820 const EntityType zero_type = MBEDGE,
2821 const int zero_side = 0)
2824 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2825 if (!dataPtr)
2826 THROW_MESSAGE("Pointer is not set");
2827 }
2828
2829 MoFEMErrorCode doWork(int side, EntityType type,
2832 const size_t nb_integration_points = getGaussPts().size2();
2833 if (type == zeroType && side == zeroSide) {
2834 dataPtr->resize(nb_integration_points, false);
2835 dataPtr->clear();
2836 }
2837
2838 const auto &local_indices = data.getLocalIndices();
2839 const int nb_dofs = local_indices.size();
2840 if (nb_dofs) {
2841
2842 std::array<double, MAX_DOFS_ON_ENTITY> dot_dofs_vector;
2843 const double *array;
2844 CHKERR VecGetArrayRead(getFEMethod()->ts_u_t, &array);
2845 for (size_t i = 0; i != local_indices.size(); ++i)
2846 if (local_indices[i] != -1)
2847 dot_dofs_vector[i] = array[local_indices[i]];
2848 else
2849 dot_dofs_vector[i] = 0;
2850 CHKERR VecRestoreArrayRead(getFEMethod()->ts_u_t, &array);
2851
2852 const size_t nb_base_functions = data.getN().size2() / Tensor_Dim1;
2853 FTensor::Index<'i', Tensor_Dim1> i;
2854 auto t_n_diff_hdiv = data.getFTensor2DiffN<Tensor_Dim1, Tensor_Dim2>();
2855 auto t_data = getFTensor0FromVec(*dataPtr);
2856 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2857 int bb = 0;
2858 for (; bb != nb_dofs; ++bb) {
2859 double div = 0;
2860 for (auto ii = 0; ii != Tensor_Dim2; ++ii)
2861 div += t_n_diff_hdiv(ii, ii);
2862 t_data += dot_dofs_vector[bb] * div;
2863 ++t_n_diff_hdiv;
2864 }
2865 for (; bb != nb_base_functions; ++bb)
2866 ++t_n_diff_hdiv;
2867 ++t_data;
2868 }
2869 }
2871 }
2872
2873private:
2874 boost::shared_ptr<VectorDouble> dataPtr;
2876 const int zeroSide;
2877};
2878
2879/**
2880 * @brief Calculate curl of vector field
2881 * @ingroup mofem_forces_and_sources_user_data_operators
2882 *
2883 * @tparam Base_Dim base function dimension
2884 * @tparam Space_Dim dimension of space
2885 * @tparam Hcurl field dimension
2886 */
2887template <int Base_Dim, int Space_Dim> struct OpCalculateHcurlVectorCurl;
2888
2889/**
2890 * @brief Calculate curl of vector field
2891 * @ingroup mofem_forces_and_sources_user_data_operators
2892 *
2893 * @tparam Base_Dim base function dimension
2894 * @tparam Space_Dim dimension of space
2895 * @tparam Hcurl field dimension
2896 */
2897template <>
2900 OpCalculateHcurlVectorCurl(const std::string field_name,
2901 boost::shared_ptr<MatrixDouble> data_ptr,
2902 const EntityType zero_type = MBEDGE,
2903 const int zero_side = 0);
2904 MoFEMErrorCode doWork(int side, EntityType type,
2906
2907private:
2908 boost::shared_ptr<MatrixDouble> dataPtr;
2910 const int zeroSide;
2911};
2912
2913/**
2914 * @brief Calculate curl of vector field
2915 * @ingroup mofem_forces_and_sources_user_data_operators
2916 *
2917 * @tparam Field_Dim dimension of field
2918 * @tparam Space_Dim dimension of space
2919 */
2920template <>
2923
2924 OpCalculateHcurlVectorCurl(const std::string field_name,
2925 boost::shared_ptr<MatrixDouble> data_ptr,
2926 const EntityType zero_type = MBVERTEX,
2927 const int zero_side = 0);
2928
2929 MoFEMErrorCode doWork(int side, EntityType type,
2931
2932private:
2933 boost::shared_ptr<MatrixDouble> dataPtr;
2935 const int zeroSide;
2936};
2937
2938/**
2939 * @brief Calculate curl of vector field
2940 * @ingroup mofem_forces_and_sources_user_data_operators
2941 *
2942 * @tparam Field_Dim dimension of field
2943 * @tparam Space_Dim dimension of space
2944 */
2945template <>
2948
2949 OpCalculateHcurlVectorCurl(const std::string field_name,
2950 boost::shared_ptr<MatrixDouble> data_ptr,
2951 const EntityType zero_type = MBVERTEX,
2952 const int zero_side = 0);
2953
2954 MoFEMErrorCode doWork(int side, EntityType type,
2956
2957private:
2958 boost::shared_ptr<MatrixDouble> dataPtr;
2960 const int zeroSide;
2961};
2962
2963/**
2964 * @brief Calculate tenor field using vectorial base, i.e. Hdiv/Hcurl
2965 * \ingroup mofem_forces_and_sources_user_data_operators
2966 *
2967 * @tparam Tensor_Dim0 rank of the field
2968 * @tparam Tensor_Dim1 dimension of space
2969 */
2970template <int Tensor_Dim0, int Tensor_Dim1>
2973
2975 boost::shared_ptr<MatrixDouble> data_ptr,
2976 boost::shared_ptr<double> scale_ptr,
2978 const EntityType zero_type = MBEDGE,
2979 const int zero_side = 0)
2982 dataPtr(data_ptr), scalePtr(scale_ptr), dataVec(data_vec),
2983 zeroType(zero_type), zeroSide(zero_side) {
2984 if (!dataPtr)
2985 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Pointer is not set");
2986 }
2987
2989 boost::shared_ptr<MatrixDouble> data_ptr,
2990 const EntityType zero_type = MBEDGE,
2991 const int zero_side = 0)
2992 : OpCalculateHVecTensorField(field_name, data_ptr, nullptr,
2993 SmartPetscObj<Vec>(), zero_type, zero_side) {
2994 }
2995
2996 MoFEMErrorCode doWork(int side, EntityType type,
2999 const size_t nb_integration_points = getGaussPts().size2();
3000 if (type == zeroType && side == zeroSide) {
3001 dataPtr->resize(Tensor_Dim0 * Tensor_Dim1, nb_integration_points, false);
3002 dataPtr->clear();
3003 }
3004 const size_t nb_dofs = data.getFieldData().size();
3005 if (nb_dofs) {
3006
3007 if (dataVec.use_count()) {
3008 dotVector.resize(nb_dofs, false);
3009 const double *array;
3010 CHKERR VecGetArrayRead(dataVec, &array);
3011 const auto &local_indices = data.getLocalIndices();
3012 for (int i = 0; i != local_indices.size(); ++i)
3013 if (local_indices[i] != -1)
3014 dotVector[i] = array[local_indices[i]];
3015 else
3016 dotVector[i] = 0;
3017 CHKERR VecRestoreArrayRead(dataVec, &array);
3018 data.getFieldData().swap(dotVector);
3019 }
3020
3021 double scale = (scalePtr) ? *scalePtr : 1.0;
3022 const size_t nb_base_functions = data.getN().size2() / 3;
3023 FTensor::Index<'i', Tensor_Dim0> i;
3024 FTensor::Index<'j', Tensor_Dim1> j;
3025 auto t_n_hvec = data.getFTensor1N<3>();
3026 auto t_data = getFTensor2FromMat<Tensor_Dim0, Tensor_Dim1>(*dataPtr);
3027 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3028 auto t_dof = data.getFTensor1FieldData<Tensor_Dim0>();
3029 size_t bb = 0;
3030 for (; bb != nb_dofs / Tensor_Dim0; ++bb) {
3031 t_data(i, j) += (scale * t_dof(i)) * t_n_hvec(j);
3032 ++t_n_hvec;
3033 ++t_dof;
3034 }
3035 for (; bb < nb_base_functions; ++bb)
3036 ++t_n_hvec;
3037 ++t_data;
3038 }
3039
3040 if (dataVec.use_count()) {
3041 data.getFieldData().swap(dotVector);
3042 }
3043 }
3045 }
3046
3047private:
3048 boost::shared_ptr<MatrixDouble> dataPtr;
3049 boost::shared_ptr<double> scalePtr;
3052 const int zeroSide;
3053 VectorDouble dotVector; ///< Keeps temporary values of time derivatives
3054};
3055
3056/** \brief Get tensor field for H-div approximation
3057 * \ingroup mofem_forces_and_sources_user_data_operators
3058 *
3059 * \warning This operator is not tested
3060 */
3061template <int Tensor_Dim0, int Tensor_Dim1>
3064
3066
3068 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
3069 SmartPetscObj<Vec> data_vec, EntityType broken_type,
3070 boost::shared_ptr<Range> broken_range_ptr = nullptr,
3071 boost::shared_ptr<double> scale_ptr = nullptr,
3072 const EntityType zero_type = MBEDGE, const int zero_side = 0)
3074 dataPtr(data_ptr), dataVec(data_vec), brokenType(broken_type),
3075 brokenRangePtr(broken_range_ptr), zeroType(zero_type) {
3076 if (!dataPtr)
3077 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Pointer is not set");
3078 }
3079
3080 /**
3081 * \brief Calculate values of vector field at integration points
3082 * @param side side entity number
3083 * @param type side entity type
3084 * @param data entity data
3085 * @return error code
3086 */
3087 MoFEMErrorCode doWork(int side, EntityType type,
3089
3090private:
3091 boost::shared_ptr<MatrixDouble> dataPtr;
3093 EntityType brokenType;
3094 boost::shared_ptr<Range> brokenRangePtr;
3095 boost::shared_ptr<double> scalePtr;
3098};
3099
3100template <int Tensor_Dim0, int Tensor_Dim1>
3103 int side, EntityType type, EntitiesFieldData::EntData &data) {
3105 const size_t nb_integration_points = OP::getGaussPts().size2();
3106 if (type == zeroType) {
3107 dataPtr->resize(Tensor_Dim0 * Tensor_Dim1, nb_integration_points, false);
3108 dataPtr->clear();
3109 }
3110 const size_t nb_dofs = data.getFieldData().size();
3111 if (!nb_dofs)
3113
3114 if (dataVec.use_count()) {
3115 dotVector.resize(nb_dofs, false);
3116 const double *array;
3117 CHKERR VecGetArrayRead(dataVec, &array);
3118 const auto &local_indices = data.getLocalIndices();
3119 for (int i = 0; i != local_indices.size(); ++i)
3120 if (local_indices[i] != -1)
3121 dotVector[i] = array[local_indices[i]];
3122 else
3123 dotVector[i] = 0;
3124 CHKERR VecRestoreArrayRead(dataVec, &array);
3125 data.getFieldData().swap(dotVector);
3126 }
3127
3128 /**
3129 * @brief Get side face dofs
3130 *
3131 * Find which base functions on borken space have adjacent given entity type
3132 * and are in the range ptr if given.
3133 *
3134 */
3135 auto get_get_side_face_dofs = [&]() {
3136 auto fe_type = OP::getFEType();
3137
3138 BaseFunction::DofsSideMap &side_dof_map =
3139 data.getFieldEntities()[0]->getDofSideMap().at(fe_type);
3140 std::vector<int> side_face_dofs;
3141 side_face_dofs.reserve(data.getIndices().size() / Tensor_Dim0);
3142
3143 for (
3144
3145 auto it = side_dof_map.get<1>().begin();
3146 it != side_dof_map.get<1>().end(); ++it
3147
3148 ) {
3149 if ((Tensor_Dim0 * it->dof) >= data.getIndices().size()) {
3150 break;
3151 }
3152 if (it->type == brokenType) {
3153 if (brokenRangePtr) {
3154 auto ent = OP::getSideEntity(it->side, brokenType);
3155 if (brokenRangePtr->find(ent) != brokenRangePtr->end()) {
3156 side_face_dofs.push_back(it->dof);
3157 }
3158 } else {
3159 side_face_dofs.push_back(it->dof);
3160 }
3161 }
3162 }
3163
3164 return side_face_dofs;
3165 };
3166
3167 auto side_face_dofs = get_get_side_face_dofs();
3168
3169 FTensor::Index<'i', Tensor_Dim0> i;
3170 FTensor::Index<'j', Tensor_Dim1> j;
3171 auto t_data = getFTensor2FromMat<Tensor_Dim0, Tensor_Dim1>(*dataPtr);
3172 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3173 for (auto b : side_face_dofs) {
3174 auto t_row_base = data.getFTensor1N<3>(gg, b);
3175 auto t_dof = getFTensor1FromPtr<Tensor_Dim0>(data.getFieldData().data() +
3176 b * Tensor_Dim0);
3177 t_data(i, j) += t_dof(i) * t_row_base(j);
3178 }
3179 ++t_data;
3180 }
3181 *dataPtr *= (scalePtr) ? *scalePtr : 1.0;
3182
3183 if (dataVec.use_count()) {
3184 data.getFieldData().swap(dotVector);
3185 }
3186
3188}
3189
3190/**
3191 * @brief Calculate tenor field using tensor base, i.e. Hdiv/Hcurl
3192 * \ingroup mofem_forces_and_sources_user_data_operators
3193 *
3194 * @tparam Tensor_Dim0 rank of the field
3195 * @tparam Tensor_Dim1 dimension of space
3196 */
3197template <int Tensor_Dim0, int Tensor_Dim1>
3200
3202 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
3203 boost::shared_ptr<double> scale_ptr,
3205 const EntityType zero_type = MBEDGE, const int zero_side = 0)
3208 dataPtr(data_ptr), scalePtr(scale_ptr), dataVec(data_vec),
3209 zeroType(zero_type), zeroSide(zero_side) {
3210 if (!dataPtr)
3211 THROW_MESSAGE("Pointer is not set");
3212 }
3213
3215 boost::shared_ptr<MatrixDouble> data_ptr,
3216 const EntityType zero_type = MBEDGE,
3217 const int zero_side = 0)
3218 : OpCalculateHTensorTensorField(field_name, data_ptr, nullptr,
3219 SmartPetscObj<Vec>(), zero_type,
3220 zero_side) {}
3221
3222 MoFEMErrorCode doWork(int side, EntityType type,
3225 const size_t nb_integration_points = getGaussPts().size2();
3226 if (type == zeroType && side == zeroSide) {
3227 dataPtr->resize(Tensor_Dim0 * Tensor_Dim1, nb_integration_points, false);
3228 dataPtr->clear();
3229 }
3230 const size_t nb_dofs = data.getFieldData().size();
3231 if (!nb_dofs)
3233
3234 if (dataVec.use_count()) {
3235 dotVector.resize(nb_dofs, false);
3236 const double *array;
3237 CHKERR VecGetArrayRead(dataVec, &array);
3238 const auto &local_indices = data.getLocalIndices();
3239 for (int i = 0; i != local_indices.size(); ++i)
3240 if (local_indices[i] != -1)
3241 dotVector[i] = array[local_indices[i]];
3242 else
3243 dotVector[i] = 0;
3244 CHKERR VecRestoreArrayRead(dataVec, &array);
3245 data.getFieldData().swap(dotVector);
3246 }
3247
3248 double scale = (scalePtr) ? *scalePtr : 1.0;
3249 const size_t nb_base_functions =
3250 data.getN().size2() / (Tensor_Dim0 * Tensor_Dim1);
3251 FTensor::Index<'i', Tensor_Dim0> i;
3252 FTensor::Index<'j', Tensor_Dim1> j;
3253 auto t_n_hten = data.getFTensor2N<Tensor_Dim0, Tensor_Dim1>();
3254 auto t_data = getFTensor2FromMat<Tensor_Dim0, Tensor_Dim1>(*dataPtr);
3255 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3256 auto t_dof = data.getFTensor0FieldData();
3257 size_t bb = 0;
3258 for (; bb != nb_dofs; ++bb) {
3259 t_data(i, j) += (scale * t_dof) * t_n_hten(i, j);
3260 ++t_n_hten;
3261 ++t_dof;
3262 }
3263 for (; bb < nb_base_functions; ++bb)
3264 ++t_n_hten;
3265 ++t_data;
3266 }
3267
3268 if (dataVec.use_count()) {
3269 data.getFieldData().swap(dotVector);
3270 }
3271
3273 }
3274
3275private:
3276 boost::shared_ptr<MatrixDouble> dataPtr;
3277 boost::shared_ptr<double> scalePtr;
3280 const int zeroSide;
3281 VectorDouble dotVector; ///< Keeps temporary values of time derivatives
3282};
3283
3284/**
3285 * @brief Calculate divergence of tonsorial field using vectorial base
3286 * \ingroup mofem_forces_and_sources_user_data_operators
3287 *
3288 * @tparam Tensor_Dim0 rank of the field
3289 * @tparam Tensor_Dim1 dimension of space
3290 */
3291template <int Tensor_Dim0, int Tensor_Dim1,
3292 CoordinateTypes CoordSys = CARTESIAN>
3295
3297 boost::shared_ptr<MatrixDouble> data_ptr,
3298 SmartPetscObj<Vec> data_vec,
3299 const EntityType zero_type = MBEDGE,
3300 const int zero_side = 0)
3303 dataPtr(data_ptr), dataVec(data_vec), zeroType(zero_type),
3304 zeroSide(zero_side) {
3305 if (!dataPtr)
3306 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Pointer is not set");
3307 }
3308
3310 boost::shared_ptr<MatrixDouble> data_ptr,
3311 const EntityType zero_type = MBEDGE,
3312 const int zero_side = 0)
3314 field_name, data_ptr, SmartPetscObj<Vec>(), zero_type, zero_side) {}
3315
3316 MoFEMErrorCode doWork(int side, EntityType type,
3319 const size_t nb_integration_points = getGaussPts().size2();
3320 if (type == zeroType && side == zeroSide) {
3321 dataPtr->resize(Tensor_Dim0, nb_integration_points, false);
3322 dataPtr->clear();
3323 }
3324 const size_t nb_dofs = data.getFieldData().size();
3325 if (nb_dofs) {
3326
3327 if (dataVec.use_count()) {
3328 dotVector.resize(nb_dofs, false);
3329 const double *array;
3330 CHKERR VecGetArrayRead(dataVec, &array);
3331 const auto &local_indices = data.getLocalIndices();
3332 for (int i = 0; i != local_indices.size(); ++i)
3333 if (local_indices[i] != -1)
3334 dotVector[i] = array[local_indices[i]];
3335 else
3336 dotVector[i] = 0;
3337 CHKERR VecRestoreArrayRead(dataVec, &array);
3338 data.getFieldData().swap(dotVector);
3339 }
3340
3341 const size_t nb_base_functions = data.getN().size2() / 3;
3342 FTensor::Index<'i', Tensor_Dim0> i;
3343 FTensor::Index<'j', Tensor_Dim1> j;
3344 auto t_n_diff_hvec = data.getFTensor2DiffN<3, Tensor_Dim1>();
3345 auto t_data = getFTensor1FromMat<Tensor_Dim0>(*dataPtr);
3346 auto t_base = data.getFTensor1N<3>();
3347 auto t_coords = getFTensor1CoordsAtGaussPts();
3348 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3349 auto t_dof = data.getFTensor1FieldData<Tensor_Dim0>();
3350 size_t bb = 0;
3351 for (; bb != nb_dofs / Tensor_Dim0; ++bb) {
3352 double div = t_n_diff_hvec(j, j);
3353 t_data(i) += t_dof(i) * div;
3354 if constexpr (CoordSys == CYLINDRICAL) {
3355 t_data(i) += t_base(0) * (t_dof(i) / t_coords(0));
3356 }
3357 ++t_n_diff_hvec;
3358 ++t_dof;
3359 ++t_base;
3360 }
3361 for (; bb < nb_base_functions; ++bb) {
3362 ++t_base;
3363 ++t_n_diff_hvec;
3364 }
3365 ++t_data;
3366 ++t_coords;
3367 }
3368
3369 if (dataVec.use_count()) {
3370 data.getFieldData().swap(dotVector);
3371 }
3372 }
3374 }
3375
3376private:
3377 boost::shared_ptr<MatrixDouble> dataPtr;
3380 const int zeroSide;
3381
3382 VectorDouble dotVector; ///< Keeps temporary values of time derivatives
3383};
3384
3385/**
3386 * @brief Calculate divergence of tonsorial field using vectorial base
3387 * \ingroup mofem_forces_and_sources_user_data_operators
3388 *
3389 * \warning This operator is not tested
3390 *
3391 * @tparam Tensor_Dim0 rank of the field
3392 * @tparam Tensor_Dim1 dimension of space
3393 */
3394template <int Tensor_Dim0, int Tensor_Dim1,
3395 CoordinateTypes CoordSys = CARTESIAN>
3398
3400
3402 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
3403 SmartPetscObj<Vec> data_vec, EntityType broken_type,
3404 boost::shared_ptr<Range> broken_range_ptr = nullptr,
3405 boost::shared_ptr<double> scale_ptr = nullptr,
3406 const EntityType zero_type = MBEDGE)
3408 dataPtr(data_ptr), dataVec(data_vec), brokenType(broken_type),
3409 brokenRangePtr(broken_range_ptr), scalePtr(scale_ptr),
3410 zeroType(zero_type) {
3411 if (!dataPtr)
3412 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Pointer is not set");
3413 }
3414
3415 MoFEMErrorCode doWork(int side, EntityType type,
3418 const size_t nb_integration_points = getGaussPts().size2();
3419 if (type == zeroType && side == 0) {
3420 dataPtr->resize(Tensor_Dim0, nb_integration_points, false);
3421 dataPtr->clear();
3422 }
3423
3424 const size_t nb_dofs = data.getFieldData().size();
3425 if (nb_dofs) {
3426
3427 if (dataVec.use_count()) {
3428 dotVector.resize(nb_dofs, false);
3429 const double *array;
3430 CHKERR VecGetArrayRead(dataVec, &array);
3431 const auto &local_indices = data.getLocalIndices();
3432 for (int i = 0; i != local_indices.size(); ++i)
3433 if (local_indices[i] != -1)
3434 dotVector[i] = array[local_indices[i]];
3435 else
3436 dotVector[i] = 0;
3437 CHKERR VecRestoreArrayRead(dataVec, &array);
3438 data.getFieldData().swap(dotVector);
3439 }
3440
3441 /**
3442 * @brief Get side face dofs
3443 *
3444 * Find which base functions on borken space have adjacent given entity
3445 * type and are in the range ptr if given.
3446 *
3447 */
3448 auto get_get_side_face_dofs = [&]() {
3449 auto fe_type = OP::getFEType();
3450
3451 BaseFunction::DofsSideMap &side_dof_map =
3452 data.getFieldEntities()[0]->getDofSideMap().at(fe_type);
3453 std::vector<int> side_face_dofs;
3454 side_face_dofs.reserve(data.getIndices().size() / Tensor_Dim0);
3455
3456 for (
3457
3458 auto it = side_dof_map.get<1>().begin();
3459 it != side_dof_map.get<1>().end(); ++it
3460
3461 ) {
3462 if ((Tensor_Dim0 * it->dof) >= data.getIndices().size()) {
3463 break;
3464 }
3465 if (it->type == brokenType) {
3466 if (brokenRangePtr) {
3467 auto ent = OP::getSideEntity(it->side, brokenType);
3468 if (brokenRangePtr->find(ent) != brokenRangePtr->end()) {
3469 side_face_dofs.push_back(it->dof);
3470 }
3471 } else {
3472 side_face_dofs.push_back(it->dof);
3473 }
3474 }
3475 }
3476
3477 return side_face_dofs;
3478 };
3479
3480 auto side_face_dofs = get_get_side_face_dofs();
3481
3482 FTensor::Index<'i', Tensor_Dim0> i;
3483 FTensor::Index<'j', Tensor_Dim1> j;
3484 auto t_data = getFTensor1FromMat<Tensor_Dim0>(*dataPtr);
3485 auto t_coords = getFTensor1CoordsAtGaussPts();
3486 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3487 for (auto b : side_face_dofs) {
3488 auto t_dof = getFTensor1FromPtr<Tensor_Dim0>(
3489 data.getFieldData().data() + b * Tensor_Dim0);
3490 auto t_base = data.getFTensor1N<3>(gg, b);
3491 auto t_diff_base = data.getFTensor2DiffN<3, Tensor_Dim1>(gg, b);
3492 double div = t_diff_base(j, j);
3493 t_data(i) += t_dof(i) * div;
3494 if constexpr (CoordSys == CYLINDRICAL) {
3495 t_data(i) += t_base(0) * (t_dof(i) / t_coords(0));
3496 }
3497 }
3498 ++t_data;
3499 ++t_coords;
3500 }
3501 }
3502
3503 if (dataVec.use_count()) {
3504 data.getFieldData().swap(dotVector);
3505 }
3506
3508 }
3509
3510private:
3511 boost::shared_ptr<MatrixDouble> dataPtr;
3513 EntityType brokenType;
3514 boost::shared_ptr<Range> brokenRangePtr;
3515 boost::shared_ptr<double> scalePtr;
3518};
3519
3520/**
3521 * @brief Calculate trace of vector (Hdiv/Hcurl) space
3522 *
3523 * @tparam Tensor_Dim
3524 * @tparam OpBase
3525 */
3526template <int Tensor_Dim, typename OpBase>
3528
3530 boost::shared_ptr<MatrixDouble> data_ptr,
3531 boost::shared_ptr<double> scale_ptr,
3532 const EntityType zero_type = MBEDGE,
3533 const int zero_side = 0)
3534 : OpBase(field_name, OpBase::OPCOL), dataPtr(data_ptr),
3535 scalePtr(scale_ptr), zeroType(zero_type), zeroSide(zero_side) {
3536 if (!dataPtr)
3537 THROW_MESSAGE("Pointer is not set");
3538 }
3539
3541 boost::shared_ptr<MatrixDouble> data_ptr,
3542 const EntityType zero_type = MBEDGE,
3543 const int zero_side = 0)
3544 : OpCalculateHVecTensorTrace(field_name, data_ptr, nullptr, zero_type,
3545 zero_side) {}
3546
3547 MoFEMErrorCode doWork(int side, EntityType type,
3550 const size_t nb_integration_points = OpBase::getGaussPts().size2();
3551 if (type == zeroType && side == 0) {
3552 dataPtr->resize(Tensor_Dim, nb_integration_points, false);
3553 dataPtr->clear();
3554 }
3555 const size_t nb_dofs = data.getFieldData().size();
3556 if (nb_dofs) {
3557 double scale_val = (scalePtr) ? *scalePtr : 1.0;
3558 auto t_normal = OpBase::getFTensor1NormalsAtGaussPts();
3559 const size_t nb_base_functions = data.getN().size2() / 3;
3560 auto t_base = data.getFTensor1N<3>();
3561 auto t_data = getFTensor1FromMat<Tensor_Dim>(*dataPtr);
3562 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3563 FTensor::Tensor1<double, Tensor_Dim> t_normalized_normal;
3564 t_normalized_normal(j) = t_normal(j);
3565 t_normalized_normal.normalize();
3566 auto t_dof = data.getFTensor1FieldData<Tensor_Dim>();
3567 size_t bb = 0;
3568 for (; bb != nb_dofs / Tensor_Dim; ++bb) {
3569 t_data(i) +=
3570 (scale_val * t_dof(i)) * (t_base(j) * t_normalized_normal(j));
3571 ++t_base;
3572 ++t_dof;
3573 }
3574 for (; bb < nb_base_functions; ++bb) {
3575 ++t_base;
3576 }
3577 ++t_data;
3578 ++t_normal;
3579 }
3580 }
3582 }
3583
3584private:
3585 boost::shared_ptr<MatrixDouble> dataPtr;
3586 boost::shared_ptr<double> scalePtr;
3588 const int zeroSide;
3589 FTensor::Index<'i', Tensor_Dim> i;
3590 FTensor::Index<'j', Tensor_Dim> j;
3591};
3592
3593/**@}*/
3594
3595/** \name Other operators */
3596
3597/**@{*/
3598
3599/**@}*/
3600
3601/** \name Operators for faces */
3602
3603/**@{*/
3604
3605/** \brief Transform local reference derivatives of shape functions to global
3606derivatives
3607
3608\ingroup mofem_forces_and_sources_tri_element
3609
3610*/
3611template <int DIM, int DERIVATIVE = 1> struct OpSetInvJacSpaceForFaceImpl;
3612
3615
3617 boost::shared_ptr<MatrixDouble> inv_jac_ptr);
3618
3619protected:
3620 /**
3621 * @brief Apply transformation to the input matrix
3622 *
3623 * @tparam D1 dimension of the derivative of base functions in input
3624 * @tparam D2 dimension of the derivative of base functions in output
3625 * @tparam J1 nb of rows in jacobian (= dimension of space)
3626 * @tparam J2 nb of columns in jacobian (= dimension of reference element)
3627 * @param diff_n
3628 * @return MoFEMErrorCode
3629 */
3630 template <int D1, int D2, int J1, int J2>
3633
3634 static_assert(D2 == J2, "Dimension of jacobian and dimension of <out> "
3635 "directive does not match");
3636
3637 size_t nb_functions = diff_n.size2() / D1;
3638 if (nb_functions) {
3639 size_t nb_gauss_pts = diff_n.size1();
3640
3641 #ifndef NDEBUG
3642 if (nb_gauss_pts != getGaussPts().size2())
3643 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3644 "Wrong number of Gauss Pts");
3645 if (diff_n.size2() % D1)
3646 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3647 "Number of directives of base functions and D1 dimension does "
3648 "not match");
3649 #endif
3650
3651 diffNinvJac.resize(diff_n.size1(), D2 * nb_functions, false);
3652
3653 FTensor::Index<'i', D2> i;
3654 FTensor::Index<'k', D1> k;
3655 auto t_diff_n = getFTensor1FromPtr<D2>(&*diffNinvJac.data().begin());
3656 auto t_diff_n_ref = getFTensor1FromPtr<D1>(&*diff_n.data().begin());
3657 auto t_inv_jac = getFTensor2FromMat<J1, J2>(*invJacPtr);
3658 for (size_t gg = 0; gg != nb_gauss_pts; ++gg, ++t_inv_jac) {
3659 for (size_t dd = 0; dd != nb_functions; ++dd) {
3660 t_diff_n(i) = t_inv_jac(k, i) * t_diff_n_ref(k);
3661 ++t_diff_n;
3662 ++t_diff_n_ref;
3663 }
3664 }
3665
3666 diff_n.swap(diffNinvJac);
3667 }
3669 }
3670
3671 boost::shared_ptr<MatrixDouble> invJacPtr;
3673};
3674
3675template <>
3678
3680
3681 MoFEMErrorCode doWork(int side, EntityType type,
3683};
3684
3685template <>
3687 : public OpSetInvJacSpaceForFaceImpl<2, 1> {
3688
3689 using OpSetInvJacSpaceForFaceImpl<2, 1>::OpSetInvJacSpaceForFaceImpl;
3690
3691 MoFEMErrorCode doWork(int side, EntityType type,
3693};
3694
3695template <>
3697 : public OpSetInvJacSpaceForFaceImpl<2, 1> {
3698
3699 using OpSetInvJacSpaceForFaceImpl<2, 1>::OpSetInvJacSpaceForFaceImpl;
3700
3701 MoFEMErrorCode doWork(int side, EntityType type,
3703};
3704
3705template <int DERIVARIVE = 1>
3707 : public OpSetInvJacSpaceForFaceImpl<2, DERIVARIVE> {
3708 OpSetInvJacH1ForFace(boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3709 : OpSetInvJacSpaceForFaceImpl<2, DERIVARIVE>(H1, inv_jac_ptr) {}
3710};
3711
3712template <int DERIVARIVE = 1>
3714 : public OpSetInvJacSpaceForFaceImpl<2, DERIVARIVE> {
3715 OpSetInvJacL2ForFace(boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3716 : OpSetInvJacSpaceForFaceImpl<2, DERIVARIVE>(L2, inv_jac_ptr) {}
3717};
3718
3719template <int DERIVARIVE = 1>
3721 : public OpSetInvJacSpaceForFaceImpl<3, DERIVARIVE> {
3723 boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3724 : OpSetInvJacSpaceForFaceImpl<3, DERIVARIVE>(H1, inv_jac_ptr) {}
3725};
3726
3727template <int DERIVARIVE = 1>
3729 : public OpSetInvJacSpaceForFaceImpl<3, DERIVARIVE> {
3731 boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3732 : OpSetInvJacSpaceForFaceImpl<3, DERIVARIVE>(L2, inv_jac_ptr) {}
3733};
3734
3735/**
3736 * \brief Transform local reference derivatives of shape function to
3737 global derivatives for face
3738
3739 * \ingroup mofem_forces_and_sources_tri_element
3740 */
3741template <int DIM> struct OpSetInvJacHcurlFaceImpl;
3742
3743template <>
3746
3747 OpSetInvJacHcurlFaceImpl(boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3749 invJacPtr(inv_jac_ptr) {}
3750
3751 MoFEMErrorCode doWork(int side, EntityType type,
3753
3754protected:
3755 boost::shared_ptr<MatrixDouble> invJacPtr;
3757};
3758
3759template <>
3761 using OpSetInvJacHcurlFaceImpl<2>::OpSetInvJacHcurlFaceImpl;
3762 MoFEMErrorCode doWork(int side, EntityType type,
3764};
3765
3768
3769/**
3770 * @brief Make Hdiv space from Hcurl space in 2d
3771 * @ingroup mofem_forces_and_sources_tri_element
3772 */
3782
3783/** \brief Transform Hcurl base fluxes from reference element to physical
3784 * triangle
3785 */
3787
3788/** \brief Apply contravariant (Piola) transfer to Hdiv space on face
3789 *
3790 * Covariant Piola transformation
3791 \f[
3792 \psi_i|_t = J^{-1}_{ij}\hat{\psi}_j\\
3793 \left.\frac{\partial \psi_i}{\partial \xi_j}\right|_t
3794 = J^{-1}_{ik}\frac{\partial \hat{\psi}_k}{\partial \xi_j}
3795 \f]
3796
3797 */
3798template <>
3801
3803 boost::shared_ptr<MatrixDouble> inv_jac_ptr);
3804
3805 MoFEMErrorCode doWork(int side, EntityType type,
3807
3808private:
3809 boost::shared_ptr<MatrixDouble> invJacPtr;
3810
3813};
3814
3817
3818/** \brief Apply contravariant (Piola) transfer to Hdiv space on face
3819 *
3820 * \note Hdiv space is generated by Hcurl space in 2d.
3821 *
3822 * Contravariant Piola transformation
3823 * \f[
3824 * \psi_i|_t = \frac{1}{\textrm{det}(J)}J_{ij}\hat{\psi}_j\\
3825 * \left.\frac{\partial \psi_i}{\partial \xi_j}\right|_t
3826 * =
3827 * \frac{1}{\textrm{det}(J)}J_{ik}\frac{\partial \hat{\psi}_k}{\partial \xi_j}
3828 * \f]
3829 *
3830 * \ingroup mofem_forces_and_sources
3831 *
3832 */
3834
3835template <>
3838
3840 boost::shared_ptr<MatrixDouble> jac_ptr)
3842 jacPtr(jac_ptr) {}
3843
3844 MoFEMErrorCode doWork(int side, EntityType type,
3846
3847protected:
3848 boost::shared_ptr<MatrixDouble> jacPtr;
3851};
3852
3853template <>
3857 2>::OpSetContravariantPiolaTransformOnFace2DImpl;
3858
3859 MoFEMErrorCode doWork(int side, EntityType type,
3861};
3862
3867
3868/**@}*/
3869
3870/** \name Operators for edges */
3871
3872/**@{*/
3873
3883
3884/**
3885 * @deprecated Name is deprecated and this is added for backward compatibility
3886 */
3889
3890/**@}*/
3891
3892/** \name Operator for fat prisms */
3893
3894/**@{*/
3895
3896/**
3897 * @brief Operator for fat prism element updating integration weights in the
3898 * volume.
3899 *
3900 * Jacobian on the distorted element is nonconstant. This operator updates
3901 * integration weight on prism to take into account nonconstat jacobian.
3902 *
3903 * \f[
3904 * W_i = w_i \left( \frac{1}{2V} \left\| \frac{\partial \mathbf{x}}{\partial
3905 * \pmb\xi} \right\| \right)
3906 * \f]
3907 * where \f$w_i\f$ is integration weight at integration point \f$i\f$,
3908 * \f$\mathbf{x}\f$ is physical coordinate, and \f$\pmb\xi\f$ is reference
3909 * element coordinate.
3910 *
3911 */
3921
3922/** \brief Calculate inverse of jacobian for face element
3923
3924 It is assumed that face element is XY plane. Applied
3925 only for 2d problems.
3926
3927 FIXME Generalize function for arbitrary face orientation in 3d space
3928 FIXME Calculate to Jacobins for two faces
3929
3930 \ingroup mofem_forces_and_sources_prism_element
3931
3932*/
3935
3936 OpCalculateInvJacForFatPrism(boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3938 invJacPtr(inv_jac_ptr), invJac(*invJacPtr) {}
3939
3943 MoFEMErrorCode doWork(int side, EntityType type,
3945
3946private:
3947 const boost::shared_ptr<MatrixDouble> invJacPtr;
3949};
3950
3951/** \brief Transform local reference derivatives of shape functions to global
3952derivatives
3953
3954FIXME Generalize to curved shapes
3955FIXME Generalize to case that top and bottom face has different shape
3956
3957\ingroup mofem_forces_and_sources_prism_element
3958
3959*/
3962
3963 OpSetInvJacH1ForFatPrism(boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3965 invJacPtr(inv_jac_ptr), invJac(*invJacPtr) {}
3966
3970
3971 MoFEMErrorCode doWork(int side, EntityType type,
3973
3974private:
3975 const boost::shared_ptr<MatrixDouble> invJacPtr;
3978};
3979
3980// Flat prism
3981
3982/** \brief Calculate inverse of jacobian for face element
3983
3984 It is assumed that face element is XY plane. Applied
3985 only for 2d problems.
3986
3987 FIXME Generalize function for arbitrary face orientation in 3d space
3988 FIXME Calculate to Jacobins for two faces
3989
3990 \ingroup mofem_forces_and_sources_prism_element
3991
3992*/
4005
4006/** \brief Transform local reference derivatives of shape functions to global
4007derivatives
4008
4009FIXME Generalize to curved shapes
4010FIXME Generalize to case that top and bottom face has different shape
4011
4012\ingroup mofem_forces_and_sources_prism_element
4013
4014*/
4029
4030/**@}*/
4031
4032/** \name Operation on matrices at integration points */
4033
4034/**@{*/
4035
4036/**
4037 * @brief Operator for inverting matrices at integration points
4038 *
4039 * This template structure computes the inverse of square matrices and their
4040 * determinants at integration points. It's commonly used in finite element
4041 * methods for coordinate transformations, constitutive relations, and other
4042 * matrix operations requiring matrix inversion.
4043 *
4044 * @tparam DIM Dimension of the square matrix to be inverted
4045 */
4046template <int DIM>
4048
4049 /**
4050 * @brief Constructor for matrix inversion operator
4051 *
4052 * @param in_ptr Shared pointer to input matrix to be inverted
4053 * @param det_ptr Shared pointer to vector for storing matrix determinants
4054 * @param out_ptr Shared pointer to output matrix for storing inverted matrices
4055 */
4056 OpInvertMatrix(boost::shared_ptr<MatrixDouble> in_ptr,
4057 boost::shared_ptr<VectorDouble> det_ptr,
4058 boost::shared_ptr<MatrixDouble> out_ptr)
4060 outPtr(out_ptr), detPtr(det_ptr) {}
4061
4062 MoFEMErrorCode doWork(int side, EntityType type,
4064
4065private:
4066 boost::shared_ptr<MatrixDouble> inPtr;
4067 boost::shared_ptr<MatrixDouble> outPtr;
4068 boost::shared_ptr<VectorDouble> detPtr;
4069};
4070
4071template <int DIM>
4075
4076 if (!inPtr)
4077 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4078 "Pointer for inPtr matrix not allocated");
4079 if (!detPtr)
4080 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4081 "Pointer for detPtr matrix not allocated");
4082
4083 const auto nb_rows = inPtr->size1();
4084 const auto nb_integration_pts = inPtr->size2();
4085
4086 // Calculate determinant
4087 {
4088 detPtr->resize(nb_integration_pts, false);
4089 auto t_in = getFTensor2FromMat<DIM, DIM>(*inPtr);
4090 auto t_det = getFTensor0FromVec(*detPtr);
4091 for (size_t gg = 0; gg != nb_integration_pts; ++gg) {
4092 t_det = determinantTensor(t_in);
4093 ++t_in;
4094 ++t_det;
4095 }
4096 }
4097
4098 // Invert jacobian
4099 if (outPtr) {
4100 outPtr->resize(nb_rows, nb_integration_pts, false);
4101 auto t_in = getFTensor2FromMat<DIM, DIM>(*inPtr);
4102 auto t_out = getFTensor2FromMat<DIM, DIM>(*outPtr);
4103 auto t_det = getFTensor0FromVec(*detPtr);
4104 for (size_t gg = 0; gg != nb_integration_pts; ++gg) {
4105 CHKERR invertTensor(t_in, t_det, t_out);
4106 ++t_in;
4107 ++t_out;
4108 ++t_det;
4109 }
4110 }
4111
4113}
4114
4115/**@}*/
4116
4117/**
4118 * @brief Operator for calculating the trace of matrices at integration points
4119 *
4120 * This template structure computes the trace (sum of diagonal elements) of
4121 * square matrices at integration points. The trace is commonly used in
4122 * mechanics for calculating volumetric strain, pressure, and other scalar
4123 * quantities derived from tensors.
4124 *
4125 * @tparam DIM Dimension of the square matrix
4126 *
4127 * @ingroup mofem_forces_and_sources
4128 */
4129template <int DIM>
4131
4132 /**
4133 * @brief Constructor for matrix trace calculation operator
4134 *
4135 * @param in_ptr Shared pointer to input matrix for trace calculation
4136 * @param out_ptr Shared pointer to output vector for storing calculated traces
4137 */
4138 OpCalculateTraceFromMat(boost::shared_ptr<MatrixDouble> in_ptr,
4139 boost::shared_ptr<VectorDouble> out_ptr)
4141 outPtr(out_ptr) {}
4142
4143 MoFEMErrorCode doWork(int side, EntityType type,
4145
4146private:
4148 boost::shared_ptr<MatrixDouble> inPtr;
4149 boost::shared_ptr<VectorDouble> outPtr;
4150};
4151
4152template <int DIM>
4157
4158 if (!inPtr)
4159 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4160 "Pointer for inPtr matrix not allocated");
4161
4162 const auto nb_integration_pts = inPtr->size2();
4163 // Invert jacobian
4164 if (outPtr) {
4165 outPtr->resize(nb_integration_pts, false);
4166 auto t_in = getFTensor2FromMat<DIM, DIM>(*inPtr);
4167 auto t_out = getFTensor0FromVec(*outPtr);
4168
4169 for (size_t gg = 0; gg != nb_integration_pts; ++gg) {
4170 t_out = t_in(i, i);
4171 ++t_in;
4172 ++t_out;
4173 }
4174 }
4175
4177}
4178
4179/**@}*/
4180
4181/** \brief Calculates the trace of an input matrix
4182
4183\ingroup mofem_forces_and_sources
4184
4185*/
4186
4187template <int DIM>
4190
4191 OpCalculateTraceFromSymmMat(boost::shared_ptr<MatrixDouble> in_ptr,
4192 boost::shared_ptr<VectorDouble> out_ptr)
4194 outPtr(out_ptr) {}
4195
4196 MoFEMErrorCode doWork(int side, EntityType type,
4198
4199private:
4201 boost::shared_ptr<MatrixDouble> inPtr;
4202 boost::shared_ptr<VectorDouble> outPtr;
4203};
4204
4205template <int DIM>
4210
4211 if (!inPtr)
4212 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4213 "Pointer for inPtr matrix not allocated");
4214
4215 const auto nb_integration_pts = inPtr->size2();
4216 // Invert jacobian
4217 if (outPtr) {
4218 outPtr->resize(nb_integration_pts, false);
4219 auto t_in = getFTensor2SymmetricFromMat<DIM>(*inPtr);
4220 auto t_out = getFTensor0FromVec(*outPtr);
4221
4222 for (size_t gg = 0; gg != nb_integration_pts; ++gg) {
4223 t_out = t_in(i, i);
4224 ++t_in;
4225 ++t_out;
4226 }
4227 }
4228
4230}
4231
4232} // namespace MoFEM
4233
4234#endif // __USER_DATA_OPERATORS_HPP__
4235
4236/**
4237 * \defgroup mofem_forces_and_sources_user_data_operators Users Operators
4238 *
4239 * \brief Classes and functions used to evaluate fields at integration pts,
4240 *jacobians, etc..
4241 *
4242 * \ingroup mofem_forces_and_sources
4243 **/
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.
@ OPCOL
operator doWork function is executed on FE columns
@ 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