49 #ifndef __INTREPID2_ARRAYTOOLS_DEF_SCALAR_HPP__ 
   50 #define __INTREPID2_ARRAYTOOLS_DEF_SCALAR_HPP__ 
   54   namespace FunctorArrayTools {
 
   58     template<
typename outputViewType,
 
   59              typename inputLeftViewType,
 
   60              typename inputRightViewType,
 
   64             outputViewType _output;
 
   65       const inputLeftViewType _inputLeft;
 
   66       const inputRightViewType _inputRight;
 
   68       KOKKOS_INLINE_FUNCTION
 
   70                        inputLeftViewType inputLeft_,
 
   71                        inputRightViewType inputRight_)
 
   73           _inputLeft(inputLeft_),
 
   74           _inputRight(inputRight_) {}
 
   77       KOKKOS_INLINE_FUNCTION
 
   78       void operator()(
const ordinal_type cl,
 
   79                       const ordinal_type pt)
 const {
 
   80         const auto val = _inputLeft(cl , pt%_inputLeft.extent(1));
 
   84         auto out = Kokkos::subview(_output, cl, pt, Kokkos::ALL(), Kokkos::ALL());
 
   87           const auto right = Kokkos::subview(_inputRight, cl, pt, Kokkos::ALL(), Kokkos::ALL());
 
   88           if (reciprocal) Kernels::inv_scalar_mult_mat(out, val, right);
 
   89           else            Kernels::    scalar_mult_mat(out, val, right);
 
   93           const auto right = Kokkos::subview(_inputRight, pt, Kokkos::ALL(), Kokkos::ALL());
 
   94           if (reciprocal) Kernels::inv_scalar_mult_mat(out, val, right);
 
   95           else            Kernels::    scalar_mult_mat(out, val, right);
 
  100       KOKKOS_INLINE_FUNCTION
 
  101       void operator()(
const ordinal_type cl,
 
  102                       const ordinal_type bf,
 
  103                       const ordinal_type pt)
 const {
 
  104         const auto val = _inputLeft(cl , pt%_inputLeft.extent(1));
 
  108         auto out = Kokkos::subview(_output, cl, bf, pt, Kokkos::ALL(), Kokkos::ALL());
 
  111           auto right = Kokkos::subview(_inputRight, cl, bf, pt, Kokkos::ALL(), Kokkos::ALL());
 
  112           if (reciprocal) Kernels::inv_scalar_mult_mat(out, val, right);
 
  113           else            Kernels::    scalar_mult_mat(out, val, right);          
 
  117           auto right = Kokkos::subview(_inputRight, bf, pt, Kokkos::ALL(), Kokkos::ALL());
 
  118           if (reciprocal) Kernels::inv_scalar_mult_mat(out, val, right);
 
  119           else            Kernels::    scalar_mult_mat(out, val, right);
 
  125   template<
typename SpT>
 
  126   template<
typename outputFieldValueType, 
class ...outputFieldProperties,
 
  127            typename inputDataValueType,   
class ...inputDataProperties,
 
  128            typename inputFieldValueType,  
class ...inputFieldProperties>
 
  132                            const Kokkos::DynRankView<inputDataValueType,  inputDataProperties...>   inputData,
 
  133                            const Kokkos::DynRankView<inputFieldValueType, inputFieldProperties...>  inputFields,
 
  134                            const bool reciprocal ) {
 
  136 #ifdef HAVE_INTREPID2_DEBUG 
  138       INTREPID2_TEST_FOR_EXCEPTION( inputData.rank() != 2, std::invalid_argument,
 
  139                                 ">>> ERROR (ArrayTools::scalarMultiplyDataField): Input data container must have rank 2.");
 
  141       if (outputFields.rank() <= inputFields.rank()) {
 
  142         INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() < 3 || inputFields.rank() > 5, std::invalid_argument,
 
  143                                   ">>> ERROR (ArrayTools::scalarMultiplyDataField): Input fields container must have rank 3, 4, or 5.");
 
  144         INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != inputFields.rank(), std::invalid_argument,
 
  145                                   ">>> ERROR (ArrayTools::scalarMultiplyDataField): Input and output fields containers must have the same rank.");
 
  146         INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(0) != inputData.extent(0), std::invalid_argument,
 
  147                                   ">>> ERROR (ArrayTools::scalarMultiplyDataField): Zeroth dimensions (number of integration domains) of the fields and data input containers must agree!");
 
  148         INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(1) != inputFields.extent(2) &&
 
  149                                   inputData.extent(1) != 1, std::invalid_argument,
 
  150                                   ">>> ERROR (ArrayTools::scalarMultiplyDataField): 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!");
 
  151         for (size_type i=0;i<inputFields.rank();++i) {
 
  152           INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(i) != outputFields.extent(i), std::invalid_argument,
 
  153                                     ">>> ERROR (ArrayTools::scalarMultiplyDataField): inputFields dimension (i) does not match to the dimension (i) of outputFields");
 
  157         INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() < 2 || inputFields.rank() > 4, std::invalid_argument,
 
  158                                   ">>> ERROR (ArrayTools::scalarMultiplyDataField): Input fields container must have rank 2, 3, or 4.");
 
  159         INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != (inputFields.rank()+1), std::invalid_argument,
 
  160                                   ">>> ERROR (ArrayTools::scalarMultiplyDataField): The rank of the input fields container must be one less than the rank of the output fields container.");
 
  161         INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(1) != inputFields.extent(1) &&
 
  162                                   inputData.extent(1) != 1, std::invalid_argument,
 
  163                                   ">>> ERROR (ArrayTools::scalarMultiplyDataField): First dimensions of fields input container and data input container (number of integration points) must agree or first data dimension must be 1!");
 
  164         INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(0) != outputFields.extent(0), std::invalid_argument,
 
  165                                   ">>> ERROR (ArrayTools::scalarMultiplyDataField): Zeroth dimensions of fields output container and data input containers (number of integration domains) must agree!");
 
  166         for (size_type i=0;i<inputFields.rank();++i) {
 
  167           INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(i) != outputFields.extent(i+1), std::invalid_argument,
 
  168                                     ">>> ERROR (ArrayTools::scalarMultiplyDataField): inputFields dimension (i) does not match to the dimension (i+1) of outputFields");
 
  174     typedef Kokkos::DynRankView<outputFieldValueType,outputFieldProperties...> outputFieldViewType;
 
  175     typedef Kokkos::DynRankView<inputDataValueType,inputDataProperties...> inputDataViewType;
 
  176     typedef Kokkos::DynRankView<inputFieldValueType,inputFieldProperties...> inputFieldViewType;
 
  178     typedef typename ExecSpace< typename inputDataViewType::execution_space , SpT >::ExecSpaceType ExecSpaceType;
 
  180     using range_policy_type = Kokkos::Experimental::MDRangePolicy
 
  181         < ExecSpaceType, Kokkos::Experimental::Rank<3>, Kokkos::IndexType<ordinal_type> >;
 
  183     const range_policy_type policy( { 0, 0, 0 },
 
  184                                     {  outputFields.extent(0),  outputFields.extent(1),  outputFields.extent(2) } );
 
  186     const bool equalRank = ( outputFields.rank() == inputFields.rank() );
 
  190         Kokkos::parallel_for( policy, FunctorType(outputFields, inputData, inputFields) );
 
  193         Kokkos::parallel_for( policy, FunctorType(outputFields, inputData, inputFields) );
 
  198         Kokkos::parallel_for( policy, FunctorType(outputFields, inputData, inputFields) );
 
  201         Kokkos::parallel_for( policy, FunctorType(outputFields, inputData, inputFields) );
 
  206   template<
