Intrepid2
Intrepid2_ArrayToolsDefScalar.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ************************************************************************
3 //
4 // Intrepid Package
5 // Copyright (2007) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Kyungjoo Kim (kyukim@sandia.gov), or
38 // Mauro Perego (mperego@sandia.gov)
39 //
40 // ************************************************************************
41 // @HEADER
42 
49 #ifndef __INTREPID2_ARRAYTOOLS_DEF_SCALAR_HPP__
50 #define __INTREPID2_ARRAYTOOLS_DEF_SCALAR_HPP__
51 
52 namespace Intrepid2 {
53 
54  namespace FunctorArrayTools {
58  template<typename outputViewType,
59  typename inputLeftViewType,
60  typename inputRightViewType,
61  bool equalRank,
62  bool reciprocal>
64  outputViewType _output;
65  const inputLeftViewType _inputLeft;
66  const inputRightViewType _inputRight;
67 
68  KOKKOS_INLINE_FUNCTION
69  F_scalarMultiply(outputViewType output_,
70  inputLeftViewType inputLeft_,
71  inputRightViewType inputRight_)
72  : _output(output_),
73  _inputLeft(inputLeft_),
74  _inputRight(inputRight_) {}
75 
76  // DataData
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));
81 
82  //const ordinal_type cp[2] = { cl, pt };
83  //ViewAdapter<2,outputViewType> out(cp, _output);
84  auto out = Kokkos::subview(_output, cl, pt, Kokkos::ALL(), Kokkos::ALL());
85  if (equalRank) {
86  //const ViewAdapter<2,inputRightViewType> right(cp, _inputRight);
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);
90  } else {
91  //const ordinal_type p[1] = { pt };
92  //const ViewAdapter<1,inputRightViewType> right(p, _inputRight);
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);
96  }
97  }
98 
99  // DataField
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));
105 
106  //const ordinal_type cfp[3] = { cl, bf, pt };
107  //ViewAdapter<3,outputViewType> out(cfp, _output);
108  auto out = Kokkos::subview(_output, cl, bf, pt, Kokkos::ALL(), Kokkos::ALL());
109  if (equalRank) {
110  //const ViewAdapter<3,inputRightViewType> right(cfp, _inputRight);
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);
114  } else {
115  //const ordinal_type fp[2] = { bf, pt };
116  //const ViewAdapter<2,inputRightViewType> right(fp, _inputRight);
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);
120  }
121  }
122  };
123  }
124 
125  template<typename SpT>
126  template<typename outputFieldValueType, class ...outputFieldProperties,
127  typename inputDataValueType, class ...inputDataProperties,
128  typename inputFieldValueType, class ...inputFieldProperties>
129  void
131  scalarMultiplyDataField( Kokkos::DynRankView<outputFieldValueType,outputFieldProperties...> outputFields,
132  const Kokkos::DynRankView<inputDataValueType, inputDataProperties...> inputData,
133  const Kokkos::DynRankView<inputFieldValueType, inputFieldProperties...> inputFields,
134  const bool reciprocal ) {
135 
136 #ifdef HAVE_INTREPID2_DEBUG
137  {
138  INTREPID2_TEST_FOR_EXCEPTION( inputData.rank() != 2, std::invalid_argument,
139  ">>> ERROR (ArrayTools::scalarMultiplyDataField): Input data container must have rank 2.");
140 
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");
154  }
155  }
156  else {
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");
169  }
170  }
171  }
172 #endif
173 
174  typedef Kokkos::DynRankView<outputFieldValueType,outputFieldProperties...> outputFieldViewType;
175  typedef Kokkos::DynRankView<inputDataValueType,inputDataProperties...> inputDataViewType;
176  typedef Kokkos::DynRankView<inputFieldValueType,inputFieldProperties...> inputFieldViewType;
177 
178  typedef typename ExecSpace< typename inputDataViewType::execution_space , SpT >::ExecSpaceType ExecSpaceType;
179 
180  using range_policy_type = Kokkos::Experimental::MDRangePolicy
181  < ExecSpaceType, Kokkos::Experimental::Rank<3>, Kokkos::IndexType<ordinal_type> >;
182 
183  const range_policy_type policy( { 0, 0, 0 },
184  { /*C*/ outputFields.extent(0), /*F*/ outputFields.extent(1), /*P*/ outputFields.extent(2) } );
185 
186  const bool equalRank = ( outputFields.rank() == inputFields.rank() );
187  if (equalRank)
188  if (reciprocal) {
190  Kokkos::parallel_for( policy, FunctorType(outputFields, inputData, inputFields) );
191  } else {
193  Kokkos::parallel_for( policy, FunctorType(outputFields, inputData, inputFields) );
194  }
195  else
196  if (reciprocal) {
198  Kokkos::parallel_for( policy, FunctorType(outputFields, inputData, inputFields) );
199  } else {
201  Kokkos::parallel_for( policy, FunctorType(outputFields, inputData, inputFields) );
202  }
203  }
204 
205 
206  template<typename SpT>
207  template<typename outputDataValueType, class ...outputDataProperties,
208  typename inputDataLeftValueType, class ...inputDataLeftProperties,
209  typename inputDataRightValueType, class ...inputDataRightProperties>
210  void
212  scalarMultiplyDataData( Kokkos::DynRankView<outputDataValueType, outputDataProperties...> outputData,
213  const Kokkos::DynRankView<inputDataLeftValueType, inputDataLeftProperties...> inputDataLeft,
214  const Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRight,
215  const bool reciprocal ) {
216 
217 #ifdef HAVE_INTREPID2_DEBUG
218  {
219  INTREPID2_TEST_FOR_EXCEPTION( inputDataLeft.rank() != 2, std::invalid_argument,
220  ">>> ERROR (ArrayTools::scalarMultiplyDataData): Left input data container must have rank 2.");
221 
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");
235  }
236  } else {
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");
249  }
250  }
251  }
252 #endif
253 
254  typedef Kokkos::DynRankView<outputDataValueType,outputDataProperties...> outputDataViewType;
255  typedef Kokkos::DynRankView<inputDataLeftValueType,inputDataLeftProperties...> inputDataLeftViewType;
256  typedef Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRightViewType;
257 
258  typedef typename ExecSpace< typename inputDataLeftViewType::execution_space , SpT >::ExecSpaceType ExecSpaceType;
259 
260 
261  using range_policy_type = Kokkos::Experimental::MDRangePolicy
262  < ExecSpaceType, Kokkos::Experimental::Rank<2>, Kokkos::IndexType<ordinal_type> >;
263 
264  const range_policy_type policy( { 0, 0 },
265  { /*C*/ outputData.extent(0), /*P*/ outputData.extent(1) } );
266 
267  const bool equalRank = ( outputData.rank() == inputDataRight.rank() );
268  if (equalRank)
269  if (reciprocal) {
271  Kokkos::parallel_for( policy, FunctorType(outputData, inputDataLeft, inputDataRight) );
272  } else {
274  Kokkos::parallel_for( policy, FunctorType(outputData, inputDataLeft, inputDataRight) );
275  }
276  else
277  if (reciprocal) {
279  Kokkos::parallel_for( policy, FunctorType(outputData, inputDataLeft, inputDataRight) );
280  } else {
282  Kokkos::parallel_for( policy, FunctorType(outputData, inputDataLeft, inputDataRight) );
283  }
284  }
285 
286 } // end namespace Intrepid2
287 
288 #endif
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...
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...
Functor for scalarMultiply see Intrepid2::ArrayTools for more.