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 
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 
246  const VectorDataType & vectorData() const
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 */
const Kokkos::Array< TensorDataType, Parameters::MaxTensorComponents > & tensorDataFamilies() const
TensorDataFamilies accessor.
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 numFieldsInFamily(const unsigned &familyOrdinal) const
returns the number of fields in the specified family
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(const BasisValues< Scalar, OtherExecSpaceType > &basisValues)
copy-like constructor for differing execution spaces. This does a deep copy of underlying views...
#define INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(test, x, msg)
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 numFamilies() const
returns the number of families
const VectorDataType & vectorData() const
VectorData accessor.
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.
Reference-space field values for a basis, designed to support typical vector-valued bases...
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 extent_int(const int &r) const
Returns the extent in the specified dimension as an int.
const TensorDataType & tensorData(const int &familyOrdinal) const
TensorData accessor for multi-family scalar data.
TensorDataType & tensorData()
TensorData accessor for single-family scalar data.
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...
KOKKOS_INLINE_FUNCTION int familyFieldOrdinalOffset(const int &familyOrdinal) const
Returns the field ordinal offset for the specified family.
BasisValues(TensorDataType tensorData)
Constructor for scalar-valued BasisValues with a single family of values.
KOKKOS_INLINE_FUNCTION unsigned rank() const
Returns the rank of this container, which is 3.
View-like interface to tensor data; tensor components are stored separately and multiplied together a...
KOKKOS_INLINE_FUNCTION int familyFieldOrdinalOffset(const int &familyOrdinal) const
Returns the field ordinal offset for the specified family.
View-like interface to tensor data; tensor components are stored separately and multiplied together a...
KOKKOS_INLINE_FUNCTION int numComponents() const
returns the number of components
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 ...