Intrepid2
Intrepid2_UtilsDef.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// functions here are moved to basis class
17//
18
19#ifndef __INTREPID2_UTILS_DEF_HPP__
20#define __INTREPID2_UTILS_DEF_HPP__
21
22#include "Intrepid2_Utils.hpp"
23
24namespace Intrepid2 {
25
26 //--------------------------------------------------------------------------------------------//
27 // //
28 // Definitions: functions for orders, cardinality and etc. of differential operators //
29 // //
30 //--------------------------------------------------------------------------------------------//
31
32 KOKKOS_INLINE_FUNCTION
33 ordinal_type getFieldRank(const EFunctionSpace spaceType) {
34 ordinal_type fieldRank = -1;
35
36 switch (spaceType) {
37
38 case FUNCTION_SPACE_HGRAD:
39 case FUNCTION_SPACE_HVOL:
40 fieldRank = 0;
41 break;
42
43 case FUNCTION_SPACE_HCURL:
44 case FUNCTION_SPACE_HDIV:
45 case FUNCTION_SPACE_VECTOR_HGRAD:
46 fieldRank = 1;
47 break;
48
49 case FUNCTION_SPACE_TENSOR_HGRAD:
50 fieldRank = 2;
51 break;
52
53 default:
54 INTREPID2_TEST_FOR_ABORT( !isValidFunctionSpace(spaceType),
55 ">>> ERROR (Intrepid2::getFieldRank): Invalid function space type");
56 }
57 return fieldRank;
58 }
59
60
61 KOKKOS_INLINE_FUNCTION
62 ordinal_type getOperatorRank(const EFunctionSpace spaceType,
63 const EOperator operatorType,
64 const ordinal_type spaceDim) {
65
66 const auto fieldRank = Intrepid2::getFieldRank(spaceType);
67#ifdef HAVE_INTREPID2_DEBUG
68 // Verify arguments: field rank can be 0,1, or 2, spaceDim can be 1,2, or 3.
69 INTREPID2_TEST_FOR_ABORT( !(0 <= fieldRank && fieldRank <= 2),
70 ">>> ERROR (Intrepid2::getOperatorRank): Invalid field rank");
71 INTREPID2_TEST_FOR_ABORT( !(1 <= spaceDim && spaceDim <= 3),
72 ">>> ERROR (Intrepid2::getOperatorRank): Invalid space dimension");
73#endif
74 ordinal_type operatorRank = -999;
75
76 // In 1D GRAD, CURL, and DIV default to d/dx; Dk defaults to d^k/dx^k, no casing needed.
77 if (spaceDim == 1) {
78 if (fieldRank == 0) {
79 // By default, in 1D any operator other than VALUE has rank 1
80 if (operatorType == OPERATOR_VALUE) {
81 operatorRank = 0;
82 } else {
83 operatorRank = 1;
84 }
85 }
86
87 // Only scalar fields are allowed in 1D
88 else {
89 INTREPID2_TEST_FOR_ABORT( fieldRank > 0,
90 ">>> ERROR (getOperatorRank): Only scalar fields are allowed in 1D");
91 } // fieldRank == 0
92 } // spaceDim == 1
93
94 // We are either in 2D or 3D
95 else {
96 switch (operatorType) {
97 case OPERATOR_VALUE:
98 operatorRank = 0;
99 break;
100
101 case OPERATOR_GRAD:
102 case OPERATOR_D1:
103 case OPERATOR_D2:
104 case OPERATOR_D3:
105 case OPERATOR_D4:
106 case OPERATOR_D5:
107 case OPERATOR_D6:
108 case OPERATOR_D7:
109 case OPERATOR_D8:
110 case OPERATOR_D9:
111 case OPERATOR_D10:
112 operatorRank = 1;
113 break;
114
115 case OPERATOR_CURL:
116
117 // operator rank for vector and tensor fields equals spaceDim - 3 (-1 in 2D and 0 in 3D)
118 if (fieldRank > 0) {
119 operatorRank = spaceDim - 3;
120 } else {
121
122 // CURL can be applied to scalar functions (rank = 0) in 2D and gives a vector (rank = 1)
123 if (spaceDim == 2) {
124 operatorRank = 3 - spaceDim;
125 }
126
127 // If we are here, fieldRank=0, spaceDim=3: CURL is undefined for 3D scalar functions
128 else {
129 INTREPID2_TEST_FOR_ABORT( ( (spaceDim == 3) && (fieldRank == 0) ),
130 ">>> ERROR (Intrepid2::getOperatorRank): CURL cannot be applied to scalar fields in 3D");
131 }
132 }
133 break;
134
135 case OPERATOR_DIV:
136
137 // DIV can be applied to vectors and tensors and has rank -1 in 2D and 3D
138 if (fieldRank > 0) {
139 operatorRank = -1;
140 }
141
142 // DIV cannot be applied to scalar fields except in 1D where it defaults to d/dx
143 else {
144 INTREPID2_TEST_FOR_ABORT( ( (spaceDim > 1) && (fieldRank == 0) ),
145 ">>> ERROR (Intrepid2::getOperatorRank): DIV cannot be applied to scalar fields in 2D and 3D");
146 }
147 break;
148
149 default:
150 INTREPID2_TEST_FOR_ABORT( !( isValidOperator(operatorType) ),
151 ">>> ERROR (Intrepid2::getOperatorRank): Invalid operator type");
152 } // switch
153 }// 2D and 3D
154
155 return operatorRank;
156 }
157
158
159 KOKKOS_INLINE_FUNCTION
160 ordinal_type getOperatorOrder(const EOperator operatorType) {
161 ordinal_type opOrder = -1;
162
163 switch (operatorType) {
164
165 case OPERATOR_VALUE:
166 opOrder = 0;
167 break;
168
169 case OPERATOR_GRAD:
170 case OPERATOR_CURL:
171 case OPERATOR_DIV:
172 case OPERATOR_D1:
173 opOrder = 1;
174 break;
175
176 case OPERATOR_D2:
177 case OPERATOR_D3:
178 case OPERATOR_D4:
179 case OPERATOR_D5:
180 case OPERATOR_D6:
181 case OPERATOR_D7:
182 case OPERATOR_D8:
183 case OPERATOR_D9:
184 case OPERATOR_D10:
185 opOrder = (ordinal_type)operatorType - (ordinal_type)OPERATOR_D1 + 1;
186 break;
187
188 default:
189 INTREPID2_TEST_FOR_ABORT( !( Intrepid2::isValidOperator(operatorType) ),
190 ">>> ERROR (Intrepid2::getOperatorOrder): Invalid operator type");
191 }
192 return opOrder;
193 }
194
195
196 KOKKOS_INLINE_FUNCTION
197 ordinal_type getDkEnumeration(const ordinal_type xMult,
198 const ordinal_type yMult,
199 const ordinal_type zMult) {
200
201 if (yMult < 0 && zMult < 0) {
202
203#ifdef HAVE_INTREPID2_DEBUG
204 // We are in 1D: verify input - xMult is non-negative and total order <= 10:
205 INTREPID2_TEST_FOR_ABORT( !( (0 <= xMult) && (xMult <= Parameters::MaxDerivative) ),
206 ">>> ERROR (Intrepid2::getDkEnumeration): Derivative order out of range");
207#endif
208
209 // there's only one derivative of order xMult
210 return 0;
211 } else {
212 if (zMult < 0) {
213
214#ifdef HAVE_INTREPID2_DEBUG
215 // We are in 2D: verify input - xMult and yMult are non-negative and total order <= 10:
216 INTREPID2_TEST_FOR_ABORT( !(0 <= xMult && 0 <= yMult && (xMult + yMult) <= Parameters::MaxDerivative),
217 ">>> ERROR (Intrepid2::getDkEnumeration): Derivative order out of range");
218#endif
219
220 // enumeration is the value of yMult
221 return yMult;
222 }
223
224 // We are in 3D: verify input - xMult, yMult and zMult are non-negative and total order <= 10:
225 else {
226 const auto order = xMult + yMult + zMult;
227#ifdef HAVE_INTREPID2_DEBUG
228 // Verify input: total order cannot exceed 10:
229 INTREPID2_TEST_FOR_ABORT( !( (0 <= xMult) && (0 <= yMult) && (0 <= zMult) &&
230 (order <= Parameters::MaxDerivative) ),
231 ">>> ERROR (Intrepid2::getDkEnumeration): Derivative order out of range");
232#endif
233 ordinal_type enumeration = zMult;
234 const ordinal_type iend = order-xMult+1;
235 for(ordinal_type i=0;i<iend;++i) {
236 enumeration += i;
237 }
238 return enumeration;
239 }
240 }
241 }
242
243// template<typename OrdinalArrayType>
244// KOKKOS_INLINE_FUNCTION
245// void getDkMultiplicities(OrdinalArrayType partialMult,
246// const ordinal_type derivativeEnum,
247// const EOperator operatorType,
248// const ordinal_type spaceDim) {
249
250// /* Hash table to convert enumeration of partial derivative to multiplicities of dx,dy,dz in 3D.
251// Multiplicities {mx,my,mz} are arranged lexicographically in bins numbered from 0 to 10.
252// The size of bins is an arithmetic progression, i.e., 1,2,3,4,5,...,11. Conversion formula is:
253// \verbatim
254// mx = derivativeOrder - binNumber
255// mz = derivativeEnum - binBegin
256// my = derivativeOrder - mx - mz = binNumber + binBegin - derivativeEnum
257// \endverbatim
258// where binBegin is the enumeration of the first element in the bin. Bin numbers and binBegin
259// values are stored in hash tables for quick access by derivative enumeration value.
260// */
261
262// // Returns the bin number for the specified derivative enumeration
263// const ordinal_type binNumber[66] = {
264// 0,
265// 1, 1,
266// 2, 2, 2,
267// 3, 3, 3, 3,
268// 4, 4, 4, 4, 4,
269// 5, 5, 5, 5, 5, 5,
270// 6, 6, 6, 6, 6, 6, 6,
271// 7, 7, 7, 7, 7, 7, 7, 7,
272// 8, 8, 8, 8, 8, 8, 8, 8, 8,
273// 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
274// 10,10,10,10,10,10,10,10,10,10,10
275// };
276
277// // Returns the binBegin value for the specified derivative enumeration
278// const ordinal_type binBegin[66] = {
279// 0,
280// 1, 1,
281// 3, 3 ,3,
282// 6, 6, 6, 6,
283// 10,10,10,10,10,
284// 15,15,15,15,15,15,
285// 21,21,21,21,21,21,21,
286// 28,28,28,28,28,28,28,28,
287// 36,36,36,36,36,36,36,36,36,
288// 45,45,45,45,45,45,45,45,45,45,
289// 55,55,55,55,55,55,55,55,55,55,55
290// };
291
292// #ifdef HAVE_INTREPID2_DEBUG
293// // Enumeration value must be between 0 and the cardinality of the derivative set
294// INTREPID2_TEST_FOR_ABORT( !( (0 <= derivativeEnum) && (derivativeEnum < getDkCardinality(operatorType,spaceDim) ) ),
295// ">>> ERROR (Intrepid2::getDkMultiplicities): Invalid derivative enumeration value for this order and space dimension");
296// #endif
297
298// // This method should only be called for Dk operators
299// ordinal_type derivativeOrder;
300// switch(operatorType) {
301
302// case OPERATOR_D1:
303// case OPERATOR_D2:
304// case OPERATOR_D3:
305// case OPERATOR_D4:
306// case OPERATOR_D5:
307// case OPERATOR_D6:
308// case OPERATOR_D7:
309// case OPERATOR_D8:
310// case OPERATOR_D9:
311// case OPERATOR_D10:
312// derivativeOrder = Intrepid2::getOperatorOrder(operatorType);
313// break;
314
315// default:
316// INTREPID2_TEST_FOR_ABORT(true,
317// ">>> ERROR (Intrepid2::getDkMultiplicities): operator type Dk required for this method");
318// }// switch
319
320// #ifdef HAVE_INTREPID2_DEBUG
321// INTREPID2_TEST_FOR_ABORT( partialMult.extent(0) != spaceDim,
322// ">>> ERROR (Intrepid2::getDkMultiplicities): partialMult must have the same dimension as spaceDim" );
323// #endif
324
325// switch(spaceDim) {
326
327// case 1:
328// // Multiplicity of dx equals derivativeOrder
329// partialMult(0) = derivativeOrder;
330// break;
331
332// case 2:
333// // Multiplicity of dy equals the enumeration of the derivative; of dx - the complement
334// partialMult(1) = derivativeEnum;
335// partialMult(0) = derivativeOrder - derivativeEnum;
336// break;
337
338// case 3:
339// // Recover multiplicities
340// partialMult(0) = derivativeOrder - binNumber[derivativeEnum];
341// partialMult(1) = binNumber[derivativeEnum] + binBegin[derivativeEnum] - derivativeEnum;
342// partialMult(2) = derivativeEnum - binBegin[derivativeEnum];
343// break;
344
345// default:
346// INTREPID2_TEST_FOR_ABORT( !( (0 < spaceDim ) && (spaceDim < 4) ),
347// ">>> ERROR (Intrepid2::getDkMultiplicities): Invalid space dimension");
348// }
349// }
350
351
352 KOKKOS_INLINE_FUNCTION
353 ordinal_type getDkCardinality(const EOperator operatorType,
354 const ordinal_type spaceDim) {
355
356 // This should only be called for Dk operators
357 ordinal_type derivativeOrder;
358 switch(operatorType) {
359
360 case OPERATOR_D1:
361 case OPERATOR_D2:
362 case OPERATOR_D3:
363 case OPERATOR_D4:
364 case OPERATOR_D5:
365 case OPERATOR_D6:
366 case OPERATOR_D7:
367 case OPERATOR_D8:
368 case OPERATOR_D9:
369 case OPERATOR_D10:
370 derivativeOrder = Intrepid2::getOperatorOrder(operatorType);
371 break;
372
373 default:
374 INTREPID2_TEST_FOR_ABORT(true,
375 ">>> ERROR (Intrepid2::getDkCardinality): operator type Dk required for this method");
376 }// switch
377
378 ordinal_type cardinality = -999;
379 switch(spaceDim) {
380
381 case 1:
382 cardinality = 1;
383 break;
384
385 case 2:
386 cardinality = derivativeOrder + 1;
387 break;
388
389 case 3:
390 cardinality = (derivativeOrder + 1)*(derivativeOrder + 2)/2;
391 break;
392
393 default:
394 INTREPID2_TEST_FOR_ABORT( !( (0 < spaceDim ) && (spaceDim < 4) ),
395 ">>> ERROR (Intrepid2::getDkcardinality): Invalid space dimension");
396 }
397
398 return cardinality;
399 }
400
401} // end namespace Intrepid2
402
403#endif
KOKKOS_INLINE_FUNCTION ordinal_type getOperatorRank(const EFunctionSpace spaceType, const EOperator operatorType, const ordinal_type spaceDim)
Returns rank of an operator.
KOKKOS_INLINE_FUNCTION ordinal_type getFieldRank(const EFunctionSpace spaceType)
Returns the rank of fields in a function space of the specified type.
KOKKOS_INLINE_FUNCTION ordinal_type getOperatorOrder(const EOperator operatorType)
Returns order of an operator.
KOKKOS_INLINE_FUNCTION ordinal_type getDkCardinality(const EOperator operatorType, const ordinal_type spaceDim)
Returns cardinality of Dk, i.e., the number of all derivatives of order k.
KOKKOS_INLINE_FUNCTION ordinal_type getDkEnumeration(const ordinal_type xMult, const ordinal_type yMult=-1, const ordinal_type zMult=-1)
Returns the ordinal of a partial derivative of order k based on the multiplicities of the partials dx...
KOKKOS_FORCEINLINE_FUNCTION bool isValidFunctionSpace(const EFunctionSpace spaceType)
Verifies validity of a function space enum.
KOKKOS_FORCEINLINE_FUNCTION bool isValidOperator(const EOperator operatorType)
Verifies validity of an operator enum.
Header function for Intrepid2::Util class and other utility functions.
static constexpr ordinal_type MaxDerivative
Maximum order of derivatives allowed in intrepid.