v0.16.0
Loading...
Searching...
No Matches
NormsOperators.cpp
Go to the documentation of this file.
1/** \file NormsOperators.cpp
2
3\brief User data operators for calculating norms and differences between
4fields
5
6*/
7
8namespace MoFEM {
9
11 boost::shared_ptr<VectorDouble> data_ptr, SmartPetscObj<Vec> data_vec,
12 const int index, boost::shared_ptr<VectorDouble> diff_data_ptr,
13 boost::shared_ptr<Range> ent_ptr)
16 dataPtr(data_ptr), dataVec(data_vec), iNdex(index),
17 diffDataPtr(diff_data_ptr), entsPtr(ent_ptr) {
18 if (!dataPtr)
19 THROW_MESSAGE("Pointer is not set");
20 if (!diffDataPtr)
22}
23
27
28 // check if entity is in the range
29 if (entsPtr) {
30 if (entsPtr->find(this->getFEEntityHandle()) == entsPtr->end())
32 }
33
34 // calculate the difference between data pointers and save them in diffDataPtr
35 if (dataPtr != diffDataPtr)
37
38 // get number of integration points
39 const auto nb_integration_points = getGaussPts().size2();
40 // get element volume
41 const double vol = getMeasure();
42 // get integration weights
44 // get values
45 auto t_data = getFTensor0FromVec(*diffDataPtr);
46 // initialise double to store norm values
47 double norm_on_element = 0.;
48 // loop over integration points
49 for (int gg = 0; gg != nb_integration_points; gg++) {
50 // add to element norm
51 norm_on_element += t_w * t_data * t_data;
52 // move to another integration weight
53 ++t_w;
54 // move to another data values
55 ++t_data;
56 }
57 // scale with volume of the element
58 norm_on_element *= vol;
59 // add to dataVec at iNdex position
60 CHKERR VecSetValue(dataVec, iNdex, norm_on_element, ADD_VALUES);
61
63}
64
65template <int DIM>
67 boost::shared_ptr<MatrixDouble> data_ptr, SmartPetscObj<Vec> data_vec,
68 const int index, boost::shared_ptr<MatrixDouble> diff_data_ptr,
69 boost::shared_ptr<Range> ent_ptr)
72 dataPtr(data_ptr), dataVec(data_vec), iNdex(index),
73 diffDataPtr(diff_data_ptr), entsPtr(ent_ptr) {
74 if (!dataPtr)
75 THROW_MESSAGE("Pointer is not set");
76 if (!diffDataPtr)
78}
79
80template <int DIM>
85
86 // check if entity is in the range
87 if (entsPtr) {
88 if (entsPtr->find(this->getFEEntityHandle()) == entsPtr->end())
90 }
91
92 // calculate the difference between data pointers and save them in diffDataPtr
93 if (dataPtr != diffDataPtr)
94 *diffDataPtr -= *dataPtr;
95
96 // Declare FTensor index
97 FTensor::Index<'i', DIM> i;
98 // get number of integration points
99 const auto nb_integration_points = getGaussPts().size2();
100 // get element volume
101 const double vol = getMeasure();
102 // get integration weights
103 auto t_w = getFTensor0IntegrationWeight();
104 // get vector values
105#ifndef NDEBUG
106 if (diffDataPtr->size2() != DIM)
107 THROW_MESSAGE("OpCalcNormL2Tensor1: wrong number of matrix columns");
108#endif
109 auto t_data = getFTensor1FromPtr<DIM, DIM>(diffDataPtr->data().data());
110 // initialise double to store norm values
111 double norm_on_element = 0.;
112 // loop over integration points
113 for (int gg = 0; gg != nb_integration_points; ++gg) {
114 // add to element norm
115 norm_on_element += t_w * (t_data(i) * t_data(i));
116 // move to another integration weight
117 ++t_w;
118 // move to another data values
119 ++t_data;
120 }
121 // scale with volume of the element
122 norm_on_element *= vol;
123 // add to dataVec at iNdex position
124 CHKERR VecSetValue(dataVec, iNdex, norm_on_element, ADD_VALUES);
125
127}
128
129template <int DIM_1, int DIM_2>
131 boost::shared_ptr<MatrixDouble> data_ptr, SmartPetscObj<Vec> data_vec,
132 const int index, boost::shared_ptr<MatrixDouble> diff_data_ptr,
133 boost::shared_ptr<Range> ent_ptr)
136 dataPtr(data_ptr), dataVec(data_vec), iNdex(index),
137 diffDataPtr(diff_data_ptr), entsPtr(ent_ptr) {
138 if (!dataPtr)
139 THROW_MESSAGE("Pointer is not set");
140 if (!diffDataPtr)
142}
143
144template <int DIM_1, int DIM_2>
149
150 // check if entity is in the range
151 if (entsPtr) {
152 if (entsPtr->find(this->getFEEntityHandle()) == entsPtr->end())
154 }
155
156 // calculate the difference between data pointers and save them in diffDataPtr
157 if (dataPtr != diffDataPtr)
158 *diffDataPtr -= *dataPtr;
159
160 // Declare FTensor index
161 FTensor::Index<'i', DIM_1> i;
162 FTensor::Index<'j', DIM_2> j;
163 // get number of integration points
164 const auto nb_integration_points = getGaussPts().size2();
165 // get element volume
166 const double vol = getMeasure();
167 // get integration weights
168 auto t_w = getFTensor0IntegrationWeight();
169 // get vector values
170 auto t_data = getFTensor2FromMat<DIM_1, DIM_2>(*diffDataPtr);
171 // initialise double to store norm values
172 double norm_on_element = 0.;
173 // loop over integration points
174 for (int gg = 0; gg != nb_integration_points; gg++) {
175 // add to element norm
176 norm_on_element += t_w * (t_data(i, j) * t_data(i, j));
177 // move to another integration weight
178 ++t_w;
179 // move to another data values
180 ++t_data;
181 }
182 // scale with volume of the element
183 norm_on_element *= vol;
184 // add to dataVec at iNdex position
185 CHKERR VecSetValue(dataVec, iNdex, norm_on_element, ADD_VALUES);
186
188}
189
190template <int DIM>
195
196 // check if entity is in the range
197 if (this->entsPtr) {
198 if (this->entsPtr->find(this->getFEEntityHandle()) == this->entsPtr->end())
200 }
201
202 // calculate the difference between data pointers and save them in diffDataPtr
203 if (this->dataPtr != this->diffDataPtr)
204 *this->diffDataPtr -= *this->dataPtr;
205
206 // Declare FTensor index
207 FTensor::Index<'i', DIM> i;
208 FTensor::Index<'j', DIM> j;
209 // get number of integration points
210 const auto nb_integration_points = this->getGaussPts().size2();
211 // get element volume
212 const double vol = this->getMeasure();
213 // get integration weights
214 auto t_w = this->getFTensor0IntegrationWeight();
215 // get symmetric tensor values
216 auto t_data = getFTensor2SymmetricFromMat<DIM>(*this->diffDataPtr);
217 // initialise double to store norm values
218 double norm_on_element = 0.;
219 // loop over integration points
220 for (int gg = 0; gg != nb_integration_points; gg++) {
221 // add Frobenius norm contribution, including both off-diagonal entries
222 norm_on_element += t_w * (t_data(i, j) * t_data(i, j));
223 // move to another integration weight
224 ++t_w;
225 // move to another data values
226 ++t_data;
227 }
228 // scale with volume of the element
229 norm_on_element *= vol;
230 // add to dataVec at iNdex position
231 CHKERR VecSetValue(this->dataVec, this->iNdex, norm_on_element, ADD_VALUES);
232
234}
235
237 boost::shared_ptr<VectorDouble> data_ptr, ScalarFun scalar_function)
240 dataPtr(data_ptr), sFunc(scalar_function) {}
241
245
246 // get number of integration points
247 const int nb_integration_pts = getGaussPts().size2();
248 // resize dataPtr to store values at integration points
249 dataPtr->resize(nb_integration_pts);
250 // get values
251 auto t_val = getFTensor0FromVec(*dataPtr);
252
253 // get coordinates at integration point
254 auto t_coords = getFTensor1CoordsAtGaussPts();
255 // loop over integration points
256 for (int gg = 0; gg != nb_integration_pts; ++gg) {
257 // set value at integration point to value of scalar function at the
258 // coordinates
259 t_val = sFunc(t_coords(0), t_coords(1), t_coords(2));
260 // move to another value
261 ++t_val;
262 // move to another coordinates
263 ++t_coords;
264 }
265
267}
268
269template <int TENS_DIM, int FUNC_DIM>
271 boost::shared_ptr<MatrixDouble> data_ptr, VectorFunc vector_function)
274 dataPtr(data_ptr), vFunc(vector_function) {}
275
276template <int TENS_DIM, int FUNC_DIM>
278 int side, EntityType type, EntitiesFieldData::EntData &data) {
280 if (TENS_DIM > FUNC_DIM) {
281 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
282 "Output tensor dimension TENS_DIM (%d) is larger than FUNC_DIM "
283 "(%d)",
284 TENS_DIM, FUNC_DIM);
285 }
286 // Copy only the components requested by the output tensor. The function
287 // buffer can be larger, e.g. a 2D tensor read from a 3D function buffer.
288 FTensor::Index<'i', TENS_DIM> i;
289 // get number of integration points
290 const int nb_integration_pts = getGaussPts().size2();
291 // resize dataPtr to store values at integration points
293 auto get_values_at_pts =
294 MatrixSizeHelper<GetFTensor1FromMatType<TENS_DIM, -1, DL>, DL>::size(
295 *dataPtr, nb_integration_pts);
296 dataPtr->clear();
297 // get values
298 auto t_val = get_values_at_pts();
299
300 // get coordinates at integration point
301 auto t_coords = getFTensor1CoordsAtGaussPts();
302 // loop over integration points
303 for (int gg = 0; gg != nb_integration_pts; ++gg) {
304 // get function values of vector function at the coordinates
305 auto func_val = vFunc(t_coords(0), t_coords(1), t_coords(2));
306 // translate function values to tensor
307 auto t_func_val = getFTensor1FromArray<FUNC_DIM, FUNC_DIM>(func_val);
308 // set values at integration point to function values at the coordinates
309 t_val(i) = t_func_val(i);
310
311 // move to another value
312 ++t_val;
313 // move to another coordinates
314 ++t_coords;
315 }
316
318}
319
320template <int TENS_DIM, int FUNC_DIM>
322 boost::shared_ptr<MatrixDouble> data_ptr, MatrixFunc matrix_function)
325 dataPtr(data_ptr), mFunc(matrix_function) {}
326
327template <int TENS_DIM, int FUNC_DIM>
329 int side, EntityType type, EntitiesFieldData::EntData &data) {
331 if (TENS_DIM > FUNC_DIM) {
332 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
333 "Output tensor dimension TENS_DIM (%d) is larger than FUNC_DIM "
334 "(%d)",
335 TENS_DIM, FUNC_DIM);
336 }
337 // Copy only the components requested by the output tensor. The function
338 // buffer can be larger, e.g. a 2D tensor read from a 3D function buffer.
339 FTensor::Index<'i', TENS_DIM> i;
340 FTensor::Index<'j', TENS_DIM> j;
341 // get number of integration points
342 const int nb_integration_pts = getGaussPts().size2();
343 // resize dataPtr to store values at integration points
344 dataPtr->resize(TENS_DIM * TENS_DIM, nb_integration_pts);
345 // get values
346 auto t_val = getFTensor2FromMat<TENS_DIM, TENS_DIM>(*(dataPtr));
347
348 // get coordinates at integration point
349 auto t_coords = getFTensor1CoordsAtGaussPts();
350 // loop over integration points
351 for (int gg = 0; gg != nb_integration_pts; ++gg) {
352 // get function values of matrix function at the coordinates
353 auto func_val = mFunc(t_coords(0), t_coords(1), t_coords(2));
354 // translate function values to tensor
355 auto t_func_val =
356 getFTensor2FromArray<FUNC_DIM, FUNC_DIM, FUNC_DIM>(func_val, 0);
357 // set values at integration point to function values at the coordinates
358 t_val(i, j) = t_func_val(i, j);
359
360 // move to another value
361 ++t_val;
362 // move to another coordinates
363 ++t_coords;
364 }
365
367}
368
369template <int TENS_DIM, int FUNC_DIM>
371 int side, EntityType type, EntitiesFieldData::EntData &data) {
373
374 if constexpr (TENS_DIM > FUNC_DIM) {
375 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY,
376 "Output tensor dimension TENS_DIM (%d) is larger than FUNC_DIM "
377 "(%d)",
378 TENS_DIM, FUNC_DIM);
379 }
380
381 const auto nb_gauss_pts = this->getGaussPts().size2();
383 auto get_values_at_gauss_pts =
385 DL>::size(*this->dataPtr, nb_gauss_pts);
386 this->dataPtr->clear();
387
388 auto t_values_at_gauss_pts = get_values_at_gauss_pts();
389 auto t_coords = this->getFTensor1CoordsAtGaussPts();
390 FTensor::Index<'i', TENS_DIM> i;
391 FTensor::Index<'j', TENS_DIM> j;
392
393 for (size_t gg = 0; gg != nb_gauss_pts; ++gg) {
394 auto values = this->mFunc(t_coords(0), t_coords(1), t_coords(2));
395 auto t_values = getFTensor2SymmetricFromMat<
396 FUNC_DIM, -1, DataLayoutTraits<DataLayout::CoeffsByGauss>>(values);
397 t_values_at_gauss_pts(i, j) = t_values(i, j);
398 ++t_values_at_gauss_pts;
399 ++t_coords;
400 }
401
403}
404
405template struct OpCalcNormL2Tensor1<2>;
406template struct OpCalcNormL2Tensor1<3>;
407template struct OpCalcNormL2Tensor2<2, 2>;
408template struct OpCalcNormL2Tensor2<3, 3>;
409template struct OpCalcNormL2Tensor2Symmetric<2>;
410template struct OpCalcNormL2Tensor2Symmetric<3>;
411template struct OpGetTensor1fromFunc<2, 2>;
412template struct OpGetTensor1fromFunc<2, 3>;
413template struct OpGetTensor1fromFunc<3, 3>;
414template struct OpGetTensor2fromFunc<2, 2>;
415template struct OpGetTensor2fromFunc<2, 3>;
416template struct OpGetTensor2fromFunc<3, 3>;
420
421} // namespace MoFEM
std::string type
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
@ NOSPACE
Definition definitions.h:83
#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
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
#define THROW_MESSAGE(msg)
Throw MoFEM exception.
boost::function< double(const double, const double, const double)> ScalarFun
Scalar function type.
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'j', 3 > j
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
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 getFTensor2SymmetricFromMat(M &data)
Get symmetric tensor rank 2 (matrix) form data matrix.
boost::function< MatrixDouble(const double, const double, const double)> MatrixFunc
boost::function< VectorDouble(const double, const double, const double)> VectorFunc
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.
Data on single entity (This is passed as argument to DataOperator::doWork)
auto getFTensor1CoordsAtGaussPts()
Get coordinates at integration points assuming linear geometry.
auto getFTensor0IntegrationWeight()
Get integration weights.
double getMeasure() const
get measure of element
MatrixDouble & getGaussPts()
matrix of integration (Gauss) points for Volume Element
structure to get information from mofem into EntitiesFieldData
boost::shared_ptr< VectorDouble > dataPtr
boost::shared_ptr< VectorDouble > diffDataPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
calculate norm of scalar values at integration points
OpCalcNormL2Tensor0(boost::shared_ptr< VectorDouble > data_ptr, SmartPetscObj< Vec > data_vec, const int index, boost::shared_ptr< VectorDouble > diff_data_ptr=nullptr, boost::shared_ptr< Range > ent_ptr=nullptr)
SmartPetscObj< Vec > dataVec
boost::shared_ptr< Range > entsPtr
Get norm of input MatrixDouble for Tensor1.
boost::shared_ptr< MatrixDouble > diffDataPtr
OpCalcNormL2Tensor1(boost::shared_ptr< MatrixDouble > data_ptr, SmartPetscObj< Vec > data_vec, const int index, boost::shared_ptr< MatrixDouble > diff_data_ptr=nullptr, boost::shared_ptr< Range > ent_ptr=nullptr)
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
calculate norm of vector values at integration points
boost::shared_ptr< MatrixDouble > dataPtr
Get norm of input MatrixDouble for symmetric Tensor2.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
calculate norm of symmetric tensor values at integration points
Get norm of input MatrixDouble for Tensor2.
OpCalcNormL2Tensor2(boost::shared_ptr< MatrixDouble > data_ptr, SmartPetscObj< Vec > data_vec, const int index, boost::shared_ptr< MatrixDouble > diff_data_ptr=nullptr, boost::shared_ptr< Range > ent_ptr=nullptr)
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
calculate norm of tensor values at integration points
boost::shared_ptr< MatrixDouble > diffDataPtr
boost::shared_ptr< MatrixDouble > dataPtr
OpGetTensor0fromFunc(boost::shared_ptr< VectorDouble > data_ptr, ScalarFun scalar_function)
boost::shared_ptr< VectorDouble > dataPtr
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
calculate values of scalar function at integration points
Get values from vector function at integration points and save them to MatrixDouble for Tensor1.
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
calculate values of vector function at integration points
OpGetTensor1fromFunc(boost::shared_ptr< MatrixDouble > data_ptr, VectorFunc vector_function)
Get values from matrix function in symmetric tensor storage at integration points and save them to Ma...
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
calculate values of matrix function at integration points
Get values from matrix function at integration points and save them to MatrixDouble for Tensor2.
OpGetTensor2fromFunc(boost::shared_ptr< MatrixDouble > data_ptr, MatrixFunc matrix_function)
MoFEMErrorCode doWork(int side, EntityType type, EntitiesFieldData::EntData &data)
calculate values of matrix function at integration points
intrusive_ptr for managing petsc objects