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
15
16#ifndef __INTREPID2_ARRAYTOOLS_DEF_SCALAR_HPP__
17#define __INTREPID2_ARRAYTOOLS_DEF_SCALAR_HPP__
18
19namespace Intrepid2 {
20
21 namespace FunctorArrayTools {
25 template<typename OutputViewType,
26 typename inputLeftViewType,
27 typename inputRightViewType,
28 bool equalRank,
29 bool reciprocal>
30 struct F_scalarMultiply {
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 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.