49 #ifndef __INTREPID2_ARRAYTOOLS_DEF_TENSOR_HPP__
50 #define __INTREPID2_ARRAYTOOLS_DEF_TENSOR_HPP__
54 namespace FunctorArrayTools {
58 template <
typename OutputViewType,
typename leftInputViewType,
typename rightInputViewType >
60 OutputViewType _output;
61 const leftInputViewType _leftInput;
62 const rightInputViewType _rightInput;
63 const bool _hasField, _isCrossProd3D;
65 KOKKOS_INLINE_FUNCTION
67 leftInputViewType leftInput_,
68 rightInputViewType rightInput_,
70 const bool isCrossProd3D_)
71 : _output(output_), _leftInput(leftInput_), _rightInput(rightInput_),
72 _hasField(hasField_), _isCrossProd3D(isCrossProd3D_) {}
74 KOKKOS_INLINE_FUNCTION
75 void operator()(
const size_type iter)
const {
76 size_type cell, field(0), point;
77 size_type rightRank = _rightInput.rank();
80 unrollIndex( cell, field, point,
86 unrollIndex( cell, point,
91 auto result = ( _hasField ? Kokkos::subview(_output, cell, field, point, Kokkos::ALL()) :
92 Kokkos::subview(_output, cell, point, Kokkos::ALL()));
94 auto left = Kokkos::subview(_leftInput, cell, point, Kokkos::ALL());
96 auto right = (rightRank == 2 + size_type(_hasField)) ?
97 ( _hasField ? Kokkos::subview(_rightInput, field, point, Kokkos::ALL()) :
98 Kokkos::subview(_rightInput, point, Kokkos::ALL())) :
99 ( _hasField ? Kokkos::subview(_rightInput, cell, field, point, Kokkos::ALL()) :
100 Kokkos::subview(_rightInput, cell, point, Kokkos::ALL()));
103 if (_isCrossProd3D) {
104 result(0) = left(1)*right(2) - left(2)*right(1);
105 result(1) = left(2)*right(0) - left(0)*right(2);
106 result(2) = left(0)*right(1) - left(1)*right(0);
108 result(0) = left(0)*right(1) - left(1)*right(0);
114 template<
typename SpT>
115 template<
typename outputValueType,
class ...outputProperties,
116 typename leftInputValueType,
class ...leftInputProperties,
117 typename rightInputValueType,
class ...rightInputProperties>
120 crossProduct( Kokkos::DynRankView<outputValueType, outputProperties...> output,
121 const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInput,
122 const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInput,
123 const bool hasField ) {
125 typedef Kokkos::DynRankView<outputValueType, outputProperties...> OutputViewType;
126 typedef const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInputViewType;
127 typedef const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInputViewType;
129 typedef typename ExecSpace< typename rightInputViewType::execution_space , SpT >::ExecSpaceType ExecSpaceType;
131 const size_type loopSize = ( hasField ? output.extent(0)*output.extent(1)*output.extent(2) :
132 output.extent(0)*output.extent(1) );
133 const bool isCrossProd3D = (leftInput.extent(2) == 3);
134 Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
135 Kokkos::parallel_for( policy, FunctorType(output, leftInput, rightInput, hasField, isCrossProd3D) );
140 template<
typename ExecSpaceType>
141 template<
typename outputFieldValueType,
class ...outputFieldProperties,
142 typename inputDataValueType,
class ...inputDataProperties,
143 typename inputFieldValueType,
class ...inputFieldProperties>
147 const Kokkos::DynRankView<inputDataValueType, inputDataProperties...> inputData,
148 const Kokkos::DynRankView<inputFieldValueType, inputFieldProperties...> inputFields ) {
150 #ifdef HAVE_INTREPID2_DEBUG
159 INTREPID2_TEST_FOR_EXCEPTION( inputData.rank() != 3, std::invalid_argument,
160 ">>> ERROR (ArrayTools::crossProductDataField): inputData must have rank 3");
161 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(2) < 2 || inputData.extent(2) > 3, std::invalid_argument,
162 ">>> ERROR (ArrayTools::crossProductDataField): inputData dimension(2) must be 2 or 3");
165 INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() < 3 || inputFields.rank() > 4, std::invalid_argument,
166 ">>> ERROR (ArrayTools::crossProductDataField): inputFields must have rank 3 or 4" );
167 INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(inputFields.rank()-1) < 2 ||
168 inputFields.extent(inputFields.rank()-1) > 3, std::invalid_argument,
169 ">>> ERROR (ArrayTools::crossProductDataField): inputFields dimension (rank-1) must have rank 2 or 3" );
172 INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != inputData.extent(2)+1, std::invalid_argument,
173 ">>> ERROR (ArrayTools::crossProductDataField): outputFields rank must match to inputData dimension(2)+1");
182 if (inputFields.rank() == 4) {
184 const size_type f1[] = { 0, 1, 2 }, f2[] = { 0, 2, 3 };
185 for (size_type i=0; i<3; ++i) {
186 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
187 ">>> ERROR (ArrayTools::crossProductDataField): inputData dimension does not match with inputFields");
191 const size_type f1[] = { 1, 2 }, f2[] = { 1, 2 };
192 for (size_type i=0; i<2; ++i) {
193 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
194 ">>> ERROR (ArrayTools::crossProductDataField): inputData dimension does not match with inputFields");
200 if (inputData.extent(2) == 2) {
203 const size_type f1[] = { 0, 2 }, f2[] = { 0, 1 };
204 for (size_type i=0; i<2; ++i) {
205 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
206 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputData");
210 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 1, 2 };
211 for (size_type i=0; i<3; ++i) {
212 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
213 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputData");
219 if (inputData.extent(2) == 2) {
221 if (inputFields.rank() == 4) {
223 const size_type f1[] = { 0, 1, 2 }, f2[] = { 0, 1, 2 };
224 for (size_type i=0; i<3; ++i) {
225 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
226 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputFields");
230 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
231 for (size_type i=0; i<2; ++i) {
232 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
233 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputFields");
238 if (inputFields.rank() == 4) {
240 for (size_type i=0; i<outputFields.rank(); ++i) {
241 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(i) != inputFields.extent(i), std::invalid_argument,
242 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputFields");
246 const size_type f1[] = { 1, 2, 3 }, f2[] = { 0, 1, 2 };
247 for (size_type i=0; i<3; ++i) {
248 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
249 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputFields");
263 template<
typename ExecSpaceType>
264 template<
typename outputDataValueType,
class ...outputDataProperties,
265 typename inputDataLeftValueType,
class ...inputDataLeftProperties,
266 typename inputDataRightValueType,
class ...inputDataRightProperties>
270 const Kokkos::DynRankView<inputDataLeftValueType, inputDataLeftProperties...> inputDataLeft,
271 const Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRight ) {
273 #ifdef HAVE_INTREPID2_DEBUG
282 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.rank() != 3, std::invalid_argument,
283 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft must have rank 3");
284 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(2) < 2 || inputDataLeft.extent(2) > 3, std::invalid_argument,
285 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft dimension(2) must be 2 or 3");
288 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() < 2 || inputDataRight.rank() > 3, std::invalid_argument,
289 ">>> ERROR (ArrayTools::crossProductDataData): inputDataRight must have rank 2 or 3" );
290 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(inputDataRight.rank()-1) < 2 ||
291 inputDataRight.extent(inputDataRight.rank()-1) > 3, std::invalid_argument,
292 ">>> ERROR (ArrayTools::crossProductDataData): inputDataRight dimension (rank-1) must have rank 2 or 3" );
295 INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != inputDataLeft.extent(2), std::invalid_argument,
296 ">>> ERROR (ArrayTools::crossProductDataData): outputData rank must match to inputDataLeft dimension(2)");
305 if (inputDataRight.rank() == 3) {
307 for (size_type i=0; i<inputDataLeft.rank(); ++i) {
308 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(i) != inputDataRight.extent(i), std::invalid_argument,
309 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft dimension does not match to inputDataRight");
314 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
315 for (size_type i=0; i<2; ++i) {
316 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
317 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft dimension does not match to inputDataRight");
323 if (inputDataLeft.extent(2) == 2) {
325 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
326 for (size_type i=0; i<2; ++i) {
327 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != outputData.extent(f2[i]), std::invalid_argument,
328 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft dimension does not match to outputData");
332 for (size_type i=0; i<inputDataLeft.rank(); ++i) {
333 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(i) != outputData.extent(i), std::invalid_argument,
334 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft dimension does not match to outputData");
340 if (inputDataLeft.extent(2) == 2) {
342 if (inputDataRight.rank() == 3) {
344 const size_type f1[] = { 0, 1 }, f2[] = { 0, 1 };
345 for (size_type i=0; i<2; ++i) {
346 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
347 ">>> ERROR (ArrayTools::crossProductDataData): outputData dimension does not match to inputDataRight");
351 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(1) != inputDataRight.extent(0), std::invalid_argument,
352 ">>> ERROR (ArrayTools::crossProductDataData): outputData dimension does not match to inputDataRight");
356 if (inputDataRight.rank() == 3) {
358 for (size_type i=0; i<outputData.rank(); ++i) {
359 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(i) != inputDataRight.extent(i), std::invalid_argument,
360 ">>> ERROR (ArrayTools::crossProductDataData): outputData dimension does not match to inputDataRight");
364 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
365 for (size_type i=0; i<2; ++i) {
366 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
367 ">>> ERROR (ArrayTools::crossProductDataData): outputData dimension does not match to inputDataRight");
381 namespace FunctorArrayTools {
385 template <
typename OutputViewType,
typename leftInputViewType,
typename rightInputViewType >
387 OutputViewType _output;
388 const leftInputViewType _leftInput;
389 const rightInputViewType _rightInput;
390 const bool _hasField;
392 KOKKOS_INLINE_FUNCTION
394 leftInputViewType leftInput_,
395 rightInputViewType rightInput_,
396 const bool hasField_)
397 : _output(output_), _leftInput(leftInput_), _rightInput(rightInput_),
398 _hasField(hasField_) {}
400 KOKKOS_INLINE_FUNCTION
401 void operator()(
const size_type iter)
const {
402 size_type cell, field(0), point;
403 size_type rightRank = _rightInput.rank();
406 unrollIndex( cell, field, point,
412 unrollIndex( cell, point,
417 auto result = ( _hasField ? Kokkos::subview(_output, cell, field, point, Kokkos::ALL(), Kokkos::ALL()) :
418 Kokkos::subview(_output, cell, point, Kokkos::ALL(), Kokkos::ALL()));
420 auto left = Kokkos::subview(_leftInput, cell, point, Kokkos::ALL());
422 auto right = (rightRank == 2 + size_type(_hasField)) ?
423 ( _hasField ? Kokkos::subview(_rightInput, field, point, Kokkos::ALL()) :
424 Kokkos::subview(_rightInput, point, Kokkos::ALL())) :
425 ( _hasField ? Kokkos::subview(_rightInput, cell, field, point, Kokkos::ALL()) :
426 Kokkos::subview(_rightInput, cell, point, Kokkos::ALL()));
428 const ordinal_type iend = result.extent(0);
429 const ordinal_type jend = result.extent(1);
430 for (ordinal_type i=0; i<iend; ++i)
431 for (ordinal_type j=0; j<jend; ++j)
432 result(i, j) = left(i)*right(j);
437 template<
typename SpT>
438 template<
typename outputValueType,
class ...outputProperties,
439 typename leftInputValueType,
class ...leftInputProperties,
440 typename rightInputValueType,
class ...rightInputProperties>
443 outerProduct( Kokkos::DynRankView<outputValueType, outputProperties...> output,
444 const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInput,
445 const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInput,
446 const bool hasField ) {
448 typedef Kokkos::DynRankView<outputValueType, outputProperties...> OutputViewType;
449 typedef const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInputViewType;
450 typedef const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInputViewType;
452 typedef typename ExecSpace< typename leftInputViewType::execution_space , SpT >::ExecSpaceType ExecSpaceType;
454 const size_type loopSize = ( hasField ? output.extent(0)*output.extent(1)*output.extent(2) :
455 output.extent(0)*output.extent(1) );
456 Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
457 Kokkos::parallel_for( policy, FunctorType(output, leftInput, rightInput, hasField) );
461 template<
typename ExecSpaceType>
462 template<
typename outputFieldValueType,
class ...outputFieldProperties,
463 typename inputDataValueType,
class ...inputDataProperties,
464 typename inputFieldValueType,
class ...inputFieldProperties>
468 const Kokkos::DynRankView<inputDataValueType, inputDataProperties...> inputData,
469 const Kokkos::DynRankView<inputFieldValueType, inputFieldProperties...> inputFields ) {
471 #ifdef HAVE_INTREPID2_DEBUG
480 INTREPID2_TEST_FOR_EXCEPTION( inputData.rank() != 3, std::invalid_argument,
481 ">>> ERROR (ArrayTools::outerProductDataField): inputData must have rank 3");
482 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(2) < 2 || inputData.extent(2) > 3, std::invalid_argument,
483 ">>> ERROR (ArrayTools::outerProductDataField): inputData dimension(2) must be 2 or 3");
486 INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() < 3 || inputFields.rank() > 4, std::invalid_argument,
487 ">>> ERROR (ArrayTools::outerProductDataField): inputFields must have rank 3 or 4" );
488 INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(inputFields.rank()-1) < 2 ||
489 inputFields.extent(inputFields.rank()-1) < 3, std::invalid_argument,
490 ">>> ERROR (ArrayTools::outerProductDataField): inputFields dimension (rank-1) must have rank 2 or 3" );
493 INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != 5, std::invalid_argument,
494 ">>> ERROR (ArrayTools::outerProductDataField): outputFields must have rank 5");
495 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(3) < 2 ||
496 outputFields.extent(3) > 3, std::invalid_argument,
497 ">>> ERROR (ArrayTools::outerProductDataField): outputFields dimension(3) must be 2 or 3");
498 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(4) < 2 ||
499 outputFields.extent(4) > 3, std::invalid_argument,
500 ">>> ERROR (ArrayTools::outerProductDataField): outputFields dimension(4) must be 2 or 3");
511 const size_type f1[] = { 0, 2, 3, 4 }, f2[] = { 0, 1, 2, 2 };
512 for (size_type i=0; i<4; ++i) {
513 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
514 ">>> ERROR (ArrayTools::outerProductDataField): outputFields dimension does not match with inputData");
521 if (inputFields.rank() == 4) {
524 const size_type f1[] = { 0, 1, 2 }, f2[] = { 0, 2, 3 };
525 for (size_type i=0; i<3; ++i) {
526 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
527 ">>> ERROR (ArrayTools::outerProductDataField): inputData dimension does not match with inputFields");
533 const size_type f1[] = { 0, 1, 2, 3, 4 }, f2[] = { 0, 1, 2, 3, 3 };
534 for (size_type i=0; i<5; ++i) {
535 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
536 ">>> ERROR (ArrayTools::outerProductDataField): outputFields dimension does not match with inputFields");
542 const size_type f1[] = { 1, 2 }, f2[] = { 1, 2 };
543 for (size_type i=0; i<2; ++i) {
544 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
545 ">>> ERROR (ArrayTools::outerProductDataField): inputData dimension does not match with inputFields");
551 const size_type f1[] = { 1, 2, 3, 4 }, f2[] = { 0, 1, 2, 2 };
552 for (size_type i=0; i<4; ++i) {
553 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
554 ">>> ERROR (ArrayTools::outerProductDataField): outputFields dimension does not match with inputFields");
568 template<
typename ExecSpaceType>
569 template<
typename outputDataValueType,
class ...outputDataProperties,
570 typename inputDataLeftValuetype,
class ...inputDataLeftProperties,
571 typename inputDataRightValueType,
class ...inputDataRightProperties>
575 const Kokkos::DynRankView<inputDataLeftValuetype, inputDataLeftProperties...> inputDataLeft,
576 const Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRight ) {
578 #ifdef HAVE_INTREPID2_DEBUG
587 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.rank() != 3, std::invalid_argument,
588 ">>> ERROR (ArrayTools::outerProductDataField): inputDataLeft must have rank 3");
589 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(2) < 2 || inputDataLeft.extent(2) > 3, std::invalid_argument,
590 ">>> ERROR (ArrayTools::outerProductDataField): inputDataLeft dimension(2) must be 2 or 3");
593 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() < 2 || inputDataRight.rank() > 3, std::invalid_argument,
594 ">>> ERROR (ArrayTools::outerProductDataField): inputDataRight must have rank 2 or 3" );
595 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(inputDataRight.rank()-1) < 2 ||
596 inputDataRight.extent(inputDataRight.rank()-1) < 3, std::invalid_argument,
597 ">>> ERROR (ArrayTools::outerProductDataField): inputDataRight dimension (rank-1) must have rank 2 or 3" );
600 INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != 4, std::invalid_argument,
601 ">>> ERROR (ArrayTools::outerProductDataField): outputData must have rank 5");
602 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(2) < 2 ||
603 outputData.extent(2) > 3, std::invalid_argument,
604 ">>> ERROR (ArrayTools::outerProductDataField): outputData dimension(3) must be 2 or 3");
605 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(3) < 2 ||
606 outputData.extent(3) > 3, std::invalid_argument,
607 ">>> ERROR (ArrayTools::outerProductDataField): outputData dimension(4) must be 2 or 3");
618 const size_type f1[] = { 0, 1, 2, 3 }, f2[] = { 0, 1, 2, 2 };
619 for (size_type i=0; i<4; ++i) {
620 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataLeft.extent(f2[i]), std::invalid_argument,
621 ">>> ERROR (ArrayTools::outerProductDataField): outputData dimension does not match with inputDataLeft");
628 if (inputDataRight.rank() == 3) {
630 for (size_type i=0; i<inputDataLeft.rank(); ++i) {
631 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(i) != inputDataRight.extent(i), std::invalid_argument,
632 ">>> ERROR (ArrayTools::outerProductDataField): inputDataLeft dimension does not match with inputDataRight");
637 const size_type f1[] = { 0, 1, 2, 3 }, f2[] = { 0, 1, 2, 2 };
638 for (size_type i=0; i<4; ++i) {
639 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
640 ">>> ERROR (ArrayTools::outerProductDataField): outputData dimension does not match with inputDataRight");
646 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
647 for (size_type i=0; i<2; ++i) {
648 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
649 ">>> ERROR (ArrayTools::outerProductDataField): inputDataLeft dimension does not match with inputDataRight");
655 const size_type f1[] = { 1, 2, 3 }, f2[] = { 0, 1, 1 };
656 for (size_type i=0; i<3; ++i) {
657 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
658 ">>> ERROR (ArrayTools::outerProductDataField): outputData dimension does not match with inputDataRight");
672 namespace FunctorArrayTools {
676 template <
typename OutputViewType,
677 typename leftInputViewType,
678 typename rightInputViewType>
680 OutputViewType _output;
681 const leftInputViewType _leftInput;
682 const rightInputViewType _rightInput;
684 const bool _isTranspose;
686 KOKKOS_INLINE_FUNCTION
688 leftInputViewType leftInput_,
689 rightInputViewType rightInput_,
690 const bool isTranspose_)
691 : _output(output_), _leftInput(leftInput_), _rightInput(rightInput_), _isTranspose(isTranspose_) {}
693 template<
typename resultViewType,
694 typename leftViewType,
695 typename rightViewType>
696 KOKKOS_FORCEINLINE_FUNCTION
698 apply_matvec_product( resultViewType &result,
699 const leftViewType &left,
700 const rightViewType &right,
701 const bool isTranspose) {
702 const ordinal_type iend = result.extent(0);
703 const ordinal_type jend = right.extent(0);
705 typedef typename resultViewType::value_type value_type;
707 switch (left.rank()) {
710 for (ordinal_type i=0;i<iend;++i) {
712 for (ordinal_type j=0;j<jend;++j)
713 tmp += left(j, i)*right(j);
717 for (ordinal_type i=0;i<iend;++i) {
719 for (ordinal_type j=0;j<jend;++j)
720 tmp += left(i, j)*right(j);
726 for (ordinal_type i=0;i<iend;++i)
727 result(i) = left(i)*right(i);
731 const value_type val = left();
732 for (ordinal_type i=0;i<iend;++i) {
733 result(i) = val*right(i);
740 KOKKOS_INLINE_FUNCTION
741 void operator()(
const ordinal_type cl,
742 const ordinal_type pt)
const {
743 const auto rightRank = _rightInput.rank();
744 const auto leftRank = _leftInput.rank();
746 auto result = Kokkos::subview(_output, cl, pt, Kokkos::ALL());
748 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
749 const auto left = ( leftRank == 4 ? Kokkos::subview(_leftInput, cl, lpt, Kokkos::ALL(), Kokkos::ALL()) :
750 leftRank == 3 ? Kokkos::subview(_leftInput, cl, lpt, Kokkos::ALL()) :
751 Kokkos::subview(_leftInput, cl, lpt));
753 const auto right = ( rightRank == 2 ? Kokkos::subview(_rightInput, pt, Kokkos::ALL()) :
754 Kokkos::subview(_rightInput, cl, pt, Kokkos::ALL()) );
755 apply_matvec_product( result, left, right, _isTranspose );
758 KOKKOS_INLINE_FUNCTION
759 void operator()(
const ordinal_type cl,
760 const ordinal_type bf,
761 const ordinal_type pt)
const {
762 const auto rightRank = _rightInput.rank();
763 const auto leftRank = _leftInput.rank();
765 auto result = Kokkos::subview(_output, cl, bf, pt, Kokkos::ALL());
767 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
768 const auto left = ( leftRank == 4 ? Kokkos::subview(_leftInput, cl, lpt, Kokkos::ALL(), Kokkos::ALL()) :
769 leftRank == 3 ? Kokkos::subview(_leftInput, cl, lpt, Kokkos::ALL()) :
770 Kokkos::subview(_leftInput, cl, lpt));
772 const auto right = ( rightRank == 3 ? Kokkos::subview(_rightInput, bf, pt, Kokkos::ALL()) :
773 Kokkos::subview(_rightInput, cl, bf, pt, Kokkos::ALL()));
775 apply_matvec_product( result, left, right, _isTranspose );
780 template<
typename SpT>
781 template<
typename outputValueType,
class ...outputProperties,
782 typename leftInputValueType,
class ...leftInputProperties,
783 typename rightInputValueType,
class ...rightInputProperties>
786 matvecProduct( Kokkos::DynRankView<outputValueType, outputProperties...> output,
787 const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInput,
788 const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInput,
790 const bool isTranspose ) {
792 typedef Kokkos::DynRankView<outputValueType, outputProperties...> OutputViewType;
793 typedef const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInputViewType;
794 typedef const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInputViewType;
796 typedef typename ExecSpace< typename leftInputViewType::execution_space , SpT >::ExecSpaceType ExecSpaceType;
799 using range_policy_type = Kokkos::Experimental::MDRangePolicy
800 < ExecSpaceType, Kokkos::Experimental::Rank<3>, Kokkos::IndexType<ordinal_type> >;
801 range_policy_type policy( { 0, 0, 0 },
802 { output.extent(0), output.extent(1), output.extent(2) } );
803 Kokkos::parallel_for( policy, FunctorType(output, leftInput, rightInput, isTranspose) );
805 using range_policy_type = Kokkos::Experimental::MDRangePolicy
806 < ExecSpaceType, Kokkos::Experimental::Rank<2>, Kokkos::IndexType<ordinal_type> >;
807 range_policy_type policy( { 0, 0 },
808 { output.extent(0), output.extent(1) } );
809 Kokkos::parallel_for( policy, FunctorType(output, leftInput, rightInput, isTranspose) );
813 template<
typename ExecSpaceType>
814 template<
typename outputFieldValueType,
class ...outputFieldProperties,
815 typename inputDataValueType,
class ...inputDataProperties,
816 typename inputFieldValueType,
class ...inputFieldProperties>
819 const Kokkos::DynRankView<inputDataValueType, inputDataProperties...> inputData,
820 const Kokkos::DynRankView<inputFieldValueType, inputFieldProperties...> inputFields,
821 const char transpose ) {
823 #ifdef HAVE_INTREPID2_DEBUG
832 INTREPID2_TEST_FOR_EXCEPTION( inputData.rank() < 2 || inputData.rank() > 4, std::invalid_argument,
833 ">>> ERROR (ArrayTools::matvecProductDataField): inputData must have rank 2,3 or 4" );
834 if (inputData.rank() > 2) {
835 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(2) < 1 ||
836 inputData.extent(2) > 3, std::invalid_argument,
837 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension(2) must be 1,2 or 3");
839 if (inputData.rank() == 4) {
840 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(3) < 1 ||
841 inputData.extent(3) > 3, std::invalid_argument,
842 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension(3) must be 1,2 or 3");
846 INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() < 3 ||
847 inputFields.rank() > 4, std::invalid_argument,
848 ">>> ERROR (ArrayTools::matvecProductDataField): inputFields must have rank 3 or 4" );
849 INTREPID2_TEST_FOR_EXCEPTION( (inputFields.rank()-1) < 1 ||
850 (inputFields.rank()-1) > 3, std::invalid_argument,
851 ">>> ERROR (ArrayTools::matvecProductDataField): inputFields dimension(rank-1) must be 1,2, or 3" );
854 INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != 4, std::invalid_argument,
855 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields must have rank 4" );
856 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(3) < 1 ||
857 outputFields.extent(3) > 3, std::invalid_argument,
858 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension(3) must be 1,2 or 3" );
871 if (inputData.extent(1) > 1) {
872 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(2) != inputData.extent(1), std::invalid_argument,
873 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension(2) must match to inputData dimension(1)" );
875 if (inputData.rank() == 2) {
876 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(0) != inputData.extent(0), std::invalid_argument,
877 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension(0) must match to inputData dimension(0)" );
879 if (inputData.rank() == 3) {
880 const size_type f1[] = { 0, 3 }, f2[] = { 0, 2 };
881 for (size_type i=0; i<2; ++i) {
882 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
883 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension does not match to inputData dimension" );
886 if (inputData.rank() == 4) {
887 const size_type f1[] = { 0, 3, 3 }, f2[] = { 0, 2, 3 };
888 for (size_type i=0; i<3; ++i) {
889 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
890 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension does not match to inputData dimension" );
897 if (inputFields.rank() == 4) {
899 if (inputData.extent(1) > 1) {
900 INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(2) != inputData.extent(1), std::invalid_argument,
901 ">>> ERROR (ArrayTools::matvecProductDataField): inputFields dimension (2) does not match to inputData dimension (1)" );
903 if (inputData.rank() == 2) {
904 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(0) != inputFields.extent(0), std::invalid_argument,
905 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension (0) does not match to inputFields dimension (0)" );
907 if (inputData.rank() == 3) {
908 const size_type f1[] = { 0, 2 }, f2[] = { 0, 3 };
909 for (size_type i=0; i<2; ++i) {
910 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
911 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension does not match to inputFields dimension" );
914 if (inputData.rank() == 4) {
915 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 3, 3 };
916 for (size_type i=0; i<3; ++i) {
917 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
918 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension does not match to inputFields dimension" );
923 for (size_type i=0; i<outputFields.rank(); ++i) {
924 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(i) != inputFields.extent(i), std::invalid_argument,
925 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension does not match to inputFields dimension" );
929 if (inputData.extent(1) > 1) {
930 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(1) != inputFields.extent(1), std::invalid_argument,
931 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension(1) does not match to inputFields dimension (1)" );
933 if (inputData.rank() == 3) {
934 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(2) != inputFields.extent(2), std::invalid_argument,
935 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension(2) does not match to inputFields dimension (2)" );
937 if (inputData.rank() == 4) {
938 const size_type f1[] = { 2, 3 }, f2[] = { 2, 2 };
939 for (size_type i=0; i<2; ++i) {
940 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
941 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension does not match to inputFields dimension" );
947 const size_type f1[] = { 1, 2, 3 }, f2[] = { 0, 1, 2 };
948 for (size_type i=0; i<3; ++i) {
949 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
950 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension does not match to inputFields dimension" );
961 transpose ==
't' || transpose ==
'T' );
966 template<
typename ExecSpaceType>
967 template<
typename outputDataValueType,
class ...outputDataProperties,
968 typename inputDataLeftValueType,
class ...inputDataLeftProperties,
969 typename inputDataRightValueType,
class ...inputDataRightProperties>
973 const Kokkos::DynRankView<inputDataLeftValueType, inputDataLeftProperties...> inputDataLeft,
974 const Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRight,
975 const char transpose ) {
977 #ifdef HAVE_INTREPID2_DEBUG
986 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.rank() < 2 ||
987 inputDataLeft.rank() > 4, std::invalid_argument,
988 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft must have rank 2,3 or 4" );
990 if (inputDataLeft.rank() > 2) {
991 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(2) < 1 ||
992 inputDataLeft.extent(2) > 3, std::invalid_argument,
993 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension(2) must be 1, 2 or 3");
995 if (inputDataLeft.rank() == 4) {
996 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(3) < 1 ||
997 inputDataLeft.extent(3) > 3, std::invalid_argument,
998 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension(3) must be 1, 2 or 3");
1002 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() < 2 ||
1003 inputDataRight.rank() > 3, std::invalid_argument,
1004 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataRight must have rank 2 or 3" );
1005 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(inputDataRight.rank()-1) < 1 ||
1006 inputDataRight.extent(inputDataRight.rank()-1) > 3, std::invalid_argument,
1007 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataRight dimension (rank-1) must be 1,2 or 3" );
1010 INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != 3, std::invalid_argument,
1011 ">>> ERROR (ArrayTools::matvecProductDataData): outputData must have rank 3" );
1012 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(2) < 1 ||
1013 outputData.extent(2) > 3, std::invalid_argument,
1014 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension(2) must be 1, 2 or 3");
1027 if (inputDataLeft.extent(1) > 1) {
1028 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(1) != inputDataLeft.extent(1), std::invalid_argument,
1029 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension(1) muat match inputDataLeft dimension(1)" );
1031 if (inputDataLeft.rank() == 2) {
1032 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(0) != inputDataLeft.extent(0), std::invalid_argument,
1033 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension(0) muat match inputDataLeft dimension(0)" );
1035 if (inputDataLeft.rank() == 3) {
1036 const size_type f1[] = { 0, 2 }, f2[] = { 0, 2 };
1037 for (size_type i=0; i<2; ++i) {
1038 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataLeft.extent(f2[i]), std::invalid_argument,
1039 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension muat match inputDataLeft dimension" );
1042 if (inputDataLeft.rank() == 4) {
1043 const size_type f1[] = { 0, 2, 2 }, f2[] = { 0, 2, 3 };
1044 for (size_type i=0; i<3; ++i) {
1045 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataLeft.extent(f2[i]), std::invalid_argument,
1046 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension muat match inputDataLeft dimension" );
1053 if (inputDataRight.rank() == 3) {
1055 if (inputDataLeft.extent(1) > 1) {
1056 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(1), std::invalid_argument,
1057 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension (1) muat match to inputDataRight dimension (1)" );
1059 if (inputDataLeft.rank() == 2) {
1060 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(0) != inputDataRight.extent(0), std::invalid_argument,
1061 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension (0) muat match to inputDataRight dimension (0)" );
1063 if (inputDataLeft.rank() == 3) {
1064 const size_type f1[] = { 0, 2 }, f2[] = { 0, 2 };
1065 for (size_type i=0; i<2; ++i) {
1066 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1067 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension muat match to inputDataRight dimension" );
1070 if (inputDataLeft.rank() == 4) {
1071 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 2, 2 };
1072 for (size_type i=0; i<3; ++i) {
1073 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1074 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension muat match to inputDataRight dimension" );
1079 for (size_type i=0; i<outputData.rank(); ++i) {
1080 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(i) != inputDataRight.extent(i), std::invalid_argument,
1081 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension muat match to inputDataRight dimension" );
1085 if (inputDataLeft.extent(1) > 1) {
1086 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(0), std::invalid_argument,
1087 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension (1) does mot match to inputDataright dimension (0)" );
1089 if (inputDataLeft.rank() == 3) {
1090 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(2) != inputDataRight.extent(1), std::invalid_argument,
1091 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension (2) does mot match to inputDataright dimension (1)" );
1093 if (inputDataLeft.rank() == 4) {
1094 const size_type f1[] = { 2, 3 }, f2[] = { 1, 1 };
1095 for (size_type i=0; i<2; ++i) {
1096 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1097 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension muat match to inputDataRight dimension" );
1103 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
1104 for (size_type i=0; i<2; ++i) {
1105 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1106 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension muat match to inputDataRight dimension" );
1117 transpose ==
't' || transpose ==
'T' );
1121 namespace FunctorArrayTools {
1125 template <
typename OutputViewType,
typename leftInputViewType,
typename rightInputViewType >
1127 OutputViewType _output;
1128 leftInputViewType _leftInput;
1129 rightInputViewType _rightInput;
1130 const bool _hasField, _isTranspose;
1131 typedef typename leftInputViewType::value_type value_type;
1133 KOKKOS_INLINE_FUNCTION
1135 leftInputViewType leftInput_,
1136 rightInputViewType rightInput_,
1137 const bool hasField_,
1138 const bool isTranspose_)
1139 : _output(output_), _leftInput(leftInput_), _rightInput(rightInput_),
1140 _hasField(hasField_), _isTranspose(isTranspose_) {}
1142 KOKKOS_INLINE_FUNCTION
1143 void operator()(
const size_type iter)
const {
1144 size_type cell(0), field(0), point(0);
1145 size_type leftRank = _leftInput.rank();
1146 size_type rightRank = _rightInput.rank();
1149 unrollIndex( cell, field, point,
1155 unrollIndex( cell, point,
1160 auto result = ( _hasField ? Kokkos::subview(_output, cell, field, point, Kokkos::ALL(), Kokkos::ALL()) :
1161 Kokkos::subview(_output, cell, point, Kokkos::ALL(), Kokkos::ALL()));
1163 const auto lpoint = (_leftInput.extent(1) == 1 ? 0 : point);
1164 auto left = ( leftRank == 4 ? Kokkos::subview(_leftInput, cell, lpoint, Kokkos::ALL(), Kokkos::ALL()) :
1165 leftRank == 3 ? Kokkos::subview(_leftInput, cell, lpoint, Kokkos::ALL()) :
1166 Kokkos::subview(_leftInput, cell, lpoint) );
1169 const bool hasCell = (_hasField ? rightRank == 5 : rightRank == 4);
1170 auto right = ( _hasField ? ( hasCell ? Kokkos::subview(_rightInput, cell, field, point, Kokkos::ALL(), Kokkos::ALL()) :
1171 Kokkos::subview(_rightInput, field, point, Kokkos::ALL(), Kokkos::ALL())):
1172 ( hasCell ? Kokkos::subview(_rightInput, cell, point, Kokkos::ALL(), Kokkos::ALL()) :
1173 Kokkos::subview(_rightInput, point, Kokkos::ALL(), Kokkos::ALL())));
1175 const ordinal_type iend = result.extent(0);
1176 const ordinal_type jend = result.extent(1);
1181 const size_type kend = right.extent(0);
1182 for (ordinal_type i=0; i<iend; ++i)
1183 for (ordinal_type j=0; j<jend; ++j) {
1184 result(i, j) = value_type(0);
1185 for (size_type k=0; k<kend; ++k)
1186 result(i, j) += left(k, i) * right(k, j);
1189 const size_type kend = right.extent(0);
1190 for (ordinal_type i=0; i<iend; ++i)
1191 for (ordinal_type j=0; j<jend; ++j) {
1192 result(i, j) = value_type(0);
1193 for (size_type k=0; k<kend; ++k)
1194 result(i, j) += left(i, k) * right(k, j);
1200 for (ordinal_type i=0; i<iend; ++i)
1201 for (ordinal_type j=0; j<jend; ++j)
1202 result(i, j) = left(i) * right(i, j);
1206 for (ordinal_type i=0; i<iend; ++i)
1207 for (ordinal_type j=0; j<jend; ++j)
1208 result(i, j) = left() * right(i, j);
1216 template<
typename SpT>
1217 template<
typename outputValueType,
class ...outputProperties,
1218 typename leftInputValueType,
class ...leftInputProperties,
1219 typename rightInputValueType,
class ...rightInputProperties>
1222 matmatProduct( Kokkos::DynRankView<outputValueType, outputProperties...> output,
1223 const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInput,
1224 const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInput,
1225 const bool hasField,
1226 const bool isTranspose ) {
1228 typedef Kokkos::DynRankView<outputValueType, outputProperties...> OutputViewType;
1229 typedef const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInputViewType;
1230 typedef const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInputViewType;
1232 typedef typename ExecSpace< typename leftInputViewType::execution_space , SpT >::ExecSpaceType ExecSpaceType;
1234 const size_type loopSize = ( hasField ? output.extent(0)*output.extent(1)*output.extent(2) :
1235 output.extent(0)*output.extent(1) );
1236 Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
1237 Kokkos::parallel_for( policy, FunctorType(output, leftInput, rightInput, hasField, isTranspose) );
1243 template<
typename ExecSpaceType>
1244 template<
typename outputFieldValueType,
class ...outputFieldProperties,
1245 typename inputDataValueType,
class ...inputDataProperties,
1246 typename inputFieldValueType,
class ...inputFieldProperties>
1250 const Kokkos::DynRankView<inputDataValueType, inputDataProperties...> inputData,
1251 const Kokkos::DynRankView<inputFieldValueType, inputFieldProperties...> inputFields,
1252 const char transpose ) {
1254 #ifdef HAVE_INTREPID2_DEBUG
1263 INTREPID2_TEST_FOR_EXCEPTION( inputData.rank() < 2 ||
1264 inputData.rank() > 4, std::invalid_argument,
1265 ">>> ERROR (ArrayTools::matmatProductDataField): inputData must have rank 2,3 or 4" );
1266 if (inputData.rank() > 2) {
1267 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(2) < 1 ||
1268 inputData.extent(2) > 3, std::invalid_argument,
1269 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension (2) must be 1,2 or 3" );
1271 if (inputData.rank() == 4) {
1272 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(3) < 1 ||
1273 inputData.extent(3) > 3, std::invalid_argument,
1274 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension (3) must be 1,2 or 3" );
1278 INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() < 4 ||
1279 inputFields.rank() > 5, std::invalid_argument,
1280 ">>> ERROR (ArrayTools::matmatProductDataField): inputFields must have rank 4 or 5");
1281 INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(inputFields.rank()-1) < 1 ||
1282 inputFields.extent(inputFields.rank()-1) > 3, std::invalid_argument,
1283 ">>> ERROR (ArrayTools::matmatProductDataField): inputFields dimension (rank-1) must be 1,2 or 3" );
1284 INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(inputFields.rank()-2) < 1 ||
1285 inputFields.extent(inputFields.rank()-2) > 3, std::invalid_argument,
1286 ">>> ERROR (ArrayTools::matmatProductDataField): inputFields dimension (rank-2) must be 1,2 or 3" );
1289 INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != 5, std::invalid_argument,
1290 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields must have rank 5" );
1291 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(3) < 1 ||
1292 outputFields.extent(3) > 3, std::invalid_argument,
1293 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension (3) must be 1,2 or 3" );
1294 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(4) < 1 ||
1295 outputFields.extent(4) > 3, std::invalid_argument,
1296 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension (4) must be 1,2 or 3" );
1309 if (inputData.extent(1) > 1) {
1310 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(2) != inputData.extent(1), std::invalid_argument,
1311 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension (2) does not match to inputData dimension (1)" );
1313 if (inputData.rank() == 2) {
1314 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(0) != inputData.extent(0), std::invalid_argument,
1315 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension (0) does not match to inputData dimension (0)" );
1317 if (inputData.rank() == 3) {
1318 const size_type f1[] = { 0, 3, 4 }, f2[] = { 0, 2, 2 };
1319 for (size_type i=0; i<3; ++i) {
1320 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
1321 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension does not match to inputData dimension" );
1324 if (inputData.rank() == 4) {
1325 const size_type f1[] = { 0, 3, 4 }, f2[] = { 0, 2, 3 };
1326 for (size_type i=0; i<3; ++i) {
1327 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
1328 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension does not match to inputData dimension" );
1335 if (inputFields.rank() == 5) {
1337 if (inputData.extent(1) > 1) {
1338 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(1) != inputFields.extent(2), std::invalid_argument,
1339 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension (1) does not match to inputFields dimension (2)" );
1341 if (inputData.rank() == 2) {
1342 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(0) != inputFields.extent(0), std::invalid_argument,
1343 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension (0) does not match to inputFields dimension (0)" );
1345 if (inputData.rank() == 3) {
1347 const size_type f1[] = { 0, 2, 2 }, f2[] = { 0, 3, 4 };
1348 for (size_type i=0; i<3; ++i) {
1349 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1350 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension does not match to inputFields dimension" );
1353 if (inputData.rank() == 4) {
1354 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 3, 4 };
1355 for (size_type i=0; i<3; ++i) {
1356 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1357 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension does not match to inputFields dimension" );
1362 for (size_type i=0; i<outputFields.rank(); ++i) {
1363 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(i) != inputFields.extent(i), std::invalid_argument,
1364 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension does not match to inputFields dimension" );
1368 if (inputData.extent(1) > 1) {
1369 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(1) != inputFields.extent(1), std::invalid_argument,
1370 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension (1) does not match to inputFields dimension (1)" );
1372 if (inputData.rank() == 3) {
1373 const size_type f1[] = { 2, 2 }, f2[] = { 2, 3 };
1374 for (size_type i=0; i<2; ++i) {
1375 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1376 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension does not match to inputFields dimension" );
1379 if (inputData.rank() == 4) {
1380 const size_type f1[] = { 2, 3 }, f2[] = { 2, 3 };
1381 for (size_type i=0; i<2; ++i) {
1382 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1383 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension does not match to inputFields dimension" );
1389 const size_type f1[] = { 1, 2, 3, 4 }, f2[] = { 0, 1, 2, 3 };
1390 for (size_type i=0; i<4; ++i) {
1391 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1392 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension does not match to inputFields dimension" );
1403 transpose ==
't' || transpose ==
'T' );
1408 template<
typename ExecSpaceType>
1409 template<
typename outputDataValueType,
class ...outputDataProperties,
1410 typename inputDataLeftValueType,
class ...inputDataLeftProperties,
1411 typename inputDataRightValueType,
class ...inputDataRightProperties>
1414 const Kokkos::DynRankView<inputDataLeftValueType, inputDataLeftProperties...> inputDataLeft,
1415 const Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRight,
1416 const char transpose ) {
1418 #ifdef HAVE_INTREPID2_DEBUG
1427 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.rank() < 2 ||
1428 inputDataLeft.rank() > 4, std::invalid_argument,
1429 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft must have rank 2,3 or 4" );
1430 if (inputDataLeft.rank() > 2) {
1431 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(2) < 1 ||
1432 inputDataLeft.extent(2) > 3, std::invalid_argument,
1433 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft dimension (2) must be 1,2 or 3" );
1435 if (inputDataLeft.rank() == 4) {
1436 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(3) < 1 ||
1437 inputDataLeft.extent(3) > 3, std::invalid_argument,
1438 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft dimension (3) must be 1,2 or 3" );
1442 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() < 3 ||
1443 inputDataRight.rank() > 4, std::invalid_argument,
1444 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataRight must have rank 3 or 4" );
1445 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(inputDataRight.rank()-1) < 1 ||
1446 inputDataRight.extent(inputDataRight.rank()-1) > 3, std::invalid_argument,
1447 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataRight (rank-1) must be 1,2 or 3" );
1448 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(inputDataRight.rank()-2) < 1 ||
1449 inputDataRight.extent(inputDataRight.rank()-2) > 3, std::invalid_argument,
1450 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataRight (rank-2) must be 1,2 or 3" );
1453 INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != 4, std::invalid_argument,
1454 ">>> ERROR (ArrayTools::matmatProductDataData): outputData must have rank 4" );
1455 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(2) < 1 ||
1456 outputData.extent(2) > 3, std::invalid_argument,
1457 ">>> ERROR (ArrayTools::matmatProductDataData): outputData (2) must be 1,2 or 3" );
1458 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(3) < 1 ||
1459 outputData.extent(3) > 3, std::invalid_argument,
1460 ">>> ERROR (ArrayTools::matmatProductDataData): outputData (3) must be 1,2 or 3" );
1473 if (inputDataLeft.extent(1) > 1) {
1474 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(1) != inputDataLeft.extent(1), std::invalid_argument,
1475 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension (1) does not match to inputDataLeft dimension (1)" );
1477 if (inputDataLeft.rank() == 2) {
1478 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(0) != inputDataLeft.extent(0), std::invalid_argument,
1479 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension (0) does not match to inputDataLeft dimension (0)" );
1481 if (inputDataLeft.rank() == 3) {
1482 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 2, 2 };
1483 for (size_type i=0; i<3; ++i) {
1484 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataLeft.extent(f2[i]), std::invalid_argument,
1485 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension does not match to inputDataLeft dimension" );
1488 if (inputDataLeft.rank() == 4) {
1489 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 2, 3 };
1490 for (size_type i=0; i<3; ++i) {
1491 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataLeft.extent(f2[i]), std::invalid_argument,
1492 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension does not match to inputDataLeft dimension" );
1499 if (inputDataRight.rank() == 4) {
1501 if (inputDataLeft.extent(1) > 1) {
1502 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(1), std::invalid_argument,
1503 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft dimension (1) does not match to inputDataRight dimension (1)" );
1505 if (inputDataLeft.rank() == 2) {
1506 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(0) != inputDataRight.extent(0), std::invalid_argument,
1507 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft dimension (0) does not match to inputDataRight dimension (0)" );
1509 if (inputDataLeft.rank() == 3) {
1510 const size_type f1[] = { 0, 2, 2 }, f2[] = { 0, 2, 3 };
1511 for (size_type i=0; i<3; ++i) {
1512 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1513 ">>> ERROR (ArrayTools::matmatProductDataData): intputDataLeft dimension does not match to inputDataRight dimension" );
1516 if (inputDataLeft.rank() == 4) {
1517 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 2, 3 };
1518 for (size_type i=0; i<3; ++i) {
1519 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1520 ">>> ERROR (ArrayTools::matmatProductDataData): intputDataLeft dimension does not match to inputDataRight dimension" );
1525 for (size_type i=0; i< outputData.rank(); ++i) {
1526 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(i) != inputDataRight.extent(i), std::invalid_argument,
1527 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension does not match to inputDataRight dimension" );
1531 if (inputDataLeft.extent(1) > 1) {
1532 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(0), std::invalid_argument,
1533 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft dimension (1) does not match to inputDataRight dimension (0)" );
1535 if (inputDataLeft.rank() == 3) {
1536 const size_type f1[] = { 2, 2 }, f2[] = { 1, 2 };
1537 for (size_type i=0; i<2; ++i) {
1538 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1539 ">>> ERROR (ArrayTools::matmatProductDataData): intputDataLeft dimension does not match to inputDataRight dimension" );
1542 if (inputDataLeft.rank() == 4) {
1543 const size_type f1[] = { 2, 3 }, f2[] = { 1, 2 };
1544 for (size_type i=0; i<2; ++i) {
1545 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1546 ">>> ERROR (ArrayTools::matmatProductDataData): intputDataLeft dimension does not match to inputDataRight dimension" );
1551 const size_type f1[] = { 1, 2, 3 }, f2[] = { 0, 1, 2 };
1552 for (size_type i=0; i<3; ++i) {
1553 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1554 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension does not match to inputDataRight dimension" );
1565 transpose ==
't' || transpose ==
'T' );