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 DeviceType>
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;
130 const size_type loopSize = ( hasField ? output.extent(0)*output.extent(1)*output.extent(2) :
131 output.extent(0)*output.extent(1) );
132 const bool isCrossProd3D = (leftInput.extent(2) == 3);
133 Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
134 Kokkos::parallel_for( policy, FunctorType(output, leftInput, rightInput, hasField, isCrossProd3D) );
139 template<
typename DeviceType>
140 template<
typename outputFieldValueType,
class ...outputFieldProperties,
141 typename inputDataValueType,
class ...inputDataProperties,
142 typename inputFieldValueType,
class ...inputFieldProperties>
146 const Kokkos::DynRankView<inputDataValueType, inputDataProperties...> inputData,
147 const Kokkos::DynRankView<inputFieldValueType, inputFieldProperties...> inputFields ) {
149 #ifdef HAVE_INTREPID2_DEBUG
158 INTREPID2_TEST_FOR_EXCEPTION( inputData.rank() != 3, std::invalid_argument,
159 ">>> ERROR (ArrayTools::crossProductDataField): inputData must have rank 3");
160 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(2) < 2 || inputData.extent(2) > 3, std::invalid_argument,
161 ">>> ERROR (ArrayTools::crossProductDataField): inputData dimension(2) must be 2 or 3");
164 INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() < 3 || inputFields.rank() > 4, std::invalid_argument,
165 ">>> ERROR (ArrayTools::crossProductDataField): inputFields must have rank 3 or 4" );
166 INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(inputFields.rank()-1) < 2 ||
167 inputFields.extent(inputFields.rank()-1) > 3, std::invalid_argument,
168 ">>> ERROR (ArrayTools::crossProductDataField): inputFields dimension (rank-1) must have rank 2 or 3" );
171 INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != inputData.extent(2)+1, std::invalid_argument,
172 ">>> ERROR (ArrayTools::crossProductDataField): outputFields rank must match to inputData dimension(2)+1");
181 if (inputFields.rank() == 4) {
183 const size_type f1[] = { 0, 1, 2 }, f2[] = { 0, 2, 3 };
184 for (size_type i=0; i<3; ++i) {
185 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
186 ">>> ERROR (ArrayTools::crossProductDataField): inputData dimension does not match with inputFields");
190 const size_type f1[] = { 1, 2 }, f2[] = { 1, 2 };
191 for (size_type i=0; i<2; ++i) {
192 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
193 ">>> ERROR (ArrayTools::crossProductDataField): inputData dimension does not match with inputFields");
199 if (inputData.extent(2) == 2) {
202 const size_type f1[] = { 0, 2 }, f2[] = { 0, 1 };
203 for (size_type i=0; i<2; ++i) {
204 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
205 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputData");
209 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 1, 2 };
210 for (size_type i=0; i<3; ++i) {
211 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
212 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputData");
218 if (inputData.extent(2) == 2) {
220 if (inputFields.rank() == 4) {
222 const size_type f1[] = { 0, 1, 2 }, f2[] = { 0, 1, 2 };
223 for (size_type i=0; i<3; ++i) {
224 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
225 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputFields");
229 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
230 for (size_type i=0; i<2; ++i) {
231 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
232 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputFields");
237 if (inputFields.rank() == 4) {
239 for (size_type i=0; i<outputFields.rank(); ++i) {
240 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(i) != inputFields.extent(i), std::invalid_argument,
241 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputFields");
245 const size_type f1[] = { 1, 2, 3 }, f2[] = { 0, 1, 2 };
246 for (size_type i=0; i<3; ++i) {
247 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
248 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputFields");
262 template<
typename DeviceType>
263 template<
typename outputDataValueType,
class ...outputDataProperties,
264 typename inputDataLeftValueType,
class ...inputDataLeftProperties,
265 typename inputDataRightValueType,
class ...inputDataRightProperties>
269 const Kokkos::DynRankView<inputDataLeftValueType, inputDataLeftProperties...> inputDataLeft,
270 const Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRight ) {
272 #ifdef HAVE_INTREPID2_DEBUG
281 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.rank() != 3, std::invalid_argument,
282 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft must have rank 3");
283 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(2) < 2 || inputDataLeft.extent(2) > 3, std::invalid_argument,
284 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft dimension(2) must be 2 or 3");
287 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() < 2 || inputDataRight.rank() > 3, std::invalid_argument,
288 ">>> ERROR (ArrayTools::crossProductDataData): inputDataRight must have rank 2 or 3" );
289 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(inputDataRight.rank()-1) < 2 ||
290 inputDataRight.extent(inputDataRight.rank()-1) > 3, std::invalid_argument,
291 ">>> ERROR (ArrayTools::crossProductDataData): inputDataRight dimension (rank-1) must have rank 2 or 3" );
294 INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != inputDataLeft.extent(2), std::invalid_argument,
295 ">>> ERROR (ArrayTools::crossProductDataData): outputData rank must match to inputDataLeft dimension(2)");
304 if (inputDataRight.rank() == 3) {
306 for (size_type i=0; i<inputDataLeft.rank(); ++i) {
307 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(i) != inputDataRight.extent(i), std::invalid_argument,
308 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft dimension does not match to inputDataRight");
313 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
314 for (size_type i=0; i<2; ++i) {
315 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
316 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft dimension does not match to inputDataRight");
322 if (inputDataLeft.extent(2) == 2) {
324 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
325 for (size_type i=0; i<2; ++i) {
326 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != outputData.extent(f2[i]), std::invalid_argument,
327 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft dimension does not match to outputData");
331 for (size_type i=0; i<inputDataLeft.rank(); ++i) {
332 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(i) != outputData.extent(i), std::invalid_argument,
333 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft dimension does not match to outputData");
339 if (inputDataLeft.extent(2) == 2) {
341 if (inputDataRight.rank() == 3) {
343 const size_type f1[] = { 0, 1 }, f2[] = { 0, 1 };
344 for (size_type i=0; i<2; ++i) {
345 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
346 ">>> ERROR (ArrayTools::crossProductDataData): outputData dimension does not match to inputDataRight");
350 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(1) != inputDataRight.extent(0), std::invalid_argument,
351 ">>> ERROR (ArrayTools::crossProductDataData): outputData dimension does not match to inputDataRight");
355 if (inputDataRight.rank() == 3) {
357 for (size_type i=0; i<outputData.rank(); ++i) {
358 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(i) != inputDataRight.extent(i), std::invalid_argument,
359 ">>> ERROR (ArrayTools::crossProductDataData): outputData dimension does not match to inputDataRight");
363 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
364 for (size_type i=0; i<2; ++i) {
365 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
366 ">>> ERROR (ArrayTools::crossProductDataData): outputData dimension does not match to inputDataRight");
380 namespace FunctorArrayTools {
384 template <
typename OutputViewType,
typename leftInputViewType,
typename rightInputViewType >
386 OutputViewType _output;
387 const leftInputViewType _leftInput;
388 const rightInputViewType _rightInput;
389 const bool _hasField;
391 KOKKOS_INLINE_FUNCTION
393 leftInputViewType leftInput_,
394 rightInputViewType rightInput_,
395 const bool hasField_)
396 : _output(output_), _leftInput(leftInput_), _rightInput(rightInput_),
397 _hasField(hasField_) {}
399 KOKKOS_INLINE_FUNCTION
400 void operator()(
const size_type iter)
const {
401 size_type cell, field(0), point;
402 size_type rightRank = _rightInput.rank();
405 unrollIndex( cell, field, point,
411 unrollIndex( cell, point,
416 auto result = ( _hasField ? Kokkos::subview(_output, cell, field, point, Kokkos::ALL(), Kokkos::ALL()) :
417 Kokkos::subview(_output, cell, point, Kokkos::ALL(), Kokkos::ALL()));
419 auto left = Kokkos::subview(_leftInput, cell, point, Kokkos::ALL());
421 auto right = (rightRank == 2 + size_type(_hasField)) ?
422 ( _hasField ? Kokkos::subview(_rightInput, field, point, Kokkos::ALL()) :
423 Kokkos::subview(_rightInput, point, Kokkos::ALL())) :
424 ( _hasField ? Kokkos::subview(_rightInput, cell, field, point, Kokkos::ALL()) :
425 Kokkos::subview(_rightInput, cell, point, Kokkos::ALL()));
427 const ordinal_type iend = result.extent(0);
428 const ordinal_type jend = result.extent(1);
429 for (ordinal_type i=0; i<iend; ++i)
430 for (ordinal_type j=0; j<jend; ++j)
431 result(i, j) = left(i)*right(j);
436 template<
typename DeviceType>
437 template<
typename outputValueType,
class ...outputProperties,
438 typename leftInputValueType,
class ...leftInputProperties,
439 typename rightInputValueType,
class ...rightInputProperties>
442 outerProduct( Kokkos::DynRankView<outputValueType, outputProperties...> output,
443 const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInput,
444 const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInput,
445 const bool hasField ) {
447 typedef Kokkos::DynRankView<outputValueType, outputProperties...> OutputViewType;
448 typedef const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInputViewType;
449 typedef const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInputViewType;
452 const size_type loopSize = ( hasField ? output.extent(0)*output.extent(1)*output.extent(2) :
453 output.extent(0)*output.extent(1) );
454 Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
455 Kokkos::parallel_for( policy, FunctorType(output, leftInput, rightInput, hasField) );
459 template<
typename DeviceType>
460 template<
typename outputFieldValueType,
class ...outputFieldProperties,
461 typename inputDataValueType,
class ...inputDataProperties,
462 typename inputFieldValueType,
class ...inputFieldProperties>
466 const Kokkos::DynRankView<inputDataValueType, inputDataProperties...> inputData,
467 const Kokkos::DynRankView<inputFieldValueType, inputFieldProperties...> inputFields ) {
469 #ifdef HAVE_INTREPID2_DEBUG
478 INTREPID2_TEST_FOR_EXCEPTION( inputData.rank() != 3, std::invalid_argument,
479 ">>> ERROR (ArrayTools::outerProductDataField): inputData must have rank 3");
480 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(2) < 2 || inputData.extent(2) > 3, std::invalid_argument,
481 ">>> ERROR (ArrayTools::outerProductDataField): inputData dimension(2) must be 2 or 3");
484 INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() < 3 || inputFields.rank() > 4, std::invalid_argument,
485 ">>> ERROR (ArrayTools::outerProductDataField): inputFields must have rank 3 or 4" );
486 INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(inputFields.rank()-1) < 2 ||
487 inputFields.extent(inputFields.rank()-1) < 3, std::invalid_argument,
488 ">>> ERROR (ArrayTools::outerProductDataField): inputFields dimension (rank-1) must have rank 2 or 3" );
491 INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != 5, std::invalid_argument,
492 ">>> ERROR (ArrayTools::outerProductDataField): outputFields must have rank 5");
493 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(3) < 2 ||
494 outputFields.extent(3) > 3, std::invalid_argument,
495 ">>> ERROR (ArrayTools::outerProductDataField): outputFields dimension(3) must be 2 or 3");
496 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(4) < 2 ||
497 outputFields.extent(4) > 3, std::invalid_argument,
498 ">>> ERROR (ArrayTools::outerProductDataField): outputFields dimension(4) must be 2 or 3");
509 const size_type f1[] = { 0, 2, 3, 4 }, f2[] = { 0, 1, 2, 2 };
510 for (size_type i=0; i<4; ++i) {
511 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
512 ">>> ERROR (ArrayTools::outerProductDataField): outputFields dimension does not match with inputData");
519 if (inputFields.rank() == 4) {
522 const size_type f1[] = { 0, 1, 2 }, f2[] = { 0, 2, 3 };
523 for (size_type i=0; i<3; ++i) {
524 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
525 ">>> ERROR (ArrayTools::outerProductDataField): inputData dimension does not match with inputFields");
531 const size_type f1[] = { 0, 1, 2, 3, 4 }, f2[] = { 0, 1, 2, 3, 3 };
532 for (size_type i=0; i<5; ++i) {
533 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
534 ">>> ERROR (ArrayTools::outerProductDataField): outputFields dimension does not match with inputFields");
540 const size_type f1[] = { 1, 2 }, f2[] = { 1, 2 };
541 for (size_type i=0; i<2; ++i) {
542 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
543 ">>> ERROR (ArrayTools::outerProductDataField): inputData dimension does not match with inputFields");
549 const size_type f1[] = { 1, 2, 3, 4 }, f2[] = { 0, 1, 2, 2 };
550 for (size_type i=0; i<4; ++i) {
551 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
552 ">>> ERROR (ArrayTools::outerProductDataField): outputFields dimension does not match with inputFields");
566 template<
typename DeviceType>
567 template<
typename outputDataValueType,
class ...outputDataProperties,
568 typename inputDataLeftValuetype,
class ...inputDataLeftProperties,
569 typename inputDataRightValueType,
class ...inputDataRightProperties>
573 const Kokkos::DynRankView<inputDataLeftValuetype, inputDataLeftProperties...> inputDataLeft,
574 const Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRight ) {
576 #ifdef HAVE_INTREPID2_DEBUG
585 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.rank() != 3, std::invalid_argument,
586 ">>> ERROR (ArrayTools::outerProductDataField): inputDataLeft must have rank 3");
587 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(2) < 2 || inputDataLeft.extent(2) > 3, std::invalid_argument,
588 ">>> ERROR (ArrayTools::outerProductDataField): inputDataLeft dimension(2) must be 2 or 3");
591 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() < 2 || inputDataRight.rank() > 3, std::invalid_argument,
592 ">>> ERROR (ArrayTools::outerProductDataField): inputDataRight must have rank 2 or 3" );
593 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(inputDataRight.rank()-1) < 2 ||
594 inputDataRight.extent(inputDataRight.rank()-1) < 3, std::invalid_argument,
595 ">>> ERROR (ArrayTools::outerProductDataField): inputDataRight dimension (rank-1) must have rank 2 or 3" );
598 INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != 4, std::invalid_argument,
599 ">>> ERROR (ArrayTools::outerProductDataField): outputData must have rank 5");
600 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(2) < 2 ||
601 outputData.extent(2) > 3, std::invalid_argument,
602 ">>> ERROR (ArrayTools::outerProductDataField): outputData dimension(3) must be 2 or 3");
603 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(3) < 2 ||
604 outputData.extent(3) > 3, std::invalid_argument,
605 ">>> ERROR (ArrayTools::outerProductDataField): outputData dimension(4) must be 2 or 3");
616 const size_type f1[] = { 0, 1, 2, 3 }, f2[] = { 0, 1, 2, 2 };
617 for (size_type i=0; i<4; ++i) {
618 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataLeft.extent(f2[i]), std::invalid_argument,
619 ">>> ERROR (ArrayTools::outerProductDataField): outputData dimension does not match with inputDataLeft");
626 if (inputDataRight.rank() == 3) {
628 for (size_type i=0; i<inputDataLeft.rank(); ++i) {
629 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(i) != inputDataRight.extent(i), std::invalid_argument,
630 ">>> ERROR (ArrayTools::outerProductDataField): inputDataLeft dimension does not match with inputDataRight");
635 const size_type f1[] = { 0, 1, 2, 3 }, f2[] = { 0, 1, 2, 2 };
636 for (size_type i=0; i<4; ++i) {
637 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
638 ">>> ERROR (ArrayTools::outerProductDataField): outputData dimension does not match with inputDataRight");
644 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
645 for (size_type i=0; i<2; ++i) {
646 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
647 ">>> ERROR (ArrayTools::outerProductDataField): inputDataLeft dimension does not match with inputDataRight");
653 const size_type f1[] = { 1, 2, 3 }, f2[] = { 0, 1, 1 };
654 for (size_type i=0; i<3; ++i) {
655 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
656 ">>> ERROR (ArrayTools::outerProductDataField): outputData dimension does not match with inputDataRight");
670 namespace FunctorArrayTools {
674 template <
typename OutputViewType,
675 typename leftInputViewType,
676 typename rightInputViewType,
677 ordinal_type leftInputRank,
678 ordinal_type rightInputRank,
682 OutputViewType _output;
683 const leftInputViewType _leftInput;
684 const rightInputViewType _rightInput;
686 const ordinal_type _iend;
687 const ordinal_type _jend;
689 using value_type =
typename OutputViewType::value_type;
691 KOKKOS_INLINE_FUNCTION
693 leftInputViewType leftInput_,
694 rightInputViewType rightInput_)
695 : _output(output_), _leftInput(leftInput_), _rightInput(rightInput_),
696 _iend(output_.extent_int(rank(output_)-1)), _jend(rightInput_.extent_int(rightInputRank-1))
700 KOKKOS_INLINE_FUNCTION
701 void operator()(
const ordinal_type cl,
702 const ordinal_type bf,
703 const ordinal_type pt)
const
705 apply_matvec_product(cl, bf, pt);
708 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
709 KOKKOS_FORCEINLINE_FUNCTION
710 typename std::enable_if_t<l==4 && r==4 && hf, void>
711 apply_matvec_product(
const ordinal_type &cl,
712 const ordinal_type &bf,
713 const ordinal_type &pt)
const {
714 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
716 for (ordinal_type i=0;i<_iend;++i) {
718 for (ordinal_type j=0;j<_jend;++j)
719 tmp += _leftInput(cl,lpt, j,i)*_rightInput(cl,bf,pt, j);
720 _output(cl,bf,pt, i) = tmp;
723 for (ordinal_type i=0;i<_iend;++i) {
725 for (ordinal_type j=0;j<_jend;++j)
726 tmp += _leftInput(cl,lpt, i,j)*_rightInput(cl,bf,pt, j);
727 _output(cl,bf,pt, i) = tmp;
732 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
733 KOKKOS_FORCEINLINE_FUNCTION
734 typename std::enable_if_t<l==4 && r==3 && hf, void>
735 apply_matvec_product(
const ordinal_type &cl,
736 const ordinal_type &bf,
737 const ordinal_type &pt)
const {
738 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
740 for (ordinal_type i=0;i<_iend;++i) {
742 for (ordinal_type j=0;j<_jend;++j)
743 tmp += _leftInput(cl,lpt, j,i)*_rightInput(bf,pt, j);
744 _output(cl,bf,pt, i) = tmp;
747 for (ordinal_type i=0;i<_iend;++i) {
749 for (ordinal_type j=0;j<_jend;++j)
750 tmp += _leftInput(cl,lpt, i,j)*_rightInput(bf,pt, j);
751 _output(cl,bf,pt, i) = tmp;
756 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
757 KOKKOS_FORCEINLINE_FUNCTION
758 typename std::enable_if_t<l==3 && r==4 && hf, void>
759 apply_matvec_product(
const ordinal_type &cl,
760 const ordinal_type &bf,
761 const ordinal_type &pt)
const {
762 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
763 for (ordinal_type i=0;i<_iend;++i)
764 _output(cl,bf,pt, i) = _leftInput(cl,lpt, i)*_rightInput(cl,bf,pt, i);
767 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
768 KOKKOS_FORCEINLINE_FUNCTION
769 typename std::enable_if_t<l==3 && r==3 && hf, void>
770 apply_matvec_product(
const ordinal_type &cl,
771 const ordinal_type &bf,
772 const ordinal_type &pt)
const {
773 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
774 for (ordinal_type i=0;i<_iend;++i)
775 _output(cl,bf,pt, i) = _leftInput(cl,lpt, i)*_rightInput(bf,pt, i);
778 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
779 KOKKOS_FORCEINLINE_FUNCTION
780 typename std::enable_if_t<l==2 && r==4 && hf, void>
781 apply_matvec_product(
const ordinal_type &cl,
782 const ordinal_type &bf,
783 const ordinal_type &pt)
const {
784 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
785 const value_type & val = _leftInput(cl,lpt);
786 for (ordinal_type i=0;i<_iend;++i) {
787 _output(cl,bf,pt, i) = val*_rightInput(cl,bf,pt, i);
791 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
792 KOKKOS_FORCEINLINE_FUNCTION
793 typename std::enable_if_t<l==2 && r==3 && hf, void>
794 apply_matvec_product(
const ordinal_type &cl,
795 const ordinal_type &bf,
796 const ordinal_type &pt)
const {
797 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
798 const value_type & val = _leftInput(cl,lpt);
799 for (ordinal_type i=0;i<_iend;++i) {
800 _output(cl,bf,pt, i) = val*_rightInput(bf,pt, i);
805 KOKKOS_INLINE_FUNCTION
806 void operator()(
const ordinal_type cl,
807 const ordinal_type pt)
const
809 apply_matvec_product(cl, pt);
812 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
813 KOKKOS_FORCEINLINE_FUNCTION
814 typename std::enable_if_t<l==4 && r==3 && !hf, void>
815 apply_matvec_product(
const ordinal_type &cl,
816 const ordinal_type &pt)
const {
817 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
819 for (ordinal_type i=0;i<_iend;++i) {
821 for (ordinal_type j=0;j<_jend;++j)
822 tmp += _leftInput(cl,lpt, j,i)*_rightInput(cl,pt, j);
823 _output(cl,pt, i) = tmp;
826 for (ordinal_type i=0;i<_iend;++i) {
828 for (ordinal_type j=0;j<_jend;++j)
829 tmp += _leftInput(cl,lpt, i,j)*_rightInput(cl,pt, j);
830 _output(cl,pt, i) = tmp;
835 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
836 KOKKOS_FORCEINLINE_FUNCTION
837 typename std::enable_if_t<l==4 && r==2 && !hf, void>
838 apply_matvec_product(
const ordinal_type &cl,
839 const ordinal_type &pt)
const {
840 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
842 for (ordinal_type i=0;i<_iend;++i) {
844 for (ordinal_type j=0;j<_jend;++j)
845 tmp += _leftInput(cl,lpt, j,i)*_rightInput(pt, j);
846 _output(cl,pt, i) = tmp;
849 for (ordinal_type i=0;i<_iend;++i) {
851 for (ordinal_type j=0;j<_jend;++j)
852 tmp += _leftInput(cl,lpt, i,j)*_rightInput(pt, j);
853 _output(cl,pt, i) = tmp;
858 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
859 KOKKOS_FORCEINLINE_FUNCTION
860 typename std::enable_if_t<l==3 && r==3 && !hf, void>
861 apply_matvec_product(
const ordinal_type &cl,
862 const ordinal_type &pt)
const {
863 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
864 for (ordinal_type i=0;i<_iend;++i)
865 _output(cl,pt, i) = _leftInput(cl,lpt, i)*_rightInput(cl,pt, i);
868 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
869 KOKKOS_FORCEINLINE_FUNCTION
870 typename std::enable_if_t<l==3 && r==2 && !hf, void>
871 apply_matvec_product(
const ordinal_type &cl,
872 const ordinal_type &pt)
const {
873 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
874 for (ordinal_type i=0;i<_iend;++i)
875 _output(cl,pt, i) = _leftInput(cl,lpt, i)*_rightInput(pt, i);
878 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
879 KOKKOS_FORCEINLINE_FUNCTION
880 typename std::enable_if_t<l==2 && r==3 && !hf, void>
881 apply_matvec_product(
const ordinal_type &cl,
882 const ordinal_type &pt)
const {
883 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
884 const value_type & val = _leftInput(cl,lpt);
885 for (ordinal_type i=0;i<_iend;++i) {
886 _output(cl,pt, i) = val*_rightInput(cl,pt, i);
890 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
891 KOKKOS_FORCEINLINE_FUNCTION
892 typename std::enable_if_t<l==2 && r==2 && !hf, void>
893 apply_matvec_product(
const ordinal_type &cl,
894 const ordinal_type &pt)
const {
895 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
896 const value_type & val = _leftInput(cl,lpt);
897 for (ordinal_type i=0;i<_iend;++i) {
898 _output(cl,pt, i) = val*_rightInput(pt, i);
904 template<
typename DeviceType>
905 template<
typename outputValueType,
class ...outputProperties,
906 typename leftInputValueType,
class ...leftInputProperties,
907 typename rightInputValueType,
class ...rightInputProperties>
910 matvecProduct( Kokkos::DynRankView<outputValueType, outputProperties...> output,
911 const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInput,
912 const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInput,
914 const bool isTranspose ) {
916 using Output = Kokkos::DynRankView<outputValueType, outputProperties...>;
917 using Left =
const Kokkos::DynRankView<leftInputValueType, leftInputProperties...>;
918 using Right =
const Kokkos::DynRankView<rightInputValueType,rightInputProperties...>;
946 const ordinal_type l = leftInput.rank();
947 const ordinal_type r = rightInput.rank();
949 using range_policy2 = Kokkos::MDRangePolicy< ExecSpaceType, Kokkos::Rank<2>, Kokkos::IndexType<ordinal_type> >;
950 range_policy2 policy2( { 0, 0 }, { output.extent(0), output.extent(1) } );
952 using range_policy3 = Kokkos::MDRangePolicy< ExecSpaceType, Kokkos::Rank<3>, Kokkos::IndexType<ordinal_type> >;
953 range_policy3 policy3( { 0, 0, 0 }, { output.extent(0), output.extent(1), output.extent(2) } );
956 const ordinal_type lr = l * 10 + r;
957 const auto &ov = output;
958 const auto &lv = leftInput;
959 const auto &rv = rightInput;
970 case 4: { FT44TT f(ov,lv,rv); Kokkos::parallel_for( policy3, f ); }
break;
971 default: { FT43TT f(ov,lv,rv); Kokkos::parallel_for( policy3, f ); }
978 case 4: { FT44TF f(ov,lv,rv); Kokkos::parallel_for( policy3, f ); }
break;
979 default: { FT43TF f(ov,lv,rv); Kokkos::parallel_for( policy3, f ); }
987 case 34: { FT34TF f(ov,lv,rv); Kokkos::parallel_for( policy3, f ); }
break;
988 case 33: { FT33TF f(ov,lv,rv); Kokkos::parallel_for( policy3, f ); }
break;
989 case 24: { FT24TF f(ov,lv,rv); Kokkos::parallel_for( policy3, f ); }
break;
990 default: { FT23TF f(ov,lv,rv); Kokkos::parallel_for( policy3, f ); }
1003 case 3: { FT43FT f(ov,lv,rv); Kokkos::parallel_for( policy2, f ); }
break;
1004 default: { FT42FT f(ov,lv,rv); Kokkos::parallel_for( policy2, f ); }
1011 case 3: { FT43FF f(ov,lv,rv); Kokkos::parallel_for( policy2, f ); }
break;
1012 default: { FT42FF f(ov,lv,rv); Kokkos::parallel_for( policy2, f ); }
1020 case 33: { FT33FF f(ov,lv,rv); Kokkos::parallel_for( policy2, f ); }
break;
1021 case 32: { FT32FF f(ov,lv,rv); Kokkos::parallel_for( policy2, f ); }
break;
1022 case 23: { FT23FF f(ov,lv,rv); Kokkos::parallel_for( policy2, f ); }
break;
1023 default: { FT22FF f(ov,lv,rv); Kokkos::parallel_for( policy2, f ); }
1029 template<
typename DeviceType>
1030 template<
typename outputFieldValueType,
class ...outputFieldProperties,
1031 typename inputDataValueType,
class ...inputDataProperties,
1032 typename inputFieldValueType,
class ...inputFieldProperties>
1035 const Kokkos::DynRankView<inputDataValueType, inputDataProperties...> inputData,
1036 const Kokkos::DynRankView<inputFieldValueType, inputFieldProperties...> inputFields,
1037 const char transpose ) {
1039 #ifdef HAVE_INTREPID2_DEBUG
1048 INTREPID2_TEST_FOR_EXCEPTION( inputData.rank() < 2 || inputData.rank() > 4, std::invalid_argument,
1049 ">>> ERROR (ArrayTools::matvecProductDataField): inputData must have rank 2,3 or 4" );
1050 if (inputData.rank() > 2) {
1051 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(2) < 1 ||
1052 inputData.extent(2) > 3, std::invalid_argument,
1053 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension(2) must be 1,2 or 3");
1055 if (inputData.rank() == 4) {
1056 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(3) < 1 ||
1057 inputData.extent(3) > 3, std::invalid_argument,
1058 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension(3) must be 1,2 or 3");
1062 INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() < 3 ||
1063 inputFields.rank() > 4, std::invalid_argument,
1064 ">>> ERROR (ArrayTools::matvecProductDataField): inputFields must have rank 3 or 4" );
1065 INTREPID2_TEST_FOR_EXCEPTION( (inputFields.rank()-1) < 1 ||
1066 (inputFields.rank()-1) > 3, std::invalid_argument,
1067 ">>> ERROR (ArrayTools::matvecProductDataField): inputFields dimension(rank-1) must be 1,2, or 3" );
1070 INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != 4, std::invalid_argument,
1071 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields must have rank 4" );
1072 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(3) < 1 ||
1073 outputFields.extent(3) > 3, std::invalid_argument,
1074 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension(3) must be 1,2 or 3" );
1087 if (inputData.extent(1) > 1) {
1088 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(2) != inputData.extent(1), std::invalid_argument,
1089 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension(2) must match to inputData dimension(1)" );
1091 if (inputData.rank() == 2) {
1092 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(0) != inputData.extent(0), std::invalid_argument,
1093 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension(0) must match to inputData dimension(0)" );
1095 if (inputData.rank() == 3) {
1096 const size_type f1[] = { 0, 3 }, f2[] = { 0, 2 };
1097 for (size_type i=0; i<2; ++i) {
1098 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
1099 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension does not match to inputData dimension" );
1102 if (inputData.rank() == 4) {
1103 const size_type f1[] = { 0, 3, 3 }, f2[] = { 0, 2, 3 };
1104 for (size_type i=0; i<3; ++i) {
1105 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
1106 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension does not match to inputData dimension" );
1113 if (inputFields.rank() == 4) {
1115 if (inputData.extent(1) > 1) {
1116 INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(2) != inputData.extent(1), std::invalid_argument,
1117 ">>> ERROR (ArrayTools::matvecProductDataField): inputFields dimension (2) does not match to inputData dimension (1)" );
1119 if (inputData.rank() == 2) {
1120 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(0) != inputFields.extent(0), std::invalid_argument,
1121 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension (0) does not match to inputFields dimension (0)" );
1123 if (inputData.rank() == 3) {
1124 const size_type f1[] = { 0, 2 }, f2[] = { 0, 3 };
1125 for (size_type i=0; i<2; ++i) {
1126 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1127 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension does not match to inputFields dimension" );
1130 if (inputData.rank() == 4) {
1131 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 3, 3 };
1132 for (size_type i=0; i<3; ++i) {
1133 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1134 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension does not match to inputFields dimension" );
1139 for (size_type i=0; i<outputFields.rank(); ++i) {
1140 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(i) != inputFields.extent(i), std::invalid_argument,
1141 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension does not match to inputFields dimension" );
1145 if (inputData.extent(1) > 1) {
1146 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(1) != inputFields.extent(1), std::invalid_argument,
1147 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension(1) does not match to inputFields dimension (1)" );
1149 if (inputData.rank() == 3) {
1150 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(2) != inputFields.extent(2), std::invalid_argument,
1151 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension(2) does not match to inputFields dimension (2)" );
1153 if (inputData.rank() == 4) {
1154 const size_type f1[] = { 2, 3 }, f2[] = { 2, 2 };
1155 for (size_type i=0; i<2; ++i) {
1156 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1157 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension does not match to inputFields dimension" );
1163 const size_type f1[] = { 1, 2, 3 }, f2[] = { 0, 1, 2 };
1164 for (size_type i=0; i<3; ++i) {
1165 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1166 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension does not match to inputFields dimension" );
1177 transpose ==
't' || transpose ==
'T' );
1182 template<
typename DeviceType>
1183 template<
typename outputDataValueType,
class ...outputDataProperties,
1184 typename inputDataLeftValueType,
class ...inputDataLeftProperties,
1185 typename inputDataRightValueType,
class ...inputDataRightProperties>
1189 const Kokkos::DynRankView<inputDataLeftValueType, inputDataLeftProperties...> inputDataLeft,
1190 const Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRight,
1191 const char transpose ) {
1193 #ifdef HAVE_INTREPID2_DEBUG
1202 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.rank() < 2 ||
1203 inputDataLeft.rank() > 4, std::invalid_argument,
1204 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft must have rank 2,3 or 4" );
1206 if (inputDataLeft.rank() > 2) {
1207 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(2) < 1 ||
1208 inputDataLeft.extent(2) > 3, std::invalid_argument,
1209 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension(2) must be 1, 2 or 3");
1211 if (inputDataLeft.rank() == 4) {
1212 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(3) < 1 ||
1213 inputDataLeft.extent(3) > 3, std::invalid_argument,
1214 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension(3) must be 1, 2 or 3");
1218 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() < 2 ||
1219 inputDataRight.rank() > 3, std::invalid_argument,
1220 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataRight must have rank 2 or 3" );
1221 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(inputDataRight.rank()-1) < 1 ||
1222 inputDataRight.extent(inputDataRight.rank()-1) > 3, std::invalid_argument,
1223 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataRight dimension (rank-1) must be 1,2 or 3" );
1226 INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != 3, std::invalid_argument,
1227 ">>> ERROR (ArrayTools::matvecProductDataData): outputData must have rank 3" );
1228 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(2) < 1 ||
1229 outputData.extent(2) > 3, std::invalid_argument,
1230 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension(2) must be 1, 2 or 3");
1243 if (inputDataLeft.extent(1) > 1) {
1244 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(1) != inputDataLeft.extent(1), std::invalid_argument,
1245 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension(1) muat match inputDataLeft dimension(1)" );
1247 if (inputDataLeft.rank() == 2) {
1248 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(0) != inputDataLeft.extent(0), std::invalid_argument,
1249 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension(0) muat match inputDataLeft dimension(0)" );
1251 if (inputDataLeft.rank() == 3) {
1252 const size_type f1[] = { 0, 2 }, f2[] = { 0, 2 };
1253 for (size_type i=0; i<2; ++i) {
1254 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataLeft.extent(f2[i]), std::invalid_argument,
1255 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension muat match inputDataLeft dimension" );
1258 if (inputDataLeft.rank() == 4) {
1259 size_type f1[] = { 0, 2}, f2[] = { 0, 2};
1260 if (transpose) f2[1] = 3;
1261 for (size_type i=0; i<2; ++i) {
1262 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataLeft.extent(f2[i]), std::invalid_argument,
1263 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension muat match inputDataLeft dimension" );
1270 if (inputDataRight.rank() == 3) {
1272 if (inputDataLeft.extent(1) > 1) {
1273 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(1), std::invalid_argument,
1274 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension (1) muat match to inputDataRight dimension (1)" );
1276 if (inputDataLeft.rank() == 2) {
1277 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(0) != inputDataRight.extent(0), std::invalid_argument,
1278 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension (0) muat match to inputDataRight dimension (0)" );
1280 if (inputDataLeft.rank() == 3) {
1281 const size_type f1[] = { 0, 2 }, f2[] = { 0, 2 };
1282 for (size_type i=0; i<2; ++i) {
1283 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1284 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension muat match to inputDataRight dimension" );
1287 if (inputDataLeft.rank() == 4) {
1288 size_type f1[] = { 0, 3}, f2[] = { 0, 2};
1289 if (transpose) f1[1] = 2;
1290 for (size_type i=0; i<2; ++i) {
1291 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1292 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension muat match to inputDataRight dimension" );
1297 for (size_type i=0; i<outputData.rank()-1; ++i) {
1298 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(i) != inputDataRight.extent(i), std::invalid_argument,
1299 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension muat match to inputDataRight dimension" );
1303 if (inputDataLeft.extent(1) > 1) {
1304 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(0), std::invalid_argument,
1305 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension (1) does mot match to inputDataright dimension (0)" );
1307 if (inputDataLeft.rank() == 3) {
1308 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(2) != inputDataRight.extent(1), std::invalid_argument,
1309 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension (2) does mot match to inputDataright dimension (1)" );
1311 if (inputDataLeft.rank() == 4) {
1312 const size_type f1[] = { 2, 3 }, f2[] = { 1, 1 };
1313 for (size_type i=0; i<2; ++i) {
1314 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1315 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension muat match to inputDataRight dimension" );
1321 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
1322 for (size_type i=0; i<2; ++i) {
1323 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1324 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension muat match to inputDataRight dimension" );
1335 transpose ==
't' || transpose ==
'T' );
1339 namespace FunctorArrayTools {
1343 template <
typename OutputViewType,
typename leftInputViewType,
typename rightInputViewType >
1345 OutputViewType _output;
1346 leftInputViewType _leftInput;
1347 rightInputViewType _rightInput;
1348 const bool _hasField, _isTranspose;
1349 typedef typename leftInputViewType::value_type value_type;
1351 KOKKOS_INLINE_FUNCTION
1353 leftInputViewType leftInput_,
1354 rightInputViewType rightInput_,
1355 const bool hasField_,
1356 const bool isTranspose_)
1357 : _output(output_), _leftInput(leftInput_), _rightInput(rightInput_),
1358 _hasField(hasField_), _isTranspose(isTranspose_) {}
1360 KOKKOS_INLINE_FUNCTION
1361 void operator()(
const size_type iter)
const {
1362 size_type cell(0), field(0), point(0);
1363 size_type leftRank = _leftInput.rank();
1364 size_type rightRank = _rightInput.rank();
1367 unrollIndex( cell, field, point,
1373 unrollIndex( cell, point,
1378 auto result = ( _hasField ? Kokkos::subview(_output, cell, field, point, Kokkos::ALL(), Kokkos::ALL()) :
1379 Kokkos::subview(_output, cell, point, Kokkos::ALL(), Kokkos::ALL()));
1381 const auto lpoint = (_leftInput.extent(1) == 1 ? 0 : point);
1382 auto left = ( leftRank == 4 ? Kokkos::subview(_leftInput, cell, lpoint, Kokkos::ALL(), Kokkos::ALL()) :
1383 leftRank == 3 ? Kokkos::subview(_leftInput, cell, lpoint, Kokkos::ALL()) :
1384 Kokkos::subview(_leftInput, cell, lpoint) );
1387 const bool hasCell = (_hasField ? rightRank == 5 : rightRank == 4);
1388 auto right = ( _hasField ? ( hasCell ? Kokkos::subview(_rightInput, cell, field, point, Kokkos::ALL(), Kokkos::ALL()) :
1389 Kokkos::subview(_rightInput, field, point, Kokkos::ALL(), Kokkos::ALL())):
1390 ( hasCell ? Kokkos::subview(_rightInput, cell, point, Kokkos::ALL(), Kokkos::ALL()) :
1391 Kokkos::subview(_rightInput, point, Kokkos::ALL(), Kokkos::ALL())));
1393 const ordinal_type iend = result.extent(0);
1394 const ordinal_type jend = result.extent(1);
1399 const size_type kend = right.extent(0);
1400 for (ordinal_type i=0; i<iend; ++i)
1401 for (ordinal_type j=0; j<jend; ++j) {
1402 result(i, j) = value_type(0);
1403 for (size_type k=0; k<kend; ++k)
1404 result(i, j) += left(k, i) * right(k, j);
1407 const size_type kend = right.extent(0);
1408 for (ordinal_type i=0; i<iend; ++i)
1409 for (ordinal_type j=0; j<jend; ++j) {
1410 result(i, j) = value_type(0);
1411 for (size_type k=0; k<kend; ++k)
1412 result(i, j) += left(i, k) * right(k, j);
1418 for (ordinal_type i=0; i<iend; ++i)
1419 for (ordinal_type j=0; j<jend; ++j)
1420 result(i, j) = left(i) * right(i, j);
1424 for (ordinal_type i=0; i<iend; ++i)
1425 for (ordinal_type j=0; j<jend; ++j)
1426 result(i, j) = left() * right(i, j);
1434 template<
typename DeviceType>
1435 template<
typename outputValueType,
class ...outputProperties,
1436 typename leftInputValueType,
class ...leftInputProperties,
1437 typename rightInputValueType,
class ...rightInputProperties>
1440 matmatProduct( Kokkos::DynRankView<outputValueType, outputProperties...> output,
1441 const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInput,
1442 const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInput,
1443 const bool hasField,
1444 const bool isTranspose ) {
1446 typedef Kokkos::DynRankView<outputValueType, outputProperties...> OutputViewType;
1447 typedef const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInputViewType;
1448 typedef const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInputViewType;
1451 const size_type loopSize = ( hasField ? output.extent(0)*output.extent(1)*output.extent(2) :
1452 output.extent(0)*output.extent(1) );
1453 Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
1454 Kokkos::parallel_for( policy, FunctorType(output, leftInput, rightInput, hasField, isTranspose) );
1460 template<
typename DeviceType>
1461 template<
typename outputFieldValueType,
class ...outputFieldProperties,
1462 typename inputDataValueType,
class ...inputDataProperties,
1463 typename inputFieldValueType,
class ...inputFieldProperties>
1467 const Kokkos::DynRankView<inputDataValueType, inputDataProperties...> inputData,
1468 const Kokkos::DynRankView<inputFieldValueType, inputFieldProperties...> inputFields,
1469 const char transpose ) {
1471 #ifdef HAVE_INTREPID2_DEBUG
1480 INTREPID2_TEST_FOR_EXCEPTION( inputData.rank() < 2 ||
1481 inputData.rank() > 4, std::invalid_argument,
1482 ">>> ERROR (ArrayTools::matmatProductDataField): inputData must have rank 2,3 or 4" );
1483 if (inputData.rank() > 2) {
1484 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(2) < 1 ||
1485 inputData.extent(2) > 3, std::invalid_argument,
1486 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension (2) must be 1,2 or 3" );
1488 if (inputData.rank() == 4) {
1489 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(3) < 1 ||
1490 inputData.extent(3) > 3, std::invalid_argument,
1491 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension (3) must be 1,2 or 3" );
1495 INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() < 4 ||
1496 inputFields.rank() > 5, std::invalid_argument,
1497 ">>> ERROR (ArrayTools::matmatProductDataField): inputFields must have rank 4 or 5");
1498 INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(inputFields.rank()-1) < 1 ||
1499 inputFields.extent(inputFields.rank()-1) > 3, std::invalid_argument,
1500 ">>> ERROR (ArrayTools::matmatProductDataField): inputFields dimension (rank-1) must be 1,2 or 3" );
1501 INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(inputFields.rank()-2) < 1 ||
1502 inputFields.extent(inputFields.rank()-2) > 3, std::invalid_argument,
1503 ">>> ERROR (ArrayTools::matmatProductDataField): inputFields dimension (rank-2) must be 1,2 or 3" );
1506 INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != 5, std::invalid_argument,
1507 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields must have rank 5" );
1508 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(3) < 1 ||
1509 outputFields.extent(3) > 3, std::invalid_argument,
1510 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension (3) must be 1,2 or 3" );
1511 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(4) < 1 ||
1512 outputFields.extent(4) > 3, std::invalid_argument,
1513 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension (4) must be 1,2 or 3" );
1526 if (inputData.extent(1) > 1) {
1527 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(2) != inputData.extent(1), std::invalid_argument,
1528 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension (2) does not match to inputData dimension (1)" );
1530 if (inputData.rank() == 2) {
1531 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(0) != inputData.extent(0), std::invalid_argument,
1532 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension (0) does not match to inputData dimension (0)" );
1534 if (inputData.rank() == 3) {
1535 const size_type f1[] = { 0, 3, 4 }, f2[] = { 0, 2, 2 };
1536 for (size_type i=0; i<3; ++i) {
1537 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
1538 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension does not match to inputData dimension" );
1541 if (inputData.rank() == 4) {
1542 const size_type f1[] = { 0, 3, 4 }, f2[] = { 0, 2, 3 };
1543 for (size_type i=0; i<3; ++i) {
1544 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
1545 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension does not match to inputData dimension" );
1552 if (inputFields.rank() == 5) {
1554 if (inputData.extent(1) > 1) {
1555 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(1) != inputFields.extent(2), std::invalid_argument,
1556 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension (1) does not match to inputFields dimension (2)" );
1558 if (inputData.rank() == 2) {
1559 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(0) != inputFields.extent(0), std::invalid_argument,
1560 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension (0) does not match to inputFields dimension (0)" );
1562 if (inputData.rank() == 3) {
1564 const size_type f1[] = { 0, 2, 2 }, f2[] = { 0, 3, 4 };
1565 for (size_type i=0; i<3; ++i) {
1566 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1567 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension does not match to inputFields dimension" );
1570 if (inputData.rank() == 4) {
1571 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 3, 4 };
1572 for (size_type i=0; i<3; ++i) {
1573 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1574 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension does not match to inputFields dimension" );
1579 for (size_type i=0; i<outputFields.rank(); ++i) {
1580 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(i) != inputFields.extent(i), std::invalid_argument,
1581 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension does not match to inputFields dimension" );
1585 if (inputData.extent(1) > 1) {
1586 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(1) != inputFields.extent(1), std::invalid_argument,
1587 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension (1) does not match to inputFields dimension (1)" );
1589 if (inputData.rank() == 3) {
1590 const size_type f1[] = { 2, 2 }, f2[] = { 2, 3 };
1591 for (size_type i=0; i<2; ++i) {
1592 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1593 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension does not match to inputFields dimension" );
1596 if (inputData.rank() == 4) {
1597 const size_type f1[] = { 2, 3 }, f2[] = { 2, 3 };
1598 for (size_type i=0; i<2; ++i) {
1599 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1600 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension does not match to inputFields dimension" );
1606 const size_type f1[] = { 1, 2, 3, 4 }, f2[] = { 0, 1, 2, 3 };
1607 for (size_type i=0; i<4; ++i) {
1608 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1609 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension does not match to inputFields dimension" );
1620 transpose ==
't' || transpose ==
'T' );
1625 template<
typename DeviceType>
1626 template<
typename outputDataValueType,
class ...outputDataProperties,
1627 typename inputDataLeftValueType,
class ...inputDataLeftProperties,
1628 typename inputDataRightValueType,
class ...inputDataRightProperties>
1631 const Kokkos::DynRankView<inputDataLeftValueType, inputDataLeftProperties...> inputDataLeft,
1632 const Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRight,
1633 const char transpose ) {
1635 #ifdef HAVE_INTREPID2_DEBUG
1644 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.rank() < 2 ||
1645 inputDataLeft.rank() > 4, std::invalid_argument,
1646 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft must have rank 2,3 or 4" );
1647 if (inputDataLeft.rank() > 2) {
1648 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(2) < 1 ||
1649 inputDataLeft.extent(2) > 3, std::invalid_argument,
1650 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft dimension (2) must be 1,2 or 3" );
1652 if (inputDataLeft.rank() == 4) {
1653 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(3) < 1 ||
1654 inputDataLeft.extent(3) > 3, std::invalid_argument,
1655 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft dimension (3) must be 1,2 or 3" );
1659 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() < 3 ||
1660 inputDataRight.rank() > 4, std::invalid_argument,
1661 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataRight must have rank 3 or 4" );
1662 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(inputDataRight.rank()-1) < 1 ||
1663 inputDataRight.extent(inputDataRight.rank()-1) > 3, std::invalid_argument,
1664 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataRight (rank-1) must be 1,2 or 3" );
1665 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(inputDataRight.rank()-2) < 1 ||
1666 inputDataRight.extent(inputDataRight.rank()-2) > 3, std::invalid_argument,
1667 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataRight (rank-2) must be 1,2 or 3" );
1670 INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != 4, std::invalid_argument,
1671 ">>> ERROR (ArrayTools::matmatProductDataData): outputData must have rank 4" );
1672 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(2) < 1 ||
1673 outputData.extent(2) > 3, std::invalid_argument,
1674 ">>> ERROR (ArrayTools::matmatProductDataData): outputData (2) must be 1,2 or 3" );
1675 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(3) < 1 ||
1676 outputData.extent(3) > 3, std::invalid_argument,
1677 ">>> ERROR (ArrayTools::matmatProductDataData): outputData (3) must be 1,2 or 3" );
1690 if (inputDataLeft.extent(1) > 1) {
1691 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(1) != inputDataLeft.extent(1), std::invalid_argument,
1692 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension (1) does not match to inputDataLeft dimension (1)" );
1694 if (inputDataLeft.rank() == 2) {
1695 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(0) != inputDataLeft.extent(0), std::invalid_argument,
1696 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension (0) does not match to inputDataLeft dimension (0)" );
1698 if (inputDataLeft.rank() == 3) {
1699 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 2, 2 };
1700 for (size_type i=0; i<3; ++i) {
1701 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataLeft.extent(f2[i]), std::invalid_argument,
1702 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension does not match to inputDataLeft dimension" );
1705 if (inputDataLeft.rank() == 4) {
1706 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 2, 3 };
1707 for (size_type i=0; i<3; ++i) {
1708 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataLeft.extent(f2[i]), std::invalid_argument,
1709 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension does not match to inputDataLeft dimension" );
1716 if (inputDataRight.rank() == 4) {
1718 if (inputDataLeft.extent(1) > 1) {
1719 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(1), std::invalid_argument,
1720 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft dimension (1) does not match to inputDataRight dimension (1)" );
1722 if (inputDataLeft.rank() == 2) {
1723 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(0) != inputDataRight.extent(0), std::invalid_argument,
1724 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft dimension (0) does not match to inputDataRight dimension (0)" );
1726 if (inputDataLeft.rank() == 3) {
1727 const size_type f1[] = { 0, 2, 2 }, f2[] = { 0, 2, 3 };
1728 for (size_type i=0; i<3; ++i) {
1729 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1730 ">>> ERROR (ArrayTools::matmatProductDataData): intputDataLeft dimension does not match to inputDataRight dimension" );
1733 if (inputDataLeft.rank() == 4) {
1734 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 2, 3 };
1735 for (size_type i=0; i<3; ++i) {
1736 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1737 ">>> ERROR (ArrayTools::matmatProductDataData): intputDataLeft dimension does not match to inputDataRight dimension" );
1742 for (size_type i=0; i< outputData.rank(); ++i) {
1743 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(i) != inputDataRight.extent(i), std::invalid_argument,
1744 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension does not match to inputDataRight dimension" );
1748 if (inputDataLeft.extent(1) > 1) {
1749 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(0), std::invalid_argument,
1750 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft dimension (1) does not match to inputDataRight dimension (0)" );
1752 if (inputDataLeft.rank() == 3) {
1753 const size_type f1[] = { 2, 2 }, f2[] = { 1, 2 };
1754 for (size_type i=0; i<2; ++i) {
1755 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1756 ">>> ERROR (ArrayTools::matmatProductDataData): intputDataLeft dimension does not match to inputDataRight dimension" );
1759 if (inputDataLeft.rank() == 4) {
1760 const size_type f1[] = { 2, 3 }, f2[] = { 1, 2 };
1761 for (size_type i=0; i<2; ++i) {
1762 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1763 ">>> ERROR (ArrayTools::matmatProductDataData): intputDataLeft dimension does not match to inputDataRight dimension" );
1768 const size_type f1[] = { 1, 2, 3 }, f2[] = { 0, 1, 2 };
1769 for (size_type i=0; i<3; ++i) {
1770 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1771 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension does not match to inputDataRight dimension" );
1782 transpose ==
't' || transpose ==
'T' );