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 
24 namespace 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
Header function for Intrepid2::Util class and other utility functions.
static constexpr ordinal_type MaxDerivative
Maximum order of derivatives allowed in intrepid.