typename SpT>
 
  207   template<
typename outputDataValueType,     
class ...outputDataProperties,
 
  208            typename inputDataLeftValueType,  
class ...inputDataLeftProperties,
 
  209            typename inputDataRightValueType, 
class ...inputDataRightProperties>
 
  213                           const Kokkos::DynRankView<inputDataLeftValueType, inputDataLeftProperties...>  inputDataLeft,
 
  214                           const Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRight,
 
  215                           const bool reciprocal ) {
 
  217 #ifdef HAVE_INTREPID2_DEBUG 
  219       INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.rank() != 2, std::invalid_argument,
 
  220                                 ">>> ERROR (ArrayTools::scalarMultiplyDataData): Left input data container must have rank 2.");
 
  222       if (outputData.rank() <= inputDataRight.rank()) {
 
  223         INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() < 2 || inputDataRight.rank() > 4, std::invalid_argument,
 
  224                                   ">>> ERROR (ArrayTools::scalarMultiplyDataData): Right input data container must have rank 2, 3, or 4.");
 
  225         INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != inputDataRight.rank(), std::invalid_argument,
 
  226                                   ">>> ERROR (ArrayTools::scalarMultiplyDataData): Right input and output data containers must have the same rank.");
 
  227         INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(0) != inputDataLeft.extent(0), std::invalid_argument,
 
  228                                   ">>> ERROR (ArrayTools::scalarMultiplyDataData): Zeroth dimensions (number of integration domains) of the left and right data input containers must agree!");
 
  229         INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(1) &&
 
  230                                   inputDataLeft.extent(1) != 1, std::invalid_argument,
 
  231                                   ">>> ERROR (ArrayTools::scalarMultiplyDataData): First dimensions of the left and right data input containers (number of integration points) must agree, or first dimension of the left data input container must be 1!");
 
  232         for (size_type i=0;i<inputDataRight.rank();++i) {
 
  233           INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(i) != outputData.extent(i), std::invalid_argument,
 
  234                                     ">>> ERROR (ArrayTools::scalarMultiplyDataData): inputDataRight dimension (i) does not match to the dimension (i) of outputData");
 
  237         INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() < 1 || inputDataRight.rank() > 3, std::invalid_argument,
 
  238                                   ">>> ERROR (ArrayTools::scalarMultiplyDataData): Right input data container must have rank 1, 2, or 3.");
 
  239         INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != (inputDataRight.rank()+1), std::invalid_argument,
 
  240                                   ">>> ERROR (ArrayTools::scalarMultiplyDataData): The rank of the right input data container must be one less than the rank of the output data container.");
 
  241         INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(0)  &&
 
  242                                   inputDataLeft.extent(1) != 1, std::invalid_argument,
 
  243                                   ">>> ERROR (ArrayTools::scalarMultiplyDataData): Zeroth dimension of the right input data container and first dimension of the left data input container (number of integration points) must agree or first dimension of the left data input container must be 1!");
 
  244         INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(0) != outputData.extent(0), std::invalid_argument,
 
  245                                   ">>> ERROR (ArrayTools::scalarMultiplyDataData): Zeroth dimensions of data output and left data input containers (number of integration domains) must agree!");
 
  246         for (size_type i=0;i<inputDataRight.rank();++i) {
 
  247           INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(i) != outputData.extent(i+1), std::invalid_argument,
 
  248                                     ">>> ERROR (ArrayTools::scalarMultiplyDataData): inputDataRight dimension (i) does not match to the dimension (i+1) of outputData");
 
  254     typedef Kokkos::DynRankView<outputDataValueType,outputDataProperties...> outputDataViewType;
 
  255     typedef Kokkos::DynRankView<inputDataLeftValueType,inputDataLeftProperties...> inputDataLeftViewType;
 
  256     typedef Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRightViewType;
 
  258     typedef typename ExecSpace< typename inputDataLeftViewType::execution_space , SpT >::ExecSpaceType ExecSpaceType;
 
  261     using range_policy_type = Kokkos::Experimental::MDRangePolicy
 
  262       < ExecSpaceType, Kokkos::Experimental::Rank<2>, Kokkos::IndexType<ordinal_type> >;
 
  264     const range_policy_type policy( { 0, 0 },
 
  265                                     {  outputData.extent(0),  outputData.extent(1) } );
 
  267     const bool equalRank = ( outputData.rank() == inputDataRight.rank() );    
 
  271         Kokkos::parallel_for( policy, FunctorType(outputData, inputDataLeft, inputDataRight) );
 
  274         Kokkos::parallel_for( policy, FunctorType(outputData, inputDataLeft, inputDataRight) );
 
  279         Kokkos::parallel_for( policy, FunctorType(outputData, inputDataLeft, inputDataRight) );
 
  282         Kokkos::parallel_for( policy, FunctorType(outputData, inputDataLeft, inputDataRight) );