16 #ifndef Intrepid2_TensorData_h
17 #define Intrepid2_TensorData_h
21 #include "Intrepid2_ScalarView.hpp"
29 template<
class Scalar,
typename DeviceType>
32 using value_type = Scalar;
33 using execution_space =
typename DeviceType::execution_space;
36 Kokkos::Array<ordinal_type, 7> extents_;
37 Kokkos::Array<Kokkos::Array<ordinal_type, Parameters::MaxTensorComponents>, 7> entryModulus_;
39 bool separateFirstComponent_ =
false;
40 ordinal_type numTensorComponents_ = 0;
47 ordinal_type maxComponentRank = -1;
48 for (ordinal_type r=0; r<numTensorComponents_; r++)
50 const ordinal_type componentRank = tensorComponents_[r].rank();
51 maxComponentRank = (maxComponentRank > componentRank) ? maxComponentRank : componentRank;
54 ordinal_type rd_start;
55 if ((maxComponentRank == 1) && separateFirstComponent_)
59 extents_[0] = tensorComponents_[0].extent_int(0);
60 entryModulus_[0][0] = extents_[0];
64 rank_ = maxComponentRank;
68 for (ordinal_type d=rd_start; d<7; d++)
71 for (ordinal_type r=rd_start; r<numTensorComponents_; r++)
73 extents_[d] *= tensorComponents_[r].extent_int(d-rd_start);
75 ordinal_type entryModulus = extents_[d];
76 for (ordinal_type r=rd_start; r<numTensorComponents_; r++)
78 entryModulus /= tensorComponents_[r].extent_int(d-rd_start);
79 entryModulus_[d][r] = entryModulus;
93 template<
size_t numTensorComponents>
101 tensorComponents_[r] = tensorComponents[r];
119 numTensorComponents_(tensorComponents.size())
121 for (ordinal_type r=0; r<numTensorComponents_; r++)
123 tensorComponents_[r] = tensorComponents[r];
163 TensorData(Kokkos::Array<
Data<Scalar,DeviceType>, 1>({tensorComponent}),
false)
173 extents_({0,0,0,0,0,0,0}),
186 numTensorComponents_(whichComps.size())
189 for (
const auto & componentOrdinal : whichComps)
198 template<typename OtherDeviceType, class = typename std::enable_if< std::is_same<typename DeviceType::memory_space, typename OtherDeviceType::memory_space>::value>::type,
199 class = typename std::enable_if<!std::is_same<DeviceType,OtherDeviceType>::value>::type>
200 TensorData(const TensorData<Scalar,OtherDeviceType> &tensorData)
202 if (tensorData.isValid())
205 for (ordinal_type r=0; r<numTensorComponents_; r++)
214 extents_ = Kokkos::Array<ordinal_type,7>{0,0,0,0,0,0,0};
222 template<typename OtherDeviceType, class = typename std::enable_if<!std::is_same<typename DeviceType::memory_space, typename OtherDeviceType::memory_space>::value>::type>
228 for (ordinal_type r=0; r<numTensorComponents_; r++)
237 extents_ = Kokkos::Array<ordinal_type,7>{0,0,0,0,0,0,0};
247 KOKKOS_INLINE_FUNCTION
250 return tensorComponents_[r];
258 template <
typename iType0>
259 KOKKOS_INLINE_FUNCTION
typename std::enable_if<std::is_integral<iType0>::value, Scalar>::type
261 #ifdef HAVE_INTREPID2_DEBUG
265 iType0 remainingEntryOrdinal = tensorEntryIndex;
266 for (ordinal_type r=0; r<numTensorComponents_; r++)
268 const ordinal_type componentEntryCount = tensorComponents_[r].extent_int(0);
269 const ordinal_type componentEntryOrdinal = remainingEntryOrdinal % componentEntryCount;
270 remainingEntryOrdinal /= componentEntryCount;
272 value *= tensorComponents_[r](componentEntryOrdinal);
283 template <
typename iType0, ordinal_type numTensorComponents>
284 KOKKOS_INLINE_FUNCTION
typename std::enable_if<std::is_integral<iType0>::value, Scalar>::type
285 operator()(
const Kokkos::Array<iType0,numTensorComponents>& entryComponents)
const {
286 #ifdef HAVE_INTREPID2_DEBUG
293 value *= tensorComponents_[r](entryComponents[r]);
308 template <
typename iType0,
typename iType1>
309 KOKKOS_INLINE_FUNCTION
typename std::enable_if<
310 (std::is_integral<iType0>::value && std::is_integral<iType1>::value),
312 operator()(
const iType0& tensorEntryIndex0,
const iType1& tensorEntryIndex1)
const {
313 #ifdef HAVE_INTREPID2_DEBUG
317 if (numTensorComponents_ == 1)
319 return tensorComponents_[0](tensorEntryIndex0,tensorEntryIndex1);
322 if (!separateFirstComponent_)
325 iType0 remainingEntryOrdinal0 = tensorEntryIndex0;
326 iType1 remainingEntryOrdinal1 = tensorEntryIndex1;
327 for (ordinal_type r=0; r<numTensorComponents_; r++)
329 auto & component = tensorComponents_[r];
330 const ordinal_type componentEntryCount0 = component.extent_int(0);
331 const ordinal_type componentEntryCount1 = component.extent_int(1);
332 const iType0 componentEntryOrdinal0 = remainingEntryOrdinal0 % componentEntryCount0;
333 const iType1 componentEntryOrdinal1 = remainingEntryOrdinal1 % componentEntryCount1;
334 remainingEntryOrdinal0 /= componentEntryCount0;
335 remainingEntryOrdinal1 /= componentEntryCount1;
337 const ordinal_type componentRank = component.rank();
339 if (componentRank == 2)
341 value *= component(componentEntryOrdinal0,componentEntryOrdinal1);
343 else if (componentRank == 1)
345 value *= component(componentEntryOrdinal0);
357 Scalar value = tensorComponents_[0](tensorEntryIndex0);
358 iType0 remainingEntryOrdinal = tensorEntryIndex1;
359 for (ordinal_type r=1; r<numTensorComponents_; r++)
361 const ordinal_type componentEntryCount = tensorComponents_[r].extent_int(0);
362 const ordinal_type componentEntryOrdinal = remainingEntryOrdinal % componentEntryCount;
363 remainingEntryOrdinal /= componentEntryCount;
365 value *= tensorComponents_[r](componentEntryOrdinal);
372 KOKKOS_INLINE_FUNCTION
373 ordinal_type
getTensorComponentIndex(
const ordinal_type &tensorComponent,
const ordinal_type &dim,
const ordinal_type &enumerationIndex)
const
375 ordinal_type remainingEntryOrdinal = enumerationIndex;
376 for (ordinal_type r=0; r<tensorComponent; r++)
378 const auto & component = tensorComponents_[r];
379 const ordinal_type & componentEntryCount = component.extent_int(dim);
381 remainingEntryOrdinal /= componentEntryCount;
383 return remainingEntryOrdinal % tensorComponents_[tensorComponent].extent_int(dim);
395 template <
typename iType0,
typename iType1,
typename iType2>
396 KOKKOS_INLINE_FUNCTION
typename std::enable_if<
397 (std::is_integral<iType0>::value && std::is_integral<iType1>::value && std::is_integral<iType2>::value),
399 operator()(
const iType0& tensorEntryIndex0,
const iType1& tensorEntryIndex1,
const iType2& tensorEntryIndex2)
const
401 #ifdef HAVE_INTREPID2_DEBUG
407 Kokkos::Array<ordinal_type,3> remainingEntryOrdinal {tensorEntryIndex0, tensorEntryIndex1, tensorEntryIndex2};
408 for (ordinal_type r=0; r<numTensorComponents_; r++)
410 auto & component = tensorComponents_[r];
411 const ordinal_type componentEntryCount0 = component.extent_int(0);
412 const ordinal_type componentEntryCount1 = component.extent_int(1);
413 const ordinal_type componentEntryCount2 = component.extent_int(2);
414 const ordinal_type componentEntryOrdinal0 = remainingEntryOrdinal[0] % componentEntryCount0;
415 const ordinal_type componentEntryOrdinal1 = remainingEntryOrdinal[1] % componentEntryCount1;
416 const ordinal_type componentEntryOrdinal2 = remainingEntryOrdinal[2] % componentEntryCount2;
417 remainingEntryOrdinal[0] /= componentEntryCount0;
418 remainingEntryOrdinal[1] /= componentEntryCount1;
419 remainingEntryOrdinal[2] /= componentEntryCount2;
421 const ordinal_type componentRank = component.rank();
423 if (componentRank == 3)
425 value *= component(componentEntryOrdinal0,componentEntryOrdinal1,componentEntryOrdinal2);
427 else if (componentRank == 2)
429 value *= component(componentEntryOrdinal0,componentEntryOrdinal1);
431 else if (componentRank == 1)
433 value *= component(componentEntryOrdinal0);
450 template <
typename iType0,
typename iType1, ordinal_type numTensorComponents>
451 KOKKOS_INLINE_FUNCTION
typename std::enable_if<
452 (std::is_integral<iType0>::value && std::is_integral<iType1>::value),
454 operator()(
const Kokkos::Array<iType0,numTensorComponents>& entryComponents0,
const Kokkos::Array<iType1,numTensorComponents>& entryComponents1)
const {
455 #ifdef HAVE_INTREPID2_DEBUG
461 auto & component = tensorComponents_[r];
462 const ordinal_type componentRank = component.rank();
463 if (componentRank == 2)
465 value *= component(entryComponents0[r],entryComponents1[r]);
467 else if (componentRank == 1)
469 value *= component(entryComponents0[r]);
484 template <
typename iType>
485 KOKKOS_INLINE_FUNCTION
486 typename std::enable_if<std::is_integral<iType>::value, ordinal_type>::type
496 template <
typename iType>
497 KOKKOS_INLINE_FUNCTION constexpr
498 typename std::enable_if<std::is_integral<iType>::value,
size_t>::type
504 KOKKOS_INLINE_FUNCTION constexpr
bool isValid()
const
506 return extents_[0] > 0;
510 KOKKOS_INLINE_FUNCTION
517 KOKKOS_INLINE_FUNCTION
520 return numTensorComponents_;
524 KOKKOS_INLINE_FUNCTION
527 return separateFirstComponent_;
533 INTREPID2_TEST_FOR_EXCEPTION(!separateFirstComponent_ && (numTensorComponents_ != 1), std::invalid_argument,
"setFirstComponentExtent() is only allowed when separateFirstComponent_ is true, or there is only one component");
534 tensorComponents_[0].setExtent(0,newExtent);
535 extents_[0] = newExtent;
TensorData(Kokkos::Array< Data< Scalar, DeviceType >, numTensorComponents > tensorComponents, bool separateFirstComponent=false)
Constructor with fixed-length Kokkos::Array argument.
#define INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(test, x, msg)
Defines the Data class, a wrapper around a Kokkos::View that allows data that is constant or repeatin...
TensorData(const TensorData &first, const TensorData &second, bool separateFirstComponent=false)
Constructor to combine two other TensorData objects.
KOKKOS_INLINE_FUNCTION ordinal_type getTensorComponentIndex(const ordinal_type &tensorComponent, const ordinal_type &dim, const ordinal_type &enumerationIndex) const
return the index into the specified tensorial component in the dimension specified corresponding to t...
KOKKOS_INLINE_FUNCTION const Data< Scalar, DeviceType > & getTensorComponent(const ordinal_type &r) const
Returns the requested tensor component.
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...
void initialize()
Initialize members based on constructor parameters.
TensorData(const TensorData< Scalar, OtherDeviceType > &tensorData)
Copy-like constructor for differing execution spaces. This performs a deep copy of the underlying dat...
KOKKOS_INLINE_FUNCTION ordinal_type rank() const
Returns the rank of the container.
TensorData(TensorData otherTensorData, std::vector< int > whichComps)
Constructor that takes a subset of the tensorial components of another TensorData container...
TensorData(std::vector< Data< Scalar, DeviceType > > tensorComponents, bool separateFirstComponent=false)
Constructor with variable-length std::vector containing the components.
Contains definitions of custom data types in Intrepid2.
KOKKOS_INLINE_FUNCTION std::enable_if< std::is_integral< iType0 >::value, Scalar >::type operator()(const iType0 &tensorEntryIndex) const
Accessor for rank-1 objects.
TensorData()
Default constructor.
void setFirstComponentExtentInDimension0(const ordinal_type &newExtent)
Sets the extent of the first component. Only valid when either there is only one component, or when separateFirstComponent() returns true. The intended use case is when the 0 dimension in first component represents a cell index, and the container is resized to match a workset size that does not evenly divide the number of cells.
KOKKOS_INLINE_FUNCTION std::enable_if< std::is_integral< iType0 >::value, Scalar >::type operator()(const Kokkos::Array< iType0, numTensorComponents > &entryComponents) const
Accessor that accepts a fixed-length array with entries corresponding to component indices...
View-like interface to tensor data; tensor components are stored separately and multiplied together a...
KOKKOS_INLINE_FUNCTION std::enable_if< std::is_integral< iType >::value, ordinal_type >::type extent_int(const iType &d) const
Returns the logical extent in the requested dimension.
KOKKOS_INLINE_FUNCTION bool separateFirstComponent() const
Returns true if the first component is indexed separately; false if not.
KOKKOS_INLINE_FUNCTION ordinal_type numTensorComponents() const
Return the number of tensorial components.
TensorData(Data< Scalar, DeviceType > tensorComponent)
Simple constructor for the case of trivial tensor-product structure (single component) ...
KOKKOS_INLINE_FUNCTION constexpr std::enable_if< std::is_integral< iType >::value, size_t >::type extent(const iType &d) const
Returns the logical extent in the requested dimension.
static constexpr ordinal_type MaxTensorComponents
Maximum number of tensor/Cartesian products that can be taken: this allows hypercube basis in 7D to b...