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 public:
81 :
82 tensorDataFamilies_({tensorData}),
83 numTensorDataFamilies_(1)
84 {}
85
87 BasisValues(std::vector<TensorDataType> tensorDataFamilies)
88 :
89 numTensorDataFamilies_(tensorDataFamilies.size())
90 {
91 for (int family=0; family<numTensorDataFamilies_; family++)
92 {
93 tensorDataFamilies_[family] = tensorDataFamilies[family];
94 }
95 }
96
99 :
100 vectorData_(vectorData)
101 {}
102
105 :
106 numTensorDataFamilies_(0)
107 {}
108
109
111 template<typename OtherExecSpaceType, class = typename std::enable_if<!std::is_same<ExecSpaceType, OtherExecSpaceType>::value>::type>
113 :
114 vectorData_(basisValues.vectorData()),
115 numTensorDataFamilies_(basisValues.numTensorDataFamilies())
116 {
117 auto otherFamilies = basisValues.tensorDataFamilies();
118 for (int family=0; family<numTensorDataFamilies_; family++)
119 {
120 tensorDataFamilies_[family] = TensorData<Scalar,ExecSpaceType>(otherFamilies[family]);
121 }
122 }
123
125 BasisValues<Scalar,ExecSpaceType> basisValuesForFields(const int &fieldStartOrdinal, const int &numFields)
126 {
127 int familyStartOrdinal = -1, familyEndOrdinal = -1;
128 const int familyCount = this->numFamilies();
129 int fieldsSoFar = 0;
130 for (int i=0; i<familyCount; i++)
131 {
132 const bool startMatches = (fieldsSoFar == fieldStartOrdinal);
133 familyStartOrdinal = startMatches ? i : familyStartOrdinal;
134 fieldsSoFar += numFieldsInFamily(i);
135 const bool endMatches = (fieldsSoFar - fieldStartOrdinal == numFields);
136 familyEndOrdinal = endMatches ? i : familyEndOrdinal;
137 }
138 INTREPID2_TEST_FOR_EXCEPTION(familyStartOrdinal == -1, std::invalid_argument, "fieldStartOrdinal does not align with the start of a family.");
139 INTREPID2_TEST_FOR_EXCEPTION(familyEndOrdinal == -1, std::invalid_argument, "fieldStartOrdinal + numFields does not align with the end of a family.");
140
141 const int numFamiliesInFieldSpan = familyEndOrdinal - familyStartOrdinal + 1;
142 if (numTensorDataFamilies_ > 0)
143 {
144 std::vector<TensorDataType> tensorDataFamilies(numFamiliesInFieldSpan);
145 for (int i=familyStartOrdinal; i<=familyEndOrdinal; i++)
146 {
147 tensorDataFamilies[i-familyStartOrdinal] = tensorDataFamilies_[i];
148 }
150 }
151 else
152 {
153 const int componentCount = vectorData_.numComponents();
154 std::vector< std::vector<TensorData<Scalar,ExecSpaceType> > > vectorComponents(numFamiliesInFieldSpan, std::vector<TensorData<Scalar,ExecSpaceType> >(componentCount));
155 for (int i=familyStartOrdinal; i<=familyEndOrdinal; i++)
156 {
157 for (int j=0; j<componentCount; j++)
158 {
159 vectorComponents[i-familyStartOrdinal][j] = vectorData_.getComponent(i,j);
160 }
161 }
162 return BasisValues<Scalar,ExecSpaceType>(vectorComponents);
163 }
164 }
165
168 {
169 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(numTensorDataFamilies_ != 1, std::invalid_argument, "this method is not supported when numTensorDataFamilies_ != 1");
170 return tensorDataFamilies_[0];
171 }
172
174 TensorDataType & tensorData(const int &familyOrdinal)
175 {
176 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(familyOrdinal >= numTensorDataFamilies_, std::invalid_argument, "familyOrdinal too large");
177 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(familyOrdinal < 0, std::invalid_argument, "familyOrdinal may not be less than 0");
178 return tensorDataFamilies_[familyOrdinal];
179 }
180
182 KOKKOS_INLINE_FUNCTION
183 int numFamilies() const
184 {
185 if (vectorData_.isValid())
186 {
187 return vectorData_.numFamilies();
188 }
189 else
190 {
191 return numTensorDataFamilies_;
192 }
193 }
194
195 KOKKOS_INLINE_FUNCTION
196 int numTensorDataFamilies() const
197 {
198 return numTensorDataFamilies_;
199 }
200
201 KOKKOS_INLINE_FUNCTION
202 int numFieldsInFamily(int familyOrdinal) const
203 {
204 if (vectorData_.isValid())
205 {
206 return vectorData_.numFieldsInFamily(familyOrdinal);
207 }
208 else
209 {
210 return tensorDataFamilies_[familyOrdinal].extent_int(0); // (F,P,…)
211 }
212 }
213
215 const Kokkos::Array<TensorDataType,Parameters::MaxTensorComponents> & tensorDataFamilies() const
216 {
217 return tensorDataFamilies_;
218 }
219
222 {
223 return vectorData_;
224 }
225
227 KOKKOS_INLINE_FUNCTION
228 Scalar operator()(const int &fieldOrdinal, const int &pointOrdinal) const
229 {
230 if (numTensorDataFamilies_ == 1)
231 {
232#ifdef HAVE_INTREPID2_DEBUG
233 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(! tensorDataFamilies_[0].isValid(), std::invalid_argument, "TensorData object not initialized!");
234#endif
235 return tensorDataFamilies_[0](fieldOrdinal, pointOrdinal);
236 }
237 else
238 {
239 int familyForField = -1;
240 int previousFamilyEnd = -1;
241 int fieldAdjustment = 0;
242 // this loop is written in such a way as to avoid branching for CUDA performance
243 for (int family=0; family<numTensorDataFamilies_; family++)
244 {
245 const int familyFieldCount = tensorDataFamilies_[family].extent_int(0);
246 const bool fieldInRange = (fieldOrdinal > previousFamilyEnd) && (fieldOrdinal <= previousFamilyEnd + familyFieldCount);
247 familyForField = fieldInRange ? family : familyForField;
248 fieldAdjustment = fieldInRange ? previousFamilyEnd + 1 : fieldAdjustment;
249 previousFamilyEnd += familyFieldCount;
250 }
251#ifdef HAVE_INTREPID2_DEBUG
252 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE( familyForField == -1, std::invalid_argument, "fieldOrdinal appears to be out of range");
253#endif
254 return tensorDataFamilies_[familyForField](fieldOrdinal-fieldAdjustment,pointOrdinal);
255 }
256 }
257
259 KOKKOS_INLINE_FUNCTION
260 Scalar operator()(const int &fieldOrdinal, const int &pointOrdinal, const int &dim) const
261 {
262#ifdef HAVE_INTREPID2_DEBUG
263 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(! vectorData_.isValid(), std::invalid_argument, "VectorData object not initialized!");
264#endif
265 return vectorData_(fieldOrdinal, pointOrdinal, dim);
266 }
267
269 KOKKOS_INLINE_FUNCTION
270 Scalar operator()(const int &cellOrdinal, const int &fieldOrdinal, const int &pointOrdinal, const int &dim) const
271 {
272 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(true, std::invalid_argument, "CVFEM support not yet implemented in BasisValues");
273 return 0;
274 }
275
276 KOKKOS_INLINE_FUNCTION
277 int extent_int(const int &i) const
278 {
279 // shape is (F,P) or (F,P,D)
280 if (i == 0) // field dimension
281 {
282 int numFields = 0;
283 for (int familyOrdinal=0; familyOrdinal<numFamilies(); familyOrdinal++)
284 {
285 numFields += numFieldsInFamily(familyOrdinal);
286 }
287 return numFields;
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}
331
332#endif /* Intrepid2_BasisValues_h */
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.
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
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.
TensorDataType & tensorData(const int &familyOrdinal)
TensorData accessor for multi-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.
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 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.