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 
49 #include "Intrepid2_TensorData.hpp"
50 #include "Intrepid2_VectorData.hpp"
51 
52 #ifndef Intrepid2_BasisValues_h
53 #define Intrepid2_BasisValues_h
54 
66 namespace 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 
221  const VectorDataType & vectorData() const
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 */
KOKKOS_INLINE_FUNCTION int extent_int(const int &r) const
Returns the extent in the specified dimension as an int.
const Kokkos::Array< TensorDataType, Parameters::MaxTensorComponents > & tensorDataFamilies() const
TensorDataFamilies accessor.
KOKKOS_INLINE_FUNCTION constexpr bool isValid() const
returns true for containers that have data; false for those that don&#39;t (e.g., those that have been co...
BasisValues(const BasisValues< Scalar, OtherExecSpaceType > &basisValues)
copy-like constructor for differing execution spaces. This does a deep copy of underlying views...
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 ...
KOKKOS_INLINE_FUNCTION int numFieldsInFamily(const unsigned &familyOrdinal) const
returns the number of fields in the specified family
KOKKOS_INLINE_FUNCTION int numComponents() const
returns the number of components
KOKKOS_INLINE_FUNCTION unsigned rank() const
Returns the rank of this container, which is 3.
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...
The data containers in Intrepid2 that support sum factorization and other reduced-data optimizations ...
BasisValues(VectorDataType vectorData)
Constructor for vector-valued BasisValues.
BasisValues()
Default constructor.
KOKKOS_INLINE_FUNCTION int numFamilies() const
For valid vectorData, returns the number of families in vectorData; otherwise, returns number of Tens...
Reference-space field values for a basis, designed to support typical vector-valued bases...
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 ...
TensorDataType & tensorData(const int &familyOrdinal)
TensorData accessor for multi-family scalar data.
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...
BasisValues(std::vector< TensorDataType > tensorDataFamilies)
Constructor for scalar-valued BasisValues, with potentially multiple families of values. (Used, e.g., for op = DIV and functionSpace = HDIV.)
KOKKOS_INLINE_FUNCTION int numFamilies() const
returns the number of families
TensorDataType & tensorData()
TensorData accessor for single-family scalar data.
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...
BasisValues(TensorDataType tensorData)
Constructor for scalar-valued BasisValues with a single family of values.
View-like interface to tensor data; tensor components are stored separately and multiplied together a...
View-like interface to tensor data; tensor components are stored separately and multiplied together a...
const VectorDataType & vectorData() const
VectorData accessor.