49 #ifndef __INTREPID2_ARRAYTOOLS_DEF_DOT_HPP__ 
   50 #define __INTREPID2_ARRAYTOOLS_DEF_DOT_HPP__ 
   54     namespace FunctorArrayTools {
 
   58     template < 
typename outputViewType, 
typename leftInputViewType, 
typename rightInputViewType >
 
   60       outputViewType _output;
 
   61       leftInputViewType _leftInput;
 
   62       rightInputViewType _rightInput;
 
   64       typedef typename outputViewType::value_type value_type;
 
   66       KOKKOS_INLINE_FUNCTION
 
   68               leftInputViewType leftInput_,
 
   69               rightInputViewType rightInput_,
 
   71         : _output(output_), _leftInput(leftInput_), _rightInput(rightInput_),
 
   72           _hasField(hasField_) {}
 
   74       KOKKOS_INLINE_FUNCTION
 
   75       void operator()(
const size_type iter)
 const {
 
   76         size_type cl(0), bf(0), pt(0);
 
   77         size_type leftRank(_leftInput.rank()), rightRank(_rightInput.rank());
 
   80           unrollIndex( cl, bf, pt, 
 
   91         auto result = ( _hasField ? Kokkos::subview(_output, cl, bf, pt) :
 
   92                                     Kokkos::subview(_output, cl,     pt));
 
   94         const auto left = (_leftInput.extent(1) == 1) ? Kokkos::subview(_leftInput, cl, 0, Kokkos::ALL(), Kokkos::ALL()) :
 
   95                                                            Kokkos::subview(_leftInput, cl, pt, Kokkos::ALL(), Kokkos::ALL());
 
   98         const auto right = (rightRank == leftRank + ordinal_type(_hasField)) ?
 
   99                              ( _hasField ? Kokkos::subview(_rightInput, cl, bf, pt, Kokkos::ALL(), Kokkos::ALL()) :
 
  100                                            Kokkos::subview(_rightInput, cl,     pt, Kokkos::ALL(), Kokkos::ALL())) :
 
  101                              ( _hasField ? Kokkos::subview(_rightInput,     bf, pt, Kokkos::ALL(), Kokkos::ALL()) :
 
  102                                            Kokkos::subview(_rightInput,         pt, Kokkos::ALL(), Kokkos::ALL()));
 
  104         const ordinal_type iend  = left.extent(0);
 
  105         const ordinal_type jend  = left.extent(1);
 
  108         for(ordinal_type i = 0; i < iend; ++i)
 
  109           for(ordinal_type j = 0; j < jend; ++j)
 
  110             tmp += left(i, j)*right(i, j);
 
  116   template<
typename SpT>
 
  117   template<
typename outputValueType,     
class ...outputProperties,
 
  118            typename leftInputValueType,  
class ...leftInputProperties,
 
  119            typename rightInputValueType, 
class ...rightInputProperties>
 
  122   dotMultiply(       Kokkos::DynRankView<outputValueType,    outputProperties...>      output,
 
  123                const Kokkos::DynRankView<leftInputValueType, leftInputProperties...>   leftInput,
 
  124                const Kokkos::DynRankView<rightInputValueType,rightInputProperties...>  rightInput, 
 
  125                const bool hasField ) {
 
  127     typedef Kokkos::DynRankView<outputValueType,    outputProperties...>      outputViewType;
 
  128     typedef Kokkos::DynRankView<leftInputValueType, leftInputProperties...>   leftInputViewType;
 
  129     typedef Kokkos::DynRankView<rightInputValueType,rightInputProperties...>  rightInputViewType;
 
  131     typedef typename ExecSpace< typename leftInputViewType::execution_space , SpT >::ExecSpaceType ExecSpaceType;
 
  133     const size_type loopSize = ( hasField ? output.extent(0)*output.extent(1)*output.extent(2) :
 
  134                                             output.extent(0)*output.extent(1) );
 
  135     Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
 
  136     Kokkos::parallel_for( policy, FunctorType(output, leftInput, rightInput, hasField) );
 
  141   template<
typename ExecSpaceType>
 
  142   template<
typename outputFieldValueType, 
class ...outputFieldProperties,
 
  143            typename inputDataValueType,   
class ...inputDataProperties,
 
  144            typename inputFieldValueType,  
class ...inputFieldProperties>
 
  148                         const Kokkos::DynRankView<inputDataValueType,  inputDataProperties...>   inputData,
 
  149                         const Kokkos::DynRankView<inputFieldValueType, inputFieldProperties...> inputFields ) {
 
  151 #ifdef HAVE_INTREPID2_DEBUG 
  153       if (inputFields.rank() > inputData.rank()) {
 
  154         INTREPID2_TEST_FOR_EXCEPTION( inputData.rank() < 2 || inputData.rank() > 4, std::invalid_argument,
 
  155                                         ">>> ERROR (ArrayTools::dotMultiplyDataField): Input data container must have rank 2, 3 or 4.");
 
  156         INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() != (inputData.rank()+1), std::invalid_argument,
 
  157                                         ">>> ERROR (ArrayTools::dotMultiplyDataField): Input fields container must have rank one larger than the rank of the input data container.");
 
  158         INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != 3, std::invalid_argument,
 
  159                                         ">>> ERROR (ArrayTools::dotMultiplyDataField): Output fields container must have rank 3.");
 
  160         INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(0) != inputData.extent(0), std::invalid_argument,
 
  161                                         ">>> ERROR (ArrayTools::dotMultiplyDataField): Zeroth dimensions (number of integration domains) of the fields and data input containers must agree!");
 
  162         INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(1) != inputFields.extent(2) &&
 
  163                                         inputData.extent(1) != 1, std::invalid_argument,
 
  164                                         ">>> ERROR (ArrayTools::dotMultiplyDataField): Second dimension of the fields input container and first dimension of data input container (number of integration points) must agree or first data dimension must be 1!");
 
  165         for (size_type i=2;i<inputData.rank();++i) {
 
  166           INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(i) != inputFields.extent(i+1), std::invalid_argument,
 
  167                                           ">>> ERROR (ArrayTools::dotMultiplyDataField): inputData dimension (i) does not match to the dimension (i+1) of inputFields");
 
  169         for (size_type i=0;i<outputFields.rank();++i) {
 
  170           INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(i) != outputFields.extent(i), std::invalid_argument,
 
  171                                           ">>> ERROR (ArrayTools::dotMultiplyDataField): inputFields dimension (i) does not match to the dimension (i+1) of outputFields");
 
  174         INTREPID2_TEST_FOR_EXCEPTION( inputData.rank() < 2 || inputData.rank() > 4, std::invalid_argument,
 
  175                                         ">>> ERROR (ArrayTools::dotMultiplyDataField): Input data container must have rank 2, 3 or 4.");
 
  176         INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() != inputData.rank(), std::invalid_argument,
 
  177                                         ">>> ERROR (ArrayTools::dotMultiplyDataField): The rank of fields input container must equal the rank of data input container.");
 
  178         INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != 3, std::invalid_argument,
 
  179                                         ">>> ERROR (ArrayTools::dotMultiplyDataField): Output fields container must have rank 3.");
 
  180         INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(1) != inputFields.extent(1) &&
 
  181                                         inputData.extent(1) != 1, std::invalid_argument,
 
  182                                         ">>> ERROR (ArrayTools::dotMultiplyDataField): First dimensions of the fields and data input containers (number of integration points) must agree or first data dimension must be 1!");
 
  183         INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(0) != outputFields.extent(1), std::invalid_argument,
 
  184                                         ">>> ERROR (ArrayTools::dotMultiplyDataField): Zeroth dimension of the fields input container and first dimension of the fields output container (number of fields) must agree!");
 
  185         INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(1) != outputFields.extent(2), std::invalid_argument,
 
  186                                         ">>> ERROR (ArrayTools::dotMultiplyDataField): First dimension of the fields input container and second dimension of the fields output container (number of integration points) must agree!");
 
  187         INTREPID2_TEST_FOR_EXCEPTION( outputFields.extent(0) != inputData.extent(0), std::invalid_argument,
 
  188                                         ">>> ERROR (ArrayTools::dotMultiplyDataField): Zeroth dimensions of the fields output and data input containers (number of integration domains) must agree!");
 
  189         for (size_type i=2;i<inputData.rank();++i) {
 
  190           INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(i) != inputFields.extent(i), std::invalid_argument,
 
  191                                           ">>> ERROR (ArrayTools::dotMultiplyDataField): inputData dimension (i) does not match to the dimension (i) of inputFields");
 
  205   template<
