Intrepid2
Intrepid2_ArrayToolsDefScalar.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Intrepid2 Package
4 //
5 // Copyright 2007 NTESS and the Intrepid2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
16 #ifndef __INTREPID2_ARRAYTOOLS_DEF_SCALAR_HPP__
17 #define __INTREPID2_ARRAYTOOLS_DEF_SCALAR_HPP__
18 
19 namespace Intrepid2 {
20 
21  namespace FunctorArrayTools {
25  template<typename OutputViewType,
26  typename inputLeftViewType,
27  typename inputRightViewType,
28  bool equalRank,
29  bool reciprocal>
31  OutputViewType _output;
32  const inputLeftViewType _inputLeft;
33  const inputRightViewType _inputRight;
34 
35  KOKKOS_INLINE_FUNCTION
36  F_scalarMultiply(OutputViewType output_,
37  inputLeftViewType inputLeft_,
38  inputRightViewType inputRight_)
39  : _output(output_),
40  _inputLeft(inputLeft_),
41  _inputRight(inputRight_) {}
42 
43  // DataData
44  KOKKOS_INLINE_FUNCTION
45  void operator()(const ordinal_type cl,
46  const ordinal_type pt) const {
47  const auto val = _inputLeft(cl , pt%_inputLeft.extent(1));
48 
49  //const ordinal_type cp[2] = { cl, pt };
50  //ViewAdapter<2,OutputViewType> out(cp, _output);
51  auto out = Kokkos::subview(_output, cl, pt, Kokkos::ALL(), Kokkos::ALL());
52  if (equalRank) {
53  //const ViewAdapter<2,inputRightViewType> right(cp, _inputRight);
54  const auto right = Kokkos::subview(_inputRight, cl, pt, Kokkos::ALL(), Kokkos::ALL());
55  if (reciprocal) Kernels::inv_scalar_mult_mat(out, val, right);
56  else Kernels:: scalar_mult_mat(out, val, right);
57  } else {
58  //const ordinal_type p[1] = { pt };
59  //const ViewAdapter<1,inputRightViewType> right(p, _inputRight);
60  const auto right = Kokkos::subview(_inputRight, pt, Kokkos::ALL(), Kokkos::ALL());
61  if (reciprocal) Kernels::inv_scalar_mult_mat(out, val, right);
62  else Kernels:: scalar_mult_mat(out, val, right);
63  }
64  }
65 
66  // DataField
67  KOKKOS_INLINE_FUNCTION
68  void operator()(const ordinal_type cl,
69  const ordinal_type bf,
70  const ordinal_type pt) const {
71  const auto val = _inputLeft(cl , pt%_inputLeft.extent(1));
72 
73  //const ordinal_type cfp[3] = { cl, bf, pt };
74  //ViewAdapter<3,OutputViewType> out(cfp, _output);
75  auto out = Kokkos::subview(_output, cl, bf, pt, Kokkos::ALL(), Kokkos::ALL());
76  if (equalRank) {
77  //const ViewAdapter<3,inputRightViewType> right(cfp, _inputRight);
78  auto right = Kokkos::subview(_inputRight, cl, bf, pt, Kokkos::ALL(), Kokkos::ALL());
79  if (reciprocal) Kernels::inv_scalar_mult_mat(out, val, right);
80  else Kernels:: scalar_mult_mat(out, val, right);
81  } else {
82  //const ordinal_type fp[2] = { bf, pt };
83  //const ViewAdapter<2,inputRightViewType> right(fp, _inputRight);
84  auto right = Kokkos::subview(_inputRight, bf, pt, Kokkos::ALL(), Kokkos::ALL());
85  if (reciprocal) Kernels::inv_scalar_mult_mat(out, val, right);
86  else Kernels:: scalar_mult_mat(out, val, right);
87  }
88  }
89  };
90  }
91 
92  template<typename DeviceType>
93  template<typename outputFieldValueType, class ...outputFieldProperties,
94  typename inputDataValueType, class ...inputDataProperties,
95  typename inputFieldValueType, class ...inputFieldProperties>
96  void
98  scalarMultiplyDataField( Kokkos::DynRankView<outputFieldValueType,outputFieldProperties...> outputFields,
99  const Kokkos::DynRankView<inputDataValueType, inputDataProperties...> inputData,
100  const Kokkos::DynRankView<inputFieldValueType, inputFieldProperties...> inputFields,
101  const bool reciprocal ) {
102 
103 #ifdef HAVE_INTREPID2_DEBUG
104  {
105  INTREPID2_TEST_FOR_EXCEPTION( inputData.rank() != 2, std::invalid_argument,
106  ">>> ERROR (ArrayTools::scalarMultiplyDataField): Input data container must have rank 2.");
107 
108  if (outputFields.rank() <= inputFields.rank()) {
109  INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() < 3 || inputFields.rank() > 5, std::invalid_argument,
110  ">>> ERROR (ArrayTools::scalarMultiplyDataField): Input fields container must have rank 3, 4, or 5.");
111  INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != inputFields.rank(), std::invalid_argument,
112  ">>> ERROR (ArrayTools::scalarMultiplyDataField): Input and output fields containers must have the same rank.");
113  INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(0) != inputData.extent(0), std::invalid_argument,
114  ">>> ERROR (ArrayTools::scalarMultiplyDataField): Zeroth dimensions (number of integration domains) of the fields and data input containers must agree!");
115  INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(1) != inputFields.extent(2) &&
116  inputData.extent(1) != 1, std::invalid_argument,
117  ">>> 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!");
118  for (size_type i=0;i<inputFields.rank();++i) {
119  INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(i) != outputFields.extent(i), std::invalid_argument,
120  ">>> ERROR (ArrayTools::scalarMultiplyDataField): inputFields dimension (i) does not match to the dimension (i) of outputFields");
121  }
122  }
123  else {
124  INTREPID2_TEST_FOR_EXCEPTION( inputFields.rank() < 2 || inputFields.rank() > 4, std::invalid_argument,
125  ">>> ERROR (ArrayTools::scalarMultiplyDataField): Input fields container must have rank 2, 3, or 4.");
126  INTREPID2_TEST_FOR_EXCEPTION( outputFields.rank() != (inputFields.rank()+1), std::invalid_argument,
127  ">>> ERROR (ArrayTools::scalarMultiplyDataField): The rank of the input fields container must be one less than the rank of the output fields container.");
128  INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(1) != inputFields.extent(1) &&
129  inputData.extent(1) != 1, std::invalid_argument,
130  ">>> 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!");
131  INTREPID2_TEST_FOR_EXCEPTION( inputData.extent(0) != outputFields.extent(0), std::invalid_argument,
132  ">>> ERROR (ArrayTools::scalarMultiplyDataField): Zeroth dimensions of fields output container and data input containers (number of integration domains) must agree!");
133  for (size_type i=0;i<inputFields.rank();++i) {
134  INTREPID2_TEST_FOR_EXCEPTION( inputFields.extent(i) != outputFields.extent(i+1), std::invalid_argument,
135  ">>> ERROR (ArrayTools::scalarMultiplyDataField): inputFields dimension (i) does not match to the dimension (i+1) of outputFields");
136  }
137  }
138  }
139 #endif
140 
141  typedef Kokkos::DynRankView<outputFieldValueType,outputFieldProperties...> outputFieldViewType;
142  typedef Kokkos::DynRankView<inputDataValueType,inputDataProperties...> inputDataViewType;
143  typedef Kokkos::DynRankView<inputFieldValueType,inputFieldProperties...> inputFieldViewType;
144 
145  using range_policy_type = Kokkos::MDRangePolicy
146  < ExecSpaceType, Kokkos::Rank<3>, Kokkos::IndexType<ordinal_type> >;
147 
148  const range_policy_type policy( { 0, 0, 0 },
149  { /*C*/ outputFields.extent(0), /*F*/ outputFields.extent(1), /*P*/ outputFields.extent(2) } );
150 
151  const bool equalRank = ( outputFields.rank() == inputFields.rank() );
152  if (equalRank)
153  if (reciprocal) {
155  Kokkos::parallel_for( policy, FunctorType(outputFields, inputData, inputFields) );
156  } else {
158  Kokkos::parallel_for( policy, FunctorType(outputFields, inputData, inputFields) );
159  }
160  else
161  if (reciprocal) {
163  Kokkos::parallel_for( policy, FunctorType(outputFields, inputData, inputFields) );
164  } else {
166  Kokkos::parallel_for( policy, FunctorType(outputFields, inputData, inputFields) );
167  }
168  }
169 
170 
171  template<typename DeviceType>
172  template<typename outputDataValueType, class ...outputDataProperties,
173  typename inputDataLeftValueType, class ...inputDataLeftProperties,
174  typename inputDataRightValueType, class ...inputDataRightProperties>
175  void
177  scalarMultiplyDataData( Kokkos::DynRankView<outputDataValueType, outputDataProperties...> outputData,
178  const Kokkos::DynRankView<inputDataLeftValueType, inputDataLeftProperties...> inputDataLeft,
179  const Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRight,
180  const bool reciprocal ) {
181 
182 #ifdef HAVE_INTREPID2_DEBUG
183  {
184  INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.rank() != 2, std::invalid_argument,
185  ">>> ERROR (ArrayTools::scalarMultiplyDataData): Left input data container must have rank 2.");
186 
187  if (outputData.rank() <= inputDataRight.rank()) {
188  INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() < 2 || inputDataRight.rank() > 4, std::invalid_argument,
189  ">>> ERROR (ArrayTools::scalarMultiplyDataData): Right input data container must have rank 2, 3, or 4.");
190  INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != inputDataRight.rank(), std::invalid_argument,
191  ">>> ERROR (ArrayTools::scalarMultiplyDataData): Right input and output data containers must have the same rank.");
192  INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(0) != inputDataLeft.extent(0), std::invalid_argument,
193  ">>> ERROR (ArrayTools::scalarMultiplyDataData): Zeroth dimensions (number of integration domains) of the left and right data input containers must agree!");
194  INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(1) &&
195  inputDataLeft.extent(1) != 1, std::invalid_argument,
196  ">>> 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!");
197  for (size_type i=0;i<inputDataRight.rank();++i) {
198  INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(i) != outputData.extent(i), std::invalid_argument,
199  ">>> ERROR (ArrayTools::scalarMultiplyDataData): inputDataRight dimension (i) does not match to the dimension (i) of outputData");
200  }
201  } else {
202  INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.rank() < 1 || inputDataRight.rank() > 3, std::invalid_argument,
203  ">>> ERROR (ArrayTools::scalarMultiplyDataData): Right input data container must have rank 1, 2, or 3.");
204  INTREPID2_TEST_FOR_EXCEPTION( outputData.rank() != (inputDataRight.rank()+1), std::invalid_argument,
205  ">>> ERROR (ArrayTools::scalarMultiplyDataData): The rank of the right input data container must be one less than the rank of the output data container.");
206  INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(1) != inputDataRight.extent(0) &&
207  inputDataLeft.extent(1) != 1, std::invalid_argument,
208  ">>> 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!");
209  INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.extent(0) != outputData.extent(0), std::invalid_argument,
210  ">>> ERROR (ArrayTools::scalarMultiplyDataData): Zeroth dimensions of data output and left data input containers (number of integration domains) must agree!");
211  for (size_type i=0;i<inputDataRight.rank();++i) {
212  INTREPID2_TEST_FOR_EXCEPTION( inputDataRight.extent(i) != outputData.extent(i+1), std::invalid_argument,
213  ">>> ERROR (ArrayTools::scalarMultiplyDataData): inputDataRight dimension (i) does not match to the dimension (i+1) of outputData");
214  }
215  }
216  }
217 #endif
218 
219  typedef Kokkos::DynRankView<outputDataValueType,outputDataProperties...> outputDataViewType;
220  typedef Kokkos::DynRankView<inputDataLeftValueType,inputDataLeftProperties...> inputDataLeftViewType;
221  typedef Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRightViewType;
222 
223  using range_policy_type = Kokkos::MDRangePolicy
224  < ExecSpaceType, Kokkos::Rank<2>, Kokkos::IndexType<ordinal_type> >;
225 
226  const range_policy_type policy( { 0, 0 },
227  { /*C*/ outputData.extent(0), /*P*/ outputData.extent(1) } );
228 
229  const bool equalRank = ( outputData.rank() == inputDataRight.rank() );
230  if (equalRank)
231  if (reciprocal) {
233  Kokkos::parallel_for( policy, FunctorType(outputData, inputDataLeft, inputDataRight) );
234  } else {
236  Kokkos::parallel_for( policy, FunctorType(outputData, inputDataLeft, inputDataRight) );
237  }
238  else
239  if (reciprocal) {
241  Kokkos::parallel_for( policy, FunctorType(outputData, inputDataLeft, inputDataRight) );
242  } else {
244  Kokkos::parallel_for( policy, FunctorType(outputData, inputDataLeft, inputDataRight) );
245  }
246  }
247 
248 } // end namespace Intrepid2
249 
250 #endif
static void scalarMultiplyDataData(Kokkos::DynRankView< outputDataValueType, outputDataProperties...> outputData, const Kokkos::DynRankView< inputDataLeftValueType, inputDataLeftProperties...> inputDataLeft, const Kokkos::DynRankView< inputDataRightValueType, inputDataRightProperties...> inputDataRight, const bool reciprocal=false)
There are two use cases: (1) multiplies a rank-2, 3, or 4 container inputDataRight with dimensions (C...
static void scalarMultiplyDataField(Kokkos::DynRankView< outputFieldValueType, outputFieldProperties...> outputFields, const Kokkos::DynRankView< inputDataValueType, inputDataProperties...> inputData, const Kokkos::DynRankView< inputFieldValueType, inputFieldProperties...> inputFields, const bool reciprocal=false)
There are two use cases: (1) multiplies a rank-3, 4, or 5 container inputFields with dimensions (C...
Functor for scalarMultiply see Intrepid2::ArrayTools for more.