50 #ifndef Intrepid2_TensorData_h 51 #define Intrepid2_TensorData_h 55 #include "Intrepid2_ScalarView.hpp" 63 template<
class Scalar,
typename DeviceType>
67 Kokkos::Array<ordinal_type, 7> extents_;
68 Kokkos::Array<Kokkos::Array<ordinal_type, Parameters::MaxTensorComponents>, 7> entryModulus_;
70 bool separateFirstComponent_ =
false;
71 ordinal_type numTensorComponents_ = 0;
78 ordinal_type maxComponentRank = -1;
79 for (ordinal_type r=0; r<numTensorComponents_; r++)
81 const ordinal_type componentRank = tensorComponents_[r].rank();
82 maxComponentRank = (maxComponentRank > componentRank) ? maxComponentRank : componentRank;
84 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(separateFirstComponent_ && (maxComponentRank != 1), std::invalid_argument,
"separateFirstComponent = true only supported if all components have rank 1");
85 ordinal_type rd_start;
86 if ((maxComponentRank == 1) && separateFirstComponent_)
90 extents_[0] = tensorComponents_[0].extent_int(0);
91 entryModulus_[0][0] = extents_[0];
95 rank_ = maxComponentRank;
99 for (ordinal_type d=rd_start; d<7; d++)
102 for (ordinal_type r=rd_start; r<numTensorComponents_; r++)
104 extents_[d] *= tensorComponents_[r].extent_int(d-rd_start);
106 ordinal_type entryModulus = extents_[d];
107 for (ordinal_type r=rd_start; r<numTensorComponents_; r++)
109 entryModulus /= tensorComponents_[r].extent_int(d-rd_start);
110 entryModulus_[d][r] = entryModulus;
124 template<
size_t numTensorComponents>
132 tensorComponents_[r] = tensorComponents[r];
150 numTensorComponents_(tensorComponents.size())
152 for (ordinal_type r=0; r<numTensorComponents_; r++)
154 tensorComponents_[r] = tensorComponents[r];
168 TensorData(Kokkos::Array<
Data<Scalar,DeviceType>, 1>({tensorComponent}),
false)
178 extents_({0,0,0,0,0,0,0}),
183 template<typename OtherDeviceType, class = typename std::enable_if< std::is_same<typename DeviceType::memory_space, typename OtherDeviceType::memory_space>::value>::type,
184 class = typename std::enable_if<!std::is_same<DeviceType,OtherDeviceType>::value>::type>
185 TensorData(const TensorData<Scalar,OtherDeviceType> &tensorData)
187 if (tensorData.isValid())
190 for (ordinal_type r=0; r<numTensorComponents_; r++)
199 extents_ = Kokkos::Array<ordinal_type,7>{0,0,0,0,0,0,0};
207 template<typename OtherDeviceType, class = typename std::enable_if<!std::is_same<typename DeviceType::memory_space, typename OtherDeviceType::memory_space>::value>::type>
213 for (ordinal_type r=0; r<numTensorComponents_; r++)
222 extents_ = Kokkos::Array<ordinal_type,7>{0,0,0,0,0,0,0};
232 KOKKOS_INLINE_FUNCTION
235 return tensorComponents_[r];
243 template <
typename iType0>
244 KOKKOS_INLINE_FUNCTION
typename std::enable_if<std::is_integral<iType0>::value, Scalar>::type
246 #ifdef HAVE_INTREPID2_DEBUG 247 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(rank_ != 1, std::invalid_argument,
"This method is only valid for rank 1 containers.");
250 iType0 remainingEntryOrdinal = tensorEntryIndex;
251 for (ordinal_type r=0; r<numTensorComponents_; r++)
253 const ordinal_type componentEntryCount = tensorComponents_[r].extent_int(0);
254 const ordinal_type componentEntryOrdinal = remainingEntryOrdinal % componentEntryCount;
255 remainingEntryOrdinal /= componentEntryCount;
257 value *= tensorComponents_[r](componentEntryOrdinal);
268 template <
typename iType0, ordinal_type numTensorComponents>
269 KOKKOS_INLINE_FUNCTION
typename std::enable_if<std::is_integral<iType0>::value, Scalar>::type
270 operator()(
const Kokkos::Array<iType0,numTensorComponents>& entryComponents)
const {
271 #ifdef HAVE_INTREPID2_DEBUG 272 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(rank_ != 1, std::invalid_argument,
"This method is only valid for rank 1 containers.");
273 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(numTensorComponents_ !=
numTensorComponents, std::invalid_argument,
"Tensorial component count mismatch");
278 value *= tensorComponents_[r](entryComponents[r]);
293 template <
typename iType0,
typename iType1>
294 KOKKOS_INLINE_FUNCTION
typename std::enable_if<
295 (std::is_integral<iType0>::value && std::is_integral<iType1>::value),
297 operator()(
const iType0& tensorEntryIndex0,
const iType1& tensorEntryIndex1)
const {
298 #ifdef HAVE_INTREPID2_DEBUG 299 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(rank_ != 2, std::invalid_argument,
"This method is only valid for rank 2 containers.");
302 if (numTensorComponents_ == 1)
304 return tensorComponents_[0](tensorEntryIndex0,tensorEntryIndex1);
307 if (!separateFirstComponent_)
310 iType0 remainingEntryOrdinal0 = tensorEntryIndex0;
311 iType1 remainingEntryOrdinal1 = tensorEntryIndex1;
312 for (ordinal_type r=0; r<numTensorComponents_; r++)
314 auto & component = tensorComponents_[r];
315 const ordinal_type componentEntryCount0 = component.extent_int(0);
316 const ordinal_type componentEntryCount1 = component.extent_int(1);
317 const iType0 componentEntryOrdinal0 = remainingEntryOrdinal0 % componentEntryCount0;
318 const iType1 componentEntryOrdinal1 = remainingEntryOrdinal1 % componentEntryCount1;
319 remainingEntryOrdinal0 /= componentEntryCount0;
320 remainingEntryOrdinal1 /= componentEntryCount1;
322 const ordinal_type componentRank = component.rank();
324 if (componentRank == 2)
326 value *= component(componentEntryOrdinal0,componentEntryOrdinal1);
328 else if (componentRank == 1)
330 value *= component(componentEntryOrdinal0);
334 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(
true, std::logic_error,
"unsupported component rank encountered");
342 Scalar value = tensorComponents_[0](tensorEntryIndex0);
343 iType0 remainingEntryOrdinal = tensorEntryIndex1;
344 for (ordinal_type r=1; r<numTensorComponents_; r++)
346 const ordinal_type componentEntryCount = tensorComponents_[r].extent_int(0);
347 const ordinal_type componentEntryOrdinal = remainingEntryOrdinal % componentEntryCount;
348 remainingEntryOrdinal /= componentEntryCount;
350 value *= tensorComponents_[r](componentEntryOrdinal);
357 KOKKOS_INLINE_FUNCTION
358 ordinal_type
getTensorComponentIndex(
const ordinal_type &tensorComponent,
const ordinal_type &dim,
const ordinal_type &enumerationIndex)
const 360 ordinal_type remainingEntryOrdinal = enumerationIndex;
361 for (ordinal_type r=0; r<tensorComponent; r++)
363 const auto & component = tensorComponents_[r];
364 const ordinal_type & componentEntryCount = component.extent_int(dim);
366 remainingEntryOrdinal /= componentEntryCount;
368 return remainingEntryOrdinal % tensorComponents_[tensorComponent].extent_int(dim);
380 template <
typename iType0,
typename iType1,
typename iType2>
381 KOKKOS_INLINE_FUNCTION
typename std::enable_if<
382 (std::is_integral<iType0>::value && std::is_integral<iType1>::value && std::is_integral<iType2>::value),
384 operator()(
const iType0& tensorEntryIndex0,
const iType1& tensorEntryIndex1,
const iType2& tensorEntryIndex2)
const 386 #ifdef HAVE_INTREPID2_DEBUG 387 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(rank_ != 3, std::invalid_argument,
"This method is only valid for rank 3 containers.");
388 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(separateFirstComponent_, std::logic_error,
"This method should never be called when separateFirstComponent is true");
392 Kokkos::Array<ordinal_type,3> remainingEntryOrdinal {tensorEntryIndex0, tensorEntryIndex1, tensorEntryIndex2};
393 for (ordinal_type r=0; r<numTensorComponents_; r++)
395 auto & component = tensorComponents_[r];
396 const ordinal_type componentEntryCount0 = component.extent_int(0);
397 const ordinal_type componentEntryCount1 = component.extent_int(1);
398 const ordinal_type componentEntryCount2 = component.extent_int(2);
399 const ordinal_type componentEntryOrdinal0 = remainingEntryOrdinal[0] % componentEntryCount0;
400 const ordinal_type componentEntryOrdinal1 = remainingEntryOrdinal[1] % componentEntryCount1;
401 const ordinal_type componentEntryOrdinal2 = remainingEntryOrdinal[2] % componentEntryCount2;
402 remainingEntryOrdinal[0] /= componentEntryCount0;
403 remainingEntryOrdinal[1] /= componentEntryCount1;
404 remainingEntryOrdinal[2] /= componentEntryCount2;
406 const ordinal_type componentRank = component.rank();
408 if (componentRank == 3)
410 value *= component(componentEntryOrdinal0,componentEntryOrdinal1,componentEntryOrdinal2);
412 else if (componentRank == 2)
414 value *= component(componentEntryOrdinal0,componentEntryOrdinal1);
416 else if (componentRank == 1)
418 value *= component(componentEntryOrdinal0);
422 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(
true, std::logic_error,
"unsupported component rank encountered");
435 template <
typename iType0,
typename iType1, ordinal_type numTensorComponents>
436 KOKKOS_INLINE_FUNCTION
typename std::enable_if<
437 (std::is_integral<iType0>::value && std::is_integral<iType1>::value),
439 operator()(
const Kokkos::Array<iType0,numTensorComponents>& entryComponents0,
const Kokkos::Array<iType1,numTensorComponents>& entryComponents1)
const {
440 #ifdef HAVE_INTREPID2_DEBUG 441 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(numTensorComponents_ !=
numTensorComponents, std::invalid_argument,
"Tensorial component count mismatch");
446 auto & component = tensorComponents_[r];
447 const ordinal_type componentRank = component.rank();
448 if (componentRank == 2)
450 value *= component(entryComponents0[r],entryComponents1[r]);
452 else if (componentRank == 1)
454 value *= component(entryComponents0[r]);
458 INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(
true, std::logic_error,
"unsupported component rank encountered");
469 template <
typename iType>
470 KOKKOS_INLINE_FUNCTION
471 typename std::enable_if<std::is_integral<iType>::value, ordinal_type>::type
481 template <
typename iType>
482 KOKKOS_INLINE_FUNCTION constexpr
483 typename std::enable_if<std::is_integral<iType>::value,
size_t>::type
489 KOKKOS_INLINE_FUNCTION constexpr
bool isValid()
const 491 return extents_[0] > 0;
495 KOKKOS_INLINE_FUNCTION
502 KOKKOS_INLINE_FUNCTION
505 return numTensorComponents_;
509 KOKKOS_INLINE_FUNCTION
512 return separateFirstComponent_;
518 INTREPID2_TEST_FOR_EXCEPTION(!separateFirstComponent_ && (numTensorComponents_ != 1), std::invalid_argument,
"setFirstComponentExtent() is only allowed when separateFirstComponent_ is true, or there is only one component");
519 tensorComponents_[0].setExtent(0,newExtent);
TensorData(Kokkos::Array< Data< Scalar, DeviceType >, numTensorComponents > tensorComponents, bool separateFirstComponent=false)
Constructor with fixed-length Kokkos::Array argument.
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...
Defines the Data class, a wrapper around a Kokkos::View that allows data that is constant or repeatin...
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(std::vector< Data< Scalar, DeviceType > > tensorComponents, bool separateFirstComponent=false)
Constructor with variable-length std::vector containing the components.
KOKKOS_INLINE_FUNCTION bool separateFirstComponent() const
Returns true if the first component is indexed separately; false if not.
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 const Data< Scalar, DeviceType > & getTensorComponent(const ordinal_type &r) const
Returns the requested tensor component.
Contains definitions of custom data types in Intrepid2.
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...
TensorData()
Default constructor.
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.
KOKKOS_INLINE_FUNCTION ordinal_type numTensorComponents() const
Return the number of tensorial components.
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 iType0 &tensorEntryIndex) const
Accessor for rank-1 objects.
View-like interface to tensor data; tensor components are stored separately and multiplied together a...
TensorData(Data< Scalar, DeviceType > tensorComponent)
Simple constructor for the case of trivial tensor-product structure (single component) ...
static constexpr ordinal_type MaxTensorComponents
Maximum number of tensor/Cartesian products that can be taken: this allows hypercube basis in 7D to b...