v0.16.0
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 with PETSc vector support
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 data_vec Smart PETSc vector object for additional data storage
79 * @param zero_type Entity type for zero-level entities (default: MBVERTEX)
80 */
83 const std::string field_name,
84 boost::shared_ptr<ublas::vector<T, A>> data_ptr,
85 SmartPetscObj<Vec> data_vec, const EntityType zero_type = MBVERTEX)
87 dataPtr(data_ptr), zeroType(zero_type), dataVec(data_vec) {
88 if (!dataPtr)
89 THROW_MESSAGE("Pointer is not set");
90 }
91
93 const std::string field_name,
94 boost::shared_ptr<ublas::vector<T, A>> data_ptr,
95 SmartPetscObj<Vec> data_vec, const EntityType zero_type = MBVERTEX)
98 data_vec, zero_type) {}
99
100 /**
101 * @brief Constructor for scalar field values calculation operator
102 *
103 * @param field_name Name of the scalar field to calculate values for
104 * @param data_ptr Shared pointer to ublas vector for storing calculated values
105 * @param zero_type Entity type for zero-level entities (default: MBVERTEX)
106 */
108 const std::string field_name,
109 boost::shared_ptr<ublas::vector<T, A>> data_ptr,
110 const EntityType zero_type = MBVERTEX)
113 SmartPetscObj<Vec>(), zero_type) {}
114
115 /**
116 * \brief calculate values of scalar field at integration points
117 * @param side side entity number
118 * @param type side entity type
119 * @param data entity data
120 * @return error code
121 */
122 MoFEMErrorCode doWork(int side, EntityType type,
124
125protected:
126 boost::shared_ptr<ublas::vector<T, A>> dataPtr;
130};
131
132/**
133 * \brief Specialization of member function
134 *
135 */
136template <class T, class A>
138 int side, EntityType type, EntitiesFieldData::EntData &data) {
140 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED, "Not implemented for T = %s",
141 typeid(T).name() // boost::core::demangle(typeid(T).name()).c_str()
142 );
144}
145
146/**
147 * @brief Specialization for double precision scalar field values calculation
148 *
149 * This structure is a specialization of OpCalculateScalarFieldValues_General
150 * for double precision scalar fields using DoubleAllocator. It provides
151 * concrete implementation for calculating scalar field values at integration
152 * points and storing them in double precision format.
153 *
154 * @ingroup mofem_forces_and_sources_user_data_operators
155 */
157 : public OpCalculateScalarFieldValues_General<double, DoubleAllocator> {
158
160 double, DoubleAllocator>::OpCalculateScalarFieldValues_General;
161
162 /**
163 * \brief calculate values of scalar field at integration points
164 * @param side side entity number
165 * @param type side entity type
166 * @param data entity data
167 * @return error code
168 */
169 MoFEMErrorCode doWork(int side, EntityType type,
172 VectorDouble &vec = *dataPtr;
173 const size_t nb_gauss_pts = getGaussPts().size2();
174 if (type == zeroType || vec.size() != nb_gauss_pts) {
175 vec.resize(nb_gauss_pts, false);
176 vec.clear();
177 }
178
179 const size_t nb_dofs = data.getFieldData().size();
180
181 if (nb_dofs) {
182
183 if (dataVec.use_count()) {
184 dotVector.resize(nb_dofs, false);
185 const double *array;
186 CHKERR VecGetArrayRead(dataVec, &array);
187 const auto &local_indices = data.getLocalIndices();
188 for (int i = 0; i != local_indices.size(); ++i)
189 if (local_indices[i] != -1)
190 dotVector[i] = array[local_indices[i]];
191 else
192 dotVector[i] = 0;
193 CHKERR VecRestoreArrayRead(dataVec, &array);
194 data.getFieldData().swap(dotVector);
195 }
196
197 const size_t nb_base_functions = data.getN().size2();
198 auto base_function = data.getFTensor0N();
199 auto values_at_gauss_pts = getFTensor0FromVec(vec);
200 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
201 auto field_data = data.getFTensor0FieldData();
202 size_t bb = 0;
203 for (; bb != nb_dofs; ++bb) {
204 values_at_gauss_pts += field_data * base_function;
205 ++field_data;
206 ++base_function;
207 }
208 // It is possible to have more base functions than dofs
209 for (; bb < nb_base_functions; ++bb)
210 ++base_function;
211 ++values_at_gauss_pts;
212 }
213
214 if (dataVec.use_count()) {
215 data.getFieldData().swap(dotVector);
216 }
217 }
218
220 }
221};
222
223/**
224 * @brief Calculate scalar field values from PETSc vector at integration points
225 *
226 * This template structure extracts scalar field values from a PETSc vector
227 * and calculates them at integration points. It supports different data contexts
228 * through the template parameter and can handle various entity types.
229 *
230 * @tparam CTX PETSc data context type specifying how data is accessed
231 *
232 * @ingroup mofem_forces_and_sources_user_data_operators
233 */
234template <PetscData::DataContext CTX>
237
238 /**
239 * @brief Constructor for PETSc vector-based scalar field calculation
240 *
241 * @param field_name Name of the scalar field to extract values from
242 * @param data_ptr Shared pointer to VectorDouble for storing calculated values
243 * @param zero_at_type Entity type where values should be zeroed (default: MBVERTEX)
244 */
246 const std::string field_name, boost::shared_ptr<VectorDouble> data_ptr,
247 const EntityType zero_at_type = MBVERTEX)
250 dataPtr(data_ptr), zeroAtType(zero_at_type) {
251 if (!dataPtr)
252 THROW_MESSAGE("Pointer is not set");
253 }
254
255 MoFEMErrorCode doWork(int side, EntityType type,
258
259 const size_t nb_gauss_pts = getGaussPts().size2();
260
261 VectorDouble &vec = *dataPtr;
262 if (type == zeroAtType || vec.size() != nb_gauss_pts) {
263 vec.resize(nb_gauss_pts, false);
264 vec.clear();
265 }
266
267 auto &local_indices = data.getLocalIndices();
268 const size_t nb_dofs = local_indices.size();
269 if (nb_dofs) {
270
271 const double *array;
272
273 auto get_array = [&](const auto ctx, auto vec) {
275 #ifndef NDEBUG
276 if ((getFEMethod()->data_ctx & ctx).none()) {
277 MOFEM_LOG_CHANNEL("SELF");
278 MOFEM_LOG("SELF", Sev::error)
279 << "In this case field degrees of freedom are read from vector. "
280 "That usually happens when time solver is used, and acces to "
281 "first or second rates is needed. You probably not set ts_u, "
282 "ts_u_t, or ts_u_tt and associated data structure, i.e. "
283 "data_ctx to CTX_SET_X, CTX_SET_X_T, or CTX_SET_X_TT "
284 "respectively";
285 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Vector not set!");
286 }
287 #endif
288 CHKERR VecGetArrayRead(vec, &array);
290 };
291
292 auto restore_array = [&](auto vec) {
293 return VecRestoreArrayRead(vec, &array);
294 };
295
296 switch (CTX) {
298 CHKERR get_array(PetscData::CtxSetX, getFEMethod()->ts_u);
299 break;
301 CHKERR get_array(PetscData::CtxSetX_T, getFEMethod()->ts_u_t);
302 break;
304 CHKERR get_array(PetscData::CtxSetX_TT, getFEMethod()->ts_u_tt);
305 break;
306 default:
307 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
308 "That case is not implemented");
309 }
310
311 std::array<double, MAX_DOFS_ON_ENTITY> dot_dofs_vector;
312 for (int i = 0; i != local_indices.size(); ++i)
313 if (local_indices[i] != -1)
314 dot_dofs_vector[i] = array[local_indices[i]];
315 else
316 dot_dofs_vector[i] = 0;
317
318 switch (CTX) {
320 CHKERR restore_array(getFEMethod()->ts_u);
321 break;
323 CHKERR restore_array(getFEMethod()->ts_u_t);
324 break;
326 CHKERR restore_array(getFEMethod()->ts_u_tt);
327 break;
328 default:
329 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
330 "That case is not implemented");
331 }
332
333 const size_t nb_base_functions = data.getN().size2();
334 auto base_function = data.getFTensor0N();
335 auto values_at_gauss_pts = getFTensor0FromVec(vec);
336
337 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
338 size_t bb = 0;
339 for (; bb != nb_dofs; ++bb) {
340 values_at_gauss_pts += dot_dofs_vector[bb] * base_function;
341 ++base_function;
342 }
343 // Number of dofs can be smaller than number of Tensor_Dim x base
344 // functions
345 for (; bb < nb_base_functions; ++bb)
346 ++base_function;
347 ++values_at_gauss_pts;
348 }
349 }
351 }
352
353private:
354 boost::shared_ptr<VectorDouble> dataPtr;
356};
357
362
363/**
364 * \deprecated Name inconsistent with other operators
365 *
366 */
368
369/**@}*/
370
371/** \name Vector field values at integration points */
372
373/**@{*/
374
375/**
376 * @brief Calculate field values for tensor field rank 1, i.e. vector field
377 *
378 * This template structure calculates vector field values at integration points
379 * and stores them in a matrix container. It supports various tensor dimensions,
380 * matrix storage types through template parameters.
381 *
382 * @tparam Tensor_Dim Dimension of the vector field (e.g., 2 for 2D, 3 for 3D)
383 * @tparam M Matrix storage type for the field values
384 */
385template <int Tensor_Dim, typename M = MatrixDouble>
388
389 /**
390 * @brief Constructor for vector field values calculation operator
391 *
392 * @param field_name Name of the vector field to calculate values for
393 * @param data_ptr Shared pointer to ublas matrix for storing calculated values
394 * @param zero_type Entity type for zero-level entities (default: MBVERTEX)
395 */
397 const std::string field_name,
398 boost::shared_ptr<M> data_ptr,
399 const EntityType zero_type = MBVERTEX)
402 dataPtr(data_ptr), zeroType(zero_type) {
403 if (!dataPtr)
404 THROW_MESSAGE("Pointer is not set");
405 }
406
407 /**
408 * \brief calculate values of vector field at integration points
409 * @param side side entity number
410 * @param type side entity type
411 * @param data entity data
412 * @return error code
413 */
414 MoFEMErrorCode doWork(int side, EntityType type,
416
417protected:
418 boost::shared_ptr<M> dataPtr;
420};
421
422template <int Tensor_Dim, typename M>
425 int side, EntityType type, EntitiesFieldData::EntData &data) {
427 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
428 "Not implemented for matrix type = %s and dim = %d",
429 typeid(M).name(), // boost::core::demangle(typeid(M).name()),
430 Tensor_Dim);
432}
433
434/** \brief Calculate field values (template specialization) for tensor field
435 * rank 1, i.e. vector field
436 *
437 */
438template <int Tensor_Dim>
441
443 boost::shared_ptr<MatrixDouble> data_ptr,
444 const EntityType zero_type = MBVERTEX)
447 dataPtr(data_ptr), zeroType(zero_type) {
448 if (!dataPtr)
449 THROW_MESSAGE("Pointer is not set");
450 }
451
453 boost::shared_ptr<MatrixDouble> data_ptr,
454 SmartPetscObj<Vec> data_vec,
455 const EntityType zero_type = MBVERTEX)
458 dataPtr(data_ptr), dataVec(data_vec), zeroType(zero_type) {
459 if (!dataPtr)
460 THROW_MESSAGE("Pointer is not set");
461 }
462
463 MoFEMErrorCode doWork(int side, EntityType type,
465
466protected:
467 boost::shared_ptr<MatrixDouble> dataPtr;
471};
472
473/**
474 * \brief Member function specialization calculating values for tenor field rank
475 *
476 */
477template <int Tensor_Dim>
479 Tensor_Dim, MatrixDouble>::doWork(int side, EntityType type,
482
483 const size_t nb_gauss_pts = getGaussPts().size2();
484 auto &mat = *dataPtr;
485
487 auto get_values_at_gauss_pts =
488 MatrixSizeHelper<GetFTensor1FromMatType<Tensor_Dim, -1, DL>, DL>::size(
489 mat, nb_gauss_pts);
490 if (type == zeroType) {
491 mat.clear();
492 }
493
494 const size_t nb_dofs = data.getFieldData().size();
495 if (nb_dofs) {
496
497 if (dataVec.use_count()) {
498 dotVector.resize(nb_dofs, false);
499 const double *array;
500 CHKERR VecGetArrayRead(dataVec, &array);
501 const auto &local_indices = data.getLocalIndices();
502 for (int i = 0; i != local_indices.size(); ++i)
503 if (local_indices[i] != -1)
504 dotVector[i] = array[local_indices[i]];
505 else
506 dotVector[i] = 0;
507 CHKERR VecRestoreArrayRead(dataVec, &array);
508 data.getFieldData().swap(dotVector);
509 }
510
511 if (nb_gauss_pts) {
512 const size_t nb_base_functions = data.getN().size2();
513 auto base_function = data.getFTensor0N();
514 auto t_values_at_gauss_pts = get_values_at_gauss_pts();
515 FTensor::Index<'I', Tensor_Dim> I;
516 const size_t size = nb_dofs / Tensor_Dim;
517 if (nb_dofs % Tensor_Dim) {
518 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
519 "Nb. of DOFs is inconsistent with Tensor_Dim");
520 }
521 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
522 auto field_data = data.getFTensor1FieldData<Tensor_Dim>();
523
524 #ifndef NDEBUG
525 if (field_data.l2() != field_data.l2()) {
526 MOFEM_LOG("SELF", Sev::error) << "field data: " << field_data;
527 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
528 "Wrong number in coefficients");
529 }
530 #endif
531
532 size_t bb = 0;
533 for (; bb != size; ++bb) {
534
535 #ifndef SINGULARITY
536 #ifndef NDEBUG
537 if (base_function != base_function) {
538 MOFEM_LOG("SELF", Sev::error) << "base function: " << base_function;
539 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
540 "Wrong number number in base functions");
541 }
542 #endif
543 #endif
544
545 t_values_at_gauss_pts(I) += field_data(I) * base_function;
546 ++field_data;
547 ++base_function;
548 }
549 // Number of dofs can be smaller than number of Tensor_Dim x base
550 // functions
551 for (; bb < nb_base_functions; ++bb)
552 ++base_function;
553 ++t_values_at_gauss_pts;
554 }
555 }
556
557 if (dataVec.use_count()) {
558 data.getFieldData().swap(dotVector);
559 }
560 }
562}
563
564/**
565 * @brief Specialization for MatrixDouble vector field values calculation
566 *
567 * This structure is a specialization of OpCalculateVectorFieldValues_General
568 * for vector fields stored in MatrixDouble. It provides a convenient interface
569 * for calculating vector field values at integration points.
570 *
571 * @tparam Tensor_Dim Dimension of the vector field (e.g., 2 for 2D, 3 for 3D)
572 *
573 * @ingroup mofem_forces_and_sources_user_data_operators
574 */
575template <int Tensor_Dim>
577 : public OpCalculateVectorFieldValues_General<Tensor_Dim> {
578
580 Tensor_Dim>::OpCalculateVectorFieldValues_General;
581};
582
583/**@}*/
584
585/** \name Vector field values at integration points */
586
587/**@{*/
588
589/**
590 * @brief Calculate divergence of vector field at integration points
591 *
592 * This template structure calculates the divergence of a vector field at
593 * integration points. It supports different coordinate systems and tensor
594 * dimensions, making it suitable for various physical applications.
595 *
596 * @tparam Tensor_Dim Dimension of the vector field (e.g., 2 for 2D, 3 for 3D)
597 * @tparam COORDINATE_SYSTEM Coordinate system type (default: CARTESIAN)
598 */
599template <int Tensor_Dim, CoordinateTypes COORDINATE_SYSTEM = CARTESIAN>
602
603 /**
604 * @brief Constructor for vector field divergence calculation operator
605 *
606 * @param field_name Name of the vector field to calculate divergence for
607 * @param data_ptr Shared pointer to VectorDouble for storing calculated divergence values
608 * @param zero_type Entity type for zero-level entities (default: MBVERTEX)
609 */
611 const std::string field_name, boost::shared_ptr<VectorDouble> data_ptr,
612 const EntityType zero_type = MBVERTEX)
615 dataPtr(data_ptr), zeroType(zero_type) {
616 if (!dataPtr)
617 THROW_MESSAGE("Pointer is not set");
618 }
619
620 MoFEMErrorCode doWork(int side, EntityType type,
623
624 // When we move to C++17 add if constexpr()
625 if constexpr (COORDINATE_SYSTEM == POLAR || COORDINATE_SYSTEM == SPHERICAL)
626 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
627 "%s coordiante not implemented",
628 CoordinateTypesNames[COORDINATE_SYSTEM]);
629
630 const size_t nb_gauss_pts = getGaussPts().size2();
631 auto &vec = *dataPtr;
632 if (type == zeroType) {
633 vec.resize(nb_gauss_pts, false);
634 vec.clear();
635 }
636
637 const size_t nb_dofs = data.getFieldData().size();
638 if (nb_dofs) {
639
640 if (nb_gauss_pts) {
641 const size_t nb_base_functions = data.getN().size2();
642 auto values_at_gauss_pts = getFTensor0FromVec(vec);
643 FTensor::Index<'I', Tensor_Dim> I;
644 const size_t size = nb_dofs / Tensor_Dim;
645 #ifndef NDEBUG
646 if (nb_dofs % Tensor_Dim) {
647 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
648 "Number of dofs should multiple of dimensions");
649 }
650 #endif
651
652 // When we move to C++17 add if constexpr()
653 if constexpr (COORDINATE_SYSTEM == CARTESIAN) {
654 auto diff_base_function = data.getFTensor1DiffN<Tensor_Dim>();
655 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
656 auto field_data = data.getFTensor1FieldData<Tensor_Dim>();
657 size_t bb = 0;
658 for (; bb != size; ++bb) {
659 values_at_gauss_pts += field_data(I) * diff_base_function(I);
660 ++field_data;
661 ++diff_base_function;
662 }
663 // Number of dofs can be smaller than number of Tensor_Dim x base
664 // functions
665 for (; bb < nb_base_functions; ++bb)
666 ++diff_base_function;
667 ++values_at_gauss_pts;
668 }
669 }
670
671 // When we move to C++17 add if constexpr()
672 if constexpr (COORDINATE_SYSTEM == CYLINDRICAL) {
673 auto t_coords = getFTensor1CoordsAtGaussPts();
674 auto values_at_gauss_pts = getFTensor0FromVec(vec);
675 auto base_function = data.getFTensor0N();
676 auto diff_base_function = data.getFTensor1DiffN<Tensor_Dim>();
677 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
678 auto field_data = data.getFTensor1FieldData<Tensor_Dim>();
679 size_t bb = 0;
680 for (; bb != size; ++bb) {
681 values_at_gauss_pts += field_data(I) * diff_base_function(I);
682 values_at_gauss_pts +=
683 base_function * (field_data(0) / t_coords(0));
684 ++field_data;
685 ++base_function;
686 ++diff_base_function;
687 }
688 // Number of dofs can be smaller than number of Tensor_Dim x base
689 // functions
690 for (; bb < nb_base_functions; ++bb) {
691 ++base_function;
692 ++diff_base_function;
693 }
694 ++values_at_gauss_pts;
695 ++t_coords;
696 }
697 }
698 }
699 }
701 }
702
703protected:
704 boost::shared_ptr<VectorDouble> dataPtr;
706};
707
708/** \brief Approximate field values for given petsc vector
709 *
710 * \note Look at PetscData to see what vectors could be extracted with that user
711 * data operator.
712 *
713 * \ingroup mofem_forces_and_sources_user_data_operators
714 */
715template <int Tensor_Dim, PetscData::DataContext CTX>
718
720 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
721 const EntityType zero_at_type = MBVERTEX, bool throw_error = true)
724 dataPtr(data_ptr), zeroAtType(zero_at_type), throwError(throw_error) {
725 if (!dataPtr)
726 THROW_MESSAGE("Pointer is not set");
727 }
728
729 MoFEMErrorCode doWork(int side, EntityType type,
732
733 auto &local_indices = data.getLocalIndices();
734 const size_t nb_dofs = local_indices.size();
735 const size_t nb_gauss_pts = getGaussPts().size2();
736
737 MatrixDouble &mat = *dataPtr;
739 auto get_values_at_gauss_pts =
740 MatrixSizeHelper<GetFTensor1FromMatType<Tensor_Dim, -1, DL>,
741 DL>::size(mat, nb_gauss_pts);
742 if (type == zeroAtType) {
743 mat.clear();
744 }
745 if (!nb_dofs)
747
748 if (!throwError) {
749 if ((getFEMethod()->data_ctx & PetscData::Switches(CTX)).none()) {
751 }
752 }
753
754 const double *array;
755
756 auto get_array = [&](const auto ctx, auto vec) {
758 #ifndef NDEBUG
759 if ((getFEMethod()->data_ctx & ctx).none()) {
760 MOFEM_LOG_CHANNEL("SELF");
761 MOFEM_LOG("SELF", Sev::error)
762 << "In this case field degrees of freedom are read from vector. "
763 "That usually happens when time solver is used, and access to "
764 "first or second rates is needed. You probably not set ts_u, "
765 "ts_u_t, or ts_u_tt and associated data structure, i.e. "
766 "data_ctx to CTX_SET_X, CTX_SET_DX, CTX_SET_X_T, or "
767 "CTX_SET_X_TT respectively";
768 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Vector not set");
769 }
770 #endif
771 CHKERR VecGetArrayRead(vec, &array);
773 };
774
775 auto restore_array = [&](auto vec) {
776 return VecRestoreArrayRead(vec, &array);
777 };
778
779 switch (CTX) {
781 CHKERR get_array(PetscData::CtxSetX, getFEMethod()->ts_u);
782 break;
784 CHKERR get_array(PetscData::CtxSetX, getFEMethod()->dx);
785 break;
787 CHKERR get_array(PetscData::CtxSetX_T, getFEMethod()->ts_u_t);
788 break;
790 CHKERR get_array(PetscData::CtxSetX_TT, getFEMethod()->ts_u_tt);
791 break;
792 default:
793 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
794 "That case is not implemented");
795 }
796
797 dotVector.resize(local_indices.size());
798 for (int i = 0; i != local_indices.size(); ++i)
799 if (local_indices[i] != -1)
800 dotVector[i] = array[local_indices[i]];
801 else
802 dotVector[i] = 0;
803
804 switch (CTX) {
806 CHKERR restore_array(getFEMethod()->ts_u);
807 break;
809 CHKERR restore_array(getFEMethod()->dx);
810 break;
812 CHKERR restore_array(getFEMethod()->ts_u_t);
813 break;
815 CHKERR restore_array(getFEMethod()->ts_u_tt);
816 break;
817 default:
818 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
819 "That case is not implemented");
820 }
821
822 const size_t nb_base_functions = data.getN().size2();
823 auto base_function = data.getFTensor0N();
824 auto t_values_at_gauss_pts = get_values_at_gauss_pts();
825
826 FTensor::Index<'I', Tensor_Dim> I;
827 const size_t size = nb_dofs / Tensor_Dim;
828 if (nb_dofs % Tensor_Dim) {
829 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Data inconsistency");
830 }
831 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
832 auto field_data = getFTensor1FromArray<Tensor_Dim, Tensor_Dim>(dotVector);
833 size_t bb = 0;
834 for (; bb != size; ++bb) {
835 t_values_at_gauss_pts(I) += field_data(I) * base_function;
836 ++field_data;
837 ++base_function;
838 }
839 // Number of dofs can be smaller than number of Tensor_Dim x base
840 // functions
841 for (; bb < nb_base_functions; ++bb)
842 ++base_function;
843 ++t_values_at_gauss_pts;
844 }
846 }
847
848protected:
849 boost::shared_ptr<MatrixDouble> dataPtr;
853};
854
855/** \brief Get rate of values at integration pts for tensor field
856 * rank 1, i.e. vector field
857 *
858 * \ingroup mofem_forces_and_sources_user_data_operators
859 */
860template <int Tensor_Dim>
864
865/** \brief Get second rate of values at integration pts for tensor
866 * field rank 1, i.e. vector field
867 *
868 * \ingroup mofem_forces_and_sources_user_data_operators
869 */
870template <int Tensor_Dim>
874
875/** \brief Get second time second update vector at integration pts for tensor
876 * field rank 1, i.e. vector field
877 *
878 * \ingroup mofem_forces_and_sources_user_data_operators
879 */
880template <int Tensor_Dim>
884
885/**@}*/
886
887/** \name Tensor field values at integration points */
888
889/**@{*/
890
891/** \brief Calculate field values for tenor field rank 2.
892 *
893 */
894template <int Tensor_Dim0, int Tensor_Dim1, typename M = MatrixDouble>
897
899 const std::string field_name,
900 boost::shared_ptr<M> data_ptr,
901 const EntityType zero_type = MBVERTEX)
904 dataPtr(data_ptr), zeroType(zero_type) {
905 if (!dataPtr)
906 THROW_MESSAGE("Pointer is not set");
907 }
908
909 MoFEMErrorCode doWork(int side, EntityType type,
911
912protected:
913 boost::shared_ptr<M> dataPtr;
915};
916
917template <int Tensor_Dim0, int Tensor_Dim1, typename M>
920 doWork(int side, EntityType type, EntitiesFieldData::EntData &data) {
922 SETERRQ(PETSC_COMM_SELF, MOFEM_NOT_IMPLEMENTED,
923 "Not implemented for matrix type = %s, dim0 = %d and dim1 = %d",
924 typeid(M).name(), // boost::core::demangle(typeid(M).name()),
925 Tensor_Dim0, Tensor_Dim1);
927}
928
929template <int Tensor_Dim0, int Tensor_Dim1>
930struct OpCalculateTensor2FieldValues_General<Tensor_Dim0, Tensor_Dim1,
933
936 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
937 SmartPetscObj<Vec> data_vec, const EntityType zero_type = MBVERTEX)
939 dataPtr(data_ptr), zeroType(zero_type), dataVec(data_vec) {
940 if (!dataPtr)
941 THROW_MESSAGE("Pointer is not set");
942 }
943
945 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
946 const EntityType zero_type = MBVERTEX)
949 SmartPetscObj<Vec>(), zero_type) {}
950
952 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
953 SmartPetscObj<Vec> data_vec, const EntityType zero_type = MBVERTEX)
956 data_vec, zero_type) {}
957
958 MoFEMErrorCode doWork(int side, EntityType type,
960
961protected:
962 boost::shared_ptr<MatrixDouble> dataPtr;
966};
967
968template <int Tensor_Dim0, int Tensor_Dim1>
970 Tensor_Dim0, Tensor_Dim1, MatrixDouble>::doWork(
971 int side, EntityType type, EntitiesFieldData::EntData &data) {
973
975 MatrixDouble &mat = *dataPtr;
976 const size_t nb_gauss_pts = data.getN().size1();
977 auto get_values_at_gauss_pts =
978 MatrixSizeHelper<GetFTensor2FromMatType<Tensor_Dim0, Tensor_Dim1, -1, DL>,
979 DL>::size(mat, nb_gauss_pts);
980 if (type == zeroType)
981 mat.clear();
982
983 const size_t nb_dofs = data.getFieldData().size();
984
985 if (dataVec.use_count()) {
986 dotVector.resize(nb_dofs, false);
987 const double *array;
988 CHKERR VecGetArrayRead(dataVec, &array);
989 const auto &local_indices = data.getLocalIndices();
990 for (int i = 0; i != local_indices.size(); ++i)
991 if (local_indices[i] != -1)
992 dotVector[i] = array[local_indices[i]];
993 else
994 dotVector[i] = 0;
995 CHKERR VecRestoreArrayRead(dataVec, &array);
996 data.getFieldData().swap(dotVector);
997 }
998
999 if (nb_dofs) {
1000 const size_t nb_base_functions = data.getN().size2();
1001 auto base_function = data.getFTensor0N();
1002 auto t_values_at_gauss_pts = get_values_at_gauss_pts();
1003 FTensor::Index<'i', Tensor_Dim0> i;
1004 FTensor::Index<'j', Tensor_Dim1> j;
1005 const size_t size = nb_dofs / (Tensor_Dim0 * Tensor_Dim1);
1006 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
1007 auto field_data = data.getFTensor2FieldData<Tensor_Dim0, Tensor_Dim1>();
1008 size_t bb = 0;
1009 for (; bb != size; ++bb) {
1010 t_values_at_gauss_pts(i, j) += field_data(i, j) * base_function;
1011 ++field_data;
1012 ++base_function;
1013 }
1014 for (; bb < nb_base_functions; ++bb)
1015 ++base_function;
1016 ++t_values_at_gauss_pts;
1017 }
1018
1019 if (dataVec.use_count()) {
1020 data.getFieldData().swap(dotVector);
1021 }
1022 }
1024}
1025
1026/** \brief Get values at integration pts for tensor field rank 2, i.e. matrix
1027 * field
1028 *
1029 * \ingroup mofem_forces_and_sources_user_data_operators
1030 */
1031template <int Tensor_Dim0, int Tensor_Dim1>
1033 : public OpCalculateTensor2FieldValues_General<Tensor_Dim0,
1034 Tensor_Dim1> {
1035
1037 Tensor_Dim0, Tensor_Dim1>::OpCalculateTensor2FieldValues_General;
1038};
1039
1040/** \brief Get time direvarive values at integration pts for tensor field rank
1041 * 2, i.e. matrix field
1042 *
1043 * \ingroup mofem_forces_and_sources_user_data_operators
1044 */
1045template <int Tensor_Dim0, int Tensor_Dim1>
1048
1050 boost::shared_ptr<MatrixDouble> data_ptr,
1051 const EntityType zero_at_type = MBVERTEX)
1054 dataPtr(data_ptr), zeroAtType(zero_at_type) {
1055 if (!dataPtr)
1056 THROW_MESSAGE("Pointer is not set");
1057 }
1058
1059 MoFEMErrorCode doWork(int side, EntityType type,
1062
1064 const size_t nb_gauss_pts = getGaussPts().size2();
1065 MatrixDouble &mat = *dataPtr;
1066 auto get_values_at_gauss_pts =
1068 GetFTensor2FromMatType<Tensor_Dim0, Tensor_Dim1, -1, DL>,
1069 DL>::size(mat, nb_gauss_pts);
1070 if (type == zeroAtType)
1071 mat.clear();
1072 const auto &local_indices = data.getLocalIndices();
1073 const size_t nb_dofs = local_indices.size();
1074 if (nb_dofs) {
1075 dotVector.resize(nb_dofs, false);
1076 const double *array;
1077 CHKERR VecGetArrayRead(getFEMethod()->ts_u_t, &array);
1078 for (size_t i = 0; i != local_indices.size(); ++i)
1079 if (local_indices[i] != -1)
1080 dotVector[i] = array[local_indices[i]];
1081 else
1082 dotVector[i] = 0;
1083 CHKERR VecRestoreArrayRead(getFEMethod()->ts_u_t, &array);
1084
1085 const size_t nb_base_functions = data.getN().size2();
1086
1087 auto base_function = data.getFTensor0N();
1088 auto t_values_at_gauss_pts = get_values_at_gauss_pts();
1089 FTensor::Index<'i', Tensor_Dim0> i;
1090 FTensor::Index<'j', Tensor_Dim1> j;
1091 const size_t size = nb_dofs / (Tensor_Dim0 * Tensor_Dim1);
1092 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
1093 auto field_data =
1094 getFTensor2FromPtr<Tensor_Dim0, Tensor_Dim1>(&*dotVector.begin());
1095 size_t bb = 0;
1096 for (; bb != size; ++bb) {
1097 t_values_at_gauss_pts(i, j) += field_data(i, j) * base_function;
1098 ++field_data;
1099 ++base_function;
1100 }
1101 for (; bb < nb_base_functions; ++bb)
1102 ++base_function;
1103 ++t_values_at_gauss_pts;
1104 }
1105 }
1107 }
1108
1109protected:
1110 boost::shared_ptr<MatrixDouble> dataPtr; ///< Data computed into this matrix
1111 EntityType zeroAtType; ///< Zero values at Gauss point at this type
1112 VectorDouble dotVector; ///< Keeps temporary values of time derivatives
1113};
1114
1115/**
1116 * @brief Calculate symmetric tensor field values at integration pts.
1117 *
1118 * @tparam Tensor_Dim
1119
1120 * \ingroup mofem_forces_and_sources_user_data_operators
1121 */
1122template <int Tensor_Dim>
1125
1127 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
1128 const EntityType zero_type = MBEDGE, const int zero_side = 0)
1131 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
1132 if (!dataPtr)
1133 THROW_MESSAGE("Pointer is not set");
1134 }
1135
1137 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
1138 SmartPetscObj<Vec> data_vec, const EntityType zero_type = MBEDGE,
1139 const int zero_side = 0)
1142 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side),
1143 dataVec(data_vec) {
1144 if (!dataPtr)
1145 THROW_MESSAGE("Pointer is not set");
1146 }
1147
1148 MoFEMErrorCode doWork(int side, EntityType type,
1151 MatrixDouble &mat = *dataPtr;
1152 const int nb_gauss_pts = getGaussPts().size2();
1154 auto get_values_at_gauss_pts =
1156 DL>::size(mat, nb_gauss_pts);
1157 if (type == this->zeroType && side == zeroSide) {
1158 mat.clear();
1159 }
1160 const int nb_dofs = data.getFieldData().size();
1161 if (!nb_dofs)
1163
1164 if (dataVec.use_count()) {
1165 dotVector.resize(nb_dofs, false);
1166 const double *array;
1167 CHKERR VecGetArrayRead(dataVec, &array);
1168 const auto &local_indices = data.getLocalIndices();
1169 for (int i = 0; i != local_indices.size(); ++i)
1170 if (local_indices[i] != -1)
1171 dotVector[i] = array[local_indices[i]];
1172 else
1173 dotVector[i] = 0;
1174 CHKERR VecRestoreArrayRead(dataVec, &array);
1175 data.getFieldData().swap(dotVector);
1176 }
1177
1178 const int nb_base_functions = data.getN().size2();
1179 auto base_function = data.getFTensor0N();
1180 auto t_values_at_gauss_pts = get_values_at_gauss_pts();
1181 FTensor::Index<'i', Tensor_Dim> i;
1182 FTensor::Index<'j', Tensor_Dim> j;
1183 const int size = nb_dofs / ((Tensor_Dim * (Tensor_Dim + 1)) / 2);
1184 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
1185 auto field_data = data.getFTensor2SymmetricFieldData<Tensor_Dim>();
1186 int bb = 0;
1187 for (; bb != size; ++bb) {
1188 t_values_at_gauss_pts(i, j) += field_data(i, j) * base_function;
1189 ++field_data;
1190 ++base_function;
1191 }
1192 for (; bb < nb_base_functions; ++bb)
1193 ++base_function;
1194 ++t_values_at_gauss_pts;
1195 }
1196
1197 if (dataVec.use_count()) {
1198 data.getFieldData().swap(dotVector);
1199 }
1200
1202 }
1203
1204protected:
1205 boost::shared_ptr<MatrixDouble> dataPtr;
1207 const int zeroSide;
1210};
1211
1212/**
1213 * @brief Calculate symmetric tensor field rates ant integratio pts.
1214 *
1215 * @tparam Tensor_Dim
1216 *
1217 * \ingroup mofem_forces_and_sources_user_data_operators
1218 */
1219template <int Tensor_Dim>
1222
1224 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
1225 const EntityType zero_type = MBEDGE, const int zero_side = 0)
1228 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
1229 if (!dataPtr)
1230 THROW_MESSAGE("Pointer is not set");
1231 }
1232
1233 MoFEMErrorCode doWork(int side, EntityType type,
1236 const int nb_gauss_pts = getGaussPts().size2();
1237 MatrixDouble &mat = *dataPtr;
1238 constexpr auto symm_size = (Tensor_Dim * (Tensor_Dim + 1)) / 2;
1240 auto get_values_at_gauss_pts =
1242 DL>::size(mat, nb_gauss_pts);
1243 if (type == zeroType && side == zeroSide) {
1244 mat.clear();
1245 }
1246 auto &local_indices = data.getLocalIndices();
1247 const int nb_dofs = local_indices.size();
1248 if (!nb_dofs)
1250
1251 #ifndef NDEBUG
1252 if ((getFEMethod()->data_ctx & PetscData::CtxSetX_T).none()) {
1253 MOFEM_LOG_CHANNEL("SELF");
1254 MOFEM_LOG("SELF", Sev::error)
1255 << "In this case field degrees of freedom are read from vector. "
1256 "That usually happens when time solver is used, and acces to "
1257 "first rates is needed. You probably not set "
1258 "ts_u_t and associated data structure data_ctx to CTX_SET_X_T "
1259 "respectively";
1260 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Vector not set!");
1261 }
1262 #endif
1263
1264 dotVector.resize(nb_dofs, false);
1265 const double *array;
1266 CHKERR VecGetArrayRead(getFEMethod()->ts_u_t, &array);
1267 for (int i = 0; i != local_indices.size(); ++i)
1268 if (local_indices[i] != -1)
1269 dotVector[i] = array[local_indices[i]];
1270 else
1271 dotVector[i] = 0;
1272 CHKERR VecRestoreArrayRead(getFEMethod()->ts_u_t, &array);
1273
1274 const int nb_base_functions = data.getN().size2();
1275
1276 auto base_function = data.getFTensor0N();
1277 auto t_values_at_gauss_pts = get_values_at_gauss_pts();
1278 FTensor::Index<'i', Tensor_Dim> i;
1279 FTensor::Index<'j', Tensor_Dim> j;
1280 const int size = nb_dofs / symm_size;
1281 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
1282 auto field_data = getFTensorDotData<Tensor_Dim>();
1283 int bb = 0;
1284 for (; bb != size; ++bb) {
1285 t_values_at_gauss_pts(i, j) += field_data(i, j) * base_function;
1286 ++field_data;
1287 ++base_function;
1288 }
1289 for (; bb < nb_base_functions; ++bb)
1290 ++base_function;
1291 ++t_values_at_gauss_pts;
1292 }
1293
1295 }
1296
1297protected:
1298 boost::shared_ptr<MatrixDouble> dataPtr;
1300 const int zeroSide;
1302
1303 template <int Dim> inline auto getFTensorDotData() {
1304 static_assert(Dim || !Dim, "not implemented");
1305 }
1306};
1307
1308template <>
1309template <>
1310inline auto
1313 &dotVector[0], &dotVector[1], &dotVector[2], &dotVector[3], &dotVector[4],
1314 &dotVector[5]);
1315}
1316
1317template <>
1318template <>
1319inline auto
1322 &dotVector[0], &dotVector[1], &dotVector[2]);
1323}
1324
1325/**@}*/
1326
1327/** \name Gradients and Hessian of scalar fields at integration points */
1328
1329/**@{*/
1330
1331/**
1332 * \brief Evaluate field gradient values for scalar field, i.e. gradient is
1333 * tensor rank 1 (vector)
1334 *
1335 */
1336template <int Tensor_Dim, typename M = MatrixDouble>
1338 : public OpCalculateVectorFieldValues_General<Tensor_Dim, M> {
1339
1341 Tensor_Dim, M>::OpCalculateVectorFieldValues_General;
1342};
1343
1344/** \brief Evaluate field gradient values for scalar field, i.e. gradient is
1345 * tensor rank 1 (vector), specialization
1346 *
1347 */
1348template <int Tensor_Dim>
1350 : public OpCalculateVectorFieldValues_General<Tensor_Dim, MatrixDouble> {
1351
1353 Tensor_Dim, MatrixDouble>::OpCalculateVectorFieldValues_General;
1354
1355 /**
1356 * \brief calculate gradient values of scalar field at integration points
1357 * @param side side entity number
1358 * @param type side entity type
1359 * @param data entity data
1360 * @return error code
1361 */
1362 MoFEMErrorCode doWork(int side, EntityType type,
1364};
1365
1366/**
1367 * \brief Member function specialization calculating scalar field gradients for
1368 * tenor field rank 1
1369 *
1370 */
1371template <int Tensor_Dim>
1373 Tensor_Dim, MatrixDouble>::doWork(int side, EntityType type,
1376
1377 const size_t nb_gauss_pts = this->getGaussPts().size2();
1378 auto &mat = *this->dataPtr;
1380 auto get_gradients_at_pts =
1381 MatrixSizeHelper<GetFTensor1FromMatType<Tensor_Dim, -1, DL>,
1382 DL>::size(mat, nb_gauss_pts);
1383 if (type == this->zeroType) {
1384 mat.clear();
1385 }
1386
1387 const int nb_dofs = data.getFieldData().size();
1388 if (nb_dofs) {
1389
1390 if (nb_gauss_pts) {
1391 const int nb_base_functions = data.getN().size2();
1392 auto diff_base_function = data.getFTensor1DiffN<Tensor_Dim>();
1393 auto t_gradients_at_pts = get_gradients_at_pts();
1394
1395 #ifndef NDEBUG
1396 if (nb_dofs > nb_base_functions)
1397 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1398 "Number of base functions inconsistent with number of DOFs "
1399 "(%d > %d)",
1400 nb_dofs, nb_base_functions);
1401
1402 if (data.getDiffN().size2() != nb_base_functions * Tensor_Dim)
1403 SETERRQ(
1404 PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1405 "Number of base functions inconsistent with number of derivatives "
1406 "(%zu != %d)",
1407 data.getDiffN().size2(), nb_base_functions);
1408
1409 if (data.getDiffN().size1() != nb_gauss_pts)
1410 SETERRQ(
1411 PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1412 "Number of base functions inconsistent with number of integration "
1413 "pts (%zu != %zu)",
1414 data.getDiffN().size1(), nb_gauss_pts);
1415
1416 #endif
1417
1418 FTensor::Index<'I', Tensor_Dim> I;
1419 for (int gg = 0; gg < nb_gauss_pts; ++gg) {
1420 auto field_data = data.getFTensor0FieldData();
1421 int bb = 0;
1422 for (; bb != nb_dofs; ++bb) {
1423 t_gradients_at_pts(I) += field_data * diff_base_function(I);
1424 ++field_data;
1425 ++diff_base_function;
1426 }
1427 // Number of dofs can be smaller than number of base functions
1428 for (; bb < nb_base_functions; ++bb)
1429 ++diff_base_function;
1430 ++t_gradients_at_pts;
1431 }
1432 }
1433 }
1434
1436}
1437
1438/** \brief Get field gradients at integration pts for scalar field rank 0, i.e.
1439 * vector field
1440 *
1441 * \ingroup mofem_forces_and_sources_user_data_operators
1442 */
1443template <int Tensor_Dim>
1445 : public OpCalculateScalarFieldGradient_General<Tensor_Dim> {
1447 Tensor_Dim>::OpCalculateScalarFieldGradient_General;
1448};
1449
1450/** \brief Evaluate field gradient values for scalar field, i.e. gradient is
1451 * tensor rank 1 (vector), specialization
1452 *
1453 */
1454template <int Tensor_Dim>
1456 : public OpCalculateVectorFieldValues_General<Tensor_Dim> {
1457
1459 Tensor_Dim>::OpCalculateVectorFieldValues_General;
1460
1461 /**
1462 * \brief calculate gradient values of scalar field at integration points
1463 * @param side side entity number
1464 * @param type side entity type
1465 * @param data entity data
1466 * @return error code
1467 */
1468 MoFEMErrorCode doWork(int side, EntityType type,
1470};
1471
1472template <int Tensor_Dim>
1474 int side, EntityType type, EntitiesFieldData::EntData &data) {
1476
1477 const size_t nb_gauss_pts = this->getGaussPts().size2();
1479 auto &mat = *this->dataPtr;
1480 auto get_hessian_at_gauss_pts =
1481 MatrixSizeHelper<GetFTensor2FromMatType<Tensor_Dim, Tensor_Dim, -1, DL>,
1482 DL>::size(mat, nb_gauss_pts);
1483 if (type == this->zeroType)
1484 mat.clear();
1485
1486 const int nb_dofs = data.getFieldData().size();
1487 if (nb_dofs) {
1488
1489 if (nb_gauss_pts) {
1490 const int nb_base_functions = data.getN().size2();
1491
1492 auto &hessian_base = data.getN(BaseDerivatives::SecondDerivative);
1493 #ifndef NDEBUG
1494 if (hessian_base.size1() != nb_gauss_pts) {
1495 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1496 "Wrong number of integration pts (%ld != %ld)",
1497 static_cast<long>(hessian_base.size1()),
1498 static_cast<long>(nb_gauss_pts));
1499 }
1500 if (hessian_base.size2() != nb_base_functions * Tensor_Dim * Tensor_Dim) {
1501 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1502 "Wrong number of base functions (%ld != %ld)",
1503 static_cast<long>(hessian_base.size2() /
1504 (Tensor_Dim * Tensor_Dim)),
1505 static_cast<long>(nb_base_functions));
1506 }
1507 if (hessian_base.size2() < nb_dofs * Tensor_Dim * Tensor_Dim) {
1508 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1509 "Wrong number of base functions (%ld < %ld)",
1510 static_cast<long>(hessian_base.size2()),
1511 static_cast<long>(nb_dofs * Tensor_Dim * Tensor_Dim));
1512 }
1513 #endif
1514
1515 auto t_diff2_base_function = getFTensor2FromPtr<Tensor_Dim, Tensor_Dim>(
1516 &*hessian_base.data().begin());
1517
1518 auto t_hessian_at_gauss_pts = get_hessian_at_gauss_pts();
1519
1520 FTensor::Index<'I', Tensor_Dim> I;
1521 FTensor::Index<'J', Tensor_Dim> J;
1522 for (int gg = 0; gg != nb_gauss_pts; ++gg) {
1523 auto field_data = data.getFTensor0FieldData();
1524 int bb = 0;
1525 for (; bb != nb_dofs; ++bb) {
1526 t_hessian_at_gauss_pts(I, J) +=
1527 field_data * t_diff2_base_function(I, J);
1528 ++field_data;
1529 ++t_diff2_base_function;
1530 }
1531 // Number of dofs can be smaller than number of base functions
1532 for (; bb < nb_base_functions; ++bb) {
1533 ++t_diff2_base_function;
1534 }
1535
1536 ++t_hessian_at_gauss_pts;
1537 }
1538 }
1539 }
1540
1542}
1543
1544/**}*/
1545
1546/** \name Gradients and hessian of tensor fields at integration points */
1547
1548/**@{*/
1549
1550/**
1551 * \brief Evaluate field gradient values for vector field, i.e. gradient is
1552 * tensor rank 2
1553 *
1554 * \tparam Tensor_Dim0 Dimension of the vector field
1555 * \tparam Tensor_Dim1 Dimension of the gradient (usually spatial dimension)
1556 * \tparam S Storage order for the field data
1557 * \tparam M Matrix storage type
1558 *
1559 */
1560template <int Tensor_Dim0, int Tensor_Dim1, int S,
1561 typename M = MatrixDouble>
1563 : public OpCalculateTensor2FieldValues_General<Tensor_Dim0, Tensor_Dim1,
1564 M> {
1565
1567 Tensor_Dim0, Tensor_Dim1, M>::OpCalculateTensor2FieldValues_General;
1568};
1569
1570template <int Tensor_Dim0, int Tensor_Dim1, int S>
1571struct OpCalculateVectorFieldGradient_General<Tensor_Dim0, Tensor_Dim1, S,
1574 Tensor_Dim0, Tensor_Dim1, MatrixDouble> {
1575
1577 Tensor_Dim0, Tensor_Dim1, MatrixDouble>::OpCalculateTensor2FieldValues_General;
1578
1579 /**
1580 * \brief calculate values of vector field at integration points
1581 * @param side side entity number
1582 * @param type side entity type
1583 * @param data entity data
1584 * @return error code
1585 */
1586 MoFEMErrorCode doWork(int side, EntityType type,
1588};
1589
1590/**
1591 * \brief Member function specialization calculating vector field gradients for
1592 * tenor field rank 2
1593 *
1594 */
1595template <int Tensor_Dim0, int Tensor_Dim1, int S>
1597 Tensor_Dim0, Tensor_Dim1, S, MatrixDouble>::doWork(
1598 int side, EntityType type, EntitiesFieldData::EntData &data) {
1600 if (!this->dataPtr)
1601 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1602 "Data pointer not allocated");
1603
1604 const size_t nb_gauss_pts = this->getGaussPts().size2();
1606 auto &mat = *this->dataPtr;
1607 auto get_gradients_at_pts =
1609 GetFTensor2FromMatType<Tensor_Dim0, Tensor_Dim1, -1, DL>,
1610 DL>::size(mat, nb_gauss_pts);
1611 if (type == this->zeroType)
1612 mat.clear();
1613
1614 if (nb_gauss_pts) {
1615 const size_t nb_dofs = data.getFieldData().size();
1616
1617 if (nb_dofs) {
1618
1619 if (this->dataVec.use_count()) {
1620 this->dotVector.resize(nb_dofs, false);
1621 const double *array;
1622 CHKERR VecGetArrayRead(this->dataVec, &array);
1623 const auto &local_indices = data.getLocalIndices();
1624 for (int i = 0; i != local_indices.size(); ++i)
1625 if (local_indices[i] != -1)
1626 this->dotVector[i] = array[local_indices[i]];
1627 else
1628 this->dotVector[i] = 0;
1629 CHKERR VecRestoreArrayRead(this->dataVec, &array);
1630 data.getFieldData().swap(this->dotVector);
1631 }
1632
1633 const int nb_base_functions = data.getN().size2();
1634 auto diff_base_function = data.getFTensor1DiffN<Tensor_Dim1>();
1635 auto t_gradients_at_pts = get_gradients_at_pts();
1636 FTensor::Index<'I', Tensor_Dim0> I;
1637 FTensor::Index<'J', Tensor_Dim1> J;
1638 int size = nb_dofs / Tensor_Dim0;
1639 if (nb_dofs % Tensor_Dim0) {
1640 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1641 "Data inconsistency");
1642 }
1643 for (int gg = 0; gg < nb_gauss_pts; ++gg) {
1644 auto field_data = getFTensor1FromPtr<Tensor_Dim0, S>(
1645 data.getFieldData().data().data());
1646
1647 #ifndef NDEBUG
1648 if (field_data.l2() != field_data.l2()) {
1649 MOFEM_LOG("SELF", Sev::error) << "field data " << field_data;
1650 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1651 "Wrong number in coefficients");
1652 }
1653 #endif
1654
1655 int bb = 0;
1656 for (; bb < size; ++bb) {
1657 #ifndef SINGULARITY
1658 #ifndef NDEBUG
1659 if (diff_base_function.l2() != diff_base_function.l2()) {
1660 MOFEM_LOG("SELF", Sev::error)
1661 << "diff_base_function: " << diff_base_function;
1662 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1663 "Wrong number number in base functions");
1664 }
1665 #endif
1666 #endif
1667
1668 t_gradients_at_pts(I, J) += field_data(I) * diff_base_function(J);
1669 ++field_data;
1670 ++diff_base_function;
1671 }
1672 // Number of dofs can be smaller than number of Tensor_Dim0 x base
1673 // functions
1674 for (; bb != nb_base_functions; ++bb)
1675 ++diff_base_function;
1676 ++t_gradients_at_pts;
1677 }
1678
1679 if (this->dataVec.use_count()) {
1680 data.getFieldData().swap(this->dotVector);
1681 }
1682 }
1683 }
1685}
1686
1687/** \brief Get field gradients at integration pts for scalar field rank 0, i.e.
1688 * vector field
1689 *
1690 * \tparam Tensor_Dim0 Dimension of the vector field
1691 * \tparam Tensor_Dim1 Dimension of the gradient (usually spatial dimension)
1692 * \tparam S Stride in the storage of the vector field, default is Tensor_Dim0
1693 *
1694 * \ingroup mofem_forces_and_sources_user_data_operators
1695 */
1696template <int Tensor_Dim0, int Tensor_Dim1, int S = Tensor_Dim0>
1698 : public OpCalculateVectorFieldGradient_General<Tensor_Dim0, Tensor_Dim1,
1699 S> {
1700
1702 Tensor_Dim0, Tensor_Dim1, S>::OpCalculateVectorFieldGradient_General;
1703};
1704
1705/** \brief Get field gradients time derivative at integration pts for scalar
1706 * field rank 0, i.e. vector field
1707 *
1708 * \ingroup mofem_forces_and_sources_user_data_operators
1709 */
1710template <int Tensor_Dim0, int Tensor_Dim1>
1713
1715 boost::shared_ptr<MatrixDouble> data_ptr,
1716 const EntityType zero_at_type = MBVERTEX)
1719 dataPtr(data_ptr), zeroAtType(zero_at_type) {
1720 if (!dataPtr)
1721 THROW_MESSAGE("Pointer is not set");
1722 }
1723
1724 MoFEMErrorCode doWork(int side, EntityType type,
1727
1728 const auto &local_indices = data.getLocalIndices();
1729 const int nb_dofs = local_indices.size();
1730 const int nb_gauss_pts = this->getGaussPts().size2();
1731
1733 auto &mat = *this->dataPtr;
1734 auto get_gradients_at_pts =
1736 GetFTensor2FromMatType<Tensor_Dim0, Tensor_Dim1, -1, DL>,
1737 DL>::size(mat, nb_gauss_pts);
1738 if (type == this->zeroAtType)
1739 mat.clear();
1740 if (!nb_dofs)
1742
1743 dotVector.resize(nb_dofs, false);
1744 const double *array;
1745 CHKERR VecGetArrayRead(getFEMethod()->ts_u_t, &array);
1746 for (int i = 0; i != local_indices.size(); ++i)
1747 if (local_indices[i] != -1)
1748 dotVector[i] = array[local_indices[i]];
1749 else
1750 dotVector[i] = 0;
1751 CHKERR VecRestoreArrayRead(getFEMethod()->ts_u_t, &array);
1752
1753 const int nb_base_functions = data.getN().size2();
1754 auto diff_base_function = data.getFTensor1DiffN<Tensor_Dim1>();
1755 auto t_gradients_at_pts = get_gradients_at_pts();
1756 FTensor::Index<'I', Tensor_Dim0> I;
1757 FTensor::Index<'J', Tensor_Dim1> J;
1758 int size = nb_dofs / Tensor_Dim0;
1759 if (nb_dofs % Tensor_Dim0) {
1760 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "Data inconsistency");
1761 }
1762
1763 for (int gg = 0; gg < nb_gauss_pts; ++gg) {
1764 auto field_data = getFTensor1FromPtr<Tensor_Dim0>(&*dotVector.begin());
1765 int bb = 0;
1766 for (; bb < size; ++bb) {
1767 t_gradients_at_pts(I, J) += field_data(I) * diff_base_function(J);
1768 ++field_data;
1769 ++diff_base_function;
1770 }
1771 // Number of dofs can be smaller than number of Tensor_Dim0 x base
1772 // functions
1773 for (; bb != nb_base_functions; ++bb)
1774 ++diff_base_function;
1775 ++t_gradients_at_pts;
1776 }
1778 }
1779
1780private:
1781 boost::shared_ptr<MatrixDouble> dataPtr; ///< Data computed into this matrix
1782 EntityType zeroAtType; ///< Zero values at Gauss point at this type
1783 VectorDouble dotVector; ///< Keeps temporary values of time derivatives
1784};
1785
1786/**
1787 * \brief Evaluate field gradient values for symmetric 2nd order tensor field,
1788 * i.e. gradient is tensor rank 3
1789 *
1790 */
1791template <int Tensor_Dim0, int Tensor_Dim1, typename M = MatrixDouble>
1793 : public OpCalculateTensor2FieldValues_General<Tensor_Dim0, Tensor_Dim1,
1794 M> {
1795
1797 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
1798 const EntityType zero_type = MBVERTEX)
1799 : OpCalculateTensor2FieldValues_General<Tensor_Dim0, Tensor_Dim1, M>(
1800 field_name, data_ptr, zero_type) {}
1801};
1802
1803template <int Tensor_Dim0, int Tensor_Dim1>
1805 Tensor_Dim1,
1808 Tensor_Dim0, Tensor_Dim1, MatrixDouble> {
1809
1811 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
1812 const EntityType zero_type = MBVERTEX)
1813 : OpCalculateTensor2FieldValues_General<Tensor_Dim0, Tensor_Dim1,
1814 MatrixDouble>(
1815 field_name, data_ptr, zero_type) {}
1816
1817 /**
1818 * \brief calculate values of vector field at integration points
1819 * @param side side entity number
1820 * @param type side entity type
1821 * @param data entity data
1822 * @return error code
1823 */
1824 MoFEMErrorCode doWork(int side, EntityType type,
1826};
1827
1828/**
1829 * \brief Member function specialization calculating tensor field gradients for
1830 * symmetric tensor field rank 2
1831 *
1832 */
1833template <int Tensor_Dim0, int Tensor_Dim1>
1834MoFEMErrorCode OpCalculateTensor2SymmetricFieldGradient_General<
1835 Tensor_Dim0, Tensor_Dim1, MatrixDouble>::doWork(
1836 int side, EntityType type, EntitiesFieldData::EntData &data) {
1838 if (!this->dataPtr)
1839 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1840 "Data pointer not allocated");
1841
1842 const size_t nb_gauss_pts = this->getGaussPts().size2();
1843 constexpr size_t msize = (Tensor_Dim0 * (Tensor_Dim0 + 1)) / 2;
1844 auto &mat = *this->dataPtr;
1845 if (type == this->zeroType) {
1846 mat.resize(msize * Tensor_Dim1, nb_gauss_pts, false);
1847 mat.clear();
1848 }
1849
1850 if (nb_gauss_pts) {
1851 const size_t nb_dofs = data.getFieldData().size();
1852
1853 if (nb_dofs) {
1854
1855 const int nb_base_functions = data.getN().size2();
1856 auto diff_base_function = data.getFTensor1DiffN<Tensor_Dim1>();
1857 auto gradients_at_pts =
1858 getFTensor3DgFromMat<Tensor_Dim0, Tensor_Dim1, -1,
1860 FTensor::Index<'I', Tensor_Dim0> I;
1861 FTensor::Index<'J', Tensor_Dim0> J;
1862 FTensor::Index<'K', Tensor_Dim1> K;
1863 int size = nb_dofs / msize;
1864 if (nb_dofs % msize) {
1865 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1866 "Data inconsistency");
1867 }
1868 for (int gg = 0; gg < nb_gauss_pts; ++gg) {
1869 auto field_data = data.getFTensor2SymmetricFieldData<Tensor_Dim0>();
1870 int bb = 0;
1871 for (; bb < size; ++bb) {
1872 gradients_at_pts(I, J, K) +=
1873 field_data(I, J) * diff_base_function(K);
1874 ++field_data;
1875 ++diff_base_function;
1876 }
1877 // Number of dofs can be smaller than number of Tensor_Dim0 x base
1878 // functions
1879 for (; bb != nb_base_functions; ++bb)
1880 ++diff_base_function;
1881 ++gradients_at_pts;
1882 }
1883 }
1884 }
1886}
1887
1888/** \brief Get field gradients at integration pts for symmetric tensorial field
1889 * rank 2
1890 *
1891 * \ingroup mofem_forces_and_sources_user_data_operators
1892 */
1893template <int Tensor_Dim0, int Tensor_Dim1>
1896 Tensor_Dim0, Tensor_Dim1> {
1897
1899 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
1900 const EntityType zero_type = MBVERTEX)
1902 Tensor_Dim0, Tensor_Dim1>(field_name, data_ptr, zero_type) {}
1903};
1904
1905template <int Tensor_Dim0, int Tensor_Dim1>
1907 : public OpCalculateTensor2FieldValues_General<Tensor_Dim0,
1908 Tensor_Dim1> {
1909
1911 Tensor_Dim0, Tensor_Dim1>::OpCalculateTensor2FieldValues_General;
1912
1913 /**
1914 * \brief calculate values of vector field at integration points
1915 * @param side side entity number
1916 * @param type side entity type
1917 * @param data entity data
1918 * @return error code
1919 */
1920 MoFEMErrorCode doWork(int side, EntityType type,
1922};
1923
1924/**
1925 * \brief Member function specialization calculating vector field gradients for
1926 * tenor field rank 2
1927 *
1928 */
1929template <int Tensor_Dim0, int Tensor_Dim1>
1931 int side, EntityType type, EntitiesFieldData::EntData &data) {
1933 if (!this->dataPtr)
1934 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1935 "Data pointer not allocated");
1936
1937 const size_t nb_gauss_pts = this->getGaussPts().size2();
1938 auto &mat = *this->dataPtr;
1940 auto get_hessian_at_gauss_pts = MatrixSizeHelper<
1941 GetFTensor3FromMatType<Tensor_Dim0, Tensor_Dim1, Tensor_Dim1, -1, DL>,
1942 DL>::size(mat, nb_gauss_pts);
1943 if (type == this->zeroType) {
1944 mat.clear();
1945 }
1946
1947 if (nb_gauss_pts) {
1948 const size_t nb_dofs = data.getFieldData().size();
1949
1950 if (nb_dofs) {
1951
1952 if (this->dataVec.use_count()) {
1953 this->dotVector.resize(nb_dofs, false);
1954 const double *array;
1955 CHKERR VecGetArrayRead(this->dataVec, &array);
1956 const auto &local_indices = data.getLocalIndices();
1957 for (int i = 0; i != local_indices.size(); ++i)
1958 if (local_indices[i] != -1)
1959 this->dotVector[i] = array[local_indices[i]];
1960 else
1961 this->dotVector[i] = 0;
1962 CHKERR VecRestoreArrayRead(this->dataVec, &array);
1963 data.getFieldData().swap(this->dotVector);
1964 }
1965
1966 const int nb_base_functions = data.getN().size2();
1967
1968 auto &hessian_base = data.getN(BaseDerivatives::SecondDerivative);
1969 #ifndef NDEBUG
1970 if (hessian_base.size1() != nb_gauss_pts) {
1971 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1972 "Wrong number of integration pts (%ld != %ld)",
1973 static_cast<long>(hessian_base.size1()),
1974 static_cast<long>(nb_gauss_pts));
1975 }
1976 if (hessian_base.size2() !=
1977 nb_base_functions * Tensor_Dim1 * Tensor_Dim1) {
1978 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1979 "Wrong number of base functions (%ld != %ld)",
1980 static_cast<long>(hessian_base.size2() /
1981 (Tensor_Dim1 * Tensor_Dim1)),
1982 static_cast<long>(nb_base_functions));
1983 }
1984 if (hessian_base.size2() <
1985 (nb_dofs / Tensor_Dim0) * Tensor_Dim1 * Tensor_Dim1) {
1986 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
1987 "Wrong number of base functions (%ld < %ld)",
1988 static_cast<long>(hessian_base.size2()),
1989 static_cast<long>((nb_dofs / Tensor_Dim0) * Tensor_Dim1 *
1990 Tensor_Dim1));
1991 }
1992 #endif
1993
1994 auto t_diff2_base_function = getFTensor2FromPtr<Tensor_Dim1, Tensor_Dim1>(
1995 &*hessian_base.data().begin());
1996
1997 auto t_hessian_at_gauss_pts = get_hessian_at_gauss_pts();
1998
1999 FTensor::Index<'I', Tensor_Dim0> I;
2000 FTensor::Index<'J', Tensor_Dim1> J;
2001 FTensor::Index<'K', Tensor_Dim1> K;
2002
2003 int size = nb_dofs / Tensor_Dim0;
2004 #ifndef NDEBUG
2005 if (nb_dofs % Tensor_Dim0) {
2006 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2007 "Data inconsistency");
2008 }
2009 #endif
2010
2011 for (int gg = 0; gg < nb_gauss_pts; ++gg) {
2012 auto field_data = data.getFTensor1FieldData<Tensor_Dim0>();
2013 int bb = 0;
2014 for (; bb < size; ++bb) {
2015 t_hessian_at_gauss_pts(I, J, K) +=
2016 field_data(I) * t_diff2_base_function(J, K);
2017 ++field_data;
2018 ++t_diff2_base_function;
2019 }
2020 // Number of dofs can be smaller than number of Tensor_Dim0 x base
2021 // functions
2022 for (; bb != nb_base_functions; ++bb)
2023 ++t_diff2_base_function;
2024 ++t_hessian_at_gauss_pts;
2025 }
2026
2027 if (this->dataVec.use_count()) {
2028 data.getFieldData().swap(this->dotVector);
2029 }
2030 }
2031 }
2033}
2034
2035/**@}*/
2036
2037/** \name Transform tensors and vectors */
2038
2039/**@{*/
2040
2041/**
2042 * @brief Calculate \f$ \pmb\sigma_{ij} = \mathbf{D}_{ijkl} \pmb\varepsilon_{kl}
2043 * \f$
2044 *
2045 * @tparam DIM
2046 *
2047 * \ingroup mofem_forces_and_sources_user_data_operators
2048 */
2049template <int DIM_01, int DIM_23, int S = 0>
2052
2055
2056 /**
2057 * @deprecated Do not use this constructor
2058 */
2061 boost::shared_ptr<MatrixDouble> in_mat,
2062 boost::shared_ptr<MatrixDouble> out_mat,
2063 boost::shared_ptr<MatrixDouble> d_mat)
2064 : UserOp(field_name, OPCOL), inMat(in_mat), outMat(out_mat), dMat(d_mat) {
2065 // Only is run for vertices
2066 std::fill(&doEntities[MBEDGE], &doEntities[MBMAXTYPE], false);
2067 if (!inMat)
2068 THROW_MESSAGE("Pointer for in mat is null");
2069 if (!outMat)
2070 THROW_MESSAGE("Pointer for out mat is null");
2071 if (!dMat)
2072 THROW_MESSAGE("Pointer for tensor mat is null");
2073 }
2074
2075 OpTensorTimesSymmetricTensor(boost::shared_ptr<MatrixDouble> in_mat,
2076 boost::shared_ptr<MatrixDouble> out_mat,
2077 boost::shared_ptr<MatrixDouble> d_mat)
2078 : UserOp(NOSPACE, OPSPACE), inMat(in_mat), outMat(out_mat), dMat(d_mat) {
2079 // Only is run for vertices
2080 if (!inMat)
2081 THROW_MESSAGE("Pointer for in mat is null");
2082 if (!outMat)
2083 THROW_MESSAGE("Pointer for out mat is null");
2084 if (!dMat)
2085 THROW_MESSAGE("Pointer for tensor mat is null");
2086 }
2087
2088 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
2090 const size_t nb_gauss_pts = getGaussPts().size2();
2092 auto get_D_at_pts =
2094 DL>::get(*dMat, nb_gauss_pts);
2095 auto get_in_at_pts =
2097 DL>::get(*inMat, nb_gauss_pts);
2098 auto get_out_at_pts =
2100 DL>::size(*outMat, nb_gauss_pts);
2101 auto t_D_at_pts = get_D_at_pts();
2102 auto t_in_at_pts = get_in_at_pts();
2103 auto t_out_at_pts = get_out_at_pts();
2104 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
2105 t_out_at_pts(i, j) = t_D_at_pts(i, j, k, l) * t_in_at_pts(k, l);
2106 ++t_in_at_pts;
2107 ++t_out_at_pts;
2108 ++t_D_at_pts;
2109 }
2111 }
2112
2113private:
2114 FTensor::Index<'i', DIM_01> i;
2115 FTensor::Index<'j', DIM_01> j;
2116 FTensor::Index<'k', DIM_23> k;
2117 FTensor::Index<'l', DIM_23> l;
2118
2119 boost::shared_ptr<MatrixDouble> inMat;
2120 boost::shared_ptr<MatrixDouble> outMat;
2121 boost::shared_ptr<MatrixDouble> dMat;
2122};
2123
2124/**
2125 * @brief Operator for symmetrizing tensor fields
2126 *
2127 * This template structure symmetrizes tensor fields by computing the symmetric
2128 * part of an input tensor and storing the result in an output matrix. It's
2129 * commonly used in mechanics where symmetric tensors (like stress and strain)
2130 * are required.
2131 *
2132 * @tparam DIM Dimension of the tensor field
2133 */
2134template <int DIM>
2136
2139
2140 /**
2141 * @deprecated Do not use this constructor
2142 */
2144 boost::shared_ptr<MatrixDouble> in_mat,
2145 boost::shared_ptr<MatrixDouble> out_mat)
2146 : UserOp(field_name, OPCOL), inMat(in_mat), outMat(out_mat) {
2147 // Only is run for vertices
2148 std::fill(&doEntities[MBEDGE], &doEntities[MBMAXTYPE], false);
2149 if (!inMat)
2150 THROW_MESSAGE("Pointer not set for in matrix");
2151 if (!outMat)
2152 THROW_MESSAGE("Pointer not set for in matrix");
2153 }
2154
2155 /**
2156 * @brief Constructor for tensor symmetrization operator
2157 *
2158 * @param in_mat Shared pointer to input matrix containing asymmetric tensor
2159 * @param out_mat Shared pointer to output matrix for storing symmetric tensor
2160 */
2161 OpSymmetrizeTensor(boost::shared_ptr<MatrixDouble> in_mat,
2162 boost::shared_ptr<MatrixDouble> out_mat)
2163 : UserOp(NOSPACE, OPSPACE), inMat(in_mat), outMat(out_mat) {
2164 // Only is run for vertices
2165 if (!inMat)
2166 THROW_MESSAGE("Pointer not set for in matrix");
2167 if (!outMat)
2168 THROW_MESSAGE("Pointer not set for in matrix");
2169 }
2170
2171 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
2173 const size_t nb_gauss_pts = getGaussPts().size2();
2175 auto get_in_at_pts =
2176 MatrixSizeHelper<GetFTensor2FromMatType<DIM, DIM, -1, DL>, DL>::get(
2177 *inMat, nb_gauss_pts);
2178 auto t_in_at_pts = get_in_at_pts();
2179 auto get_out_at_pts =
2181 DL>::size(*outMat, nb_gauss_pts);
2182 auto t_out_at_pts = get_out_at_pts();
2183 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
2184 t_out_at_pts(i, j) = (t_in_at_pts(i, j) || t_in_at_pts(j, i)) / 2;
2185 ++t_in_at_pts;
2186 ++t_out_at_pts;
2187 }
2189 }
2190
2191private:
2194 boost::shared_ptr<MatrixDouble> inMat;
2195 boost::shared_ptr<MatrixDouble> outMat;
2196};
2197
2198/**
2199 * @brief Operator for scaling matrix values by a scalar factor
2200 *
2201 * This structure performs element-wise scaling of matrix data by multiplying
2202 * all elements by a scalar value. It's useful for applying material properties,
2203 * coordinate transformations, or other scaling operations in finite element
2204 * computations.
2205 */
2207
2210
2211 /**
2212 * @deprecated Do not use this constructor
2213 */
2214 DEPRECATED OpScaleMatrix(const std::string field_name, const double scale,
2215 boost::shared_ptr<MatrixDouble> in_mat,
2216 boost::shared_ptr<MatrixDouble> out_mat)
2217 : UserOp(field_name, OPCOL), inMat(in_mat), outMat(out_mat) {
2218 scalePtr = boost::make_shared<double>(scale);
2219 // Only is run for vertices
2220 std::fill(&doEntities[MBEDGE], &doEntities[MBMAXTYPE], false);
2221 if (!inMat)
2222 THROW_MESSAGE("Pointer not set for in matrix");
2223 if (!outMat)
2224 THROW_MESSAGE("Pointer not set for in matrix");
2225 }
2226
2227 /**
2228 * @brief Constructor for matrix scaling operator
2229 *
2230 * @param scale_ptr Shared pointer to scalar value for scaling matrix elements
2231 * @param in_mat Shared pointer to input matrix to be scaled
2232 * @param out_mat Shared pointer to output matrix for storing scaled results
2233 */
2234 OpScaleMatrix(boost::shared_ptr<double> scale_ptr,
2235 boost::shared_ptr<MatrixDouble> in_mat,
2236 boost::shared_ptr<MatrixDouble> out_mat)
2237 : UserOp(NOSPACE, OPSPACE), scalePtr(scale_ptr), inMat(in_mat),
2238 outMat(out_mat) {
2239 if (!scalePtr)
2240 THROW_MESSAGE("Pointer not set for scale");
2241 if (!inMat)
2242 THROW_MESSAGE("Pointer not set for in matrix");
2243 if (!outMat)
2244 THROW_MESSAGE("Pointer not set for in matrix");
2245 }
2246
2247 MoFEMErrorCode doWork(int side, EntityType type, EntData &data) {
2249 outMat->resize(inMat->size1(), inMat->size2(), false);
2250 noalias(*outMat) = (*scalePtr) * (*inMat);
2252 }
2253
2254private:
2255 boost::shared_ptr<double> scalePtr;
2256 boost::shared_ptr<MatrixDouble> inMat;
2257 boost::shared_ptr<MatrixDouble> outMat;
2258};
2259
2260/**@}*/
2261
2262/** \name H-div/H-curls (Vectorial bases) values at integration points */
2263
2264/**@{*/
2265
2266/** \brief Get vector field for H-div approximation
2267 * \ingroup mofem_forces_and_sources_user_data_operators
2268 */
2269template <int Base_Dim, int Field_Dim, typename M = MatrixDouble>
2271
2272/** \brief Get vector field for H-div approximation
2273 * \ingroup mofem_forces_and_sources_user_data_operators
2274 */
2275template <int Field_Dim>
2278
2280 boost::shared_ptr<MatrixDouble> data_ptr,
2281 SmartPetscObj<Vec> data_vec,
2282 const EntityType zero_type = MBEDGE,
2283 const int zero_side = 0)
2286 dataPtr(data_ptr), dataVec(data_vec), zeroType(zero_type),
2287 zeroSide(zero_side) {
2288 if (!dataPtr)
2289 THROW_MESSAGE("Pointer is not set");
2290 }
2291
2293 boost::shared_ptr<MatrixDouble> data_ptr,
2294 const EntityType zero_type = MBEDGE,
2295 const int zero_side = 0)
2297 field_name, data_ptr, SmartPetscObj<Vec>(), zero_type, zero_side) {}
2298
2299 /**
2300 * \brief Calculate values of vector field at integration points
2301 * @param side side entity number
2302 * @param type side entity type
2303 * @param data entity data
2304 * @return error code
2305 */
2306 MoFEMErrorCode doWork(int side, EntityType type,
2308
2309private:
2310 boost::shared_ptr<MatrixDouble> dataPtr;
2313 const int zeroSide;
2315};
2316
2317template <int Field_Dim>
2319 3, Field_Dim, MatrixDouble>::doWork(int side, EntityType type,
2322 const size_t nb_integration_points = this->getGaussPts().size2();
2323 auto &mat = *dataPtr;
2325 auto get_data_at_pts =
2326 MatrixSizeHelper<GetFTensor1FromMatType<Field_Dim, -1, DL>,
2327 DL>::size(mat, nb_integration_points);
2328 if (type == zeroType && side == zeroSide) {
2329 mat.clear();
2330 }
2331 const size_t nb_dofs = data.getFieldData().size();
2332 if (!nb_dofs)
2334
2335 if (dataVec.use_count()) {
2336 dotVector.resize(nb_dofs, false);
2337 const double *array;
2338 CHKERR VecGetArrayRead(dataVec, &array);
2339 const auto &local_indices = data.getLocalIndices();
2340 for (int i = 0; i != local_indices.size(); ++i)
2341 if (local_indices[i] != -1)
2342 dotVector[i] = array[local_indices[i]];
2343 else
2344 dotVector[i] = 0;
2345 CHKERR VecRestoreArrayRead(dataVec, &array);
2346 data.getFieldData().swap(dotVector);
2347 }
2348
2349 const size_t nb_base_functions = data.getN().size2() / 3;
2350 FTensor::Index<'i', Field_Dim> i;
2351 auto t_n_hdiv = data.getFTensor1N<3>();
2352 auto t_data_at_pts = get_data_at_pts();
2353 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2354 auto t_dof = data.getFTensor0FieldData();
2355 int bb = 0;
2356 for (; bb != nb_dofs; ++bb) {
2357 t_data_at_pts(i) += t_n_hdiv(i) * t_dof;
2358 ++t_n_hdiv;
2359 ++t_dof;
2360 }
2361 for (; bb != nb_base_functions; ++bb)
2362 ++t_n_hdiv;
2363 ++t_data_at_pts;
2364 }
2365
2366 if (dataVec.use_count()) {
2367 data.getFieldData().swap(dotVector);
2368 }
2370}
2371
2372/** \brief Get vector field for H-div approximation
2373 *
2374 * \ingroup mofem_forces_and_sources_user_data_operators
2375 */
2376template <int Base_Dim, int Field_Dim = Base_Dim>
2378 : public OpCalculateHVecVectorField_General<Base_Dim, Field_Dim> {
2380 Base_Dim, Field_Dim>::OpCalculateHVecVectorField_General;
2381};
2382
2383/** \brief Get vector field for H-div approximation
2384 * \ingroup mofem_forces_and_sources_user_data_operators
2385 */
2386template <int Base_Dim, int Field_Dim = Base_Dim>
2388
2389template <int Field_Dim>
2392
2394 boost::shared_ptr<MatrixDouble> data_ptr,
2395 const EntityType zero_type = MBEDGE,
2396 const int zero_side = 0)
2399 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2400 if (!dataPtr)
2401 THROW_MESSAGE("Pointer is not set");
2402 }
2403
2404 /**
2405 * \brief Calculate values of vector field at integration points
2406 * @param side side entity number
2407 * @param type side entity type
2408 * @param data entity data
2409 * @return error code
2410 */
2411 MoFEMErrorCode doWork(int side, EntityType type,
2413
2414private:
2415 boost::shared_ptr<MatrixDouble> dataPtr;
2417 const int zeroSide;
2418};
2419
2420template <int Field_Dim>
2422 int side, EntityType type, EntitiesFieldData::EntData &data) {
2424
2425 const size_t nb_integration_points = this->getGaussPts().size2();
2426 auto &mat = *dataPtr;
2428 auto get_data_at_pts =
2429 MatrixSizeHelper<GetFTensor1FromMatType<Field_Dim, -1, DL>,
2430 DL>::size(mat, nb_integration_points);
2431 if (type == zeroType && side == zeroSide) {
2432 mat.clear();
2433 }
2434
2435 auto &local_indices = data.getIndices();
2436 const size_t nb_dofs = local_indices.size();
2437 if (nb_dofs) {
2438
2439 std::array<double, MAX_DOFS_ON_ENTITY> dot_dofs_vector;
2440 const double *array;
2441 CHKERR VecGetArrayRead(getFEMethod()->ts_u_t, &array);
2442 for (size_t i = 0; i != nb_dofs; ++i)
2443 if (local_indices[i] != -1)
2444 dot_dofs_vector[i] = array[local_indices[i]];
2445 else
2446 dot_dofs_vector[i] = 0;
2447 CHKERR VecRestoreArrayRead(getFEMethod()->ts_u_t, &array);
2448
2449 const size_t nb_base_functions = data.getN().size2() / 3;
2450 FTensor::Index<'i', Field_Dim> i;
2451 auto t_n_hdiv = data.getFTensor1N<3>();
2452 auto t_data_at_pts = get_data_at_pts();
2453 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2454 int bb = 0;
2455 for (; bb != nb_dofs; ++bb) {
2456 t_data_at_pts(i) += t_n_hdiv(i) * dot_dofs_vector[bb];
2457 ++t_n_hdiv;
2458 }
2459 for (; bb != nb_base_functions; ++bb)
2460 ++t_n_hdiv;
2461 ++t_data_at_pts;
2462 }
2463 }
2464
2466}
2467
2468/**
2469 * @brief Calculate divergence of vector field
2470 * @ingroup mofem_forces_and_sources_user_data_operators
2471 *
2472 * @tparam BASE_DIM
2473 * @tparam SPACE_DIM
2474 */
2475template <int BASE_DIM, int SPACE_DIM>
2478
2480 boost::shared_ptr<VectorDouble> data_ptr,
2481 const EntityType zero_type = MBEDGE,
2482 const int zero_side = 0)
2485 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2486 if (!dataPtr)
2487 THROW_MESSAGE("Pointer is not set");
2488 }
2489
2490 MoFEMErrorCode doWork(int side, EntityType type,
2493 const size_t nb_integration_points = getGaussPts().size2();
2494 if (type == zeroType && side == zeroSide) {
2495 dataPtr->resize(nb_integration_points, false);
2496 dataPtr->clear();
2497 }
2498 const size_t nb_dofs = data.getFieldData().size();
2499 if (!nb_dofs)
2501 const size_t nb_base_functions = data.getN().size2() / BASE_DIM;
2504 auto t_n_diff_hdiv = data.getFTensor2DiffN<BASE_DIM, SPACE_DIM>();
2505 auto t_data = getFTensor0FromVec(*dataPtr);
2506 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2507 auto t_dof = data.getFTensor0FieldData();
2508 int bb = 0;
2509 for (; bb != nb_dofs; ++bb) {
2510 t_data += t_dof * t_n_diff_hdiv(j, j);
2511 ++t_n_diff_hdiv;
2512 ++t_dof;
2513 }
2514 for (; bb != nb_base_functions; ++bb)
2515 ++t_n_diff_hdiv;
2516 ++t_data;
2517 }
2519 }
2520
2521private:
2522 boost::shared_ptr<VectorDouble> dataPtr;
2524 const int zeroSide;
2525};
2526
2527/**
2528 * @brief Calculate gradient of vector field
2529 * @ingroup mofem_forces_and_sources_user_data_operators
2530 *
2531 * @tparam BASE_DIM
2532 * @tparam SPACE_DIM
2533 */
2534template <int BASE_DIM, int SPACE_DIM>
2537
2539 boost::shared_ptr<MatrixDouble> data_ptr,
2540 const EntityType zero_type = MBEDGE,
2541 const int zero_side = 0)
2544 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2545 if (!dataPtr)
2546 THROW_MESSAGE("Pointer is not set");
2547 }
2548
2549 MoFEMErrorCode doWork(int side, EntityType type,
2552 const size_t nb_integration_points = getGaussPts().size2();
2554 auto get_data_at_pts =
2557 DL>::size(*dataPtr, nb_integration_points);
2558 if (type == zeroType && side == zeroSide)
2559 dataPtr->clear();
2560 const size_t nb_dofs = data.getFieldData().size();
2561 if (!nb_dofs)
2563 const size_t nb_base_functions = data.getN().size2() / BASE_DIM;
2566 auto t_base_diff = data.getFTensor2DiffN<BASE_DIM, SPACE_DIM>();
2567 auto t_data_at_pts = get_data_at_pts();
2568 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2569 auto t_dof = data.getFTensor0FieldData();
2570 int bb = 0;
2571 for (; bb != nb_dofs; ++bb) {
2572 t_data_at_pts(i, j) += t_dof * t_base_diff(i, j);
2573 ++t_base_diff;
2574 ++t_dof;
2575 }
2576 for (; bb != nb_base_functions; ++bb)
2577 ++t_base_diff;
2578 ++t_data_at_pts;
2579 }
2581 }
2582
2583private:
2584 boost::shared_ptr<MatrixDouble> dataPtr;
2586 const int zeroSide;
2587};
2588
2589/**
2590 * @brief Calculate gradient of tensor field
2591 * @ingroup mofem_forces_and_sources_user_data_operators
2592 *
2593 * @tparam BASE_DIM
2594 * @tparam FIELD_DIM
2595 * @tparam SPACE_DIM
2596 */
2597template <int BASE_DIM, int FIELD_DIM, int SPACE_DIM>
2599
2600/**
2601 * @brief Specialisation for 3D tensor field gradient calculation
2602 * @ingroup mofem_forces_and_sources_user_data_operators
2603 *
2604 */
2605template <>
2608
2610 boost::shared_ptr<MatrixDouble> data_ptr,
2611 const EntityType zero_type = MBEDGE,
2612 const int zero_side = 0)
2615 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2616 if (!dataPtr)
2617 THROW_MESSAGE("Pointer is not set");
2618 }
2619
2620 MoFEMErrorCode doWork(int side, EntityType type,
2623
2624 const size_t nb_integration_points = getGaussPts().size2();
2626 auto get_data_at_pts =
2628 DL>::size(*dataPtr, nb_integration_points);
2629 if (type == zeroType && side == zeroSide) {
2630 dataPtr->clear();
2631 }
2632
2633 #ifndef NDEBUG
2634 if (data.getFieldData().size() % 3) {
2635 SETERRQ(
2636 PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2637 "Data inconsistency, nb_dofs %% COEFF_DIM != 0, that is %ld %% %d "
2638 "!= 0",
2639 data.getFieldData().size(), 3);
2640 }
2641 #endif
2642
2643 const auto nb_dofs = data.getFieldData().size() / 3;
2644 if (!nb_dofs)
2646
2647 const size_t nb_base_functions = data.getN().size2() / 3;
2648 FTensor::Index<'i', 3> i;
2649 FTensor::Index<'j', 3> j;
2650 FTensor::Index<'k', 3> k;
2651
2652 auto t_base_diff = data.getFTensor2DiffN<3, 3>();
2653 auto t_data_at_pts = get_data_at_pts();
2654 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2655 auto t_dof = data.getFTensor1FieldData<3>();
2656 int bb = 0;
2657 for (; bb != nb_dofs; ++bb) {
2658 t_data_at_pts(k, i, j) += t_base_diff(i, j) * t_dof(k);
2659 ++t_base_diff;
2660 ++t_dof;
2661 }
2662 for (; bb != nb_base_functions; ++bb)
2663 ++t_base_diff;
2664 ++t_data_at_pts;
2665 }
2667 }
2668
2669private:
2670 boost::shared_ptr<MatrixDouble> dataPtr;
2672 const int zeroSide;
2673};
2674
2675template <>
2678
2680 boost::shared_ptr<MatrixDouble> data_ptr,
2681 const EntityType zero_type = MBEDGE,
2682 const int zero_side = 0)
2685 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2686 if (!dataPtr)
2687 THROW_MESSAGE("Pointer is not set");
2688 }
2689
2690 MoFEMErrorCode doWork(int side, EntityType type,
2693
2694 const size_t nb_integration_points = getGaussPts().size2();
2696 auto get_data_at_pts =
2698 DL>::size(*dataPtr, nb_integration_points);
2699 if (type == zeroType && side == zeroSide) {
2700 dataPtr->clear();
2701 }
2702
2703 const auto nb_dofs = data.getFieldData().size();
2704 if (!nb_dofs)
2706
2707 const size_t nb_base_functions = data.getN().size2() / 9;
2708
2709 #ifndef NDEBUG
2710 if (data.getDiffN().size1() != nb_integration_points) {
2711 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2712 "Wrong number of integration pts (%ld != %ld)",
2713 static_cast<long>(data.getDiffN().size1()),
2714 static_cast<long>(nb_integration_points));
2715 }
2716 if (data.getDiffN().size2() != nb_base_functions * 27) {
2717 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2718 "Wrong number of base functions (%ld != %ld)",
2719 static_cast<long>(data.getDiffN().size2() / 27),
2720 static_cast<long>(nb_base_functions));
2721 }
2722 if (nb_base_functions < nb_dofs) {
2723 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2724 "Wrong number of base functions (%ld < %ld)",
2725 static_cast<long>(nb_base_functions),
2726 static_cast<long>(nb_dofs));
2727 }
2728 #endif
2729
2730 FTensor::Index<'i', 3> i;
2731 FTensor::Index<'j', 3> j;
2732 FTensor::Index<'k', 3> k;
2733
2734 auto t_base_diff = data.getFTensor3DiffN<3, 3, 3>();
2735 auto t_data_at_pts = get_data_at_pts();
2736 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2737 auto t_dof = data.getFTensor0FieldData();
2738 int bb = 0;
2739 for (; bb != nb_dofs; ++bb) {
2740 t_data_at_pts(k, i, j) += t_base_diff(k, i, j) * t_dof;
2741 ++t_base_diff;
2742 ++t_dof;
2743 }
2744 for (; bb != nb_base_functions; ++bb)
2745 ++t_base_diff;
2746 ++t_data_at_pts;
2747 }
2748
2750 }
2751
2752private:
2753 boost::shared_ptr<MatrixDouble> dataPtr;
2755 const int zeroSide;
2756};
2757
2758/**
2759 * @brief Calculate gradient of vector field
2760 * @ingroup mofem_forces_and_sources_user_data_operators
2761 *
2762 * @tparam BASE_DIM
2763 * @tparam SPACE_DIM
2764 */
2765template <int BASE_DIM, int SPACE_DIM>
2768
2770 boost::shared_ptr<MatrixDouble> data_ptr,
2771 const EntityType zero_type = MBEDGE,
2772 const int zero_side = 0)
2775 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2776 if (!dataPtr)
2777 THROW_MESSAGE("Pointer is not set");
2778 }
2779
2780 MoFEMErrorCode doWork(int side, EntityType type,
2783 const size_t nb_integration_points = getGaussPts().size2();
2785 auto get_data_at_pts = MatrixSizeHelper<
2787 DL>::size(*dataPtr, nb_integration_points);
2788 if (type == zeroType && side == zeroSide) {
2789 dataPtr->clear();
2790 }
2791 const size_t nb_dofs = data.getFieldData().size();
2792 if (!nb_dofs)
2794
2795 const int nb_base_functions = data.getN().size2() / BASE_DIM;
2796
2797 #ifndef NDEBUG
2798 auto &hessian_base = data.getN(BaseDerivatives::SecondDerivative);
2799 if (hessian_base.size1() != nb_integration_points) {
2800 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2801 "Wrong number of integration pts (%ld != %ld)",
2802 static_cast<long>(hessian_base.size1()),
2803 static_cast<long>(nb_integration_points));
2804 }
2805 if (hessian_base.size2() !=
2806 BASE_DIM * nb_base_functions * SPACE_DIM * SPACE_DIM) {
2807 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2808 "Wrong number of base functions (%ld != %ld)",
2809 static_cast<long>(hessian_base.size2() /
2811 static_cast<long>(nb_base_functions));
2812 }
2813 if (hessian_base.size2() < BASE_DIM * nb_dofs * SPACE_DIM * SPACE_DIM) {
2814 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
2815 "Wrong number of base functions (%ld < %ld)",
2816 static_cast<long>(hessian_base.size2()),
2817 static_cast<long>(BASE_DIM * nb_dofs * SPACE_DIM * SPACE_DIM));
2818 }
2819 #endif
2820
2824
2825 auto t_base_diff2 =
2827 auto t_data_at_pts = get_data_at_pts();
2828 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2829 auto t_dof = data.getFTensor0FieldData();
2830 int bb = 0;
2831 for (; bb != nb_dofs; ++bb) {
2832 t_data_at_pts(i, j, k) += t_dof * t_base_diff2(i, j, k);
2833
2834 ++t_base_diff2;
2835 ++t_dof;
2836 }
2837 for (; bb != nb_base_functions; ++bb)
2838 ++t_base_diff2;
2839 ++t_data_at_pts;
2840 }
2842 }
2843
2844private:
2845 boost::shared_ptr<MatrixDouble> dataPtr;
2847 const int zeroSide;
2848};
2849
2850/**
2851 * @brief Calculate divergence of vector field dot
2852 * @ingroup mofem_forces_and_sources_user_data_operators
2853 *
2854 * @tparam Tensor_Dim dimension of space
2855 */
2856template <int Tensor_Dim1, int Tensor_Dim2>
2859
2861 boost::shared_ptr<VectorDouble> data_ptr,
2862 const EntityType zero_type = MBEDGE,
2863 const int zero_side = 0)
2866 dataPtr(data_ptr), zeroType(zero_type), zeroSide(zero_side) {
2867 if (!dataPtr)
2868 THROW_MESSAGE("Pointer is not set");
2869 }
2870
2871 MoFEMErrorCode doWork(int side, EntityType type,
2874 const size_t nb_integration_points = getGaussPts().size2();
2875 if (type == zeroType && side == zeroSide) {
2876 dataPtr->resize(nb_integration_points, false);
2877 dataPtr->clear();
2878 }
2879
2880 const auto &local_indices = data.getLocalIndices();
2881 const int nb_dofs = local_indices.size();
2882 if (nb_dofs) {
2883
2884 std::array<double, MAX_DOFS_ON_ENTITY> dot_dofs_vector;
2885 const double *array;
2886 CHKERR VecGetArrayRead(getFEMethod()->ts_u_t, &array);
2887 for (size_t i = 0; i != local_indices.size(); ++i)
2888 if (local_indices[i] != -1)
2889 dot_dofs_vector[i] = array[local_indices[i]];
2890 else
2891 dot_dofs_vector[i] = 0;
2892 CHKERR VecRestoreArrayRead(getFEMethod()->ts_u_t, &array);
2893
2894 const size_t nb_base_functions = data.getN().size2() / Tensor_Dim1;
2895 FTensor::Index<'i', Tensor_Dim1> i;
2896 auto t_n_diff_hdiv = data.getFTensor2DiffN<Tensor_Dim1, Tensor_Dim2>();
2897 auto t_data = getFTensor0FromVec(*dataPtr);
2898 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
2899 int bb = 0;
2900 for (; bb != nb_dofs; ++bb) {
2901 double div = 0;
2902 for (auto ii = 0; ii != Tensor_Dim2; ++ii)
2903 div += t_n_diff_hdiv(ii, ii);
2904 t_data += dot_dofs_vector[bb] * div;
2905 ++t_n_diff_hdiv;
2906 }
2907 for (; bb != nb_base_functions; ++bb)
2908 ++t_n_diff_hdiv;
2909 ++t_data;
2910 }
2911 }
2913 }
2914
2915private:
2916 boost::shared_ptr<VectorDouble> dataPtr;
2918 const int zeroSide;
2919};
2920
2921/**
2922 * @brief Calculate curl of vector field
2923 * @ingroup mofem_forces_and_sources_user_data_operators
2924 *
2925 * @tparam Base_Dim base function dimension
2926 * @tparam Space_Dim dimension of space
2927 * @tparam Hcurl field dimension
2928 */
2929template <int Base_Dim, int Space_Dim> struct OpCalculateHcurlVectorCurl;
2930
2931/**
2932 * @brief Calculate curl of vector field
2933 * @ingroup mofem_forces_and_sources_user_data_operators
2934 *
2935 * @tparam Base_Dim base function dimension
2936 * @tparam Space_Dim dimension of space
2937 * @tparam Hcurl field dimension
2938 */
2939template <>
2942 OpCalculateHcurlVectorCurl(const std::string field_name,
2943 boost::shared_ptr<MatrixDouble> data_ptr,
2944 const EntityType zero_type = MBEDGE,
2945 const int zero_side = 0);
2946 MoFEMErrorCode doWork(int side, EntityType type,
2948
2949private:
2950 boost::shared_ptr<MatrixDouble> dataPtr;
2952 const int zeroSide;
2953};
2954
2955/**
2956 * @brief Calculate curl of vector field
2957 * @ingroup mofem_forces_and_sources_user_data_operators
2958 *
2959 * @tparam Field_Dim dimension of field
2960 * @tparam Space_Dim dimension of space
2961 */
2962template <>
2965
2966 OpCalculateHcurlVectorCurl(const std::string field_name,
2967 boost::shared_ptr<MatrixDouble> data_ptr,
2968 const EntityType zero_type = MBVERTEX,
2969 const int zero_side = 0);
2970
2971 MoFEMErrorCode doWork(int side, EntityType type,
2973
2974private:
2975 boost::shared_ptr<MatrixDouble> dataPtr;
2977 const int zeroSide;
2978};
2979
2980/**
2981 * @brief Calculate curl of vector field
2982 * @ingroup mofem_forces_and_sources_user_data_operators
2983 *
2984 * @tparam Field_Dim dimension of field
2985 * @tparam Space_Dim dimension of space
2986 */
2987template <>
2990
2991 OpCalculateHcurlVectorCurl(const std::string field_name,
2992 boost::shared_ptr<MatrixDouble> data_ptr,
2993 const EntityType zero_type = MBVERTEX,
2994 const int zero_side = 0);
2995
2996 MoFEMErrorCode doWork(int side, EntityType type,
2998
2999private:
3000 boost::shared_ptr<MatrixDouble> dataPtr;
3002 const int zeroSide;
3003};
3004
3005/**
3006 * @brief Calculate tenor field using vectorial base, i.e. Hdiv/Hcurl
3007 * \ingroup mofem_forces_and_sources_user_data_operators
3008 *
3009 * @tparam Tensor_Dim0 rank of the field
3010 * @tparam Tensor_Dim1 dimension of space
3011 */
3012template <int Tensor_Dim0, int Tensor_Dim1>
3015
3017 boost::shared_ptr<MatrixDouble> data_ptr,
3018 boost::shared_ptr<double> scale_ptr,
3020 const EntityType zero_type = MBEDGE,
3021 const int zero_side = 0)
3024 dataPtr(data_ptr), scalePtr(scale_ptr), dataVec(data_vec),
3025 zeroType(zero_type), zeroSide(zero_side) {
3026 if (!dataPtr)
3027 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Pointer is not set");
3028 }
3029
3031 boost::shared_ptr<MatrixDouble> data_ptr,
3032 const EntityType zero_type = MBEDGE,
3033 const int zero_side = 0)
3034 : OpCalculateHVecTensorField(field_name, data_ptr, nullptr,
3035 SmartPetscObj<Vec>(), zero_type, zero_side) {
3036 }
3037
3038 MoFEMErrorCode doWork(int side, EntityType type,
3041 const size_t nb_integration_points = getGaussPts().size2();
3043 auto get_data_at_pts =
3045 GetFTensor2FromMatType<Tensor_Dim0, Tensor_Dim1, -1, DL>,
3046 DL>::size(*dataPtr, nb_integration_points);
3047 if (type == zeroType && side == zeroSide)
3048 dataPtr->clear();
3049 const size_t nb_dofs = data.getFieldData().size();
3050 if (nb_dofs) {
3051
3052 if (dataVec.use_count()) {
3053 dotVector.resize(nb_dofs, false);
3054 const double *array;
3055 CHKERR VecGetArrayRead(dataVec, &array);
3056 const auto &local_indices = data.getLocalIndices();
3057 for (int i = 0; i != local_indices.size(); ++i)
3058 if (local_indices[i] != -1)
3059 dotVector[i] = array[local_indices[i]];
3060 else
3061 dotVector[i] = 0;
3062 CHKERR VecRestoreArrayRead(dataVec, &array);
3063 data.getFieldData().swap(dotVector);
3064 }
3065
3066 double scale = (scalePtr) ? *scalePtr : 1.0;
3067 const size_t nb_base_functions = data.getN().size2() / 3;
3068 FTensor::Index<'i', Tensor_Dim0> i;
3069 FTensor::Index<'j', Tensor_Dim1> j;
3070 auto t_n_hvec = data.getFTensor1N<3>();
3071 auto t_data_at_pts = get_data_at_pts();
3072 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3073 auto t_dof = data.getFTensor1FieldData<Tensor_Dim0>();
3074 size_t bb = 0;
3075 for (; bb != nb_dofs / Tensor_Dim0; ++bb) {
3076 t_data_at_pts(i, j) += (scale * t_dof(i)) * t_n_hvec(j);
3077 ++t_n_hvec;
3078 ++t_dof;
3079 }
3080 for (; bb < nb_base_functions; ++bb)
3081 ++t_n_hvec;
3082 ++t_data_at_pts;
3083 }
3084
3085 if (dataVec.use_count()) {
3086 data.getFieldData().swap(dotVector);
3087 }
3088 }
3090 }
3091
3092private:
3093 boost::shared_ptr<MatrixDouble> dataPtr;
3094 boost::shared_ptr<double> scalePtr;
3097 const int zeroSide;
3098 VectorDouble dotVector; ///< Keeps temporary values of time derivatives
3099};
3100
3101/** \brief Get tensor field for H-div approximation
3102 * \ingroup mofem_forces_and_sources_user_data_operators
3103 *
3104 * \warning This operator is not tested
3105 */
3106template <int Tensor_Dim0, int Tensor_Dim1>
3109
3111
3113 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
3114 SmartPetscObj<Vec> data_vec, EntityType broken_type,
3115 boost::shared_ptr<Range> broken_range_ptr = nullptr,
3116 boost::shared_ptr<double> scale_ptr = nullptr,
3117 const EntityType zero_type = MBEDGE, const int zero_side = 0)
3119 dataPtr(data_ptr), dataVec(data_vec), brokenType(broken_type),
3120 brokenRangePtr(broken_range_ptr), zeroType(zero_type) {
3121 if (!dataPtr)
3122 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Pointer is not set");
3123 }
3124
3125 /**
3126 * \brief Calculate values of vector field at integration points
3127 * @param side side entity number
3128 * @param type side entity type
3129 * @param data entity data
3130 * @return error code
3131 */
3132 MoFEMErrorCode doWork(int side, EntityType type,
3134
3135private:
3136 boost::shared_ptr<MatrixDouble> dataPtr;
3138 EntityType brokenType;
3139 boost::shared_ptr<Range> brokenRangePtr;
3140 boost::shared_ptr<double> scalePtr;
3143};
3144
3145template <int Tensor_Dim0, int Tensor_Dim1>
3148 int side, EntityType type, EntitiesFieldData::EntData &data) {
3150 const size_t nb_integration_points = OP::getGaussPts().size2();
3152 auto get_data_at_pts =
3154 GetFTensor2FromMatType<Tensor_Dim0, Tensor_Dim1, -1, DL>,
3155 DL>::size(*dataPtr, nb_integration_points);
3156 if (type == zeroType)
3157 dataPtr->clear();
3158 const size_t nb_dofs = data.getFieldData().size();
3159 if (!nb_dofs)
3161
3162 if (dataVec.use_count()) {
3163 dotVector.resize(nb_dofs, false);
3164 const double *array;
3165 CHKERR VecGetArrayRead(dataVec, &array);
3166 const auto &local_indices = data.getLocalIndices();
3167 for (int i = 0; i != local_indices.size(); ++i)
3168 if (local_indices[i] != -1)
3169 dotVector[i] = array[local_indices[i]];
3170 else
3171 dotVector[i] = 0;
3172 CHKERR VecRestoreArrayRead(dataVec, &array);
3173 data.getFieldData().swap(dotVector);
3174 }
3175
3176 /**
3177 * @brief Get side face dofs
3178 *
3179 * Find which base functions on borken space have adjacent given entity type
3180 * and are in the range ptr if given.
3181 *
3182 */
3183 auto get_get_side_face_dofs = [&]() {
3184 auto fe_type = OP::getFEType();
3185
3186 BaseFunction::DofsSideMap &side_dof_map =
3187 data.getFieldEntities()[0]->getDofSideMap().at(fe_type);
3188 std::vector<int> side_face_dofs;
3189 side_face_dofs.reserve(data.getIndices().size() / Tensor_Dim0);
3190
3191 for (
3192
3193 auto it = side_dof_map.get<1>().begin();
3194 it != side_dof_map.get<1>().end(); ++it
3195
3196 ) {
3197 if ((Tensor_Dim0 * it->dof) >= data.getIndices().size()) {
3198 break;
3199 }
3200 if (it->type == brokenType) {
3201 if (brokenRangePtr) {
3202 auto ent = OP::getSideEntity(it->side, brokenType);
3203 if (brokenRangePtr->find(ent) != brokenRangePtr->end()) {
3204 side_face_dofs.push_back(it->dof);
3205 }
3206 } else {
3207 side_face_dofs.push_back(it->dof);
3208 }
3209 }
3210 }
3211
3212 return side_face_dofs;
3213 };
3214
3215 auto side_face_dofs = get_get_side_face_dofs();
3216
3217 FTensor::Index<'i', Tensor_Dim0> i;
3218 FTensor::Index<'j', Tensor_Dim1> j;
3219 auto t_data_at_pts = get_data_at_pts();
3220 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3221 for (auto b : side_face_dofs) {
3222 auto t_row_base = data.getFTensor1N<3>(gg, b);
3223 auto t_dof = getFTensor1FromPtr<Tensor_Dim0>(data.getFieldData().data() +
3224 b * Tensor_Dim0);
3225 t_data_at_pts(i, j) += t_dof(i) * t_row_base(j);
3226 }
3227 ++t_data_at_pts;
3228 }
3229 *dataPtr *= (scalePtr) ? *scalePtr : 1.0;
3230
3231 if (dataVec.use_count()) {
3232 data.getFieldData().swap(dotVector);
3233 }
3234
3236}
3237
3238/**
3239 * @brief Calculate tenor field using tensor base, i.e. Hdiv/Hcurl
3240 * \ingroup mofem_forces_and_sources_user_data_operators
3241 *
3242 * @tparam Tensor_Dim0 rank of the field
3243 * @tparam Tensor_Dim1 dimension of space
3244 */
3245template <int Tensor_Dim0, int Tensor_Dim1>
3248
3250 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
3251 boost::shared_ptr<double> scale_ptr,
3253 const EntityType zero_type = MBEDGE, const int zero_side = 0)
3256 dataPtr(data_ptr), scalePtr(scale_ptr), dataVec(data_vec),
3257 zeroType(zero_type), zeroSide(zero_side) {
3258 if (!dataPtr)
3259 THROW_MESSAGE("Pointer is not set");
3260 }
3261
3263 boost::shared_ptr<MatrixDouble> data_ptr,
3264 const EntityType zero_type = MBEDGE,
3265 const int zero_side = 0)
3266 : OpCalculateHTensorTensorField(field_name, data_ptr, nullptr,
3267 SmartPetscObj<Vec>(), zero_type,
3268 zero_side) {}
3269
3270 MoFEMErrorCode doWork(int side, EntityType type,
3273 const size_t nb_integration_points = getGaussPts().size2();
3275 auto get_data_at_pts =
3277 GetFTensor2FromMatType<Tensor_Dim0, Tensor_Dim1, -1, DL>,
3278 DL>::size(*dataPtr, nb_integration_points);
3279 if (type == zeroType && side == zeroSide)
3280 dataPtr->clear();
3281 const size_t nb_dofs = data.getFieldData().size();
3282 if (!nb_dofs)
3284
3285 if (dataVec.use_count()) {
3286 dotVector.resize(nb_dofs, false);
3287 const double *array;
3288 CHKERR VecGetArrayRead(dataVec, &array);
3289 const auto &local_indices = data.getLocalIndices();
3290 for (int i = 0; i != local_indices.size(); ++i)
3291 if (local_indices[i] != -1)
3292 dotVector[i] = array[local_indices[i]];
3293 else
3294 dotVector[i] = 0;
3295 CHKERR VecRestoreArrayRead(dataVec, &array);
3296 data.getFieldData().swap(dotVector);
3297 }
3298
3299 double scale = (scalePtr) ? *scalePtr : 1.0;
3300 const size_t nb_base_functions =
3301 data.getN().size2() / (Tensor_Dim0 * Tensor_Dim1);
3302 FTensor::Index<'i', Tensor_Dim0> i;
3303 FTensor::Index<'j', Tensor_Dim1> j;
3304 auto t_n_hten = data.getFTensor2N<Tensor_Dim0, Tensor_Dim1>();
3305 auto t_data_at_pts = get_data_at_pts();
3306 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3307 auto t_dof = data.getFTensor0FieldData();
3308 size_t bb = 0;
3309 for (; bb != nb_dofs; ++bb) {
3310 t_data_at_pts(i, j) += (scale * t_dof) * t_n_hten(i, j);
3311 ++t_n_hten;
3312 ++t_dof;
3313 }
3314 for (; bb < nb_base_functions; ++bb)
3315 ++t_n_hten;
3316 ++t_data_at_pts;
3317 }
3318
3319 if (dataVec.use_count()) {
3320 data.getFieldData().swap(dotVector);
3321 }
3322
3324 }
3325
3326private:
3327 boost::shared_ptr<MatrixDouble> dataPtr;
3328 boost::shared_ptr<double> scalePtr;
3331 const int zeroSide;
3332 VectorDouble dotVector; ///< Keeps temporary values of time derivatives
3333};
3334
3335/**
3336 * @brief Calculate divergence of tonsorial field using vectorial base
3337 * \ingroup mofem_forces_and_sources_user_data_operators
3338 *
3339 * @tparam Tensor_Dim0 rank of the field
3340 * @tparam Tensor_Dim1 dimension of space
3341 */
3342template <int Tensor_Dim0, int Tensor_Dim1,
3343 CoordinateTypes CoordSys = CARTESIAN>
3346
3348 boost::shared_ptr<MatrixDouble> data_ptr,
3349 SmartPetscObj<Vec> data_vec,
3350 const EntityType zero_type = MBEDGE,
3351 const int zero_side = 0)
3354 dataPtr(data_ptr), dataVec(data_vec), zeroType(zero_type),
3355 zeroSide(zero_side) {
3356 if (!dataPtr)
3357 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Pointer is not set");
3358 }
3359
3361 boost::shared_ptr<MatrixDouble> data_ptr,
3362 const EntityType zero_type = MBEDGE,
3363 const int zero_side = 0)
3365 field_name, data_ptr, SmartPetscObj<Vec>(), zero_type, zero_side) {}
3366
3367 MoFEMErrorCode doWork(int side, EntityType type,
3370 const size_t nb_integration_points = getGaussPts().size2();
3371 auto &mat = *dataPtr;
3373 auto get_data_at_pts =
3374 MatrixSizeHelper<GetFTensor1FromMatType<Tensor_Dim0, -1, DL>,
3375 DL>::size(mat, nb_integration_points);
3376 if (type == zeroType && side == zeroSide) {
3377 mat.clear();
3378 }
3379 const size_t nb_dofs = data.getFieldData().size();
3380 if (nb_dofs) {
3381
3382 if (dataVec.use_count()) {
3383 dotVector.resize(nb_dofs, false);
3384 const double *array;
3385 CHKERR VecGetArrayRead(dataVec, &array);
3386 const auto &local_indices = data.getLocalIndices();
3387 for (int i = 0; i != local_indices.size(); ++i)
3388 if (local_indices[i] != -1)
3389 dotVector[i] = array[local_indices[i]];
3390 else
3391 dotVector[i] = 0;
3392 CHKERR VecRestoreArrayRead(dataVec, &array);
3393 data.getFieldData().swap(dotVector);
3394 }
3395
3396 const size_t nb_base_functions = data.getN().size2() / 3;
3397 FTensor::Index<'i', Tensor_Dim0> i;
3398 FTensor::Index<'j', Tensor_Dim1> j;
3399 auto t_n_diff_hvec = data.getFTensor2DiffN<3, Tensor_Dim1>();
3400 auto t_data_at_pts = get_data_at_pts();
3401 auto t_base = data.getFTensor1N<3>();
3402 auto t_coords = getFTensor1CoordsAtGaussPts();
3403 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3404 auto t_dof = data.getFTensor1FieldData<Tensor_Dim0>();
3405 size_t bb = 0;
3406 for (; bb != nb_dofs / Tensor_Dim0; ++bb) {
3407 double div = t_n_diff_hvec(j, j);
3408 t_data_at_pts(i) += t_dof(i) * div;
3409 if constexpr (CoordSys == CYLINDRICAL) {
3410 t_data_at_pts(i) += t_base(0) * (t_dof(i) / t_coords(0));
3411 }
3412 ++t_n_diff_hvec;
3413 ++t_dof;
3414 ++t_base;
3415 }
3416 for (; bb < nb_base_functions; ++bb) {
3417 ++t_base;
3418 ++t_n_diff_hvec;
3419 }
3420 ++t_data_at_pts;
3421 ++t_coords;
3422 }
3423
3424 if (dataVec.use_count()) {
3425 data.getFieldData().swap(dotVector);
3426 }
3427 }
3429 }
3430
3431private:
3432 boost::shared_ptr<MatrixDouble> dataPtr;
3435 const int zeroSide;
3436
3437 VectorDouble dotVector; ///< Keeps temporary values of time derivatives
3438};
3439
3440/**
3441 * @brief Calculate divergence of tonsorial field using vectorial base
3442 * \ingroup mofem_forces_and_sources_user_data_operators
3443 *
3444 * \warning This operator is not tested
3445 *
3446 * @tparam Tensor_Dim0 rank of the field
3447 * @tparam Tensor_Dim1 dimension of space
3448 */
3449template <int Tensor_Dim0, int Tensor_Dim1,
3450 CoordinateTypes CoordSys = CARTESIAN>
3453
3455
3457 const std::string field_name, boost::shared_ptr<MatrixDouble> data_ptr,
3458 SmartPetscObj<Vec> data_vec, EntityType broken_type,
3459 boost::shared_ptr<Range> broken_range_ptr = nullptr,
3460 boost::shared_ptr<double> scale_ptr = nullptr,
3461 const EntityType zero_type = MBEDGE)
3463 dataPtr(data_ptr), dataVec(data_vec), brokenType(broken_type),
3464 brokenRangePtr(broken_range_ptr), scalePtr(scale_ptr),
3465 zeroType(zero_type) {
3466 if (!dataPtr)
3467 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Pointer is not set");
3468 }
3469
3470 MoFEMErrorCode doWork(int side, EntityType type,
3473 const size_t nb_integration_points = getGaussPts().size2();
3474 auto &mat = *dataPtr;
3476 auto get_data_at_pts =
3477 MatrixSizeHelper<GetFTensor1FromMatType<Tensor_Dim0, -1, DL>,
3478 DL>::size(mat, nb_integration_points);
3479 if (type == zeroType && side == 0) {
3480 mat.clear();
3481 }
3482
3483 const size_t nb_dofs = data.getFieldData().size();
3484 if (nb_dofs) {
3485
3486 if (dataVec.use_count()) {
3487 dotVector.resize(nb_dofs, false);
3488 const double *array;
3489 CHKERR VecGetArrayRead(dataVec, &array);
3490 const auto &local_indices = data.getLocalIndices();
3491 for (int i = 0; i != local_indices.size(); ++i)
3492 if (local_indices[i] != -1)
3493 dotVector[i] = array[local_indices[i]];
3494 else
3495 dotVector[i] = 0;
3496 CHKERR VecRestoreArrayRead(dataVec, &array);
3497 data.getFieldData().swap(dotVector);
3498 }
3499
3500 /**
3501 * @brief Get side face dofs
3502 *
3503 * Find which base functions on borken space have adjacent given entity
3504 * type and are in the range ptr if given.
3505 *
3506 */
3507 auto get_get_side_face_dofs = [&]() {
3508 auto fe_type = OP::getFEType();
3509
3510 BaseFunction::DofsSideMap &side_dof_map =
3511 data.getFieldEntities()[0]->getDofSideMap().at(fe_type);
3512 std::vector<int> side_face_dofs;
3513 side_face_dofs.reserve(data.getIndices().size() / Tensor_Dim0);
3514
3515 for (
3516
3517 auto it = side_dof_map.get<1>().begin();
3518 it != side_dof_map.get<1>().end(); ++it
3519
3520 ) {
3521 if ((Tensor_Dim0 * it->dof) >= data.getIndices().size()) {
3522 break;
3523 }
3524 if (it->type == brokenType) {
3525 if (brokenRangePtr) {
3526 auto ent = OP::getSideEntity(it->side, brokenType);
3527 if (brokenRangePtr->find(ent) != brokenRangePtr->end()) {
3528 side_face_dofs.push_back(it->dof);
3529 }
3530 } else {
3531 side_face_dofs.push_back(it->dof);
3532 }
3533 }
3534 }
3535
3536 return side_face_dofs;
3537 };
3538
3539 auto side_face_dofs = get_get_side_face_dofs();
3540
3541 FTensor::Index<'i', Tensor_Dim0> i;
3542 FTensor::Index<'j', Tensor_Dim1> j;
3543 auto t_data_at_pts = get_data_at_pts();
3544 auto t_coords = getFTensor1CoordsAtGaussPts();
3545 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3546 for (auto b : side_face_dofs) {
3547 auto t_dof = getFTensor1FromPtr<Tensor_Dim0>(
3548 data.getFieldData().data() + b * Tensor_Dim0);
3549 auto t_base = data.getFTensor1N<3>(gg, b);
3550 auto t_diff_base = data.getFTensor2DiffN<3, Tensor_Dim1>(gg, b);
3551 double div = t_diff_base(j, j);
3552 t_data_at_pts(i) += t_dof(i) * div;
3553 if constexpr (CoordSys == CYLINDRICAL) {
3554 t_data_at_pts(i) += t_base(0) * (t_dof(i) / t_coords(0));
3555 }
3556 }
3557 ++t_data_at_pts;
3558 ++t_coords;
3559 }
3560 }
3561
3562 if (dataVec.use_count()) {
3563 data.getFieldData().swap(dotVector);
3564 }
3565
3567 }
3568
3569private:
3570 boost::shared_ptr<MatrixDouble> dataPtr;
3572 EntityType brokenType;
3573 boost::shared_ptr<Range> brokenRangePtr;
3574 boost::shared_ptr<double> scalePtr;
3577};
3578
3579/**
3580 * @brief Calculate trace of vector (Hdiv/Hcurl) space
3581 *
3582 * @tparam Tensor_Dim
3583 * @tparam OpBase
3584 */
3585template <int Tensor_Dim, typename OpBase>
3587
3589 boost::shared_ptr<MatrixDouble> data_ptr,
3590 boost::shared_ptr<double> scale_ptr,
3591 const EntityType zero_type = MBEDGE,
3592 const int zero_side = 0)
3593 : OpBase(field_name, OpBase::OPCOL), dataPtr(data_ptr),
3594 scalePtr(scale_ptr), zeroType(zero_type), zeroSide(zero_side) {
3595 if (!dataPtr)
3596 THROW_MESSAGE("Pointer is not set");
3597 }
3598
3600 boost::shared_ptr<MatrixDouble> data_ptr,
3601 const EntityType zero_type = MBEDGE,
3602 const int zero_side = 0)
3603 : OpCalculateHVecTensorTrace(field_name, data_ptr, nullptr, zero_type,
3604 zero_side) {}
3605
3606 MoFEMErrorCode doWork(int side, EntityType type,
3609 const size_t nb_integration_points = OpBase::getGaussPts().size2();
3610 auto &mat = *dataPtr;
3612 auto get_data_at_pts =
3613 MatrixSizeHelper<GetFTensor1FromMatType<Tensor_Dim, -1, DL>,
3614 DL>::size(mat, nb_integration_points);
3615 if (type == zeroType && side == 0) {
3616 mat.clear();
3617 }
3618 const size_t nb_dofs = data.getFieldData().size();
3619 if (nb_dofs) {
3620 double scale_val = (scalePtr) ? *scalePtr : 1.0;
3621 auto t_normal = OpBase::getFTensor1NormalsAtGaussPts();
3622 const size_t nb_base_functions = data.getN().size2() / 3;
3623 auto t_base = data.getFTensor1N<3>();
3624 auto t_data_at_pts = get_data_at_pts();
3625 for (size_t gg = 0; gg != nb_integration_points; ++gg) {
3626 FTensor::Tensor1<double, Tensor_Dim> t_normalized_normal;
3627 t_normalized_normal(j) = t_normal(j);
3628 t_normalized_normal.normalize();
3629 auto t_dof = data.getFTensor1FieldData<Tensor_Dim>();
3630 size_t bb = 0;
3631 for (; bb != nb_dofs / Tensor_Dim; ++bb) {
3632 t_data_at_pts(i) +=
3633 (scale_val * t_dof(i)) * (t_base(j) * t_normalized_normal(j));
3634 ++t_base;
3635 ++t_dof;
3636 }
3637 for (; bb < nb_base_functions; ++bb) {
3638 ++t_base;
3639 }
3640 ++t_data_at_pts;
3641 ++t_normal;
3642 }
3643 }
3645 }
3646
3647private:
3648 boost::shared_ptr<MatrixDouble> dataPtr;
3649 boost::shared_ptr<double> scalePtr;
3651 const int zeroSide;
3652 FTensor::Index<'i', Tensor_Dim> i;
3653 FTensor::Index<'j', Tensor_Dim> j;
3654};
3655
3656/**@}*/
3657
3658/** \name Other operators */
3659
3660/**@{*/
3661
3662/**@}*/
3663
3664/** \name Operators for faces */
3665
3666/**@{*/
3667
3668/** \brief Transform local reference derivatives of shape functions to global
3669derivatives
3670
3671\ingroup mofem_forces_and_sources_tri_element
3672
3673*/
3674template <int DIM, int DERIVATIVE = 1> struct OpSetInvJacSpaceForFaceImpl;
3675
3678
3680 boost::shared_ptr<MatrixDouble> inv_jac_ptr);
3681
3682protected:
3683 /**
3684 * @brief Apply transformation to the input matrix
3685 *
3686 * @tparam D1 dimension of the derivative of base functions in input
3687 * @tparam D2 dimension of the derivative of base functions in output
3688 * @tparam J1 nb of rows in jacobian (= dimension of space)
3689 * @tparam J2 nb of columns in jacobian (= dimension of reference element)
3690 * @param diff_n
3691 * @return MoFEMErrorCode
3692 */
3693 template <int D1, int D2, int J1, int J2>
3696
3697 static_assert(D2 == J2, "Dimension of jacobian and dimension of <out> "
3698 "directive does not match");
3699
3700 size_t nb_functions = diff_n.size2() / D1;
3701 if (nb_functions) {
3702 size_t nb_gauss_pts = diff_n.size1();
3703
3704 #ifndef NDEBUG
3705 if (nb_gauss_pts != getGaussPts().size2())
3706 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3707 "Wrong number of Gauss Pts");
3708 if (diff_n.size2() % D1)
3709 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
3710 "Number of directives of base functions and D1 dimension does "
3711 "not match");
3712 #endif
3713
3714 diffNinvJac.resize(diff_n.size1(), D2 * nb_functions, false);
3715
3716 FTensor::Index<'i', D2> i;
3717 FTensor::Index<'k', D1> k;
3718 auto t_diff_n = getFTensor1FromPtr<D2>(&*diffNinvJac.data().begin());
3719 auto t_diff_n_ref = getFTensor1FromPtr<D1>(&*diff_n.data().begin());
3721 auto get_inv_jac_at_pts =
3722 MatrixSizeHelper<GetFTensor2FromMatType<J1, J2, -1, DL>, DL>::get(
3723 *invJacPtr, nb_gauss_pts);
3724 auto t_inv_jac_at_pts = get_inv_jac_at_pts();
3725 for (size_t gg = 0; gg != nb_gauss_pts; ++gg, ++t_inv_jac_at_pts) {
3726 for (size_t dd = 0; dd != nb_functions; ++dd) {
3727 t_diff_n(i) = t_inv_jac_at_pts(k, i) * t_diff_n_ref(k);
3728 ++t_diff_n;
3729 ++t_diff_n_ref;
3730 }
3731 }
3732
3733 diff_n.swap(diffNinvJac);
3734 }
3736 }
3737
3738 boost::shared_ptr<MatrixDouble> invJacPtr;
3740};
3741
3742template <>
3745
3747
3748 MoFEMErrorCode doWork(int side, EntityType type,
3750};
3751
3752template <>
3754 : public OpSetInvJacSpaceForFaceImpl<2, 1> {
3755
3756 using OpSetInvJacSpaceForFaceImpl<2, 1>::OpSetInvJacSpaceForFaceImpl;
3757
3758 MoFEMErrorCode doWork(int side, EntityType type,
3760};
3761
3762template <>
3764 : public OpSetInvJacSpaceForFaceImpl<2, 1> {
3765
3766 using OpSetInvJacSpaceForFaceImpl<2, 1>::OpSetInvJacSpaceForFaceImpl;
3767
3768 MoFEMErrorCode doWork(int side, EntityType type,
3770};
3771
3772template <int DERIVARIVE = 1>
3774 : public OpSetInvJacSpaceForFaceImpl<2, DERIVARIVE> {
3775 OpSetInvJacH1ForFace(boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3776 : OpSetInvJacSpaceForFaceImpl<2, DERIVARIVE>(H1, inv_jac_ptr) {}
3777};
3778
3779template <int DERIVARIVE = 1>
3781 : public OpSetInvJacSpaceForFaceImpl<2, DERIVARIVE> {
3782 OpSetInvJacL2ForFace(boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3783 : OpSetInvJacSpaceForFaceImpl<2, DERIVARIVE>(L2, inv_jac_ptr) {}
3784};
3785
3786template <int DERIVARIVE = 1>
3788 : public OpSetInvJacSpaceForFaceImpl<3, DERIVARIVE> {
3790 boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3791 : OpSetInvJacSpaceForFaceImpl<3, DERIVARIVE>(H1, inv_jac_ptr) {}
3792};
3793
3794template <int DERIVARIVE = 1>
3796 : public OpSetInvJacSpaceForFaceImpl<3, DERIVARIVE> {
3798 boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3799 : OpSetInvJacSpaceForFaceImpl<3, DERIVARIVE>(L2, inv_jac_ptr) {}
3800};
3801
3802/**
3803 * \brief Transform local reference derivatives of shape function to
3804 global derivatives for face
3805
3806 * \ingroup mofem_forces_and_sources_tri_element
3807 */
3808template <int DIM> struct OpSetInvJacHcurlFaceImpl;
3809
3810template <>
3813
3814 OpSetInvJacHcurlFaceImpl(boost::shared_ptr<MatrixDouble> inv_jac_ptr)
3816 invJacPtr(inv_jac_ptr) {}
3817
3818 MoFEMErrorCode doWork(int side, EntityType type,
3820
3821protected:
3822 boost::shared_ptr<MatrixDouble> invJacPtr;
3824};
3825
3826template <>
3828 using OpSetInvJacHcurlFaceImpl<2>::OpSetInvJacHcurlFaceImpl;
3829 MoFEMErrorCode doWork(int side, EntityType type,
3831};
3832
3835
3836/**
3837 * @brief Make Hdiv space from Hcurl space in 2d
3838 * @ingroup mofem_forces_and_sources_tri_element
3839 */
3849
3850/** \brief Transform Hcurl base fluxes from reference element to physical
3851 * triangle
3852 */
3854
3855/** \brief Apply contravariant (Piola) transfer to Hdiv space on face
3856 *
3857 * Covariant Piola transformation
3858 \f[
3859 \psi_i|_t = J^{-1}_{ij}\hat{\psi}_j\\
3860 \left.\frac{\partial \psi_i}{\partial \xi_j}\right|_t
3861 = J^{-1}_{ik}\frac{\partial \hat{\psi}_k}{\partial \xi_j}
3862 \f]
3863
3864 */
3865template <>
3868
3870 boost::shared_ptr<MatrixDouble> inv_jac_ptr);
3871
3872 MoFEMErrorCode doWork(int side, EntityType type,
3874
3875private:
3876 boost::shared_ptr<MatrixDouble> invJacPtr;
3877
3880};
3881
3884
3885/** \brief Apply contravariant (Piola) transfer to Hdiv space on face
3886 *
3887 * \note Hdiv space is generated by Hcurl space in 2d.
3888 *
3889 * Contravariant Piola transformation
3890 * \f[
3891 * \psi_i|_t = \frac{1}{\textrm{det}(J)}J_{ij}\hat{\psi}_j\\
3892 * \left.\frac{\partial \psi_i}{\partial \xi_j}\right|_t
3893 * =
3894 * \frac{1}{\textrm{det}(J)}J_{ik}\frac{\partial \hat{\psi}_k}{\partial \xi_j}
3895 * \f]
3896 *
3897 * \ingroup mofem_forces_and_sources
3898 *
3899 */
3901
3902template <>
3905
3907 boost::shared_ptr<MatrixDouble> jac_ptr)
3909 jacPtr(jac_ptr) {}
3910
3911 MoFEMErrorCode doWork(int side, EntityType type,
3913
3914protected:
3915 boost::shared_ptr<MatrixDouble> jacPtr;
3918};
3919
3920template <>
3924 2>::OpSetContravariantPiolaTransformOnFace2DImpl;
3925
3926 MoFEMErrorCode doWork(int side, EntityType type,
3928};
3929
3934
3935/**@}*/
3936
3937/** \name Operators for edges */
3938
3939/**@{*/
3940
3950
3951/**
3952 * @deprecated Name is deprecated and this is added for backward compatibility
3953 */
3956
3957/**@}*/
3958
3959/** \name Operator for fat prisms */
3960
3961/**@{*/
3962
3963/**
3964 * @brief Operator for fat prism element updating integration weights in the
3965 * volume.
3966 *
3967 * Jacobian on the distorted element is nonconstant. This operator updates
3968 * integration weight on prism to take into account nonconstat jacobian.
3969 *
3970 * \f[
3971 * W_i = w_i \left( \frac{1}{2V} \left\| \frac{\partial \mathbf{x}}{\partial
3972 * \pmb\xi} \right\| \right)
3973 * \f]
3974 * where \f$w_i\f$ is integration weight at integration point \f$i\f$,
3975 * \f$\mathbf{x}\f$ is physical coordinate, and \f$\pmb\xi\f$ is reference
3976 * element coordinate.
3977 *
3978 */
3988
3989/** \brief Calculate inverse of jacobian for face element
3990
3991 It is assumed that face element is XY plane. Applied
3992 only for 2d problems.
3993
3994 FIXME Generalize function for arbitrary face orientation in 3d space
3995 FIXME Calculate to Jacobins for two faces
3996
3997 \ingroup mofem_forces_and_sources_prism_element
3998
3999*/
4002
4003 OpCalculateInvJacForFatPrism(boost::shared_ptr<MatrixDouble> inv_jac_ptr)
4005 invJacPtr(inv_jac_ptr), invJac(*invJacPtr) {}
4006
4010 MoFEMErrorCode doWork(int side, EntityType type,
4012
4013private:
4014 const boost::shared_ptr<MatrixDouble> invJacPtr;
4016};
4017
4018/** \brief Transform local reference derivatives of shape functions to global
4019derivatives
4020
4021FIXME Generalize to curved shapes
4022FIXME Generalize to case that top and bottom face has different shape
4023
4024\ingroup mofem_forces_and_sources_prism_element
4025
4026*/
4029
4030 OpSetInvJacH1ForFatPrism(boost::shared_ptr<MatrixDouble> inv_jac_ptr)
4032 invJacPtr(inv_jac_ptr), invJac(*invJacPtr) {}
4033
4037
4038 MoFEMErrorCode doWork(int side, EntityType type,
4040
4041private:
4042 const boost::shared_ptr<MatrixDouble> invJacPtr;
4045};
4046
4047// Flat prism
4048
4049/** \brief Calculate inverse of jacobian for face element
4050
4051 It is assumed that face element is XY plane. Applied
4052 only for 2d problems.
4053
4054 FIXME Generalize function for arbitrary face orientation in 3d space
4055 FIXME Calculate to Jacobins for two faces
4056
4057 \ingroup mofem_forces_and_sources_prism_element
4058
4059*/
4072
4073/** \brief Transform local reference derivatives of shape functions to global
4074derivatives
4075
4076FIXME Generalize to curved shapes
4077FIXME Generalize to case that top and bottom face has different shape
4078
4079\ingroup mofem_forces_and_sources_prism_element
4080
4081*/
4096
4097/**@}*/
4098
4099/** \name Operation on matrices at integration points */
4100
4101/**@{*/
4102
4103/**
4104 * @brief Operator for inverting matrices at integration points
4105 *
4106 * This template structure computes the inverse of square matrices and their
4107 * determinants at integration points. It's commonly used in finite element
4108 * methods for coordinate transformations, constitutive relations, and other
4109 * matrix operations requiring matrix inversion.
4110 *
4111 * @tparam DIM Dimension of the square matrix to be inverted
4112 */
4113template <int DIM>
4115
4116 /**
4117 * @brief Constructor for matrix inversion operator
4118 *
4119 * @param in_ptr Shared pointer to input matrix to be inverted
4120 * @param det_ptr Shared pointer to vector for storing matrix determinants
4121 * @param out_ptr Shared pointer to output matrix for storing inverted matrices
4122 */
4123 template <typename T>
4124 OpInvertMatrix(boost::shared_ptr<MatrixDouble> in_ptr,
4125 boost::shared_ptr<T> det_ptr,
4126 boost::shared_ptr<MatrixDouble> out_ptr)
4128 outPtr(out_ptr), detPtrVariant(det_ptr) {}
4129
4130 MoFEMErrorCode doWork(int side, EntityType type,
4132
4133private:
4134 boost::shared_ptr<MatrixDouble> inPtr;
4135 boost::shared_ptr<MatrixDouble> outPtr;
4136 std::variant<boost::shared_ptr<VectorDouble>, boost::shared_ptr<MatrixDouble>>
4138};
4139
4140template <int DIM>
4144
4145#ifndef NDEBUG
4146 if (!inPtr)
4147 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4148 "Pointer for inPtr matrix not allocated");
4149
4150 if (!std::holds_alternative<boost::shared_ptr<VectorDouble>>(detPtrVariant) &&
4151 !std::holds_alternative<boost::shared_ptr<MatrixDouble>>(detPtrVariant)) {
4152 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4153 "detPtrVariant must hold either VectorDouble or MatrixDouble");
4154 }
4155#endif
4156 const auto nb_integration_pts = inPtr->size1();
4157
4158#ifndef NDEBUG
4159 const auto nb_rows = inPtr->size2();
4160 if (nb_rows != DIM * DIM)
4161 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4162 "Wrong number of matrix coefficients");
4163#endif
4164
4165 std::visit(
4166 [&](auto ptr) {
4167 using T = std::decay_t<decltype(ptr)>;
4168
4169 if constexpr (std::is_same_v<T, boost::shared_ptr<VectorDouble>>) {
4170 ptr->resize(nb_integration_pts, false);
4171 } else if constexpr (std::is_same_v<T, boost::shared_ptr<MatrixDouble>>) {
4172 ptr->resize(nb_integration_pts, 1, false);
4173 }
4174 },
4175 detPtrVariant);
4176
4178 auto get_in_at_pts =
4179 MatrixSizeHelper<GetFTensor2FromMatType<DIM, DIM, -1, DL>, DL>::get(
4180 *inPtr, nb_integration_pts);
4181
4182 // Calculate determinant
4183 {
4184 auto t_in_at_pts = get_in_at_pts();
4185 auto det_it = std::visit(
4186 [](auto p) -> std::vector<double>::iterator {
4187 return p->data().begin();
4188 },
4189 detPtrVariant);
4190 for (size_t gg = 0; gg != nb_integration_pts; ++gg) {
4191 *det_it = determinantTensor(t_in_at_pts);
4192 ++t_in_at_pts;
4193 ++det_it;
4194 }
4195 }
4196
4197 // Invert jacobian
4198 if (outPtr) {
4199 auto get_out_at_pts =
4200 MatrixSizeHelper<GetFTensor2FromMatType<DIM, DIM, -1, DL>, DL>::size(
4201 *outPtr, nb_integration_pts);
4202 auto t_in_at_pts = get_in_at_pts();
4203 auto t_out_at_pts = get_out_at_pts();
4204 auto det_it = std::visit(
4205 [](auto p) -> std::vector<double>::iterator {
4206 return p->data().begin();
4207 },
4208 detPtrVariant);
4209 for (size_t gg = 0; gg != nb_integration_pts; ++gg) {
4210 CHKERR invertTensor(t_in_at_pts, *det_it, t_out_at_pts);
4211 ++t_in_at_pts;
4212 ++t_out_at_pts;
4213 ++det_it;
4214 }
4215 }
4216
4218}
4219
4220/**@}*/
4221
4222/**
4223 * @brief Operator for calculating the trace of matrices at integration points
4224 *
4225 * This template structure computes the trace (sum of diagonal elements) of
4226 * square matrices at integration points. The trace is commonly used in
4227 * mechanics for calculating volumetric strain, pressure, and other scalar
4228 * quantities derived from tensors.
4229 *
4230 * @tparam DIM Dimension of the square matrix
4231 *
4232 * @ingroup mofem_forces_and_sources
4233 */
4234template <int DIM>
4236
4237 /**
4238 * @brief Constructor for matrix trace calculation operator
4239 *
4240 * @param in_ptr Shared pointer to input matrix for trace calculation
4241 * @param out_ptr Shared pointer to output vector for storing calculated traces
4242 */
4243 OpCalculateTraceFromMat(boost::shared_ptr<MatrixDouble> in_ptr,
4244 boost::shared_ptr<VectorDouble> out_ptr)
4246 outPtr(out_ptr) {}
4247
4248 MoFEMErrorCode doWork(int side, EntityType type,
4250
4251private:
4253 boost::shared_ptr<MatrixDouble> inPtr;
4254 boost::shared_ptr<VectorDouble> outPtr;
4255};
4256
4257template <int DIM>
4262
4263 if (!inPtr)
4264 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4265 "Pointer for inPtr matrix not allocated");
4266
4267 const auto nb_integration_pts = inPtr->size1();
4268 // Invert jacobian
4269 if (outPtr) {
4271 auto get_in_at_pts =
4272 MatrixSizeHelper<GetFTensor2FromMatType<DIM, DIM, -1, DL>, DL>::get(
4273 *inPtr, nb_integration_pts);
4274 outPtr->resize(nb_integration_pts, false);
4275 auto t_in_at_pts = get_in_at_pts();
4276 auto t_out = getFTensor0FromVec(*outPtr);
4277
4278 for (size_t gg = 0; gg != nb_integration_pts; ++gg) {
4279 t_out = t_in_at_pts(i, i);
4280 ++t_in_at_pts;
4281 ++t_out;
4282 }
4283 }
4284
4286}
4287
4288/**@}*/
4289
4290/** \brief Calculates the trace of an input matrix
4291
4292\ingroup mofem_forces_and_sources
4293
4294*/
4295
4296template <int DIM>
4299
4300 OpCalculateTraceFromSymmMat(boost::shared_ptr<MatrixDouble> in_ptr,
4301 boost::shared_ptr<VectorDouble> out_ptr)
4303 outPtr(out_ptr) {}
4304
4305 MoFEMErrorCode doWork(int side, EntityType type,
4307
4308private:
4310 boost::shared_ptr<MatrixDouble> inPtr;
4311 boost::shared_ptr<VectorDouble> outPtr;
4312};
4313
4314template <int DIM>
4319
4320 if (!inPtr)
4321 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
4322 "Pointer for inPtr matrix not allocated");
4323
4324 const auto nb_integration_pts = inPtr->size1();
4325 // Invert jacobian
4326 if (outPtr) {
4327 outPtr->resize(nb_integration_pts, false);
4329 auto get_in_at_pts =
4331 DL>::get(*inPtr, nb_integration_pts);
4332 auto t_in_at_pts = get_in_at_pts();
4333 auto t_out = getFTensor0FromVec(*outPtr);
4334
4335 for (size_t gg = 0; gg != nb_integration_pts; ++gg) {
4336 t_out = t_in_at_pts(i, i);
4337 ++t_in_at_pts;
4338 ++t_out;
4339 }
4340 }
4341
4343}
4344
4345} // namespace MoFEM
4346
4347#endif // __USER_DATA_OPERATORS_HPP__
4348
4349/**
4350 * \defgroup mofem_forces_and_sources_user_data_operators Users Operators
4351 *
4352 * \brief Classes and functions used to evaluate fields at integration pts,
4353 *jacobians, etc..
4354 *
4355 * \ingroup mofem_forces_and_sources
4356 **/
std::string type
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.
UBlasMatrix< double > MatrixDouble
Definition Types.hpp:77
VecAllocator< double > DoubleAllocator
Definition Types.hpp:62
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
decltype(GetFTensor2SymmetricFromMatImpl< Tensor_Dim, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor2SymmetricFromMatType
static auto getFTensor3DgFromMat(M &data)
Get symmetric tensor rank 3 on the first two indices from form data matrix.
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.
OpCalculateScalarFieldValuesFromPetscVecImpl< PetscData::CTX_SET_X_T > OpCalculateScalarFieldValuesDot
decltype(GetFTensor1FromMatImpl< Tensor_Dim, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor1FromMatType
static auto getFTensor0FromVec(V &data)
Get tensor rank 0 (scalar) form data vector.
decltype(GetFTensor3FromMatImpl< Tensor_Dim0, Tensor_Dim1, Tensor_Dim2, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor3FromMatType
decltype(GetFTensor2FromMatImpl< Tensor_Dim0, Tensor_Dim1, S, DL, M >::get(std::declval< M & >(), 0, 0)) GetFTensor2FromMatType
constexpr IntegrationType I
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.
auto getFTensor2SymmetricFieldData()
Return symmetric FTensor rank 2, i.e. matrix from field data coefficients.
auto getFTensor2FieldData()
Return FTensor rank 2, i.e. matrix from field data coefficients.
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)
auto getFTensor1FieldData()
Return FTensor of rank 1, i.e. vector from field data coefficients.
auto getFTensor2N(FieldApproximationBase base)
Get base functions for Hdiv/Hcurl spaces.
auto getFTensor1DiffN(const FieldApproximationBase base)
Get derivatives of base functions.
MatrixDouble & getN(const FieldApproximationBase base)
get base functions this return matrix (nb. of rows is equal to nb. of Gauss pts, nb....
const VectorDouble & getFieldData() const
Get DOF values on entity.
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.
auto getFTensor1N(FieldApproximationBase base)
Get base functions for Hdiv/Hcurl spaces.
FTensor::Tensor0< FTensor::PackPtr< double *, 1 > > getFTensor0FieldData()
Return scalar files as a FTensor of rank 0.
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.
OpType
Controls loop over entities on element.
@ 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, const EntityType zero_type=MBEDGE, const int zero_side=0)
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)
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)
boost::shared_ptr< ublas::vector< T, A > > dataPtr
OpCalculateScalarFieldValues_General(const ForcesAndSourcesCore::UserDataOperator::OpType op_type, 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.
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< MatrixDouble > data_ptr, const EntityType zero_type=MBVERTEX)
OpCalculateTensor2FieldValues_General(ForcesAndSourcesCore::UserDataOperator::OpType op_type, const std::string field_name, boost::shared_ptr< MatrixDouble > data_ptr, SmartPetscObj< Vec > data_vec, const EntityType zero_type=MBVERTEX)
OpCalculateTensor2FieldValues_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 tenor field rank 2.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
Operator for linear form, usually to calculate values on right hand side.
OpCalculateTensor2FieldValues_General(const std::string field_name, boost::shared_ptr< M > data_ptr, const EntityType zero_type=MBVERTEX)
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.
OpCalculateVectorFieldValues_General(const std::string field_name, boost::shared_ptr< M > data_ptr, const EntityType zero_type=MBVERTEX)
Constructor for vector field values calculation operator.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
calculate values of vector field at integration points
Specialization for MatrixDouble vector field values calculation.
Operator for inverting matrices at integration points.
OpInvertMatrix(boost::shared_ptr< MatrixDouble > in_ptr, boost::shared_ptr< T > det_ptr, boost::shared_ptr< MatrixDouble > out_ptr)
Constructor for matrix inversion operator.
boost::shared_ptr< MatrixDouble > outPtr
boost::shared_ptr< MatrixDouble > inPtr
std::variant< boost::shared_ptr< VectorDouble >, boost::shared_ptr< MatrixDouble > > detPtrVariant
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:124