Intrepid2
Intrepid2_ArrayToolsDefDot.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_DOT_HPP__
50 #define __INTREPID2_ARRAYTOOLS_DEF_DOT_HPP__
51 
52 namespace Intrepid2 {
53 
54  namespace FunctorArrayTools {
58  template < typename OutputViewType, typename leftInputViewType, typename rightInputViewType >
59  struct F_dotMultiply {
60  OutputViewType _output;
61  leftInputViewType _leftInput;
62  rightInputViewType _rightInput;
63  const bool _hasField;
64  typedef typename OutputViewType::value_type value_type;
65 
66  KOKKOS_INLINE_FUNCTION
67  F_dotMultiply(OutputViewType output_,
68  leftInputViewType leftInput_,
69  rightInputViewType rightInput_,
70  const bool hasField_)
71  : _output(output_), _leftInput(leftInput_), _rightInput(rightInput_),
72  _hasField(hasField_) {}
73 
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());
78 
79  if (_hasField)
80  unrollIndex( cl, bf, pt,
81  _output.extent(0),
82  _output.extent(1),
83  _output.extent(2),
84  iter );
85  else
86  unrollIndex( cl, pt,
87  _output.extent(0),
88  _output.extent(1),
89  iter);
90 
91  auto result = ( _hasField ? Kokkos::subview(_output, cl, bf, pt) :
92  Kokkos::subview(_output, cl, pt));
93 
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());
96 
97 
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()));
103 
104  const ordinal_type iend = left.extent(0);
105  const ordinal_type jend = left.extent(1);
106 
107  value_type tmp(0);
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);
111  result() = tmp;
112  }
113  };
114  } //namespace
115 
116  template<typename SpT>
117  template<typename outputValueType, class ...outputProperties,
118  typename leftInputValueType, class ...leftInputProperties,
119  typename rightInputValueType, class ...rightInputProperties>
120  void
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 ) {
126 
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;
132 
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) );
137  }
138 
139 
140 
141  template<typename ExecSpaceType>
142  template<typename outputFieldValueType, class ...outputFieldProperties,
143  typename inputDataValueType, class ...inputDataProperties,
144  typename inputFieldValueType, class ...inputFieldProperties>
145  void
147  dotMultiplyDataField( Kokkos::DynRankView<outputFieldValueType,outputFieldProperties...> outputFields,
148  const Kokkos::DynRankView<inputDataValueType, inputDataProperties...> inputData,
149  const Kokkos::DynRankView<inputFieldValueType, inputFieldProperties...> inputFields ) {
150 
151 #ifdef HAVE_INTREPID2_DEBUG
152  {
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");
168  }
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");
172  }
173  } else {
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");
192  }
193  }
194  }
195 #endif
196 
198  inputData,
199  inputFields,
200  true );
201  }
202 
203 
204 
205  template<typename ExecSpaceType>
206  template<typename outputDataValueType, class ...outputDataProperties,
207  typename inputDataLeftValueType, class ...inputDataLeftProperties,
208  typename inputDataRightValueType, class ...inputDataRightProperties>
209  void
211  dotMultiplyDataData( Kokkos::DynRankView<outputDataValueType, outputDataProperties...> outputData,
212  const Kokkos::DynRankView<inputDataLeftValueType, inputDataLeftProperties...> inputDataLeft,
213  const Kokkos::DynRankView<inputDataRightValueType,inputDataRightProperties...> inputDataRight ) {
214 
215 #ifdef HAVE_INTREPID2_DEBUG
216  {
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) {
228  if (i != 1) {
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");
231  }
232  }
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");
236  }
237  } else {
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");
254  }
255  }
256  }
257 #endif
258 
260  inputDataLeft,
261  inputDataRight,
262  false );
263  }
264 
265 } // end namespace Intrepid2
266 #endif
static void dotMultiplyDataField(Kokkos::DynRankView< outputFieldValueType, outputFieldProperties...> outputFields, const Kokkos::DynRankView< inputDataValueType, inputDataProperties...> inputData, const Kokkos::DynRankView< inputFieldValueType, inputFieldProperties...> inputFields)
There are two use cases: (1) dot product of a rank-3, 4 or 5 container inputFields with dimensions (C...
static void dotMultiplyDataData(Kokkos::DynRankView< outputDataValueType, outputDataProperties...> outputData, const Kokkos::DynRankView< inputDataLeftValueType, inputDataLeftProperties...> inputDataLeft, const Kokkos::DynRankView< inputDataRightValueType, inputDataRightProperties...> inputDataRight)
There are two use cases: (1) dot product of a rank-2, 3 or 4 container inputDataRight with dimensions...
Functor for dotMultiply see Intrepid2::ArrayTools for more.
Utility class that provides methods for higher-order algebraic manipulation of user-defined arrays...