Intrepid2
Intrepid2_BasisValues.hpp
Go to the documentation of this file.
1// @HEADER
2// ************************************************************************
3//
4// Intrepid2 Package
5// Copyright (2007) Sandia Corporation
6//
7// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8// license for use of this work by or on behalf of the U.S. Government.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions are
12// met:
13//
14// 1. Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// 3. Neither the name of the Corporation nor the names of the
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36//
37// Questions? Contact Kyungjoo Kim (kyukim@sandia.gov),
38// Mauro Perego (mperego@sandia.gov), or
39// Nate Roberts (nvrober@sandia.gov)
40//
41// ************************************************************************
42// @HEADER
43
51
52#ifndef Intrepid2_BasisValues_h
53#define Intrepid2_BasisValues_h
54
66namespace Intrepid2
67{
68 template<class Scalar, typename ExecSpaceType>
70 {
73
74 Kokkos::Array<TensorDataType,Parameters::MaxTensorComponents> tensorDataFamilies_;
75 VectorDataType vectorData_;
76
77 int numTensorDataFamilies_ = -1;
78
79 Kokkos::View<ordinal_type*,ExecSpaceType> ordinalFilter_;
80 public:
83 :
84 tensorDataFamilies_({tensorData}),
85 numTensorDataFamilies_(1)
86 {}
87
89 BasisValues(std::vector<TensorDataType> tensorDataFamilies)
90 :
91 numTensorDataFamilies_(tensorDataFamilies.size())
92 {
93 for (int family=0; family<numTensorDataFamilies_; family++)
94 {
95 tensorDataFamilies_[family] = tensorDataFamilies[family];
96 }
97 }
98
101 :
102 vectorData_(vectorData)
103 {}
104
107 :
108 numTensorDataFamilies_(0)
109 {}
110
111
113 template<typename OtherExecSpaceType, class = typename std::enable_if<!std::is_same<ExecSpaceType, OtherExecSpaceType>::value>::type>
115 :
116 vectorData_(basisValues.vectorData()),
117 numTensorDataFamilies_(basisValues.numTensorDataFamilies())
118 {
119 auto otherFamilies = basisValues.tensorDataFamilies();
120 for (int family=0; family<numTensorDataFamilies_; family++)
121 {
122 tensorDataFamilies_[family] = TensorData<Scalar,ExecSpaceType>(otherFamilies[family]);
123 }
124 auto otherOrdinalFilter = basisValues.ordinalFilter();
125 ordinalFilter_ = Kokkos::View<ordinal_type*,ExecSpaceType>("BasisValues::ordinalFilter_",otherOrdinalFilter.extent(0));
126
127 Kokkos::deep_copy(ordinalFilter_, otherOrdinalFilter);
128 }
129
131 BasisValues<Scalar,ExecSpaceType> basisValuesForFields(const int &fieldStartOrdinal, const int &numFields)
132 {
133 int familyStartOrdinal = -1, familyEndOrdinal = -1;
134 const int familyCount = this->numFamilies();
135 int fieldsSoFar = 0;
136 for (int i=0; i<familyCount; i++)
137 {
138 const bool startMatches = (fieldsSoFar == fieldStartOrdinal);
139 familyStartOrdinal = startMatches ? i : familyStartOrdinal;
140 fieldsSoFar += numFieldsInFamily(i);
141 const bool endMatches = (fieldsSoFar - fieldStartOrdinal == numFields);
142 familyEndOrdinal = endMatches ? i : familyEndOrdinal;
143 }
144 INTREPID2_TEST_FOR_EXCEPTION(familyStartOrdinal == -1, std::invalid_argument, "fieldStartOrdinal does not align with the start of a family.");
145 INTREPID2_TEST_FOR_EXCEPTION(familyEndOrdinal == -1, std::invalid_argument, "fieldStartOrdinal + numFields does not align with the end of a family.");
146
147 const int numFamiliesInFieldSpan = familyEndOrdinal - familyStartOrdinal + 1;
148 if (numTensorDataFamilies_ > 0)
149 {
150 std::vector<TensorDataType> tensorDataFamilies(numFamiliesInFieldSpan);
151 for (int i=familyStartOrdinal; i<=familyEndOrdinal; i++)
152 {
153 tensorDataFamilies[i-familyStartOrdinal] = tensorDataFamilies_[i];
154 }
156 }
157 else
158 {
159 const int componentCount = vectorData_.numComponents();
160 std::vector< std::vector<TensorData<Scalar,ExecSpaceType> > > vectorComponents(numFamiliesInFieldSpan, std::vector<TensorData<Scalar,ExecSpaceType> >(componentCount));
161 for (int i=familyStartOrdinal; i<=familyEndOrdinal; i++)
162 {
163 for (int j=0; j<componentCount; j++)
164 {
165 vectorComponents[i-familyStartOrdinal][j] = vectorData_.getComponent(i,j);
166 }
167 }
168 return BasisValues<Scalar,ExecSpaceType>(vectorComponents);
169 }
170 }
171
173 KOKKOS_INLINE_FUNCTION
174 int familyFieldOrdinalOffset(const int &familyOrdinal) const
175 {
176 if (vectorData_.isValid())
177 {
178 return vectorData_.familyFieldOrdinalOffset(familyOrdinal);
179 }
180 else
181 {
182 int offset = 0;
183 for (int i=0; i<familyOrdinal; i++)
184 {
185 offset += tensorDataFamilies_[i].extent_int(0); // (F,P,…)
186 }
187 return offset;
188 }
189 }
190
193 {
194 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(numTensorDataFamilies_ != 1, std::invalid_argument, "this method is not supported when numTensorDataFamilies_ != 1");
195 return tensorDataFamilies_[0];
196 }
197
199 const TensorDataType & tensorData(const int &familyOrdinal) const
200 {
201 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(familyOrdinal >= numTensorDataFamilies_, std::invalid_argument, "familyOrdinal too large");
202 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(familyOrdinal < 0, std::invalid_argument, "familyOrdinal may not be less than 0");
203 return tensorDataFamilies_[familyOrdinal];
204 }
205
207 KOKKOS_INLINE_FUNCTION
208 int numFamilies() const
209 {
210 if (vectorData_.isValid())
211 {
212 return vectorData_.numFamilies();
213 }
214 else
215 {
216 return numTensorDataFamilies_;
217 }
218 }
219
220 KOKKOS_INLINE_FUNCTION
221 int numTensorDataFamilies() const
222 {
223 return numTensorDataFamilies_;
224 }
225
226 KOKKOS_INLINE_FUNCTION
227 int numFieldsInFamily(int familyOrdinal) const
228 {
229 if (vectorData_.isValid())
230 {
231 return vectorData_.numFieldsInFamily(familyOrdinal);
232 }
233 else
234 {
235 return tensorDataFamilies_[familyOrdinal].extent_int(0); // (F,P,…)
236 }
237 }
238
240 const Kokkos::Array<TensorDataType,Parameters::MaxTensorComponents> & tensorDataFamilies() const
241 {
242 return tensorDataFamilies_;
243 }
244
247 {
248 return vectorData_;
249 }
250
252 KOKKOS_INLINE_FUNCTION
253 Scalar operator()(const int &fieldOrdinal, const int &pointOrdinal) const
254 {
255 const int &tensorFieldOrdinal = (ordinalFilter_.extent(0) > 0) ? ordinalFilter_(fieldOrdinal) : fieldOrdinal;
256 if (numTensorDataFamilies_ == 1)
257 {
258#ifdef HAVE_INTREPID2_DEBUG
259 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(! tensorDataFamilies_[0].isValid(), std::invalid_argument, "TensorData object not initialized!");
260#endif
261 return tensorDataFamilies_[0](tensorFieldOrdinal, pointOrdinal);
262 }
263 else
264 {
265 int familyForField = -1;
266 int previousFamilyEnd = -1;
267 int fieldAdjustment = 0;
268 // this loop is written in such a way as to avoid branching for CUDA performance
269 for (int family=0; family<numTensorDataFamilies_; family++)
270 {
271 const int familyFieldCount = tensorDataFamilies_[family].extent_int(0);
272 const bool fieldInRange = (tensorFieldOrdinal > previousFamilyEnd) && (tensorFieldOrdinal <= previousFamilyEnd + familyFieldCount);
273 familyForField = fieldInRange ? family : familyForField;
274 fieldAdjustment = fieldInRange ? previousFamilyEnd + 1 : fieldAdjustment;
275 previousFamilyEnd += familyFieldCount;
276 }
277#ifdef HAVE_INTREPID2_DEBUG
278 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE( familyForField == -1, std::invalid_argument, "fieldOrdinal appears to be out of range");
279#endif
280 return tensorDataFamilies_[familyForField](tensorFieldOrdinal-fieldAdjustment,pointOrdinal);
281 }
282 }
283
285 KOKKOS_INLINE_FUNCTION
286 Scalar operator()(const int &fieldOrdinal, const int &pointOrdinal, const int &dim) const
287 {
288#ifdef HAVE_INTREPID2_DEBUG
289 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(! vectorData_.isValid(), std::invalid_argument, "VectorData object not initialized!");
290#endif
291 const int &tensorFieldOrdinal = (ordinalFilter_.extent(0) > 0) ? ordinalFilter_(fieldOrdinal) : fieldOrdinal;
292 return vectorData_(tensorFieldOrdinal, pointOrdinal, dim);
293 }
294
296 KOKKOS_INLINE_FUNCTION
297 Scalar operator()(const int &cellOrdinal, const int &fieldOrdinal, const int &pointOrdinal, const int &dim) const
298 {
299 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(true, std::invalid_argument, "CVFEM support not yet implemented in BasisValues");
300 return 0;
301 }
302
303 KOKKOS_INLINE_FUNCTION
304 int extent_int(const int &i) const
305 {
306 // shape is (F,P) or (F,P,D)
307 if (i == 0) // field dimension
308 {
309 if (ordinalFilter_.extent_int(0) == 0)
310 {
311 int numFields = 0;
312 for (int familyOrdinal=0; familyOrdinal<numFamilies(); familyOrdinal++)
313 {
314 numFields += numFieldsInFamily(familyOrdinal);
315 }
316 return numFields;
317 }
318 else
319 {
320 return ordinalFilter_.extent_int(0);
321 }
322 }
323 else
324 {
325 if (vectorData_.isValid())
326 {
327 return vectorData_.extent_int(i);
328 }
329 else if (tensorDataFamilies_[0].isValid())
330 {
331 return tensorDataFamilies_[0].extent_int(i);
332 }
333 else
334 {
335 return 0;
336 }
337 }
338 }
339
340
341 KOKKOS_INLINE_FUNCTION
342 size_t extent(const int &i) const
343 {
344 return static_cast<size_t>(extent_int(i));
345 }
346
347 KOKKOS_INLINE_FUNCTION
348 size_t rank() const
349 {
350 if (vectorData_.isValid())
351 {
352 return vectorData_.rank();
353 }
354 else if (tensorDataFamilies_[0].isValid())
355 {
356 return tensorDataFamilies_[0].rank();
357 }
358 else
359 {
360 return 0;
361 }
362 }
363
364 void setOrdinalFilter(Kokkos::View<ordinal_type*,ExecSpaceType> ordinalFilter)
365 {
366 ordinalFilter_ = ordinalFilter;
367 }
368
369 Kokkos::View<ordinal_type*,ExecSpaceType> ordinalFilter() const
370 {
371 return ordinalFilter_;
372 }
373 };
374}
375
376#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 &fieldOrdinal, const int &pointOrdinal) const
operator() for (F,P) scalar data; throws an exception if this is not a scalar-valued container
KOKKOS_INLINE_FUNCTION int familyFieldOrdinalOffset(const int &familyOrdinal) const
Returns the field ordinal offset for the specified family.
const VectorDataType & vectorData() const
VectorData accessor.
KOKKOS_INLINE_FUNCTION int numFamilies() const
For valid vectorData, returns the number of families in vectorData; otherwise, returns number of Tens...
TensorDataType & tensorData()
TensorData accessor for single-family scalar data.
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(TensorDataType tensorData)
Constructor for scalar-valued BasisValues with a single family of values.
BasisValues(const BasisValues< Scalar, OtherExecSpaceType > &basisValues)
copy-like constructor for differing execution spaces. This does a deep copy of underlying views.
BasisValues(std::vector< TensorDataType > tensorDataFamilies)
Constructor for scalar-valued BasisValues, with potentially multiple families of values....
BasisValues()
Default constructor.
const TensorDataType & tensorData(const int &familyOrdinal) const
TensorData accessor for multi-family scalar data.
BasisValues(VectorDataType vectorData)
Constructor for vector-valued BasisValues.
BasisValues< Scalar, ExecSpaceType > basisValuesForFields(const int &fieldStartOrdinal, const int &numFields)
field start and length must align with families in vectorData_ or tensorDataFamilies_ (whichever is v...
const Kokkos::Array< TensorDataType, Parameters::MaxTensorComponents > & tensorDataFamilies() const
TensorDataFamilies accessor.
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...
View-like interface to tensor data; tensor components are stored separately and multiplied together a...
KOKKOS_INLINE_FUNCTION int numFieldsInFamily(const unsigned &familyOrdinal) const
returns the number of fields in the specified family
KOKKOS_INLINE_FUNCTION unsigned rank() const
Returns the rank of this container, which is 3.
KOKKOS_INLINE_FUNCTION int numComponents() const
returns the number of components
KOKKOS_INLINE_FUNCTION int familyFieldOrdinalOffset(const int &familyOrdinal) const
Returns the field ordinal offset for the specified family.
KOKKOS_INLINE_FUNCTION const TensorData< Scalar, DeviceType > & getComponent(const int &componentOrdinal) const
Single-argument component accessor for the axial-component or the single-family case; in this case,...
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...
KOKKOS_INLINE_FUNCTION int numFamilies() const
returns the number of families
KOKKOS_INLINE_FUNCTION int extent_int(const int &r) const
Returns the extent in the specified dimension as an int.