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");