Intrepid2
Intrepid2_HCURL_HEX_In_FEMDef.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ************************************************************************
3 //
4 // Intrepid2 Package
5 // Copyright (2007) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Kyungjoo Kim (kyukim@sandia.gov), or
38 // Mauro Perego (mperego@sandia.gov)
39 //
40 // ************************************************************************
41 // @HEADER
42 
49 #ifndef __INTREPID2_HCURL_HEX_IN_FEM_DEF_HPP__
50 #define __INTREPID2_HCURL_HEX_IN_FEM_DEF_HPP__
51 
52 namespace Intrepid2 {
53 
54  // -------------------------------------------------------------------------------------
55  namespace Impl {
56 
57  template<EOperator opType>
58  template<typename outputViewType,
59  typename inputViewType,
60  typename workViewType,
61  typename vinvViewType>
62  KOKKOS_INLINE_FUNCTION
63  void
64  Basis_HCURL_HEX_In_FEM::Serial<opType>::
65  getValues( outputViewType output,
66  const inputViewType input,
67  workViewType work,
68  const vinvViewType vinvLine,
69  const vinvViewType vinvBubble) {
70  const ordinal_type cardLine = vinvLine.extent(0);
71  const ordinal_type cardBubble = vinvBubble.extent(0);
72 
73  const ordinal_type npts = input.extent(0);
74 
75  typedef Kokkos::pair<ordinal_type,ordinal_type> range_type;
76  const auto input_x = Kokkos::subview(input, Kokkos::ALL(), range_type(0,1));
77  const auto input_y = Kokkos::subview(input, Kokkos::ALL(), range_type(1,2));
78  const auto input_z = Kokkos::subview(input, Kokkos::ALL(), range_type(2,3));
79 
80  const ordinal_type dim_s = get_dimension_scalar(work);
81  auto ptr0 = work.data();
82  auto ptr1 = work.data() + cardLine*npts*dim_s;
83  auto ptr2 = work.data() + 2*cardLine*npts*dim_s;
84  auto ptr3 = work.data() + 3*cardLine*npts*dim_s;
85 
86  typedef typename Kokkos::DynRankView<typename workViewType::value_type, typename workViewType::memory_space> viewType;
87  auto vcprop = Kokkos::common_view_alloc_prop(work);
88 
89  switch (opType) {
90  case OPERATOR_VALUE: {
91 
92  viewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts);
93  viewType outputLine_A(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts);
94  viewType outputLine_B(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts);
95  viewType outputBubble(Kokkos::view_wrap(ptr3, vcprop), cardBubble, npts);
96 
97  // tensor product
98  ordinal_type idx = 0;
99  {
100  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
101  getValues(outputBubble, input_x, workLine, vinvBubble);
102 
103  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
104  getValues(outputLine_A, input_y, workLine, vinvLine);
105 
106  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
107  getValues(outputLine_B, input_z, workLine, vinvLine);
108 
109  // x component (lineBasis(z) lineBasis(y) bubbleBasis(x))
110  const auto output_x = outputBubble;
111  const auto output_y = outputLine_A;
112  const auto output_z = outputLine_B;
113 
114  for (ordinal_type k=0;k<cardLine;++k) // z
115  for (ordinal_type j=0;j<cardLine;++j) // y
116  for (ordinal_type i=0;i<cardBubble;++i,++idx) // x
117  for (ordinal_type l=0;l<npts;++l) {
118  output.access(idx,l,0) = output_x.access(i,l)*output_y.access(j,l)*output_z.access(k,l);
119  output.access(idx,l,1) = 0.0;
120  output.access(idx,l,2) = 0.0;
121  }
122  }
123  {
124  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
125  getValues(outputLine_A, input_x, workLine, vinvLine);
126 
127  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
128  getValues(outputBubble, input_y, workLine, vinvBubble);
129 
130  //Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
131  // getValues(outputLine_B, input_z, workLine, vinvLine);
132 
133  // y component (lineBasis(z) bubbleBasis(y) lineBasis(x))
134  const auto output_x = outputLine_A;
135  const auto output_y = outputBubble;
136  const auto output_z = outputLine_B;
137 
138  for (ordinal_type k=0;k<cardLine;++k) // z
139  for (ordinal_type j=0;j<cardBubble;++j) // y
140  for (ordinal_type i=0;i<cardLine;++i,++idx) // x
141  for (ordinal_type l=0;l<npts;++l) {
142  output.access(idx,l,0) = 0.0;
143  output.access(idx,l,1) = output_x.access(i,l)*output_y.access(j,l)*output_z.access(k,l);
144  output.access(idx,l,2) = 0.0;
145  }
146  }
147  {
148  //Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
149  // getValues(outputLine_A, input_x, workLine, vinvLine);
150 
151  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
152  getValues(outputLine_B, input_y, workLine, vinvLine);
153 
154  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
155  getValues(outputBubble, input_z, workLine, vinvBubble);
156 
157  // z component (bubbleBasis(z) bubbleBasis(y) lineBasis(x))
158  const auto output_x = outputLine_A;
159  const auto output_y = outputLine_B;
160  const auto output_z = outputBubble;
161 
162  for (ordinal_type k=0;k<cardBubble;++k) // z
163  for (ordinal_type j=0;j<cardLine;++j) // y
164  for (ordinal_type i=0;i<cardLine;++i,++idx) // x
165  for (ordinal_type l=0;l<npts;++l) {
166  output.access(idx,l,0) = 0.0;
167  output.access(idx,l,1) = 0.0;
168  output.access(idx,l,2) = output_x.access(i,l)*output_y.access(j,l)*output_z.access(k,l);
169  }
170  }
171  break;
172  }
173  case OPERATOR_CURL: {
174 
175  auto ptr4 = work.data() + 4*cardLine*npts*dim_s;
176  auto ptr5 = work.data() + 5*cardLine*npts*dim_s;
177 
178  viewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts);
179  viewType outputLine_A(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts);
180  viewType outputLine_B(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts);
181  viewType outputLine_DA(Kokkos::view_wrap(ptr3, vcprop), cardLine, npts, 1);
182  viewType outputLine_DB(Kokkos::view_wrap(ptr4, vcprop), cardLine, npts, 1);
183  viewType outputBubble(Kokkos::view_wrap(ptr5, vcprop), cardBubble, npts);
184 
185  // tensor product
186  ordinal_type idx = 0;
187 
188  { // x - component
189  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
190  getValues(outputBubble, input_x, workLine, vinvBubble);
191 
192  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
193  getValues(outputLine_A, input_y, workLine, vinvLine);
194 
195  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
196  getValues(outputLine_DA, input_y, workLine, vinvLine, 1);
197 
198  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
199  getValues(outputLine_B, input_z, workLine, vinvLine);
200 
201  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
202  getValues(outputLine_DB, input_z, workLine, vinvLine, 1);
203 
204  // x component (lineBasis(z) lineBasis(y) bubbleBasis(x))
205  const auto output_x = outputBubble;
206  const auto output_y = outputLine_A;
207  const auto output_dy = outputLine_DA;
208  const auto output_z = outputLine_B;
209  const auto output_dz = outputLine_DB;
210 
211  for (ordinal_type k=0;k<cardLine;++k) // z
212  for (ordinal_type j=0;j<cardLine;++j) // y
213  for (ordinal_type i=0;i<cardBubble;++i,++idx) // x
214  for (ordinal_type l=0;l<npts;++l) {
215  output.access(idx,l,0) = 0.0;
216  output.access(idx,l,1) = output_x.access(i,l)*output_y.access (j,l) *output_dz.access(k,l,0);
217  output.access(idx,l,2) = -output_x.access(i,l)*output_dy.access(j,l,0)*output_z.access (k,l);
218  }
219  }
220  { // y - component
221  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
222  getValues(outputLine_A, input_x, workLine, vinvLine);
223 
224  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
225  getValues(outputLine_DA, input_x, workLine, vinvLine, 1);
226 
227  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
228  getValues(outputBubble, input_y, workLine, vinvBubble);
229 
230  //Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
231  // getValues(outputLine_B, input_z, workLine, vinvLine);
232 
233  //Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
234  // getValues(outputLine_DB, input_z, workLine, vinvLine, 1);
235 
236  // x component (lineBasis(z) lineBasis(y) bubbleBasis(x))
237  const auto output_x = outputLine_A;
238  const auto output_dx = outputLine_DA;
239  const auto output_y = outputBubble;
240  const auto output_z = outputLine_B;
241  const auto output_dz = outputLine_DB;
242 
243  for (ordinal_type k=0;k<cardLine;++k) // z
244  for (ordinal_type j=0;j<cardBubble;++j) // y
245  for (ordinal_type i=0;i<cardLine;++i,++idx) // x
246  for (ordinal_type l=0;l<npts;++l) {
247  output.access(idx,l,0) = -output_x.access (i,l) *output_y.access(j,l)*output_dz.access(k,l,0);
248  output.access(idx,l,1) = 0.0;
249  output.access(idx,l,2) = output_dx(i,l,0)*output_y.access(j,l)*output_z.access (k,l);
250  }
251  }
252  { // z - component
253  // Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
254  // getValues(outputLine_A, input_x, workLine, vinvLine);
255 
256  // Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
257  // getValues(outputLine_DA, input_x, workLine, vinvLine, 1);
258 
259  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
260  getValues(outputLine_B, input_y, workLine, vinvLine);
261 
262  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
263  getValues(outputLine_DB, input_y, workLine, vinvLine, 1);
264 
265  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
266  getValues(outputBubble, input_z, workLine, vinvBubble);
267 
268  // x component (lineBasis(z) lineBasis(y) bubbleBasis(x))
269  const auto output_x = outputLine_A;
270  const auto output_dx = outputLine_DA;
271  const auto output_y = outputLine_B;
272  const auto output_dy = outputLine_DB;
273  const auto output_z = outputBubble;
274 
275  for (ordinal_type k=0;k<cardBubble;++k) // z
276  for (ordinal_type j=0;j<cardLine;++j) // y
277  for (ordinal_type i=0;i<cardLine;++i,++idx) // x
278  for (ordinal_type l=0;l<npts;++l) {
279  output.access(idx,l,0) = output_x.access (i,l) *output_dy.access(j,l,0)*output_z.access(k,l);
280  output.access(idx,l,1) = -output_dx(i,l,0)*output_y.access (j,l) *output_z.access(k,l);
281  output.access(idx,l,2) = 0.0;
282  }
283  }
284  break;
285  }
286  default: {
287  INTREPID2_TEST_FOR_ABORT( true,
288  ">>> ERROR: (Intrepid2::Basis_HCURL_HEX_In_FEM::Serial::getValues) operator is not supported" );
289  }
290  }
291  }
292  template<typename SpT, ordinal_type numPtsPerEval,
293  typename outputValueValueType, class ...outputValueProperties,
294  typename inputPointValueType, class ...inputPointProperties,
295  typename vinvValueType, class ...vinvProperties>
296  void
297  Basis_HCURL_HEX_In_FEM::
298  getValues( Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValues,
299  const Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPoints,
300  const Kokkos::DynRankView<vinvValueType, vinvProperties...> vinvLine,
301  const Kokkos::DynRankView<vinvValueType, vinvProperties...> vinvBubble,
302  const EOperator operatorType ) {
303  typedef Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValueViewType;
304  typedef Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPointViewType;
305  typedef Kokkos::DynRankView<vinvValueType, vinvProperties...> vinvViewType;
306  typedef typename ExecSpace<typename inputPointViewType::execution_space,SpT>::ExecSpaceType ExecSpaceType;
307 
308  // loopSize corresponds to cardinality
309  const auto loopSizeTmp1 = (inputPoints.extent(0)/numPtsPerEval);
310  const auto loopSizeTmp2 = (inputPoints.extent(0)%numPtsPerEval != 0);
311  const auto loopSize = loopSizeTmp1 + loopSizeTmp2;
312  Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
313 
314  typedef typename inputPointViewType::value_type inputPointType;
315 
316  const ordinal_type cardinality = outputValues.extent(0);
317  //get basis order based on basis cardinality.
318  ordinal_type order = 0;
319  ordinal_type cardBubble; // = std::cbrt(cardinality/3);
320  ordinal_type cardLine; // = cardBubble+1;
321  do {
322  cardBubble = Intrepid2::getPnCardinality<1>(order);
323  cardLine = Intrepid2::getPnCardinality<1>(++order);
324  } while((3*cardBubble*cardLine*cardLine != cardinality) && (order != Parameters::MaxOrder));
325  auto vcprop = Kokkos::common_view_alloc_prop(inputPoints);
326  typedef typename Kokkos::DynRankView< inputPointType, typename inputPointViewType::memory_space> workViewType;
327 
328  switch (operatorType) {
329  case OPERATOR_VALUE: {
330  auto workSize = Serial<OPERATOR_VALUE>::getWorkSizePerPoint(order);
331  workViewType work(Kokkos::view_alloc("Basis_CURL_HEX_In_FEM::getValues::work", vcprop), workSize, inputPoints.extent(0));
332  typedef Functor<outputValueViewType,inputPointViewType,vinvViewType, workViewType,
333  OPERATOR_VALUE,numPtsPerEval> FunctorType;
334  Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinvLine, vinvBubble, work) );
335  break;
336  }
337  case OPERATOR_CURL: {
338  auto workSize = Serial<OPERATOR_CURL>::getWorkSizePerPoint(order);
339  workViewType work(Kokkos::view_alloc("Basis_CURL_HEX_In_FEM::getValues::work", vcprop), workSize, inputPoints.extent(0));
340  typedef Functor<outputValueViewType,inputPointViewType,vinvViewType, workViewType,
341  OPERATOR_CURL,numPtsPerEval> FunctorType;
342  Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinvLine, vinvBubble, work) );
343  break;
344  }
345  default: {
346  INTREPID2_TEST_FOR_EXCEPTION( true , std::invalid_argument,
347  ">>> ERROR (Basis_HCURL_HEX_In_FEM): Operator type not implemented" );
348  // break;commented out since exception is thrown
349  }
350  }
351  }
352  }
353 
354  // -------------------------------------------------------------------------------------
355 
356  template<typename SpT, typename OT, typename PT>
358  Basis_HCURL_HEX_In_FEM( const ordinal_type order,
359  const EPointType pointType ) {
360 
361  INTREPID2_TEST_FOR_EXCEPTION( !(pointType == POINTTYPE_EQUISPACED ||
362  pointType == POINTTYPE_WARPBLEND), std::invalid_argument,
363  ">>> ERROR (Basis_HCURL_HEX_In_FEM): pointType must be either equispaced or warpblend.");
364 
365  // this should be created in host and vinv should be deep copied into device space
366  Basis_HGRAD_LINE_Cn_FEM<SpT,OT,PT> lineBasis( order, pointType );
367  Basis_HGRAD_LINE_Cn_FEM<SpT,OT,PT> bubbleBasis( order - 1, POINTTYPE_GAUSS );
368 
369  const ordinal_type
370  cardLine = lineBasis.getCardinality(),
371  cardBubble = bubbleBasis.getCardinality();
372 
373  this->vinvLine_ = Kokkos::DynRankView<typename scalarViewType::value_type,SpT>("Hcurl::Hex::In::vinvLine", cardLine, cardLine);
374  this->vinvBubble_ = Kokkos::DynRankView<typename scalarViewType::value_type,SpT>("Hcurl::Hex::In::vinvBubble", cardBubble, cardBubble);
375 
376  lineBasis.getVandermondeInverse(this->vinvLine_);
377  bubbleBasis.getVandermondeInverse(this->vinvBubble_);
378 
379  this->basisCardinality_ = 3*cardLine*cardLine*cardBubble;
380  this->basisDegree_ = order;
381  this->basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<8> >() );
382  this->basisType_ = BASIS_FEM_FIAT;
383  this->basisCoordinates_ = COORDINATES_CARTESIAN;
384 
385  // initialize tags
386  {
387  // Basis-dependent initializations
388  const ordinal_type tagSize = 4; // size of DoF tag, i.e., number of fields in the tag
389  const ordinal_type posScDim = 0; // position in the tag, counting from 0, of the subcell dim
390  const ordinal_type posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal
391  const ordinal_type posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell
392 
393  // An array with local DoF tags assigned to the basis functions, in the order of their local enumeration
394  constexpr ordinal_type maxCardLine = Parameters::MaxOrder + 1;
395  ordinal_type tags[3*maxCardLine*maxCardLine*maxCardLine][4];
396 
397  const ordinal_type edge_x[2][2] = { {0, 4}, {2, 6} };
398  const ordinal_type edge_y[2][2] = { {3, 7}, {1, 5} };
399  const ordinal_type edge_z[2][2] = { {8,11}, {9,10} };
400 
401  const ordinal_type face_yz[2] = {3, 1};
402  const ordinal_type face_xz[2] = {0, 2};
403  const ordinal_type face_xy[2] = {4, 5};
404 
405  {
406  ordinal_type idx = 0;
407 
411 
412  // since there are x/y components in the interior
413  // dof sum should be computed before the information
414  // is assigned to tags
415  const ordinal_type
416  face_ndofs_per_direction = (cardLine-2)*cardBubble,
417  face_ndofs = 2*face_ndofs_per_direction,
418  intr_ndofs_per_direction = (cardLine-2)*(cardLine-2)*cardBubble,
419  intr_ndofs = 3*intr_ndofs_per_direction;
420 
421  // x component (lineBasis(z) lineBasis(y) bubbleBasis(x))
422  for (ordinal_type k=0;k<cardLine;++k) { // z
423  const auto tag_z = lineBasis.getDofTag(k);
424  for (ordinal_type j=0;j<cardLine;++j) { // y
425  const auto tag_y = lineBasis.getDofTag(j);
426  for (ordinal_type i=0;i<cardBubble;++i,++idx) { // x
427  const auto tag_x = bubbleBasis.getDofTag(i);
428 
429  if (tag_x(0) == 1 && tag_y(0) == 0 && tag_z(0) == 0) {
430  // edge: x edge, y vert, z vert
431  tags[idx][0] = 1; // edge dof
432  tags[idx][1] = edge_x[tag_y(1)][tag_z(1)]; // edge id
433  tags[idx][2] = tag_x(2); // local dof id
434  tags[idx][3] = tag_x(3); // total number of dofs in this edge
435  } else if (tag_x(0) == 1 && tag_y(0) == 0 && tag_z(0) == 1) {
436  // face, x edge, y vert, z edge
437  tags[idx][0] = 2; // face dof
438  tags[idx][1] = face_xz[tag_y(1)]; // face id
439  tags[idx][2] = tag_x(2) + tag_x(3)*tag_z(2); // local dof id
440  tags[idx][3] = face_ndofs; // total number of dofs in this face
441  } else if (tag_x(0) == 1 && tag_y(0) == 1 && tag_z(0) == 0) {
442  // face, x edge, y edge, z vert
443  tags[idx][0] = 2; // face dof
444  tags[idx][1] = face_xy[tag_z(1)]; // face id
445  tags[idx][2] = tag_x(2) + tag_x(3)*tag_y(2); // local dof id
446  tags[idx][3] = face_ndofs; // total number of dofs in this face
447  } else {
448  // interior
449  tags[idx][0] = 3; // interior dof
450  tags[idx][1] = 0;
451  tags[idx][2] = tag_x(2) + tag_x(3)*tag_y(2) + tag_x(3)*tag_y(3)*tag_z(2); // local dof id
452  tags[idx][3] = intr_ndofs; // total number of dofs in this vertex
453  }
454  }
455  }
456  }
457 
458  // y component (lineBasis(z) bubbleBasis(y) lineBasis(x))
459  for (ordinal_type k=0;k<cardLine;++k) { // z
460  const auto tag_z = lineBasis.getDofTag(k);
461  for (ordinal_type j=0;j<cardBubble;++j) { // y
462  const auto tag_y = bubbleBasis.getDofTag(j);
463  for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
464  const auto tag_x = lineBasis.getDofTag(i);
465 
466  if (tag_x(0) == 0 && tag_y(0) == 1 && tag_z(0) == 0) {
467  // edge: x vert, y edge, z vert
468  tags[idx][0] = 1; // edge dof
469  tags[idx][1] = edge_y[tag_x(1)][tag_z(1)]; // edge id
470  tags[idx][2] = tag_y(2); // local dof id
471  tags[idx][3] = tag_y(3); // total number of dofs in this vertex
472  } else if (tag_x(0) == 0 && tag_y(0) == 1 && tag_z(0) == 1) {
473  // face, x vert, y edge, z edge
474  tags[idx][0] = 2; // face dof
475  tags[idx][1] = face_yz[tag_x(1)]; // face id
476  tags[idx][2] = tag_y(2) + tag_y(3)*tag_z(2); // local dof id
477  tags[idx][3] = face_ndofs; // total number of dofs in this vertex
478  } else if (tag_x(0) == 1 && tag_y(0) == 1 && tag_z(0) == 0) {
479  // face, x edge, y edge, z vert
480  tags[idx][0] = 2; // face dof
481  tags[idx][1] = face_xy[tag_z(1)]; // face id
482  tags[idx][2] = face_ndofs_per_direction + tag_x(2) + tag_x(3)*tag_y(2); // local dof id
483  tags[idx][3] = face_ndofs; // total number of dofs in this vertex
484  } else {
485  // interior
486  tags[idx][0] = 3; // interior dof
487  tags[idx][1] = 0;
488  tags[idx][2] = intr_ndofs_per_direction + tag_x(2) + tag_x(3)*tag_y(2) + tag_x(3)*tag_y(3)*tag_z(2); // local dof id
489  tags[idx][3] = intr_ndofs; // total number of dofs in this vertex
490  }
491  }
492  }
493  }
494 
495  // z component (bubbleBasis(z) lineBasis(y) lineBasis(x))
496  for (ordinal_type k=0;k<cardBubble;++k) { // y
497  const auto tag_z = bubbleBasis.getDofTag(k);
498  for (ordinal_type j=0;j<cardLine;++j) { // z
499  const auto tag_y = lineBasis.getDofTag(j);
500  for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
501  const auto tag_x = lineBasis.getDofTag(i);
502 
503  if (tag_x(0) == 0 && tag_y(0) == 0 && tag_z(0) == 1) {
504  // edge: x vert, y vert, z edge
505  tags[idx][0] = 1; // edge dof
506  tags[idx][1] = edge_z[tag_x(1)][tag_y(1)]; // edge id
507  tags[idx][2] = tag_z(2); // local dof id
508  tags[idx][3] = tag_z(3); // total number of dofs in this vertex
509  } else if (tag_x(0) == 0 && tag_y(0) == 1 && tag_z(0) == 1) {
510  // face, x vert, y edge, z edge
511  tags[idx][0] = 2; // face dof
512  tags[idx][1] = face_yz[tag_x(1)]; // face id
513  tags[idx][2] = face_ndofs_per_direction + tag_y(2) + tag_y(3)*tag_z(2); // local dof id
514  tags[idx][3] = face_ndofs; // total number of dofs in this vertex
515  } else if (tag_x(0) == 1 && tag_y(0) == 0 && tag_z(0) == 1) {
516  // face, x edge, y vert, z edge
517  tags[idx][0] = 2; // face dof
518  tags[idx][1] = face_xz[tag_y(1)]; // face id
519  tags[idx][2] = face_ndofs_per_direction + tag_x(2) + tag_x(3)*tag_z(2); // local dof id
520  tags[idx][3] = face_ndofs; // total number of dofs in this vertex
521  } else {
522  // interior
523  tags[idx][0] = 3; // interior dof
524  tags[idx][1] = 0;
525  tags[idx][2] = 2*intr_ndofs_per_direction + tag_x(2) + tag_x(3)*tag_y(2) + tag_x(3)*tag_y(3)*tag_z(2); // local dof id
526  tags[idx][3] = intr_ndofs; // total number of dofs in this vertex
527  }
528  }
529  }
530  }
531 
532  INTREPID2_TEST_FOR_EXCEPTION( idx != this->basisCardinality_ , std::runtime_error,
533  ">>> ERROR (Basis_HCURL_HEX_In_FEM): " \
534  "counted tag index is not same as cardinality." );
535  }
536 
537  ordinal_type_array_1d_host tagView(&tags[0][0], this->basisCardinality_*4);
538 
539  // Basis-independent function sets tag and enum data in tagToOrdinal_ and ordinalToTag_ arrays:
540  // tags are constructed on host
541  this->setOrdinalTagData(this->tagToOrdinal_,
542  this->ordinalToTag_,
543  tagView,
544  this->basisCardinality_,
545  tagSize,
546  posScDim,
547  posScOrd,
548  posDfOrd);
549  }
550 
551  // dofCoords on host and create its mirror view to device
552  Kokkos::DynRankView<typename scalarViewType::value_type,typename SpT::array_layout,Kokkos::HostSpace>
553  dofCoordsHost("dofCoordsHost", this->basisCardinality_, this->basisCellTopology_.getDimension());
554 
555  // dofCoords on host and create its mirror view to device
556  Kokkos::DynRankView<typename scalarViewType::value_type,typename SpT::array_layout,Kokkos::HostSpace>
557  dofCoeffsHost("dofCoeffsHost", this->basisCardinality_, this->basisCellTopology_.getDimension());
558 
559  Kokkos::DynRankView<typename scalarViewType::value_type,SpT>
560  dofCoordsLine("dofCoordsLine", cardLine, 1),
561  dofCoordsBubble("dofCoordsBubble", cardBubble, 1);
562 
563  lineBasis.getDofCoords(dofCoordsLine);
564  auto dofCoordsLineHost = Kokkos::create_mirror_view(Kokkos::HostSpace(), dofCoordsLine);
565  Kokkos::deep_copy(dofCoordsLineHost, dofCoordsLine);
566 
567  bubbleBasis.getDofCoords(dofCoordsBubble);
568  auto dofCoordsBubbleHost = Kokkos::create_mirror_view(Kokkos::HostSpace(), dofCoordsBubble);
569  Kokkos::deep_copy(dofCoordsBubbleHost, dofCoordsBubble);
570 
571  {
572  ordinal_type idx = 0;
573 
574  // x component (lineBasis(z) lineBasis(y) bubbleBasis(x))
575  for (ordinal_type k=0;k<cardLine;++k) { // z
576  for (ordinal_type j=0;j<cardLine;++j) { // y
577  for (ordinal_type i=0;i<cardBubble;++i,++idx) { // x
578  dofCoordsHost(idx,0) = dofCoordsBubbleHost(i,0);
579  dofCoordsHost(idx,1) = dofCoordsLineHost(j,0);
580  dofCoordsHost(idx,2) = dofCoordsLineHost(k,0);
581  dofCoeffsHost(idx,0) = 1.0;
582  }
583  }
584  }
585 
586  // y component (lineBasis(z) bubbleBasis(y) lineBasis(x))
587  for (ordinal_type k=0;k<cardLine;++k) { // z
588  for (ordinal_type j=0;j<cardBubble;++j) { // y
589  for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
590  dofCoordsHost(idx,0) = dofCoordsLineHost(i,0);
591  dofCoordsHost(idx,1) = dofCoordsBubbleHost(j,0);
592  dofCoordsHost(idx,2) = dofCoordsLineHost(k,0);
593  dofCoeffsHost(idx,1) = 1.0;
594  }
595  }
596  }
597 
598  // z component (bubbleBasis(z) lineBasis(y) lineBasis(x))
599  for (ordinal_type k=0;k<cardBubble;++k) { // z
600  for (ordinal_type j=0;j<cardLine;++j) { // y
601  for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
602  dofCoordsHost(idx,0) = dofCoordsLineHost(i,0);
603  dofCoordsHost(idx,1) = dofCoordsLineHost(j,0);
604  dofCoordsHost(idx,2) = dofCoordsBubbleHost(k,0);
605  dofCoeffsHost(idx,2) = 1.0;
606  }
607  }
608  }
609  }
610 
611  this->dofCoords_ = Kokkos::create_mirror_view(typename SpT::memory_space(), dofCoordsHost);
612  Kokkos::deep_copy(this->dofCoords_, dofCoordsHost);
613 
614  this->dofCoeffs_ = Kokkos::create_mirror_view(typename SpT::memory_space(), dofCoeffsHost);
615  Kokkos::deep_copy(this->dofCoeffs_, dofCoeffsHost);
616  }
617 }
618 
619 #endif
ordinal_type getCardinality() const
Returns cardinality of the basis.
Kokkos::View< ordinal_type *,typename ExecSpaceType::array_layout, Kokkos::HostSpace > ordinal_type_array_1d_host
View type for 1d host array.
const ordinal_type_array_stride_1d_host getDofTag(const ordinal_type dofOrd) const
DoF ordinal to DoF tag lookup.
Implementation of the locally H(grad)-compatible FEM basis of variable order on the [-1...
Basis_HCURL_HEX_In_FEM(const ordinal_type order, const EPointType pointType=POINTTYPE_EQUISPACED)
Constructor.
static constexpr ordinal_type MaxOrder
The maximum reconstruction order.
virtual void getDofCoords(scalarViewType dofCoords) const
Returns spatial locations (coordinates) of degrees of freedom on the reference cell.