16 #ifndef __INTREPID2_ARRAYTOOLS_DEF_TENSOR_HPP__
17 #define __INTREPID2_ARRAYTOOLS_DEF_TENSOR_HPP__
21 namespace FunctorArrayTools {
25 template <
typename OutputViewType,
typename leftInputViewType,
typename rightInputViewType >
27 OutputViewType _output;
28 const leftInputViewType _leftInput;
29 const rightInputViewType _rightInput;
30 const bool _hasField, _isCrossProd3D;
32 KOKKOS_INLINE_FUNCTION
34 leftInputViewType leftInput_,
35 rightInputViewType rightInput_,
37 const bool isCrossProd3D_)
38 : _output(output_), _leftInput(leftInput_), _rightInput(rightInput_),
39 _hasField(hasField_), _isCrossProd3D(isCrossProd3D_) {}
41 KOKKOS_INLINE_FUNCTION
42 void operator()(
const size_type iter)
const {
43 size_type cell, field(0), point;
44 size_type rightRank = _rightInput.rank();
47 unrollIndex( cell, field, point,
53 unrollIndex( cell, point,
59 auto left = Kokkos::subview(_leftInput, cell, point, Kokkos::ALL());
61 auto right = (rightRank == 2 + size_type(_hasField)) ?
62 ( _hasField ? Kokkos::subview(_rightInput, field, point, Kokkos::ALL()) :
63 Kokkos::subview(_rightInput, point, Kokkos::ALL())) :
64 ( _hasField ? Kokkos::subview(_rightInput, cell, field, point, Kokkos::ALL()) :
65 Kokkos::subview(_rightInput, cell, point, Kokkos::ALL()));
69 auto result = ( _hasField ? Kokkos::subview(_output, cell, field, point, Kokkos::ALL()) :
70 Kokkos::subview(_output, cell, point, Kokkos::ALL()));
71 result(0) = left(1)*right(2) - left(2)*right(1);
72 result(1) = left(2)*right(0) - left(0)*right(2);
73 result(2) = left(0)*right(1) - left(1)*right(0);
75 typename OutputViewType::reference_type result = _hasField ? _output(cell, field, point) : _output(cell, point);
76 result = left(0)*right(1) - left(1)*right(0);
82 template<
typename DeviceType>
83 template<
typename outputValueType,
class ...outputProperties,
84 typename leftInputValueType,
class ...leftInputProperties,
85 typename rightInputValueType,
class ...rightInputProperties>
88 crossProduct( Kokkos::DynRankView<outputValueType, outputProperties...> output,
89 const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInput,
90 const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInput,
91 const bool hasField ) {
93 typedef Kokkos::DynRankView<outputValueType, outputProperties...> OutputViewType;
94 typedef const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInputViewType;
95 typedef const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInputViewType;
98 const size_type loopSize = ( hasField ? output.extent(0)*output.extent(1)*output.extent(2) :
99 output.extent(0)*output.extent(1) );
100 const bool isCrossProd3D = (leftInput.extent(2) == 3);
101 Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
102 Kokkos::parallel_for( policy, FunctorType(output, leftInput, rightInput, hasField, isCrossProd3D) );
107 template<
typename DeviceType>
108 template<
typename outputFieldValueType,
class ...outputFieldProperties,
109 typename inputDataValueType,
class ...inputDataProperties,
110 typename inputFieldValueType,
class ...inputFieldProperties>
114 const Kokkos::DynRankView<inputDataValueType, inputDataProperties...> inputData,
115 const Kokkos::DynRankView<inputFieldValueType, inputFieldProperties...> inputFields ) {
117 #ifdef HAVE_INTREPID2_DEBUG
126 INTREPID2_TEST_FOR_EXCEPTION( inputData.rank() != 3, std::invalid_argument,
127 ">>> ERROR (ArrayTools::crossProductDataField): inputData must have rank 3");
128 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(2) < 2 || inputData.extent(2) > 3, std::invalid_argument,
129 ">>> ERROR (ArrayTools::crossProductDataField): inputData dimension(2) must be 2 or 3");
132 INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() < 3 || inputFields.rank() > 4, std::invalid_argument,
133 ">>> ERROR (ArrayTools::crossProductDataField): inputFields must have rank 3 or 4" );
134 INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(inputFields.rank()-1) < 2 ||
135 inputFields.extent(inputFields.rank()-1) > 3, std::invalid_argument,
136 ">>> ERROR (ArrayTools::crossProductDataField): inputFields dimension (rank-1) must have rank 2 or 3" );
139 INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != inputData.extent(2)+1, std::invalid_argument,
140 ">>> ERROR (ArrayTools::crossProductDataField): outputFields rank must match to inputData dimension(2)+1");
149 if (inputFields.rank() == 4) {
151 const size_type f1[] = { 0, 1, 2 }, f2[] = { 0, 2, 3 };
152 for (size_type i=0; i<3; ++i) {
153 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
154 ">>> ERROR (ArrayTools::crossProductDataField): inputData dimension does not match with inputFields");
158 const size_type f1[] = { 1, 2 }, f2[] = { 1, 2 };
159 for (size_type i=0; i<2; ++i) {
160 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
161 ">>> ERROR (ArrayTools::crossProductDataField): inputData dimension does not match with inputFields");
167 if (inputData.extent(2) == 2) {
170 const size_type f1[] = { 0, 2 }, f2[] = { 0, 1 };
171 for (size_type i=0; i<2; ++i) {
172 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
173 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputData");
177 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 1, 2 };
178 for (size_type i=0; i<3; ++i) {
179 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
180 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputData");
186 if (inputData.extent(2) == 2) {
188 if (inputFields.rank() == 4) {
190 const size_type f1[] = { 0, 1, 2 }, f2[] = { 0, 1, 2 };
191 for (size_type i=0; i<3; ++i) {
192 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
193 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputFields");
197 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
198 for (size_type i=0; i<2; ++i) {
199 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
200 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputFields");
205 if (inputFields.rank() == 4) {
207 for (size_type i=0; i<outputFields.rank(); ++i) {
208 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(i) != inputFields.extent(i), std::invalid_argument,
209 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputFields");
213 const size_type f1[] = { 1, 2, 3 }, f2[] = { 0, 1, 2 };
214 for (size_type i=0; i<3; ++i) {
215 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
216 ">>> ERROR (ArrayTools::crossProductDataField): outputFields dimension does not match with inputFields");
230 template<
typename DeviceType>
231 template<
typename outputDataValueType,
class ...outputDataProperties,
232 typename inputDataLeftValueType,
class ...inputDataLeftProperties,
233 typename inputDataRightValueType,
class ...inputDataRightProperties>
237 const Kokkos::DynRankView<inputDataLeftValueType, inputDataLeftProperties...> inputDataLeft,
238 const Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRight ) {
240 #ifdef HAVE_INTREPID2_DEBUG
249 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.rank() != 3, std::invalid_argument,
250 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft must have rank 3");
251 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(2) < 2 || inputDataLeft.extent(2) > 3, std::invalid_argument,
252 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft dimension(2) must be 2 or 3");
255 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() < 2 || inputDataRight.rank() > 3, std::invalid_argument,
256 ">>> ERROR (ArrayTools::crossProductDataData): inputDataRight must have rank 2 or 3" );
257 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(inputDataRight.rank()-1) < 2 ||
258 inputDataRight.extent(inputDataRight.rank()-1) > 3, std::invalid_argument,
259 ">>> ERROR (ArrayTools::crossProductDataData): inputDataRight dimension (rank-1) must have rank 2 or 3" );
262 INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != inputDataLeft.extent(2), std::invalid_argument,
263 ">>> ERROR (ArrayTools::crossProductDataData): outputData rank must match to inputDataLeft dimension(2)");
272 if (inputDataRight.rank() == 3) {
274 for (size_type i=0; i<inputDataLeft.rank(); ++i) {
275 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(i) != inputDataRight.extent(i), std::invalid_argument,
276 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft dimension does not match to inputDataRight");
281 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
282 for (size_type i=0; i<2; ++i) {
283 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
284 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft dimension does not match to inputDataRight");
290 if (inputDataLeft.extent(2) == 2) {
292 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
293 for (size_type i=0; i<2; ++i) {
294 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != outputData.extent(f2[i]), std::invalid_argument,
295 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft dimension does not match to outputData");
299 for (size_type i=0; i<inputDataLeft.rank(); ++i) {
300 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(i) != outputData.extent(i), std::invalid_argument,
301 ">>> ERROR (ArrayTools::crossProductDataData): inputDataLeft dimension does not match to outputData");
307 if (inputDataLeft.extent(2) == 2) {
309 if (inputDataRight.rank() == 3) {
311 const size_type f1[] = { 0, 1 }, f2[] = { 0, 1 };
312 for (size_type i=0; i<2; ++i) {
313 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
314 ">>> ERROR (ArrayTools::crossProductDataData): outputData dimension does not match to inputDataRight");
318 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(1) != inputDataRight.extent(0), std::invalid_argument,
319 ">>> ERROR (ArrayTools::crossProductDataData): outputData dimension does not match to inputDataRight");
323 if (inputDataRight.rank() == 3) {
325 for (size_type i=0; i<outputData.rank(); ++i) {
326 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(i) != inputDataRight.extent(i), std::invalid_argument,
327 ">>> ERROR (ArrayTools::crossProductDataData): outputData dimension does not match to inputDataRight");
331 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
332 for (size_type i=0; i<2; ++i) {
333 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
334 ">>> ERROR (ArrayTools::crossProductDataData): outputData dimension does not match to inputDataRight");
348 namespace FunctorArrayTools {
352 template <
typename OutputViewType,
typename leftInputViewType,
typename rightInputViewType >
354 OutputViewType _output;
355 const leftInputViewType _leftInput;
356 const rightInputViewType _rightInput;
357 const bool _hasField;
359 KOKKOS_INLINE_FUNCTION
361 leftInputViewType leftInput_,
362 rightInputViewType rightInput_,
363 const bool hasField_)
364 : _output(output_), _leftInput(leftInput_), _rightInput(rightInput_),
365 _hasField(hasField_) {}
367 KOKKOS_INLINE_FUNCTION
368 void operator()(
const size_type iter)
const {
369 size_type cell, field(0), point;
370 size_type rightRank = _rightInput.rank();
373 unrollIndex( cell, field, point,
379 unrollIndex( cell, point,
384 auto result = ( _hasField ? Kokkos::subview(_output, cell, field, point, Kokkos::ALL(), Kokkos::ALL()) :
385 Kokkos::subview(_output, cell, point, Kokkos::ALL(), Kokkos::ALL()));
387 auto left = Kokkos::subview(_leftInput, cell, point, Kokkos::ALL());
389 auto right = (rightRank == 2 + size_type(_hasField)) ?
390 ( _hasField ? Kokkos::subview(_rightInput, field, point, Kokkos::ALL()) :
391 Kokkos::subview(_rightInput, point, Kokkos::ALL())) :
392 ( _hasField ? Kokkos::subview(_rightInput, cell, field, point, Kokkos::ALL()) :
393 Kokkos::subview(_rightInput, cell, point, Kokkos::ALL()));
395 const ordinal_type iend = result.extent(0);
396 const ordinal_type jend = result.extent(1);
397 for (ordinal_type i=0; i<iend; ++i)
398 for (ordinal_type j=0; j<jend; ++j)
399 result(i, j) = left(i)*right(j);
404 template<
typename DeviceType>
405 template<
typename outputValueType,
class ...outputProperties,
406 typename leftInputValueType,
class ...leftInputProperties,
407 typename rightInputValueType,
class ...rightInputProperties>
410 outerProduct( Kokkos::DynRankView<outputValueType, outputProperties...> output,
411 const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInput,
412 const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInput,
413 const bool hasField ) {
415 typedef Kokkos::DynRankView<outputValueType, outputProperties...> OutputViewType;
416 typedef const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInputViewType;
417 typedef const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInputViewType;
420 const size_type loopSize = ( hasField ? output.extent(0)*output.extent(1)*output.extent(2) :
421 output.extent(0)*output.extent(1) );
422 Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
423 Kokkos::parallel_for( policy, FunctorType(output, leftInput, rightInput, hasField) );
427 template<
typename DeviceType>
428 template<
typename outputFieldValueType,
class ...outputFieldProperties,
429 typename inputDataValueType,
class ...inputDataProperties,
430 typename inputFieldValueType,
class ...inputFieldProperties>
434 const Kokkos::DynRankView<inputDataValueType, inputDataProperties...> inputData,
435 const Kokkos::DynRankView<inputFieldValueType, inputFieldProperties...> inputFields ) {
437 #ifdef HAVE_INTREPID2_DEBUG
446 INTREPID2_TEST_FOR_EXCEPTION( inputData.rank() != 3, std::invalid_argument,
447 ">>> ERROR (ArrayTools::outerProductDataField): inputData must have rank 3");
448 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(2) < 2 || inputData.extent(2) > 3, std::invalid_argument,
449 ">>> ERROR (ArrayTools::outerProductDataField): inputData dimension(2) must be 2 or 3");
452 INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() < 3 || inputFields.rank() > 4, std::invalid_argument,
453 ">>> ERROR (ArrayTools::outerProductDataField): inputFields must have rank 3 or 4" );
454 INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(inputFields.rank()-1) < 2 ||
455 inputFields.extent(inputFields.rank()-1) < 3, std::invalid_argument,
456 ">>> ERROR (ArrayTools::outerProductDataField): inputFields dimension (rank-1) must have rank 2 or 3" );
459 INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != 5, std::invalid_argument,
460 ">>> ERROR (ArrayTools::outerProductDataField): outputFields must have rank 5");
461 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(3) < 2 ||
462 outputFields.extent(3) > 3, std::invalid_argument,
463 ">>> ERROR (ArrayTools::outerProductDataField): outputFields dimension(3) must be 2 or 3");
464 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(4) < 2 ||
465 outputFields.extent(4) > 3, std::invalid_argument,
466 ">>> ERROR (ArrayTools::outerProductDataField): outputFields dimension(4) must be 2 or 3");
477 const size_type f1[] = { 0, 2, 3, 4 }, f2[] = { 0, 1, 2, 2 };
478 for (size_type i=0; i<4; ++i) {
479 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
480 ">>> ERROR (ArrayTools::outerProductDataField): outputFields dimension does not match with inputData");
487 if (inputFields.rank() == 4) {
490 const size_type f1[] = { 0, 1, 2 }, f2[] = { 0, 2, 3 };
491 for (size_type i=0; i<3; ++i) {
492 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
493 ">>> ERROR (ArrayTools::outerProductDataField): inputData dimension does not match with inputFields");
499 const size_type f1[] = { 0, 1, 2, 3, 4 }, f2[] = { 0, 1, 2, 3, 3 };
500 for (size_type i=0; i<5; ++i) {
501 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
502 ">>> ERROR (ArrayTools::outerProductDataField): outputFields dimension does not match with inputFields");
508 const size_type f1[] = { 1, 2 }, f2[] = { 1, 2 };
509 for (size_type i=0; i<2; ++i) {
510 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
511 ">>> ERROR (ArrayTools::outerProductDataField): inputData dimension does not match with inputFields");
517 const size_type f1[] = { 1, 2, 3, 4 }, f2[] = { 0, 1, 2, 2 };
518 for (size_type i=0; i<4; ++i) {
519 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
520 ">>> ERROR (ArrayTools::outerProductDataField): outputFields dimension does not match with inputFields");
534 template<
typename DeviceType>
535 template<
typename outputDataValueType,
class ...outputDataProperties,
536 typename inputDataLeftValuetype,
class ...inputDataLeftProperties,
537 typename inputDataRightValueType,
class ...inputDataRightProperties>
541 const Kokkos::DynRankView<inputDataLeftValuetype, inputDataLeftProperties...> inputDataLeft,
542 const Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRight ) {
544 #ifdef HAVE_INTREPID2_DEBUG
553 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.rank() != 3, std::invalid_argument,
554 ">>> ERROR (ArrayTools::outerProductDataField): inputDataLeft must have rank 3");
555 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(2) < 2 || inputDataLeft.extent(2) > 3, std::invalid_argument,
556 ">>> ERROR (ArrayTools::outerProductDataField): inputDataLeft dimension(2) must be 2 or 3");
559 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() < 2 || inputDataRight.rank() > 3, std::invalid_argument,
560 ">>> ERROR (ArrayTools::outerProductDataField): inputDataRight must have rank 2 or 3" );
561 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(inputDataRight.rank()-1) < 2 ||
562 inputDataRight.extent(inputDataRight.rank()-1) < 3, std::invalid_argument,
563 ">>> ERROR (ArrayTools::outerProductDataField): inputDataRight dimension (rank-1) must have rank 2 or 3" );
566 INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != 4, std::invalid_argument,
567 ">>> ERROR (ArrayTools::outerProductDataField): outputData must have rank 5");
568 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(2) < 2 ||
569 outputData.extent(2) > 3, std::invalid_argument,
570 ">>> ERROR (ArrayTools::outerProductDataField): outputData dimension(3) must be 2 or 3");
571 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(3) < 2 ||
572 outputData.extent(3) > 3, std::invalid_argument,
573 ">>> ERROR (ArrayTools::outerProductDataField): outputData dimension(4) must be 2 or 3");
584 const size_type f1[] = { 0, 1, 2, 3 }, f2[] = { 0, 1, 2, 2 };
585 for (size_type i=0; i<4; ++i) {
586 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataLeft.extent(f2[i]), std::invalid_argument,
587 ">>> ERROR (ArrayTools::outerProductDataField): outputData dimension does not match with inputDataLeft");
594 if (inputDataRight.rank() == 3) {
596 for (size_type i=0; i<inputDataLeft.rank(); ++i) {
597 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(i) != inputDataRight.extent(i), std::invalid_argument,
598 ">>> ERROR (ArrayTools::outerProductDataField): inputDataLeft dimension does not match with inputDataRight");
603 const size_type f1[] = { 0, 1, 2, 3 }, f2[] = { 0, 1, 2, 2 };
604 for (size_type i=0; i<4; ++i) {
605 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
606 ">>> ERROR (ArrayTools::outerProductDataField): outputData dimension does not match with inputDataRight");
612 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
613 for (size_type i=0; i<2; ++i) {
614 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
615 ">>> ERROR (ArrayTools::outerProductDataField): inputDataLeft dimension does not match with inputDataRight");
621 const size_type f1[] = { 1, 2, 3 }, f2[] = { 0, 1, 1 };
622 for (size_type i=0; i<3; ++i) {
623 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
624 ">>> ERROR (ArrayTools::outerProductDataField): outputData dimension does not match with inputDataRight");
638 namespace FunctorArrayTools {
642 template <
typename OutputViewType,
643 typename leftInputViewType,
644 typename rightInputViewType,
645 ordinal_type leftInputRank,
646 ordinal_type rightInputRank,
650 OutputViewType _output;
651 const leftInputViewType _leftInput;
652 const rightInputViewType _rightInput;
654 const ordinal_type _iend;
655 const ordinal_type _jend;
657 using value_type =
typename OutputViewType::value_type;
659 KOKKOS_INLINE_FUNCTION
661 leftInputViewType leftInput_,
662 rightInputViewType rightInput_)
663 : _output(output_), _leftInput(leftInput_), _rightInput(rightInput_),
664 _iend(output_.extent_int(rank(output_)-1)), _jend(rightInput_.extent_int(rightInputRank-1))
668 KOKKOS_INLINE_FUNCTION
669 void operator()(
const ordinal_type cl,
670 const ordinal_type bf,
671 const ordinal_type pt)
const
673 apply_matvec_product(cl, bf, pt);
676 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
677 KOKKOS_FORCEINLINE_FUNCTION
678 typename std::enable_if_t<l==4 && r==4 && hf, void>
679 apply_matvec_product(
const ordinal_type &cl,
680 const ordinal_type &bf,
681 const ordinal_type &pt)
const {
682 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
684 for (ordinal_type i=0;i<_iend;++i) {
686 for (ordinal_type j=0;j<_jend;++j)
687 tmp += _leftInput(cl,lpt, j,i)*_rightInput(cl,bf,pt, j);
688 _output(cl,bf,pt, i) = tmp;
691 for (ordinal_type i=0;i<_iend;++i) {
693 for (ordinal_type j=0;j<_jend;++j)
694 tmp += _leftInput(cl,lpt, i,j)*_rightInput(cl,bf,pt, j);
695 _output(cl,bf,pt, i) = tmp;
700 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
701 KOKKOS_FORCEINLINE_FUNCTION
702 typename std::enable_if_t<l==4 && r==3 && hf, void>
703 apply_matvec_product(
const ordinal_type &cl,
704 const ordinal_type &bf,
705 const ordinal_type &pt)
const {
706 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
708 for (ordinal_type i=0;i<_iend;++i) {
710 for (ordinal_type j=0;j<_jend;++j)
711 tmp += _leftInput(cl,lpt, j,i)*_rightInput(bf,pt, j);
712 _output(cl,bf,pt, i) = tmp;
715 for (ordinal_type i=0;i<_iend;++i) {
717 for (ordinal_type j=0;j<_jend;++j)
718 tmp += _leftInput(cl,lpt, i,j)*_rightInput(bf,pt, j);
719 _output(cl,bf,pt, i) = tmp;
724 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
725 KOKKOS_FORCEINLINE_FUNCTION
726 typename std::enable_if_t<l==3 && r==4 && hf, void>
727 apply_matvec_product(
const ordinal_type &cl,
728 const ordinal_type &bf,
729 const ordinal_type &pt)
const {
730 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
731 for (ordinal_type i=0;i<_iend;++i)
732 _output(cl,bf,pt, i) = _leftInput(cl,lpt, i)*_rightInput(cl,bf,pt, i);
735 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
736 KOKKOS_FORCEINLINE_FUNCTION
737 typename std::enable_if_t<l==3 && r==3 && hf, void>
738 apply_matvec_product(
const ordinal_type &cl,
739 const ordinal_type &bf,
740 const ordinal_type &pt)
const {
741 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
742 for (ordinal_type i=0;i<_iend;++i)
743 _output(cl,bf,pt, i) = _leftInput(cl,lpt, i)*_rightInput(bf,pt, i);
746 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
747 KOKKOS_FORCEINLINE_FUNCTION
748 typename std::enable_if_t<l==2 && r==4 && hf, void>
749 apply_matvec_product(
const ordinal_type &cl,
750 const ordinal_type &bf,
751 const ordinal_type &pt)
const {
752 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
753 const value_type & val = _leftInput(cl,lpt);
754 for (ordinal_type i=0;i<_iend;++i) {
755 _output(cl,bf,pt, i) = val*_rightInput(cl,bf,pt, i);
759 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
760 KOKKOS_FORCEINLINE_FUNCTION
761 typename std::enable_if_t<l==2 && r==3 && hf, void>
762 apply_matvec_product(
const ordinal_type &cl,
763 const ordinal_type &bf,
764 const ordinal_type &pt)
const {
765 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
766 const value_type & val = _leftInput(cl,lpt);
767 for (ordinal_type i=0;i<_iend;++i) {
768 _output(cl,bf,pt, i) = val*_rightInput(bf,pt, i);
773 KOKKOS_INLINE_FUNCTION
774 void operator()(
const ordinal_type cl,
775 const ordinal_type pt)
const
777 apply_matvec_product(cl, pt);
780 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
781 KOKKOS_FORCEINLINE_FUNCTION
782 typename std::enable_if_t<l==4 && r==3 && !hf, void>
783 apply_matvec_product(
const ordinal_type &cl,
784 const ordinal_type &pt)
const {
785 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
787 for (ordinal_type i=0;i<_iend;++i) {
789 for (ordinal_type j=0;j<_jend;++j)
790 tmp += _leftInput(cl,lpt, j,i)*_rightInput(cl,pt, j);
791 _output(cl,pt, i) = tmp;
794 for (ordinal_type i=0;i<_iend;++i) {
796 for (ordinal_type j=0;j<_jend;++j)
797 tmp += _leftInput(cl,lpt, i,j)*_rightInput(cl,pt, j);
798 _output(cl,pt, i) = tmp;
803 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
804 KOKKOS_FORCEINLINE_FUNCTION
805 typename std::enable_if_t<l==4 && r==2 && !hf, void>
806 apply_matvec_product(
const ordinal_type &cl,
807 const ordinal_type &pt)
const {
808 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
810 for (ordinal_type i=0;i<_iend;++i) {
812 for (ordinal_type j=0;j<_jend;++j)
813 tmp += _leftInput(cl,lpt, j,i)*_rightInput(pt, j);
814 _output(cl,pt, i) = tmp;
817 for (ordinal_type i=0;i<_iend;++i) {
819 for (ordinal_type j=0;j<_jend;++j)
820 tmp += _leftInput(cl,lpt, i,j)*_rightInput(pt, j);
821 _output(cl,pt, i) = tmp;
826 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
827 KOKKOS_FORCEINLINE_FUNCTION
828 typename std::enable_if_t<l==3 && r==3 && !hf, void>
829 apply_matvec_product(
const ordinal_type &cl,
830 const ordinal_type &pt)
const {
831 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
832 for (ordinal_type i=0;i<_iend;++i)
833 _output(cl,pt, i) = _leftInput(cl,lpt, i)*_rightInput(cl,pt, i);
836 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
837 KOKKOS_FORCEINLINE_FUNCTION
838 typename std::enable_if_t<l==3 && r==2 && !hf, void>
839 apply_matvec_product(
const ordinal_type &cl,
840 const ordinal_type &pt)
const {
841 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
842 for (ordinal_type i=0;i<_iend;++i)
843 _output(cl,pt, i) = _leftInput(cl,lpt, i)*_rightInput(pt, i);
846 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
847 KOKKOS_FORCEINLINE_FUNCTION
848 typename std::enable_if_t<l==2 && r==3 && !hf, void>
849 apply_matvec_product(
const ordinal_type &cl,
850 const ordinal_type &pt)
const {
851 const auto lpt = (_leftInput.extent(1) == 1 ? size_type(0) : pt);
852 const value_type & val = _leftInput(cl,lpt);
853 for (ordinal_type i=0;i<_iend;++i) {
854 _output(cl,pt, i) = val*_rightInput(cl,pt, i);
858 template <ordinal_type l=leftInputRank, ordinal_type r=rightInputRank,
bool hf=hasField>
859 KOKKOS_FORCEINLINE_FUNCTION
860 typename std::enable_if_t<l==2 && r==2 && !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 const value_type & val = _leftInput(cl,lpt);
865 for (ordinal_type i=0;i<_iend;++i) {
866 _output(cl,pt, i) = val*_rightInput(pt, i);
872 template<
typename DeviceType>
873 template<
typename outputValueType,
class ...outputProperties,
874 typename leftInputValueType,
class ...leftInputProperties,
875 typename rightInputValueType,
class ...rightInputProperties>
878 matvecProduct( Kokkos::DynRankView<outputValueType, outputProperties...> output,
879 const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInput,
880 const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInput,
882 const bool isTranspose ) {
884 using Output = Kokkos::DynRankView<outputValueType, outputProperties...>;
885 using Left =
const Kokkos::DynRankView<leftInputValueType, leftInputProperties...>;
886 using Right =
const Kokkos::DynRankView<rightInputValueType,rightInputProperties...>;
914 const ordinal_type l = leftInput.rank();
915 const ordinal_type r = rightInput.rank();
917 using range_policy2 = Kokkos::MDRangePolicy< ExecSpaceType, Kokkos::Rank<2>, Kokkos::IndexType<ordinal_type> >;
918 range_policy2 policy2( { 0, 0 }, { output.extent(0), output.extent(1) } );
920 using range_policy3 = Kokkos::MDRangePolicy< ExecSpaceType, Kokkos::Rank<3>, Kokkos::IndexType<ordinal_type> >;
921 range_policy3 policy3( { 0, 0, 0 }, { output.extent(0), output.extent(1), output.extent(2) } );
924 const ordinal_type lr = l * 10 + r;
925 const auto &ov = output;
926 const auto &lv = leftInput;
927 const auto &rv = rightInput;
938 case 4: { FT44TT f(ov,lv,rv); Kokkos::parallel_for( policy3, f ); }
break;
939 default: { FT43TT f(ov,lv,rv); Kokkos::parallel_for( policy3, f ); }
946 case 4: { FT44TF f(ov,lv,rv); Kokkos::parallel_for( policy3, f ); }
break;
947 default: { FT43TF f(ov,lv,rv); Kokkos::parallel_for( policy3, f ); }
955 case 34: { FT34TF f(ov,lv,rv); Kokkos::parallel_for( policy3, f ); }
break;
956 case 33: { FT33TF f(ov,lv,rv); Kokkos::parallel_for( policy3, f ); }
break;
957 case 24: { FT24TF f(ov,lv,rv); Kokkos::parallel_for( policy3, f ); }
break;
958 default: { FT23TF f(ov,lv,rv); Kokkos::parallel_for( policy3, f ); }
971 case 3: { FT43FT f(ov,lv,rv); Kokkos::parallel_for( policy2, f ); }
break;
972 default: { FT42FT f(ov,lv,rv); Kokkos::parallel_for( policy2, f ); }
979 case 3: { FT43FF f(ov,lv,rv); Kokkos::parallel_for( policy2, f ); }
break;
980 default: { FT42FF f(ov,lv,rv); Kokkos::parallel_for( policy2, f ); }
988 case 33: { FT33FF f(ov,lv,rv); Kokkos::parallel_for( policy2, f ); }
break;
989 case 32: { FT32FF f(ov,lv,rv); Kokkos::parallel_for( policy2, f ); }
break;
990 case 23: { FT23FF f(ov,lv,rv); Kokkos::parallel_for( policy2, f ); }
break;
991 default: { FT22FF f(ov,lv,rv); Kokkos::parallel_for( policy2, f ); }
997 template<
typename DeviceType>
998 template<
typename outputFieldValueType,
class ...outputFieldProperties,
999 typename inputDataValueType,
class ...inputDataProperties,
1000 typename inputFieldValueType,
class ...inputFieldProperties>
1003 const Kokkos::DynRankView<inputDataValueType, inputDataProperties...> inputData,
1004 const Kokkos::DynRankView<inputFieldValueType, inputFieldProperties...> inputFields,
1005 const char transpose ) {
1007 #ifdef HAVE_INTREPID2_DEBUG
1016 INTREPID2_TEST_FOR_EXCEPTION( inputData.rank() < 2 || inputData.rank() > 4, std::invalid_argument,
1017 ">>> ERROR (ArrayTools::matvecProductDataField): inputData must have rank 2,3 or 4" );
1018 if (inputData.rank() > 2) {
1019 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(2) < 1 ||
1020 inputData.extent(2) > 3, std::invalid_argument,
1021 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension(2) must be 1,2 or 3");
1023 if (inputData.rank() == 4) {
1024 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(3) < 1 ||
1025 inputData.extent(3) > 3, std::invalid_argument,
1026 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension(3) must be 1,2 or 3");
1030 INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() < 3 ||
1031 inputFields.rank() > 4, std::invalid_argument,
1032 ">>> ERROR (ArrayTools::matvecProductDataField): inputFields must have rank 3 or 4" );
1033 INTREPID2_TEST_FOR_EXCEPTION( (inputFields.rank()-1) < 1 ||
1034 (inputFields.rank()-1) > 3, std::invalid_argument,
1035 ">>> ERROR (ArrayTools::matvecProductDataField): inputFields dimension(rank-1) must be 1,2, or 3" );
1038 INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != 4, std::invalid_argument,
1039 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields must have rank 4" );
1040 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(3) < 1 ||
1041 outputFields.extent(3) > 3, std::invalid_argument,
1042 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension(3) must be 1,2 or 3" );
1055 if (inputData.extent(1) > 1) {
1056 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(2) != inputData.extent(1), std::invalid_argument,
1057 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension(2) must match to inputData dimension(1)" );
1059 if (inputData.rank() == 2) {
1060 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(0) != inputData.extent(0), std::invalid_argument,
1061 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension(0) must match to inputData dimension(0)" );
1063 if (inputData.rank() == 3) {
1064 const size_type f1[] = { 0, 3 }, f2[] = { 0, 2 };
1065 for (size_type i=0; i<2; ++i) {
1066 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
1067 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension does not match to inputData dimension" );
1070 if (inputData.rank() == 4) {
1071 const size_type f1[] = { 0, 3, 3 }, f2[] = { 0, 2, 3 };
1072 for (size_type i=0; i<3; ++i) {
1073 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
1074 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension does not match to inputData dimension" );
1081 if (inputFields.rank() == 4) {
1083 if (inputData.extent(1) > 1) {
1084 INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(2) != inputData.extent(1), std::invalid_argument,
1085 ">>> ERROR (ArrayTools::matvecProductDataField): inputFields dimension (2) does not match to inputData dimension (1)" );
1087 if (inputData.rank() == 2) {
1088 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(0) != inputFields.extent(0), std::invalid_argument,
1089 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension (0) does not match to inputFields dimension (0)" );
1091 if (inputData.rank() == 3) {
1092 const size_type f1[] = { 0, 2 }, f2[] = { 0, 3 };
1093 for (size_type i=0; i<2; ++i) {
1094 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1095 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension does not match to inputFields dimension" );
1098 if (inputData.rank() == 4) {
1099 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 3, 3 };
1100 for (size_type i=0; i<3; ++i) {
1101 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1102 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension does not match to inputFields dimension" );
1107 for (size_type i=0; i<outputFields.rank(); ++i) {
1108 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(i) != inputFields.extent(i), std::invalid_argument,
1109 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension does not match to inputFields dimension" );
1113 if (inputData.extent(1) > 1) {
1114 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(1) != inputFields.extent(1), std::invalid_argument,
1115 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension(1) does not match to inputFields dimension (1)" );
1117 if (inputData.rank() == 3) {
1118 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(2) != inputFields.extent(2), std::invalid_argument,
1119 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension(2) does not match to inputFields dimension (2)" );
1121 if (inputData.rank() == 4) {
1122 const size_type f1[] = { 2, 3 }, f2[] = { 2, 2 };
1123 for (size_type i=0; i<2; ++i) {
1124 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1125 ">>> ERROR (ArrayTools::matvecProductDataField): inputData dimension does not match to inputFields dimension" );
1131 const size_type f1[] = { 1, 2, 3 }, f2[] = { 0, 1, 2 };
1132 for (size_type i=0; i<3; ++i) {
1133 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1134 ">>> ERROR (ArrayTools::matvecProductDataField): outputFields dimension does not match to inputFields dimension" );
1145 transpose ==
't' || transpose ==
'T' );
1150 template<
typename DeviceType>
1151 template<
typename outputDataValueType,
class ...outputDataProperties,
1152 typename inputDataLeftValueType,
class ...inputDataLeftProperties,
1153 typename inputDataRightValueType,
class ...inputDataRightProperties>
1157 const Kokkos::DynRankView<inputDataLeftValueType, inputDataLeftProperties...> inputDataLeft,
1158 const Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRight,
1159 const char transpose ) {
1161 #ifdef HAVE_INTREPID2_DEBUG
1170 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.rank() < 2 ||
1171 inputDataLeft.rank() > 4, std::invalid_argument,
1172 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft must have rank 2,3 or 4" );
1174 if (inputDataLeft.rank() > 2) {
1175 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(2) < 1 ||
1176 inputDataLeft.extent(2) > 3, std::invalid_argument,
1177 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension(2) must be 1, 2 or 3");
1179 if (inputDataLeft.rank() == 4) {
1180 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(3) < 1 ||
1181 inputDataLeft.extent(3) > 3, std::invalid_argument,
1182 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension(3) must be 1, 2 or 3");
1186 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() < 2 ||
1187 inputDataRight.rank() > 3, std::invalid_argument,
1188 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataRight must have rank 2 or 3" );
1189 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(inputDataRight.rank()-1) < 1 ||
1190 inputDataRight.extent(inputDataRight.rank()-1) > 3, std::invalid_argument,
1191 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataRight dimension (rank-1) must be 1,2 or 3" );
1194 INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != 3, std::invalid_argument,
1195 ">>> ERROR (ArrayTools::matvecProductDataData): outputData must have rank 3" );
1196 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(2) < 1 ||
1197 outputData.extent(2) > 3, std::invalid_argument,
1198 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension(2) must be 1, 2 or 3");
1211 if (inputDataLeft.extent(1) > 1) {
1212 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(1) != inputDataLeft.extent(1), std::invalid_argument,
1213 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension(1) muat match inputDataLeft dimension(1)" );
1215 if (inputDataLeft.rank() == 2) {
1216 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(0) != inputDataLeft.extent(0), std::invalid_argument,
1217 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension(0) muat match inputDataLeft dimension(0)" );
1219 if (inputDataLeft.rank() == 3) {
1220 const size_type f1[] = { 0, 2 }, f2[] = { 0, 2 };
1221 for (size_type i=0; i<2; ++i) {
1222 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataLeft.extent(f2[i]), std::invalid_argument,
1223 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension muat match inputDataLeft dimension" );
1226 if (inputDataLeft.rank() == 4) {
1227 size_type f1[] = { 0, 2}, f2[] = { 0, 2};
1228 if (transpose) f2[1] = 3;
1229 for (size_type i=0; i<2; ++i) {
1230 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataLeft.extent(f2[i]), std::invalid_argument,
1231 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension muat match inputDataLeft dimension" );
1238 if (inputDataRight.rank() == 3) {
1240 if (inputDataLeft.extent(1) > 1) {
1241 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(1), std::invalid_argument,
1242 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension (1) muat match to inputDataRight dimension (1)" );
1244 if (inputDataLeft.rank() == 2) {
1245 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(0) != inputDataRight.extent(0), std::invalid_argument,
1246 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension (0) muat match to inputDataRight dimension (0)" );
1248 if (inputDataLeft.rank() == 3) {
1249 const size_type f1[] = { 0, 2 }, f2[] = { 0, 2 };
1250 for (size_type i=0; i<2; ++i) {
1251 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1252 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension muat match to inputDataRight dimension" );
1255 if (inputDataLeft.rank() == 4) {
1256 size_type f1[] = { 0, 3}, f2[] = { 0, 2};
1257 if (transpose) f1[1] = 2;
1258 for (size_type i=0; i<2; ++i) {
1259 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1260 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension muat match to inputDataRight dimension" );
1265 for (size_type i=0; i<outputData.rank()-1; ++i) {
1266 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(i) != inputDataRight.extent(i), std::invalid_argument,
1267 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension muat match to inputDataRight dimension" );
1271 if (inputDataLeft.extent(1) > 1) {
1272 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(0), std::invalid_argument,
1273 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension (1) does mot match to inputDataright dimension (0)" );
1275 if (inputDataLeft.rank() == 3) {
1276 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(2) != inputDataRight.extent(1), std::invalid_argument,
1277 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension (2) does mot match to inputDataright dimension (1)" );
1279 if (inputDataLeft.rank() == 4) {
1280 const size_type f1[] = { 2, 3 }, f2[] = { 1, 1 };
1281 for (size_type i=0; i<2; ++i) {
1282 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1283 ">>> ERROR (ArrayTools::matvecProductDataData): inputDataLeft dimension muat match to inputDataRight dimension" );
1289 const size_type f1[] = { 1, 2 }, f2[] = { 0, 1 };
1290 for (size_type i=0; i<2; ++i) {
1291 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1292 ">>> ERROR (ArrayTools::matvecProductDataData): outputData dimension muat match to inputDataRight dimension" );
1303 transpose ==
't' || transpose ==
'T' );
1307 namespace FunctorArrayTools {
1311 template <
typename OutputViewType,
typename leftInputViewType,
typename rightInputViewType >
1313 OutputViewType _output;
1314 leftInputViewType _leftInput;
1315 rightInputViewType _rightInput;
1316 const bool _hasField, _isTranspose;
1317 typedef typename leftInputViewType::value_type value_type;
1319 KOKKOS_INLINE_FUNCTION
1321 leftInputViewType leftInput_,
1322 rightInputViewType rightInput_,
1323 const bool hasField_,
1324 const bool isTranspose_)
1325 : _output(output_), _leftInput(leftInput_), _rightInput(rightInput_),
1326 _hasField(hasField_), _isTranspose(isTranspose_) {}
1328 KOKKOS_INLINE_FUNCTION
1329 void operator()(
const size_type iter)
const {
1330 size_type cell(0), field(0), point(0);
1331 size_type leftRank = _leftInput.rank();
1332 size_type rightRank = _rightInput.rank();
1335 unrollIndex( cell, field, point,
1341 unrollIndex( cell, point,
1346 auto result = ( _hasField ? Kokkos::subview(_output, cell, field, point, Kokkos::ALL(), Kokkos::ALL()) :
1347 Kokkos::subview(_output, cell, point, Kokkos::ALL(), Kokkos::ALL()));
1349 const auto lpoint = (_leftInput.extent(1) == 1 ? 0 : point);
1350 auto left = ( leftRank == 4 ? Kokkos::subview(_leftInput, cell, lpoint, Kokkos::ALL(), Kokkos::ALL()) :
1351 leftRank == 3 ? Kokkos::subview(_leftInput, cell, lpoint, Kokkos::ALL()) :
1352 Kokkos::subview(_leftInput, cell, lpoint) );
1355 const bool hasCell = (_hasField ? rightRank == 5 : rightRank == 4);
1356 auto right = ( _hasField ? ( hasCell ? Kokkos::subview(_rightInput, cell, field, point, Kokkos::ALL(), Kokkos::ALL()) :
1357 Kokkos::subview(_rightInput, field, point, Kokkos::ALL(), Kokkos::ALL())):
1358 ( hasCell ? Kokkos::subview(_rightInput, cell, point, Kokkos::ALL(), Kokkos::ALL()) :
1359 Kokkos::subview(_rightInput, point, Kokkos::ALL(), Kokkos::ALL())));
1361 const ordinal_type iend = result.extent(0);
1362 const ordinal_type jend = result.extent(1);
1367 const size_type kend = right.extent(0);
1368 for (ordinal_type i=0; i<iend; ++i)
1369 for (ordinal_type j=0; j<jend; ++j) {
1370 result(i, j) = value_type(0);
1371 for (size_type k=0; k<kend; ++k)
1372 result(i, j) += left(k, i) * right(k, j);
1375 const size_type kend = right.extent(0);
1376 for (ordinal_type i=0; i<iend; ++i)
1377 for (ordinal_type j=0; j<jend; ++j) {
1378 result(i, j) = value_type(0);
1379 for (size_type k=0; k<kend; ++k)
1380 result(i, j) += left(i, k) * right(k, j);
1386 for (ordinal_type i=0; i<iend; ++i)
1387 for (ordinal_type j=0; j<jend; ++j)
1388 result(i, j) = left(i) * right(i, j);
1392 for (ordinal_type i=0; i<iend; ++i)
1393 for (ordinal_type j=0; j<jend; ++j)
1394 result(i, j) = left() * right(i, j);
1402 template<
typename DeviceType>
1403 template<
typename outputValueType,
class ...outputProperties,
1404 typename leftInputValueType,
class ...leftInputProperties,
1405 typename rightInputValueType,
class ...rightInputProperties>
1408 matmatProduct( Kokkos::DynRankView<outputValueType, outputProperties...> output,
1409 const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInput,
1410 const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInput,
1411 const bool hasField,
1412 const bool isTranspose ) {
1414 typedef Kokkos::DynRankView<outputValueType, outputProperties...> OutputViewType;
1415 typedef const Kokkos::DynRankView<leftInputValueType, leftInputProperties...> leftInputViewType;
1416 typedef const Kokkos::DynRankView<rightInputValueType,rightInputProperties...> rightInputViewType;
1419 const size_type loopSize = ( hasField ? output.extent(0)*output.extent(1)*output.extent(2) :
1420 output.extent(0)*output.extent(1) );
1421 Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
1422 Kokkos::parallel_for( policy, FunctorType(output, leftInput, rightInput, hasField, isTranspose) );
1428 template<
typename DeviceType>
1429 template<
typename outputFieldValueType,
class ...outputFieldProperties,
1430 typename inputDataValueType,
class ...inputDataProperties,
1431 typename inputFieldValueType,
class ...inputFieldProperties>
1435 const Kokkos::DynRankView<inputDataValueType, inputDataProperties...> inputData,
1436 const Kokkos::DynRankView<inputFieldValueType, inputFieldProperties...> inputFields,
1437 const char transpose ) {
1439 #ifdef HAVE_INTREPID2_DEBUG
1448 INTREPID2_TEST_FOR_EXCEPTION( inputData.rank() < 2 ||
1449 inputData.rank() > 4, std::invalid_argument,
1450 ">>> ERROR (ArrayTools::matmatProductDataField): inputData must have rank 2,3 or 4" );
1451 if (inputData.rank() > 2) {
1452 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(2) < 1 ||
1453 inputData.extent(2) > 3, std::invalid_argument,
1454 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension (2) must be 1,2 or 3" );
1456 if (inputData.rank() == 4) {
1457 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(3) < 1 ||
1458 inputData.extent(3) > 3, std::invalid_argument,
1459 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension (3) must be 1,2 or 3" );
1463 INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() < 4 ||
1464 inputFields.rank() > 5, std::invalid_argument,
1465 ">>> ERROR (ArrayTools::matmatProductDataField): inputFields must have rank 4 or 5");
1466 INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(inputFields.rank()-1) < 1 ||
1467 inputFields.extent(inputFields.rank()-1) > 3, std::invalid_argument,
1468 ">>> ERROR (ArrayTools::matmatProductDataField): inputFields dimension (rank-1) must be 1,2 or 3" );
1469 INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(inputFields.rank()-2) < 1 ||
1470 inputFields.extent(inputFields.rank()-2) > 3, std::invalid_argument,
1471 ">>> ERROR (ArrayTools::matmatProductDataField): inputFields dimension (rank-2) must be 1,2 or 3" );
1474 INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != 5, std::invalid_argument,
1475 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields must have rank 5" );
1476 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(3) < 1 ||
1477 outputFields.extent(3) > 3, std::invalid_argument,
1478 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension (3) must be 1,2 or 3" );
1479 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(4) < 1 ||
1480 outputFields.extent(4) > 3, std::invalid_argument,
1481 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension (4) must be 1,2 or 3" );
1494 if (inputData.extent(1) > 1) {
1495 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(2) != inputData.extent(1), std::invalid_argument,
1496 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension (2) does not match to inputData dimension (1)" );
1498 if (inputData.rank() == 2) {
1499 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(0) != inputData.extent(0), std::invalid_argument,
1500 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension (0) does not match to inputData dimension (0)" );
1502 if (inputData.rank() == 3) {
1503 const size_type f1[] = { 0, 3, 4 }, f2[] = { 0, 2, 2 };
1504 for (size_type i=0; i<3; ++i) {
1505 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
1506 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension does not match to inputData dimension" );
1509 if (inputData.rank() == 4) {
1510 const size_type f1[] = { 0, 3, 4 }, f2[] = { 0, 2, 3 };
1511 for (size_type i=0; i<3; ++i) {
1512 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputData.extent(f2[i]), std::invalid_argument,
1513 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension does not match to inputData dimension" );
1520 if (inputFields.rank() == 5) {
1522 if (inputData.extent(1) > 1) {
1523 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(1) != inputFields.extent(2), std::invalid_argument,
1524 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension (1) does not match to inputFields dimension (2)" );
1526 if (inputData.rank() == 2) {
1527 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(0) != inputFields.extent(0), std::invalid_argument,
1528 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension (0) does not match to inputFields dimension (0)" );
1530 if (inputData.rank() == 3) {
1532 const size_type f1[] = { 0, 2, 2 }, f2[] = { 0, 3, 4 };
1533 for (size_type i=0; i<3; ++i) {
1534 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1535 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension does not match to inputFields dimension" );
1538 if (inputData.rank() == 4) {
1539 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 3, 4 };
1540 for (size_type i=0; i<3; ++i) {
1541 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1542 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension does not match to inputFields dimension" );
1547 for (size_type i=0; i<outputFields.rank(); ++i) {
1548 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(i) != inputFields.extent(i), std::invalid_argument,
1549 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension does not match to inputFields dimension" );
1553 if (inputData.extent(1) > 1) {
1554 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(1) != inputFields.extent(1), std::invalid_argument,
1555 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension (1) does not match to inputFields dimension (1)" );
1557 if (inputData.rank() == 3) {
1558 const size_type f1[] = { 2, 2 }, f2[] = { 2, 3 };
1559 for (size_type i=0; i<2; ++i) {
1560 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1561 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension does not match to inputFields dimension" );
1564 if (inputData.rank() == 4) {
1565 const size_type f1[] = { 2, 3 }, f2[] = { 2, 3 };
1566 for (size_type i=0; i<2; ++i) {
1567 INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1568 ">>> ERROR (ArrayTools::matmatProductDataField): inputData dimension does not match to inputFields dimension" );
1574 const size_type f1[] = { 1, 2, 3, 4 }, f2[] = { 0, 1, 2, 3 };
1575 for (size_type i=0; i<4; ++i) {
1576 INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(f1[i]) != inputFields.extent(f2[i]), std::invalid_argument,
1577 ">>> ERROR (ArrayTools::matmatProductDataField): outputFields dimension does not match to inputFields dimension" );
1588 transpose ==
't' || transpose ==
'T' );
1593 template<
typename DeviceType>
1594 template<
typename outputDataValueType,
class ...outputDataProperties,
1595 typename inputDataLeftValueType,
class ...inputDataLeftProperties,
1596 typename inputDataRightValueType,
class ...inputDataRightProperties>
1599 const Kokkos::DynRankView<inputDataLeftValueType, inputDataLeftProperties...> inputDataLeft,
1600 const Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRight,
1601 const char transpose ) {
1603 #ifdef HAVE_INTREPID2_DEBUG
1612 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.rank() < 2 ||
1613 inputDataLeft.rank() > 4, std::invalid_argument,
1614 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft must have rank 2,3 or 4" );
1615 if (inputDataLeft.rank() > 2) {
1616 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(2) < 1 ||
1617 inputDataLeft.extent(2) > 3, std::invalid_argument,
1618 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft dimension (2) must be 1,2 or 3" );
1620 if (inputDataLeft.rank() == 4) {
1621 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(3) < 1 ||
1622 inputDataLeft.extent(3) > 3, std::invalid_argument,
1623 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft dimension (3) must be 1,2 or 3" );
1627 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() < 3 ||
1628 inputDataRight.rank() > 4, std::invalid_argument,
1629 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataRight must have rank 3 or 4" );
1630 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(inputDataRight.rank()-1) < 1 ||
1631 inputDataRight.extent(inputDataRight.rank()-1) > 3, std::invalid_argument,
1632 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataRight (rank-1) must be 1,2 or 3" );
1633 INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(inputDataRight.rank()-2) < 1 ||
1634 inputDataRight.extent(inputDataRight.rank()-2) > 3, std::invalid_argument,
1635 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataRight (rank-2) must be 1,2 or 3" );
1638 INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != 4, std::invalid_argument,
1639 ">>> ERROR (ArrayTools::matmatProductDataData): outputData must have rank 4" );
1640 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(2) < 1 ||
1641 outputData.extent(2) > 3, std::invalid_argument,
1642 ">>> ERROR (ArrayTools::matmatProductDataData): outputData (2) must be 1,2 or 3" );
1643 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(3) < 1 ||
1644 outputData.extent(3) > 3, std::invalid_argument,
1645 ">>> ERROR (ArrayTools::matmatProductDataData): outputData (3) must be 1,2 or 3" );
1658 if (inputDataLeft.extent(1) > 1) {
1659 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(1) != inputDataLeft.extent(1), std::invalid_argument,
1660 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension (1) does not match to inputDataLeft dimension (1)" );
1662 if (inputDataLeft.rank() == 2) {
1663 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(0) != inputDataLeft.extent(0), std::invalid_argument,
1664 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension (0) does not match to inputDataLeft dimension (0)" );
1666 if (inputDataLeft.rank() == 3) {
1667 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 2, 2 };
1668 for (size_type i=0; i<3; ++i) {
1669 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataLeft.extent(f2[i]), std::invalid_argument,
1670 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension does not match to inputDataLeft dimension" );
1673 if (inputDataLeft.rank() == 4) {
1674 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 2, 3 };
1675 for (size_type i=0; i<3; ++i) {
1676 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataLeft.extent(f2[i]), std::invalid_argument,
1677 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension does not match to inputDataLeft dimension" );
1684 if (inputDataRight.rank() == 4) {
1686 if (inputDataLeft.extent(1) > 1) {
1687 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(1), std::invalid_argument,
1688 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft dimension (1) does not match to inputDataRight dimension (1)" );
1690 if (inputDataLeft.rank() == 2) {
1691 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(0) != inputDataRight.extent(0), std::invalid_argument,
1692 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft dimension (0) does not match to inputDataRight dimension (0)" );
1694 if (inputDataLeft.rank() == 3) {
1695 const size_type f1[] = { 0, 2, 2 }, f2[] = { 0, 2, 3 };
1696 for (size_type i=0; i<3; ++i) {
1697 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1698 ">>> ERROR (ArrayTools::matmatProductDataData): intputDataLeft dimension does not match to inputDataRight dimension" );
1701 if (inputDataLeft.rank() == 4) {
1702 const size_type f1[] = { 0, 2, 3 }, f2[] = { 0, 2, 3 };
1703 for (size_type i=0; i<3; ++i) {
1704 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1705 ">>> ERROR (ArrayTools::matmatProductDataData): intputDataLeft dimension does not match to inputDataRight dimension" );
1710 for (size_type i=0; i< outputData.rank(); ++i) {
1711 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(i) != inputDataRight.extent(i), std::invalid_argument,
1712 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension does not match to inputDataRight dimension" );
1716 if (inputDataLeft.extent(1) > 1) {
1717 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(0), std::invalid_argument,
1718 ">>> ERROR (ArrayTools::matmatProductDataData): inputDataLeft dimension (1) does not match to inputDataRight dimension (0)" );
1720 if (inputDataLeft.rank() == 3) {
1721 const size_type f1[] = { 2, 2 }, f2[] = { 1, 2 };
1722 for (size_type i=0; i<2; ++i) {
1723 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1724 ">>> ERROR (ArrayTools::matmatProductDataData): intputDataLeft dimension does not match to inputDataRight dimension" );
1727 if (inputDataLeft.rank() == 4) {
1728 const size_type f1[] = { 2, 3 }, f2[] = { 1, 2 };
1729 for (size_type i=0; i<2; ++i) {
1730 INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1731 ">>> ERROR (ArrayTools::matmatProductDataData): intputDataLeft dimension does not match to inputDataRight dimension" );
1736 const size_type f1[] = { 1, 2, 3 }, f2[] = { 0, 1, 2 };
1737 for (size_type i=0; i<3; ++i) {
1738 INTREPID2_TEST_FOR_EXCEPTION( outputData.extent(f1[i]) != inputDataRight.extent(f2[i]), std::invalid_argument,
1739 ">>> ERROR (ArrayTools::matmatProductDataData): outputData dimension does not match to inputDataRight dimension" );
1750 transpose ==
't' || transpose ==
'T' );