Intrepid2
Intrepid2_TransformedBasisValues.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Intrepid2 Package
4//
5// Copyright 2007 NTESS and the Intrepid2 contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
18#ifndef Intrepid2_TransformedBasisValues_h
19#define Intrepid2_TransformedBasisValues_h
20
23#include "Intrepid2_ScalarView.hpp"
24#include "Intrepid2_Utils.hpp"
25
26namespace Intrepid2 {
32 template<class Scalar, typename DeviceType>
34 {
35 public:
36 using value_type = Scalar;
37
38 ordinal_type numCells_;
39
40 Data<Scalar,DeviceType> transform_; // vector case: (C,P,D,D) jacobian or jacobian inverse; can also be unset for identity transform. Scalar case: (C,P), or unset for identity. Contracted vector case: (C,P,D) transform, to be contracted with a vector field to produce a scalar result.
41
42 bool transformIsDiagonal_;
43
45
52 :
53 numCells_(transform.extent_int(0)),
54 transform_(transform),
55 transformIsDiagonal_(transform.isDiagonal()),
56 basisValues_(basisValues)
57 {
58 // sanity check: when transform is diagonal, we expect there to be no pointwise variation.
59 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(transformIsDiagonal_ && (transform_.getVariationTypes()[1] != CONSTANT), std::invalid_argument, "When transform is diagonal, we assume in various places that there is no pointwise variation; the transform_ Data should have CONSTANT as its variation type in dimension 1.");
60 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE((transform_.rank() < 2) || (transform_.rank() > 4), std::invalid_argument, "Only transforms of rank 2, 3, or 4 are supported");
61 }
62
67 TransformedBasisValues(const ordinal_type &numCells, const BasisValues<Scalar,DeviceType> &basisValues)
68 :
69 numCells_(numCells),
70 transformIsDiagonal_(true),
71 basisValues_(basisValues)
72 {}
73
75 template<typename OtherDeviceType, class = typename std::enable_if<!std::is_same<DeviceType, OtherDeviceType>::value>::type>
77 :
78 numCells_(transformedVectorData.numCells()),
79 transform_(transformedVectorData.transform()),
80 transformIsDiagonal_(transformedVectorData.transform().isDiagonal()),
81 basisValues_(transformedVectorData.basisValues())
82 {}
83
88 :
89 numCells_(-1),
90 transformIsDiagonal_(true)
91 {}
92
94 KOKKOS_INLINE_FUNCTION bool axisAligned() const
95 {
96 return transformIsDiagonal_;
97 }
98
99 const BasisValues<Scalar, DeviceType> & basisValues() const
100 {
101 return basisValues_;
102 }
103
105 KOKKOS_INLINE_FUNCTION int cellDataExtent() const
106 {
107 return transform_.getDataExtent(0);
108 }
109
111 KOKKOS_INLINE_FUNCTION DataVariationType cellVariationType() const
112 {
113 return transform_.getVariationTypes()[0];
114 }
115
117 template<class ViewType>
118 void multiplyByPointwiseWeights(const ViewType &weights)
119 {
120 ordinal_type weightRank = getFunctorRank(weights); // .rank() or ::rank, depending on weights type
121 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(weightRank != 2, std::invalid_argument, "pointwise weights must have shape (C,P).");
122
123 Data<Scalar,DeviceType> weightData(weights);
124 if (!transform_.isValid())
125 {
126 // empty transform_ is understood as identity; multiplying by weightData is thus
127 // the same as transform_ = weightData
128 transform_ = weightData;
129 return;
130 }
131 else
132 {
133 if ((transform_.rank() == 4) || (transform_.rank() == 3))
134 {
135 transform_ = DataTools::multiplyByCPWeights(transform_,weightData);
136 }
137 else // transformRank == 2
138 {
139 auto result = Data<Scalar,DeviceType>::allocateInPlaceCombinationResult(weightData, transform_);
140
141 result.storeInPlaceProduct(weightData,transform_);
142 transform_ = result;
143 }
144 }
145 }
146
148 KOKKOS_INLINE_FUNCTION int numCells() const
149 {
150 return numCells_;
151 }
152
154 KOKKOS_INLINE_FUNCTION int numFields() const
155 {
156 return basisValues_.extent_int(0);
157 }
158
160 KOKKOS_INLINE_FUNCTION int numPoints() const
161 {
162 return basisValues_.extent_int(1);
163 }
164
166 KOKKOS_INLINE_FUNCTION int spaceDim() const
167 {
168 if ((transform_.rank() == 3) && (basisValues_.rank() == 3)) // (C,P,D) contracted in D against (F,P,D)
169 {
170 return 1; // spaceDim contracted away
171 }
172 else if ((transform_.rank() == 3) && (basisValues_.rank() == 2)) // (C,P,D) weighting (F,P)
173 {
174 return transform_.extent_int(2);
175 }
176 else if (transform_.isValid())
177 {
178 return transform_.extent_int(2);
179 }
180 else
181 {
182 return basisValues_.extent_int(2);
183 }
184 }
185
187 KOKKOS_INLINE_FUNCTION Scalar operator()(const int &cellOrdinal, const int &fieldOrdinal, const int &pointOrdinal) const
188 {
189 if (!transform_.isValid())
190 {
191 // null transform is understood as the identity
192 return basisValues_(fieldOrdinal,pointOrdinal);
193 }
194 else if (transform_.rank() == 2)
195 {
196 return transform_(cellOrdinal,pointOrdinal) * basisValues_(fieldOrdinal,pointOrdinal);
197 }
198 else if (transform_.rank() == 3)
199 {
200 Scalar value = 0;
201 for (int d=0; d<transform_.extent_int(2); d++)
202 {
203 value += transform_(cellOrdinal,pointOrdinal,d) * basisValues_(fieldOrdinal,pointOrdinal,d);
204 }
205 return value;
206 }
207 return 0; // should not be reachable
208 }
209
211 KOKKOS_INLINE_FUNCTION Scalar operator()(const int &cellOrdinal, const int &fieldOrdinal, const int &pointOrdinal, const int &dim) const
212 {
213 if (!transform_.isValid())
214 {
215 // null transform is understood as the identity
216 return basisValues_(fieldOrdinal,pointOrdinal,dim);
217 }
218 else if (transformIsDiagonal_)
219 {
220 return transform_(cellOrdinal,pointOrdinal,dim,dim) * basisValues_(fieldOrdinal,pointOrdinal,dim);
221 }
222 else if (transform_.rank() == 4)
223 {
224 Scalar value = 0.0;
225 for (int d2=0; d2<transform_.extent_int(2); d2++)
226 {
227 value += transform_(cellOrdinal,pointOrdinal,dim,d2) * basisValues_(fieldOrdinal,pointOrdinal,d2);
228 }
229 return value;
230 }
231 else if (transform_.rank() == 3)
232 {
233 Scalar value = transform_(cellOrdinal,pointOrdinal,dim) * basisValues_(fieldOrdinal,pointOrdinal);
234 return value;
235 }
236 else // rank 2 transform
237 {
238 Scalar value = transform_(cellOrdinal,pointOrdinal) * basisValues_(fieldOrdinal,pointOrdinal,dim);
239 return value;
240 }
241 }
242
244 KOKKOS_INLINE_FUNCTION Scalar transformWeight(const int &cellOrdinal, const int &pointOrdinal) const
245 {
246 if (!transform_.isValid())
247 {
248 // null transform is understood as identity
249 return 1.0;
250 }
251 else
252 {
253 return transform_(cellOrdinal,pointOrdinal);
254 }
255 }
256
258 KOKKOS_INLINE_FUNCTION Scalar transformWeight(const int &cellOrdinal, const int &pointOrdinal, const int &d) const
259 {
260 if (!transform_.isValid())
261 {
262 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(true, std::invalid_argument, "three-argument transformWeight() is not supported for invalid transform_ object -- no meaningful interpretation for vector-valued identity");
263 }
264 else
265 {
266 return transform_(cellOrdinal,pointOrdinal,d);
267 }
268 }
269
271 KOKKOS_INLINE_FUNCTION Scalar transformWeight(const int &cellOrdinal, const int &pointOrdinal, const int &dim1, const int &dim2) const
272 {
273 if (!transform_.isValid())
274 {
275 // null transform is understood as identity
276 return (dim1 == dim2) ? 1.0 : 0.0;
277 }
278 else
279 {
280 return transform_(cellOrdinal,pointOrdinal,dim1,dim2);
281 }
282 }
283
286 {
287 return transform_;
288 }
289
292 {
293 return basisValues_.vectorData();
294 }
295
297 KOKKOS_INLINE_FUNCTION
298 unsigned rank() const
299 {
300 if ((transform_.rank() == 4) && (basisValues_.rank() == 3))
301 {
302 return 4; // (C,F,P,D)
303 }
304 else if (transform_.rank() == 2)
305 {
306 return basisValues_.rank() + 1; // transformation adds a cell dimension
307 }
308 else if (transform_.rank() == 3)
309 {
310 if (basisValues_.rank() == 3)
311 {
312 // transform contracts with basisValues in D dimension
313 return 3; // (C,F,P)
314 }
315 else if (basisValues_.rank() == 2) // (F,P)
316 {
317 return 4; // (C,F,P,D)
318 }
319 }
320 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(true, std::invalid_argument, "Unhandled basisValues_/transform_ rank combination");
321 }
322
324 KOKKOS_INLINE_FUNCTION
325 int extent_int(const int &r) const
326 {
327 if (r == 0) return numCells();
328 else if (r == 1) return numFields();
329 else if (r == 2) return numPoints();
330 else if (r == 3) return spaceDim();
331 else if (r > 3) return 1;
332
333 return -1; // unreachable return; here to avoid compiler warnings.
334 }
335 };
336}
337
338#endif /* Intrepid2_TransformedBasisValues_h */
Header file for the data-wrapper class Intrepid2::BasisValues.
Utility methods for manipulating Intrepid2::Data objects.
Header function for Intrepid2::Util class and other utility functions.
enable_if_t< has_rank_method< Functor >::value, unsigned > KOKKOS_INLINE_FUNCTION getFunctorRank(const Functor &functor)
#define INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(test, x, msg)
The data containers in Intrepid2 that support sum factorization and other reduced-data optimizations ...
const VectorDataType & vectorData() const
VectorData accessor.
static void multiplyByCPWeights(Data< Scalar, DeviceType > &resultMatrixData, const Data< Scalar, DeviceType > &matrixDataIn, const Data< Scalar, DeviceType > &scalarDataIn)
Wrapper around a Kokkos::View that allows data that is constant or repeating in various logical dimen...
KOKKOS_INLINE_FUNCTION int extent_int(const int &r) const
Returns the logical extent in the specified dimension.
KOKKOS_INLINE_FUNCTION constexpr bool isValid() const
returns true for containers that have data; false for those that don't (namely, those that have been ...
static Data< DataScalar, DeviceType > allocateInPlaceCombinationResult(const Data< DataScalar, DeviceType > &A, const Data< DataScalar, DeviceType > &B)
KOKKOS_INLINE_FUNCTION const Kokkos::Array< DataVariationType, 7 > & getVariationTypes() const
Returns an array with the variation types in each logical dimension.
KOKKOS_INLINE_FUNCTION int getDataExtent(const ordinal_type &d) const
returns the true extent of the data corresponding to the logical dimension provided; if the data does...
KOKKOS_INLINE_FUNCTION unsigned rank() const
Returns the logical rank of the Data container.
Structure-preserving representation of transformed vector data; reference space values and transforma...
KOKKOS_INLINE_FUNCTION int cellDataExtent() const
Returns the true data extent in the cell dimension (e.g., will be 1 for transform matrices that do no...
KOKKOS_INLINE_FUNCTION DataVariationType cellVariationType() const
Returns the variation type corresponding to the cell dimension.
TransformedBasisValues(const Data< Scalar, DeviceType > &transform, const BasisValues< Scalar, DeviceType > &basisValues)
Standard constructor.
KOKKOS_INLINE_FUNCTION bool axisAligned() const
Returns true if the transformation matrix is diagonal.
KOKKOS_INLINE_FUNCTION Scalar transformWeight(const int &cellOrdinal, const int &pointOrdinal) const
Returns the specified entry in the (scalar) transform. (Only valid for scalar-valued BasisValues; see...
KOKKOS_INLINE_FUNCTION int extent_int(const int &r) const
Returns the extent in the specified dimension as an int.
KOKKOS_INLINE_FUNCTION unsigned rank() const
Returns the rank of the container, which is 3 for scalar values, and 4 for vector values.
const VectorData< Scalar, DeviceType > & vectorData() const
Returns the reference-space vector data.
KOKKOS_INLINE_FUNCTION Scalar operator()(const int &cellOrdinal, const int &fieldOrdinal, const int &pointOrdinal, const int &dim) const
Vector accessor, with arguments (C,F,P,D).
KOKKOS_INLINE_FUNCTION int spaceDim() const
Returns the logical extent in the space dimension, which is the 3 dimension in this container.
TransformedBasisValues(const ordinal_type &numCells, const BasisValues< Scalar, DeviceType > &basisValues)
Constructor for the case of an identity transform.
KOKKOS_INLINE_FUNCTION Scalar transformWeight(const int &cellOrdinal, const int &pointOrdinal, const int &dim1, const int &dim2) const
Returns the specified entry in the transform matrix.
const Data< Scalar, DeviceType > & transform() const
Returns the transform matrix. An invalid/empty container indicates the identity transform.
KOKKOS_INLINE_FUNCTION int numCells() const
Returns the logical extent in the cell dimension, which is the 0 dimension in this container.
KOKKOS_INLINE_FUNCTION int numPoints() const
Returns the logical extent in the points dimension, which is the 2 dimension in this container.
TransformedBasisValues()
Default constructor; an invalid container. Will return -1 for numCells().
TransformedBasisValues(const TransformedBasisValues< Scalar, OtherDeviceType > &transformedVectorData)
copy-like constructor for differing device types. This may do a deep_copy of underlying views,...
KOKKOS_INLINE_FUNCTION Scalar operator()(const int &cellOrdinal, const int &fieldOrdinal, const int &pointOrdinal) const
Scalar accessor, with arguments (C,F,P).
void multiplyByPointwiseWeights(const ViewType &weights)
Replaces the internal pullback (transformation operator) with the result of the pullback multiplied b...
KOKKOS_INLINE_FUNCTION int numFields() const
Returns the logical extent in the fields dimension, which is the 1 dimension in this container.
KOKKOS_INLINE_FUNCTION Scalar transformWeight(const int &cellOrdinal, const int &pointOrdinal, const int &d) const
Returns the specified entry in the transformation vector.
Reference-space field values for a basis, designed to support typical vector-valued bases.