typename ExecSpaceType>
 
  206   template<
typename outputDataValueType,     
class ...outputDataProperties,
 
  207            typename inputDataLeftValueType,  
class ...inputDataLeftProperties,
 
  208            typename inputDataRightValueType, 
class ...inputDataRightProperties>
 
  212                        const Kokkos::DynRankView<inputDataLeftValueType, inputDataLeftProperties...>  inputDataLeft,
 
  213                        const Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRight ) {
 
  215 #ifdef HAVE_INTREPID2_DEBUG 
  217       if (inputDataRight.rank() >= inputDataLeft.rank()) {
 
  218         INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.rank() < 2 || inputDataLeft.rank() > 4, std::invalid_argument,
 
  219                                         ">>> ERROR (ArrayTools::dotMultiplyDataData): Left data input container must have rank 2, 3 or 4.");
 
  220         INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() != inputDataLeft.rank(), std::invalid_argument,
 
  221                                         ">>> ERROR (ArrayTools::dotMultiplyDataData): The rank of the right data input container must equal the rank of the left data input container.");
 
  222         INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != 2, std::invalid_argument,
 
  223                                         ">>> ERROR (ArrayTools::dotMultiplyDataData): Data output container must have rank 2.");
 
  224         INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(1) &&
 
  225                                         inputDataLeft.extent(1) != 1, std::invalid_argument,
 
  226                                         ">>> ERROR (ArrayTools::dotMultiplyDataData): First dimensions of the left and right data input containers (number of integration points) must agree or first left data dimension must be 1!");
 
  227         for (size_type i=0;i<inputDataLeft.rank();++i) {
 
  229             INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(i) != inputDataRight.extent(i), std::invalid_argument,
 
  230                                             ">>> ERROR (ArrayTools::dotMultiplyDataData): inputDataLeft dimension (i) does not match to the dimension (i) of inputDataRight");
 
  233         for (size_type i=0;i<outputData.rank();++i) {
 
  234           INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(i) != outputData.extent(i), std::invalid_argument,
 
  235                                           ">>> ERROR (ArrayTools::dotMultiplyDataData): inputDataRight dimension (i) does not match to the dimension (i) of outputData");
 
  238         INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.rank() < 2 || inputDataLeft.rank() > 4, std::invalid_argument,
 
  239                                         ">>> ERROR (ArrayTools::dotMultiplyDataData): Left data input container must have rank 2, 3 or 4.");
 
  240         INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() != (inputDataLeft.rank()-1), std::invalid_argument,
 
  241                                         ">>> ERROR (ArrayTools::dotMultiplyDataData): Right data input container must have rank one less than the rank of left data input container.");
 
  242         INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != 2, std::invalid_argument,
 
  243                                         ">>> ERROR (ArrayTools::dotMultiplyDataData): Data output container must have rank 2.");
 
  244         INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(0) &&
 
  245                                         inputDataLeft.extent(1) != 1, std::invalid_argument,
 
  246                                         ">>> ERROR (ArrayTools::dotMultiplyDataData): Zeroth dimension of the right data input container and first dimension of left data input container (number of integration points) must agree or first left data dimension must be 1!");
 
  247         INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(0) != outputData.extent(1), std::invalid_argument,
 
  248                                         ">>> ERROR (ArrayTools::dotMultiplyDataData): Zeroth dimension of the right data input container and first dimension of output data container (number of integration points) must agree!");
 
  249         INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(0) != outputData.extent(0), std::invalid_argument,
 
  250                                         ">>> ERROR (ArrayTools::dotMultiplyDataData): Zeroth dimensions of the left data input and data output containers (number of integration domains) must agree!");
 
  251         for (size_type i=1;i<inputDataRight.rank();++i) {
 
  252           INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(i+1) != inputDataRight.extent(i), std::invalid_argument,
 
  253                                           ">>> ERROR (ArrayTools::dotMultiplyDataData): inputDataLeft dimension (i+1) does not match to the dimension (i) of inputDataRight");