Intrepid2
Intrepid2_HGRAD_PYR_I2_FEMDef.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 
16 #ifndef __INTREPID2_HGRAD_PYR_I2_SERENDIPITY_FEM_DEF_HPP__
17 #define __INTREPID2_HGRAD_PYR_I2_SERENDIPITY_FEM_DEF_HPP__
18 
19 namespace Intrepid2 {
20 
21  // -------------------------------------------------------------------------------------
22 
23  namespace Impl {
24 
25  template<EOperator opType>
26  template<typename OutputViewType,
27  typename inputViewType>
28  KOKKOS_INLINE_FUNCTION
29  void
30  Basis_HGRAD_PYR_I2_FEM::Serial<opType>::
31  getValues( OutputViewType output,
32  const inputViewType input ) {
33  const auto eps = epsilon();
34 
35  static_assert(std::is_same<
36  typename OutputViewType::value_type,
37  typename inputViewType::value_type>::value,"Input/output view has different value types");
38 
39  typedef typename OutputViewType::value_type value_type;
40 
41  const value_type x = input(0);
42  const value_type y = input(1);
43  const value_type ztmp = input(2);
44 
45  //be sure that the basis functions are defined when z is very close to 1.
46  const value_type z = ( (value_type(1.0) - ztmp) < value_type(eps) ? value_type(1.0 - eps) : ztmp );
47 
48  switch (opType) {
49 
50  case OPERATOR_VALUE: {
51  const value_type w = 1.0/(1.0 - z);
52 
53  output.access(0) = 0.25 * (-x - y - 1.0)*((1.0-x)*(1.0-y) - z + x*y*z*w);
54  output.access(1) = 0.25 * ( x - y - 1.0)*((1.0+x)*(1.0-y) - z - x*y*z*w);
55  output.access(2) = 0.25 * ( x + y - 1.0)*((1.0+x)*(1.0+y) - z + x*y*z*w);
56  output.access(3) = 0.25 * (-x + y - 1.0)*((1.0-x)*(1.0+y) - z - x*y*z*w);
57 
58  output.access(4) = z * (2.0*z - 1.0);
59 
60  output.access(5) = 0.5 * (1.0 + x - z)*(1.0 - x - z)*(1.0 - y - z)*w;
61  output.access(6) = 0.5 * (1.0 + y - z)*(1.0 - y - z)*(1.0 + x - z)*w;
62  output.access(7) = 0.5 * (1.0 + x - z)*(1.0 - x - z)*(1.0 + y - z)*w;
63  output.access(8) = 0.5 * (1.0 + y - z)*(1.0 - y - z)*(1.0 - x - z)*w;
64 
65  output.access(9) = z*(1.0 - x - z)*(1.0 - y - z)*w;
66  output.access(10) = z*(1.0 + x - z)*(1.0 - y - z)*w;
67  output.access(11) = z*(1.0 + x - z)*(1.0 + y - z)*w;
68  output.access(12) = z*(1.0 - x - z)*(1.0 + y - z)*w;
69 
70  break;
71  }
72  case OPERATOR_GRAD:
73  case OPERATOR_D1: {
74  const value_type w = 1.0/(1.0 - z);
75 
76  output.access(0, 0) = 0.25*(-1.0-x-y)*(-1.0+y + y*z*w) - 0.25*((1.0-x)*(1.0-y)-z + x*y*z*w);
77  output.access(0, 1) = 0.25*(-1.0-x-y)*(-1.0+x + x*z*w) - 0.25*((1.0-x)*(1.0-y)-z + x*y*z*w);
78  output.access(0, 2) = 0.25*(-1.0-x-y)*(-1.0 + x*y*w + x*y*z*w*w);
79 
80  output.access(1, 0) = 0.25*(-1.0+x-y)*( 1.0-y - y*z*w) + 0.25*((1.0+x)*(1.0-y)-z - x*y*z*w);
81  output.access(1, 1) = 0.25*(-1.0+x-y)*(-1.0-x - x*z*w) - 0.25*((1.0+x)*(1.0-y)-z - x*y*z*w);
82  output.access(1, 2) = 0.25*(-1.0+x-y)*(-1.0 - x*y*w - x*y*z*w*w);
83 
84  output.access(2, 0) = 0.25*(-1.0+x+y)*(1.0+y + y*z*w) + 0.25*((1.0+x)*(1.0+y)-z + x*y*z*w);
85  output.access(2, 1) = 0.25*(-1.0+x+y)*(1.0+x + x*z*w) + 0.25*((1.0+x)*(1.0+y)-z + x*y*z*w);
86  output.access(2, 2) = 0.25*(-1.0+x+y)*(-1.0 + x*y*w + x*y*z*w*w);
87 
88  output.access(3, 0) = 0.25*(-1.0-x+y)*(-1.0-y - y*z*w) - 0.25*((1.0-x)*(1.0+y)-z - x*y*z*w);
89  output.access(3, 1) = 0.25*(-1.0-x+y)*( 1.0-x - x*z*w) + 0.25*((1.0-x)*(1.0+y)-z - x*y*z*w);
90  output.access(3, 2) = 0.25*(-1.0-x+y)*(-1.0 - x*y*w - x*y*z*w*w);
91 
92  output.access(4, 0) = 0.0;
93  output.access(4, 1) = 0.0;
94  output.access(4, 2) = -1.0 + 4.0*z;
95 
96  output.access(5, 0) = -x*w*(1.0-y-z);
97  output.access(5, 1) = -0.5*(1.0-x-z)*(1.0+x-z)*w;
98  output.access(5, 2) = 0.5*y*x*x*w*w + 0.5*y - 1.0+z;
99 
100  output.access(6, 0) = 0.5*(1.0-y-z)*(1.0+y-z)*w;
101  output.access(6, 1) = -y*w*(1.0+x-z);
102  output.access(6, 2) = -0.5*x*y*y*w*w - 0.5*x - 1.0+z;
103 
104  output.access(7, 0) = -x*w*(1.0+y-z);
105  output.access(7, 1) = 0.5*(1.0-x-z)*(1.0+x-z)*w;
106  output.access(7, 2) = -0.5*y*x*x*w*w - 0.5*y - 1.0+z;
107 
108  output.access(8, 0) = -0.5*(1.0-y-z)*(1.0+y-z)*w;
109  output.access(8, 1) = -y*w*(1.0-x-z);
110  output.access(8, 2) = 0.5*x*y*y*w*w + 0.5*x - 1.0+z;
111 
112  output.access(9, 0) = -(1.0-y-z)*z*w;
113  output.access(9, 1) = -(1.0-x-z)*z*w;
114  output.access(9, 2) = x*y*w*w + 1.0 - x - y - 2.0*z;
115 
116  output.access(10,0) = (1.0-y-z)*z*w;
117  output.access(10,1) = -(1.0+x-z)*z*w;
118  output.access(10,2) = -x*y*w*w + 1.0 + x - y - 2.0*z;
119 
120  output.access(11,0) = (1.0+y-z)*z*w;
121  output.access(11,1) = (1.0+x-z)*z*w;
122  output.access(11,2) = x*y*w*w + 1.0 + x + y - 2.0*z;
123 
124  output.access(12,0) = -(1.0+y-z)*z*w;
125  output.access(12,1) = (1.0-x-z)*z*w;
126  output.access(12,2) = -x*y*w*w + 1.0 - x + y - 2.0*z;
127 
128  break;
129  }
130  case OPERATOR_D2: {
131  const value_type w = 1.0/(1.0 - z);
132 
133  output.access(0, 0) = -0.5*(-1.0+y+y*z*w);
134  output.access(0, 1) = -(-0.25 + 0.5*x + 0.5*y + 0.5*z)*w;
135  output.access(0, 2) = 0.25 + (-0.25*y-0.5*x*y-0.25*y*y)*w*w;
136  output.access(0, 3) = -0.5*(-1.0+x+x*z*w);
137  output.access(0, 4) = 0.25 + (-0.25*x*x-0.25*x-0.5*x*y)*w*w;
138  output.access(0, 5) = 0.5*x*y*(-1.0-x-y)*w*w*w;
139 
140  output.access(1, 0) = 0.5*(1.0-y-y*z*w);
141  output.access(1, 1) =-(0.25 + 0.5*x - 0.5*y - 0.5*z)*w;
142  output.access(1, 2) = -0.25 + (0.25*y-0.5*x*y+0.25*y*y)*w*w;
143  output.access(1, 3) = -0.5*(-1.0-x-x*z*w);
144  output.access(1, 4) = 0.25 + (-0.25*x*x + 0.25*x + 0.5*x*y)*w*w;
145  output.access(1, 5) = -0.5*x*y*(-1.0+x-y)*w*w*w;
146 
147  output.access(2, 0) = 0.5*(1.0+y+y*z*w);
148  output.access(2, 1) =-(-0.25 - 0.5*x - 0.5*y + 0.5*z)*w;
149  output.access(2, 2) = -0.25 + (-0.25*y+0.5*x*y+0.25*y*y)*w*w;
150  output.access(2, 3) = 0.5*(1.0+x+x*z*w);
151  output.access(2, 4) = -0.25 + (0.25*x*x -0.25*x + 0.5*x*y)*w*w;
152  output.access(2, 5) = 0.5*x*y*(-1.0+x+y)*w*w*w;
153 
154  output.access(3, 0) = -0.5*(-1.0-y-y*z*w);
155  output.access(3, 1) =-(0.25 - 0.5*x + 0.5*y - 0.5*z)*w;
156  output.access(3, 2) = 0.25 + (0.25*y+0.5*x*y-0.25*y*y)*w*w;
157  output.access(3, 3) = 0.5*(1.0-x-x*z*w);
158  output.access(3, 4) = -0.25 + (0.25*x + 0.25*x*x - 0.5*x*y)*w*w;
159  output.access(3, 5) = -0.5*x*y*(-1.0-x+y)*w*w*w;
160 
161  output.access(4, 0) = 0.0;
162  output.access(4, 1) = 0.0;
163  output.access(4, 2) = 0.0;
164  output.access(4, 3) = 0.0;
165  output.access(4, 4) = 0.0;
166  output.access(4, 5) = 4.0;
167 
168  output.access(5, 0) = -(1.0-y-z)*w;
169  output.access(5, 1) = x*w;
170  output.access(5, 2) = x*y*w*w;
171  output.access(5, 3) = 0.0;
172  output.access(5, 4) = 0.5*x*x*w*w + 0.5;
173  output.access(5, 5) = x*x*y*w*w*w + 1.0;
174 
175  output.access(6, 0) = 0.0;
176  output.access(6, 1) = -y*w;
177  output.access(6, 2) = -0.5*y*y*w*w - 0.5;
178  output.access(6, 3) =-(1.0+x-z)*w;
179  output.access(6, 4) = -x*y*w*w;
180  output.access(6, 5) = -x*y*y*w*w*w + 1.0;
181 
182  output.access(7, 0) = -(1.0+y-z)*w;
183  output.access(7, 1) = -x*w;
184  output.access(7, 2) = -x*y*w*w;
185  output.access(7, 3) = 0.0;
186  output.access(7, 4) = -0.5*x*x*w*w - 0.5;
187  output.access(7, 5) = -x*x*y*w*w*w + 1.0;
188 
189  output.access(8, 0) = 0.0;
190  output.access(8, 1) = y*w;
191  output.access(8, 2) = 0.5*y*y*w*w + 0.5;
192  output.access(8, 3) = -(1.0-x-z)*w;
193  output.access(8, 4) = x*y*w*w;
194  output.access(8, 5) = x*y*y*w*w*w + 1.0;
195 
196  output.access(9, 0) = 0.0;
197  output.access(9, 1) = z*w;
198  output.access(9, 2) = y*w*w - 1.0;
199  output.access(9, 3) = 0.0;
200  output.access(9, 4) = x*w*w - 1.0;
201  output.access(9, 5) = 2.0*x*y*w*w*w - 2.0;
202 
203  output.access(10,0) = 0.0;
204  output.access(10,1) = -z*w;
205  output.access(10,2) = -y*w*w + 1.0;
206  output.access(10,3) = 0.0;
207  output.access(10,4) = -x*w*w - 1.0;
208  output.access(10,5) = -2.0*x*y*w*w*w - 2.0;
209 
210  output.access(11,0) = 0.0;
211  output.access(11,1) = z*w;
212  output.access(11,2) = y*w*w + 1.0;
213  output.access(11,3) = 0.0;
214  output.access(11,4) = x*w*w + 1.0;
215  output.access(11,5) = 2.0*x*y*w*w*w - 2.0;
216 
217  output.access(12,0) = 0.0;
218  output.access(12,1) = -z*w;
219  output.access(12,2) = -y*w*w - 1.0;
220  output.access(12,3) = 0.0;
221  output.access(12,4) = -x*w*w + 1.0;
222  output.access(12,5) = -2.0*x*y*w*w*w - 2.0;
223 
224  break;
225  }
226  default: {
227  INTREPID2_TEST_FOR_ABORT( opType != OPERATOR_VALUE &&
228  opType != OPERATOR_GRAD &&
229  opType != OPERATOR_D1 &&
230  opType != OPERATOR_D2,
231  ">>> ERROR: (Intrepid2::Basis_HGRAD_PYR_I2_FEM::Serial::getValues) operator is not supported");
232  }
233  }
234  }
235 
236  template<typename DT,
237  typename outputValueValueType, class ...outputValueProperties,
238  typename inputPointValueType, class ...inputPointProperties>
239  void
240  Basis_HGRAD_PYR_I2_FEM::
241  getValues( Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValues,
242  const Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPoints,
243  const EOperator operatorType ) {
244  typedef Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValueViewType;
245  typedef Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPointViewType;
246  typedef typename ExecSpace<typename inputPointViewType::execution_space,typename DT::execution_space>::ExecSpaceType ExecSpaceType;
247 
248  // Number of evaluation points = dim 0 of inputPoints
249  const auto loopSize = inputPoints.extent(0);
250  Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
251 
252  switch (operatorType) {
253 
254  case OPERATOR_VALUE: {
255  typedef Functor<outputValueViewType,inputPointViewType,OPERATOR_VALUE> FunctorType;
256  Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints) );
257  break;
258  }
259  case OPERATOR_GRAD:
260  case OPERATOR_D1: {
261  typedef Functor<outputValueViewType,inputPointViewType,OPERATOR_GRAD> FunctorType;
262  Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints) );
263  break;
264  }
265  case OPERATOR_CURL: {
266  INTREPID2_TEST_FOR_EXCEPTION( operatorType == OPERATOR_CURL, std::invalid_argument,
267  ">>> ERROR (Basis_HGRAD_PYR_I2_FEM): CURL is invalid operator for rank-0 (scalar) functions in 3D");
268  break;
269  }
270  case OPERATOR_DIV: {
271  INTREPID2_TEST_FOR_EXCEPTION( (operatorType == OPERATOR_DIV), std::invalid_argument,
272  ">>> ERROR (Basis_HGRAD_PYR_I2_FEM): DIV is invalid operator for rank-0 (scalar) functions in 3D");
273  break;
274  }
275  case OPERATOR_D2: {
276  typedef Functor<outputValueViewType,inputPointViewType,OPERATOR_D2> FunctorType;
277  Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints) );
278  break;
279  }
280  case OPERATOR_D3:
281  case OPERATOR_D4:
282  case OPERATOR_D5:
283  case OPERATOR_D6:
284  case OPERATOR_D7:
285  case OPERATOR_D8:
286  case OPERATOR_D9:
287  case OPERATOR_D10: {
288  INTREPID2_TEST_FOR_EXCEPTION( true, std::invalid_argument,
289  ">>> ERROR (Basis_HGRAD_PYR_I2_FEM): Operator not implemented yet");
290  break;
291  }
292  default: {
293  INTREPID2_TEST_FOR_EXCEPTION( !( Intrepid2::isValidOperator(operatorType) ), std::invalid_argument,
294  ">>> ERROR (Basis_HGRAD_PYR_I2_FEM): Invalid operator type");
295  }
296  }
297  }
298  }
299 
300  // -------------------------------------------------------------------------------------
301 
302  template<typename DT, typename OT, typename PT>
305  const ordinal_type spaceDim = 3;
306  this->basisCardinality_ = 13;
307  this->basisDegree_ = 2;
308  this->basisCellTopologyKey_ = shards::Pyramid<5>::key;
309  this->basisType_ = BASIS_FEM_DEFAULT;
310  this->basisCoordinates_ = COORDINATES_CARTESIAN;
311  this->functionSpace_ = FUNCTION_SPACE_HGRAD;
312 
313  // initialize tags
314  {
315  // Basis-dependent intializations
316  const ordinal_type tagSize = 4; // size of DoF tag
317  const ordinal_type posScDim = 0; // position in the tag, counting from 0, of the subcell dim
318  const ordinal_type posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal
319  const ordinal_type posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell
320 
321  // An array with local DoF tags assigned to basis functions, in the order of their local enumeration
322  ordinal_type tags[52] = { 0, 0, 0, 1,
323  0, 1, 0, 1,
324  0, 2, 0, 1,
325  0, 3, 0, 1,
326  0, 4, 0, 1,
327  1, 0, 0, 1,
328  1, 1, 0, 1,
329  1, 2, 0, 1,
330  1, 3, 0, 1,
331  1, 4, 0, 1,
332  1, 5, 0, 1,
333  1, 6, 0, 1,
334  1, 7, 0, 1 };
335 
336 
337  // host tags
338  OrdinalTypeArray1DHost tagView(&tags[0], 52);
339 
340  // Basis-independent function sets tag and enum data in tagToOrdinal_ and ordinalToTag_ arrays:
341  this->setOrdinalTagData(this->tagToOrdinal_,
342  this->ordinalToTag_,
343  tagView,
344  this->basisCardinality_,
345  tagSize,
346  posScDim,
347  posScOrd,
348  posDfOrd);
349  }
350 
351  // dofCoords on host and create its mirror view to device
352  Kokkos::DynRankView<typename ScalarViewType::value_type,typename DT::execution_space::array_layout,Kokkos::HostSpace>
353  dofCoords("dofCoordsHost", this->basisCardinality_,spaceDim);
354 
355  dofCoords(0,0) = -1.0; dofCoords(0,1) = -1.0; dofCoords(0,2) = 0.0;
356  dofCoords(1,0) = 1.0; dofCoords(1,1) = -1.0; dofCoords(1,2) = 0.0;
357  dofCoords(2,0) = 1.0; dofCoords(2,1) = 1.0; dofCoords(2,2) = 0.0;
358  dofCoords(3,0) = -1.0; dofCoords(3,1) = 1.0; dofCoords(3,2) = 0.0;
359  dofCoords(4,0) = 0.0; dofCoords(4,1) = 0.0; dofCoords(4,2) = 1.0;
360 
361  dofCoords(5,0) = 0.0; dofCoords(5,1) = -1.0; dofCoords(5,2) = 0.0;
362  dofCoords(6,0) = 1.0; dofCoords(6,1) = 0.0; dofCoords(6,2) = 0.0;
363  dofCoords(7,0) = 0.0; dofCoords(7,1) = 1.0; dofCoords(7,2) = 0.0;
364  dofCoords(8,0) = -1.0; dofCoords(8,1) = 0.0; dofCoords(8,2) = 0.0;
365  dofCoords(9,0) = -0.5; dofCoords(9,1) = -0.5; dofCoords(9,2) = 0.5;
366  dofCoords(10,0) = 0.5; dofCoords(10,1) = -0.5; dofCoords(10,2) = 0.5;
367  dofCoords(11,0) = 0.5; dofCoords(11,1) = 0.5; dofCoords(11,2) = 0.5;
368  dofCoords(12,0) = -0.5; dofCoords(12,1) = 0.5; dofCoords(12,2) = 0.5;
369 
370  this->dofCoords_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoords);
371  Kokkos::deep_copy(this->dofCoords_, dofCoords);
372  }
373 
374  template<typename DT, typename OT, typename PT>
375  void
377  ordinal_type& perTeamSpaceSize,
378  ordinal_type& perThreadSpaceSize,
379  const PointViewType inputPoints,
380  const EOperator operatorType) const {
381  perTeamSpaceSize = 0;
382  perThreadSpaceSize = 0;
383  }
384 
385  template<typename DT, typename OT, typename PT>
386  KOKKOS_INLINE_FUNCTION
387  void
388  Basis_HGRAD_PYR_I2_FEM<DT,OT,PT>::getValues(
389  OutputViewType outputValues,
390  const PointViewType inputPoints,
391  const EOperator operatorType,
392  const typename Kokkos::TeamPolicy<typename DT::execution_space>::member_type& team_member,
393  const typename DT::execution_space::scratch_memory_space & scratchStorage,
394  const ordinal_type subcellDim,
395  const ordinal_type subcellOrdinal) const {
396 
397  INTREPID2_TEST_FOR_ABORT( !((subcellDim <= 0) && (subcellOrdinal == -1)),
398  ">>> ERROR: (Intrepid2::Basis_HGRAD_PYR_I2_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet.");
399 
400  (void) scratchStorage; //avoid unused variable warning
401 
402  const int numPoints = inputPoints.extent(0);
403 
404  switch(operatorType) {
405  case OPERATOR_VALUE:
406  Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) {
407  auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() );
408  const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() );
409  Impl::Basis_HGRAD_PYR_I2_FEM::Serial<OPERATOR_VALUE>::getValues( output, input);
410  });
411  break;
412  case OPERATOR_GRAD:
413  Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) {
414  auto output = Kokkos::subview( outputValues, Kokkos::ALL(), pt, Kokkos::ALL() );
415  const auto input = Kokkos::subview( inputPoints, pt, Kokkos::ALL() );
416  Impl::Basis_HGRAD_PYR_I2_FEM::Serial<OPERATOR_GRAD>::getValues( output, input);
417  });
418  break;
419  default: {}
420  }
421  }
422 
423 }// namespace Intrepid2
424 #endif
Implementation of an H(grad)-compatible FEM basis of degree 2 on a Pyramid cell.