Intrepid2
Intrepid2_BasisValues.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
14
17
18#ifndef Intrepid2_BasisValues_h
19#define Intrepid2_BasisValues_h
20
31
32namespace Intrepid2
33{
34 template<class Scalar, typename DeviceType>
36 {
37 using TensorDataType = TensorData<Scalar,DeviceType>;
38 using VectorDataType = VectorData<Scalar,DeviceType>;
39
40 Kokkos::Array<TensorDataType,Parameters::MaxTensorComponents> tensorDataFamilies_;
41 VectorDataType vectorData_;
42
43 int numTensorDataFamilies_ = -1;
44
45 Kokkos::View<ordinal_type*,DeviceType> ordinalFilter_;
46 public:
48 BasisValues(TensorDataType tensorData)
49 :
50 tensorDataFamilies_({tensorData}),
51 numTensorDataFamilies_(1)
52 {}
53
55 BasisValues(std::vector<TensorDataType> tensorDataFamilies)
56 :
57 numTensorDataFamilies_(tensorDataFamilies.size())
58 {
59 for (int family=0; family<numTensorDataFamilies_; family++)
60 {
61 tensorDataFamilies_[family] = tensorDataFamilies[family];
62 }
63 }
64
66 BasisValues(VectorDataType vectorData)
67 :
68 vectorData_(vectorData)
69 {}
70
73 :
74 numTensorDataFamilies_(0)
75 {}
76
77
79 template<typename OtherDeviceType, class = typename std::enable_if<!std::is_same<DeviceType, OtherDeviceType>::value>::type>
81 :
82 vectorData_(basisValues.vectorData()),
83 numTensorDataFamilies_(basisValues.numTensorDataFamilies())
84 {
85 auto otherFamilies = basisValues.tensorDataFamilies();
86 for (int family=0; family<numTensorDataFamilies_; family++)
87 {
88 tensorDataFamilies_[family] = TensorData<Scalar,DeviceType>(otherFamilies[family]);
89 }
90 auto otherOrdinalFilter = basisValues.ordinalFilter();
91 ordinalFilter_ = Kokkos::View<ordinal_type*,DeviceType>("BasisValues::ordinalFilter_",otherOrdinalFilter.extent(0));
92
93 Kokkos::deep_copy(ordinalFilter_, otherOrdinalFilter);
94 }
95
97 BasisValues<Scalar,DeviceType> basisValuesForFields(const int &fieldStartOrdinal, const int &numFields)
98 {
99 int familyStartOrdinal = -1, familyEndOrdinal = -1;
100 const int familyCount = this->numFamilies();
101 int fieldsSoFar = 0;
102 for (int i=0; i<familyCount; i++)
103 {
104 const bool startMatches = (fieldsSoFar == fieldStartOrdinal);
105 familyStartOrdinal = startMatches ? i : familyStartOrdinal;
106 fieldsSoFar += numFieldsInFamily(i);
107 const bool endMatches = (fieldsSoFar - fieldStartOrdinal == numFields);
108 familyEndOrdinal = endMatches ? i : familyEndOrdinal;
109 }
110 INTREPID2_TEST_FOR_EXCEPTION(familyStartOrdinal == -1, std::invalid_argument, "fieldStartOrdinal does not align with the start of a family.");
111 INTREPID2_TEST_FOR_EXCEPTION(familyEndOrdinal == -1, std::invalid_argument, "fieldStartOrdinal + numFields does not align with the end of a family.");
112
113 const int numFamiliesInFieldSpan = familyEndOrdinal - familyStartOrdinal + 1;
114 if (numTensorDataFamilies_ > 0)
115 {
116 std::vector<TensorDataType> tensorDataFamilies(numFamiliesInFieldSpan);
117 for (int i=familyStartOrdinal; i<=familyEndOrdinal; i++)
118 {
119 tensorDataFamilies[i-familyStartOrdinal] = tensorDataFamilies_[i];
120 }
122 }
123 else
124 {
125 const int componentCount = vectorData_.numComponents();
126 std::vector< std::vector<TensorData<Scalar,DeviceType> > > vectorComponents(numFamiliesInFieldSpan, std::vector<TensorData<Scalar,DeviceType> >(componentCount));
127 for (int i=familyStartOrdinal; i<=familyEndOrdinal; i++)
128 {
129 for (int j=0; j<componentCount; j++)
130 {
131 vectorComponents[i-familyStartOrdinal][j] = vectorData_.getComponent(i,j);
132 }
133 }
134 return BasisValues<Scalar,DeviceType>(vectorComponents);
135 }
136 }
137
139 KOKKOS_INLINE_FUNCTION
140 int familyFieldOrdinalOffset(const int &familyOrdinal) const
141 {
142 if (vectorData_.isValid())
143 {
144 return vectorData_.familyFieldOrdinalOffset(familyOrdinal);
145 }
146 else
147 {
148 int offset = 0;
149 for (int i=0; i<familyOrdinal; i++)
150 {
151 offset += tensorDataFamilies_[i].extent_int(0); // (F,P,…)
152 }
153 return offset;
154 }
155 }
156
158 TensorDataType & tensorData()
159 {
160 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(numTensorDataFamilies_ != 1, std::invalid_argument, "this method is not supported when numTensorDataFamilies_ != 1");
161 return tensorDataFamilies_[0];
162 }
163
165 const TensorDataType & tensorData(const int &familyOrdinal) const
166 {
167 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(familyOrdinal >= numTensorDataFamilies_, std::invalid_argument, "familyOrdinal too large");
168 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(familyOrdinal < 0, std::invalid_argument, "familyOrdinal may not be less than 0");
169 return tensorDataFamilies_[familyOrdinal];
170 }
171
173 KOKKOS_INLINE_FUNCTION
174 int numFamilies() const
175 {
176 if (vectorData_.isValid())
177 {
178 return vectorData_.numFamilies();
179 }
180 else
181 {
182 return numTensorDataFamilies_;
183 }
184 }
185
186 KOKKOS_INLINE_FUNCTION
187 int numTensorDataFamilies() const
188 {
189 return numTensorDataFamilies_;
190 }
191
192 KOKKOS_INLINE_FUNCTION
193 int numFieldsInFamily(int familyOrdinal) const
194 {
195 if (vectorData_.isValid())
196 {
197 return vectorData_.numFieldsInFamily(familyOrdinal);
198 }
199 else
200 {
201 return tensorDataFamilies_[familyOrdinal].extent_int(0); // (F,P,…)
202 }
203 }
204
206 const Kokkos::Array<TensorDataType,Parameters::MaxTensorComponents> & tensorDataFamilies() const
207 {
208 return tensorDataFamilies_;
209 }
210
212 const VectorDataType & vectorData() const
213 {
214 return vectorData_;
215 }
216
218 KOKKOS_INLINE_FUNCTION
219 Scalar operator()(const int &fieldOrdinal, const int &pointOrdinal) const
220 {
221 const int &tensorFieldOrdinal = (ordinalFilter_.extent(0) > 0) ? ordinalFilter_(fieldOrdinal) : fieldOrdinal;
222 if (numTensorDataFamilies_ == 1)
223 {
224#ifdef HAVE_INTREPID2_DEBUG
225 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(! tensorDataFamilies_[0].isValid(), std::invalid_argument, "TensorData object not initialized!");
226#endif
227 return tensorDataFamilies_[0](tensorFieldOrdinal, pointOrdinal);
228 }
229 else
230 {
231 int familyForField = -1;
232 int previousFamilyEnd = -1;
233 int fieldAdjustment = 0;
234 // this loop is written in such a way as to avoid branching for CUDA performance
235 for (int family=0; family<numTensorDataFamilies_; family++)
236 {
237 const int familyFieldCount = tensorDataFamilies_[family].extent_int(0);
238 const bool fieldInRange = (tensorFieldOrdinal > previousFamilyEnd) && (tensorFieldOrdinal <= previousFamilyEnd + familyFieldCount);
239 familyForField = fieldInRange ? family : familyForField;
240 fieldAdjustment = fieldInRange ? previousFamilyEnd + 1 : fieldAdjustment;
241 previousFamilyEnd += familyFieldCount;
242 }
243#ifdef HAVE_INTREPID2_DEBUG
244 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE( familyForField == -1, std::invalid_argument, "fieldOrdinal appears to be out of range");
245#endif
246 return tensorDataFamilies_[familyForField](tensorFieldOrdinal-fieldAdjustment,pointOrdinal);
247 }
248 }
249
251 KOKKOS_INLINE_FUNCTION
252 Scalar operator()(const int &fieldOrdinal, const int &pointOrdinal, const int &dim) const
253 {
254#ifdef HAVE_INTREPID2_DEBUG
255 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(! vectorData_.isValid(), std::invalid_argument, "VectorData object not initialized!");
256#endif
257 const int &tensorFieldOrdinal = (ordinalFilter_.extent(0) > 0) ? ordinalFilter_(fieldOrdinal) : fieldOrdinal;
258 return vectorData_(tensorFieldOrdinal, pointOrdinal, dim);
259 }
260
262 KOKKOS_INLINE_FUNCTION
263 Scalar operator()(const int &cellOrdinal, const int &fieldOrdinal, const int &pointOrdinal, const int &dim) const
264 {
265 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(true, std::invalid_argument, "CVFEM support not yet implemented in BasisValues");
266 return 0;
267 }
268
269 KOKKOS_INLINE_FUNCTION
270 int extent_int(const int &i) const
271 {
272 // shape is (F,P) or (F,P,D)
273 if (i == 0) // field dimension
274 {
275 if (ordinalFilter_.extent_int(0) == 0)
276 {
277 int numFields = 0;
278 for (int familyOrdinal=0; familyOrdinal<numFamilies(); familyOrdinal++)
279 {
280 numFields += numFieldsInFamily(familyOrdinal);
281 }
282 return numFields;
283 }
284 else
285 {
286 return ordinalFilter_.extent_int(0);
287 }
288 }
289 else
290 {
291 if (vectorData_.isValid())
292 {
293 return vectorData_.extent_int(i);
294 }
295 else if (tensorDataFamilies_[0].isValid())
296 {
297 return tensorDataFamilies_[0].extent_int(i);
298 }
299 else
300 {
301 return 0;
302 }
303 }
304 }
305
306
307 KOKKOS_INLINE_FUNCTION
308 size_t extent(const int &i) const
309 {
310 return static_cast<size_t>(extent_int(i));
311 }
312
313 KOKKOS_INLINE_FUNCTION
314 size_t rank() const
315 {
316 if (vectorData_.isValid())
317 {
318 return vectorData_.rank();
319 }
320 else if (tensorDataFamilies_[0].isValid())
321 {
322 return tensorDataFamilies_[0].rank();
323 }
324 else
325 {
326 return 0;
327 }
328 }
329
330 void setOrdinalFilter(Kokkos::View<ordinal_type*,DeviceType> ordinalFilter)
331 {
332 ordinalFilter_ = ordinalFilter;
333 }
334
335 Kokkos::View<ordinal_type*,DeviceType> ordinalFilter() const
336 {
337 return ordinalFilter_;
338 }
339 };
340
341 template<class Scalar, typename DeviceType>
342 KOKKOS_INLINE_FUNCTION unsigned rank(const BasisValues<Scalar,DeviceType> &basisValues)
343 {
344 return basisValues.rank();
345 }
346} // namespace Intrepid2
347
348#endif /* Intrepid2_BasisValues_h */
View-like interface to tensor data; tensor components are stored separately and multiplied together a...
#define INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(test, x, msg)
Reference-space field values for a basis, designed to support typical vector-valued bases.
The data containers in Intrepid2 that support sum factorization and other reduced-data optimizations ...
KOKKOS_INLINE_FUNCTION Scalar operator()(const int &cellOrdinal, const int &fieldOrdinal, const int &pointOrdinal, const int &dim) const
operator() for (C,F,P,D) data, which arises in CVFEM; at present unimplemented, and only declared her...
KOKKOS_INLINE_FUNCTION Scalar operator()(const int &fieldOrdinal, const int &pointOrdinal, const int &dim) const
operator() for (F,P,D) vector data; throws an exception if this is not a vector-valued container
BasisValues(const BasisValues< Scalar, OtherDeviceType > &basisValues)
copy-like constructor for differing execution spaces. This does a deep copy of underlying views.
BasisValues(TensorDataType tensorData)
Constructor for scalar-valued BasisValues with a single family of values.
const Kokkos::Array< TensorDataType, Parameters::MaxTensorComponents > & tensorDataFamilies() const
TensorDataFamilies accessor.
KOKKOS_INLINE_FUNCTION Scalar operator()(const int &fieldOrdinal, const int &pointOrdinal) const
operator() for (F,P) scalar data; throws an exception if this is not a scalar-valued container
const VectorDataType & vectorData() const
VectorData accessor.
BasisValues< Scalar, DeviceType > basisValuesForFields(const int &fieldStartOrdinal, const int &numFields)
field start and length must align with families in vectorData_ or tensorDataFamilies_ (whichever is v...
BasisValues()
Default constructor.
const TensorDataType & tensorData(const int &familyOrdinal) const
TensorData accessor for multi-family scalar data.
KOKKOS_INLINE_FUNCTION int numFamilies() const
For valid vectorData, returns the number of families in vectorData; otherwise, returns number of Tens...
KOKKOS_INLINE_FUNCTION int familyFieldOrdinalOffset(const int &familyOrdinal) const
Returns the field ordinal offset for the specified family.
BasisValues(VectorDataType vectorData)
Constructor for vector-valued BasisValues.
BasisValues(std::vector< TensorDataType > tensorDataFamilies)
Constructor for scalar-valued BasisValues, with potentially multiple families of values....
TensorDataType & tensorData()
TensorData accessor for single-family scalar data.
View-like interface to tensor data; tensor components are stored separately and multiplied together a...
Reference-space field values for a basis, designed to support typical vector-valued bases.
KOKKOS_INLINE_FUNCTION int numFieldsInFamily(const unsigned &familyOrdinal) const
returns the number of fields in the specified family
KOKKOS_INLINE_FUNCTION constexpr bool isValid() const
returns true for containers that have data; false for those that don't (e.g., those that have been co...