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  this->functionSpace_ = FUNCTION_SPACE_HCURL;
385 
386  // initialize tags
387  {
388  // Basis-dependent initializations
389  const ordinal_type tagSize = 4; // size of DoF tag, i.e., number of fields in the tag
390  const ordinal_type posScDim = 0; // position in the tag, counting from 0, of the subcell dim
391  const ordinal_type posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal
392  const ordinal_type posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell
393 
394  // An array with local DoF tags assigned to the basis functions, in the order of their local enumeration
395  constexpr ordinal_type maxCardLine = Parameters::MaxOrder + 1;
396  ordinal_type tags[3*maxCardLine*maxCardLine*maxCardLine][4];
397 
398  const ordinal_type edge_x[2][2] = { {0, 4}, {2, 6} };
399  const ordinal_type edge_y[2][2] = { {3, 7}, {1, 5} };
400  const ordinal_type edge_z[2][2] = { {8,11}, {9,10} };
401 
402  const ordinal_type face_yz[2] = {3, 1};
403  const ordinal_type face_xz[2] = {0, 2};
404  const ordinal_type face_xy[2] = {4, 5};
405 
406  {
407  ordinal_type idx = 0;
408 
412 
413  // since there are x/y components in the interior
414  // dof sum should be computed before the information
415  // is assigned to tags
416  const ordinal_type
417  face_ndofs_per_direction = (cardLine-2)*cardBubble,
418  face_ndofs = 2*face_ndofs_per_direction,
419  intr_ndofs_per_direction = (cardLine-2)*(cardLine-2)*cardBubble,
420  intr_ndofs = 3*intr_ndofs_per_direction;
421 
422  // x component (lineBasis(z) lineBasis(y) bubbleBasis(x))
423  for (ordinal_type k=0;k<cardLine;++k) { // z
424  const auto tag_z = lineBasis.getDofTag(k);
425  for (ordinal_type j=0;j<cardLine;++j) { // y
426  const auto tag_y = lineBasis.getDofTag(j);
427  for (ordinal_type i=0;i<cardBubble;++i,++idx) { // x
428  const auto tag_x = bubbleBasis.getDofTag(i);
429 
430  if (tag_x(0) == 1 && tag_y(0) == 0 && tag_z(0) == 0) {
431  // edge: x edge, y vert, z vert
432  tags[idx][0] = 1; // edge dof
433  tags[idx][1] = edge_x[tag_y(1)][tag_z(1)]; // edge id
434  tags[idx][2] = tag_x(2); // local dof id
435  tags[idx][3] = tag_x(3); // total number of dofs in this edge
436  } else if (tag_x(0) == 1 && tag_y(0) == 0 && tag_z(0) == 1) {
437  // face, x edge, y vert, z edge
438  tags[idx][0] = 2; // face dof
439  tags[idx][1] = face_xz[tag_y(1)]; // face id
440  tags[idx][2] = tag_x(2) + tag_x(3)*tag_z(2); // local dof id
441  tags[idx][3] = face_ndofs; // total number of dofs in this face
442  } else if (tag_x(0) == 1 && tag_y(0) == 1 && tag_z(0) == 0) {
443  // face, x edge, y edge, z vert
444  tags[idx][0] = 2; // face dof
445  tags[idx][1] = face_xy[tag_z(1)]; // face id
446  tags[idx][2] = tag_x(2) + tag_x(3)*tag_y(2); // local dof id
447  tags[idx][3] = face_ndofs; // total number of dofs in this face
448  } else {
449  // interior
450  tags[idx][0] = 3; // interior dof
451  tags[idx][1] = 0;
452  tags[idx][2] = tag_x(2) + tag_x(3)*tag_y(2) + tag_x(3)*tag_y(3)*tag_z(2); // local dof id
453  tags[idx][3] = intr_ndofs; // total number of dofs in this vertex
454  }
455  }
456  }
457  }
458 
459  // y component (lineBasis(z) bubbleBasis(y) lineBasis(x))
460  for (ordinal_type k=0;k<cardLine;++k) { // z
461  const auto tag_z = lineBasis.getDofTag(k);
462  for (ordinal_type j=0;j<cardBubble;++j) { // y
463  const auto tag_y = bubbleBasis.getDofTag(j);
464  for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
465  const auto tag_x = lineBasis.getDofTag(i);
466 
467  if (tag_x(0) == 0 && tag_y(0) == 1 && tag_z(0) == 0) {
468  // edge: x vert, y edge, z vert
469  tags[idx][0] = 1; // edge dof
470  tags[idx][1] = edge_y[tag_x(1)][tag_z(1)]; // edge id
471  tags[idx][2] = tag_y(2); // local dof id
472  tags[idx][3] = tag_y(3); // total number of dofs in this vertex
473  } else if (tag_x(0) == 0 && tag_y(0) == 1 && tag_z(0) == 1) {
474  // face, x vert, y edge, z edge
475  tags[idx][0] = 2; // face dof
476  tags[idx][1] = face_yz[tag_x(1)]; // face id
477  tags[idx][2] = tag_y(2) + tag_y(3)*tag_z(2); // local dof id
478  tags[idx][3] = face_ndofs; // total number of dofs in this vertex
479  } else if (tag_x(0) == 1 && tag_y(0) == 1 && tag_z(0) == 0) {
480  // face, x edge, y edge, z vert
481  tags[idx][0] = 2; // face dof
482  tags[idx][1] = face_xy[tag_z(1)]; // face id
483  tags[idx][2] = face_ndofs_per_direction + tag_x(2) + tag_x(3)*tag_y(2); // local dof id
484  tags[idx][3] = face_ndofs; // total number of dofs in this vertex
485  } else {
486  // interior
487  tags[idx][0] = 3; // interior dof
488  tags[idx][1] = 0;
489  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
490  tags[idx][3] = intr_ndofs; // total number of dofs in this vertex
491  }
492  }
493  }
494  }
495 
496  // z component (bubbleBasis(z) lineBasis(y) lineBasis(x))
497  for (ordinal_type k=0;k<cardBubble;++k) { // y
498  const auto tag_z = bubbleBasis.getDofTag(k);
499  for (ordinal_type j=0;j<cardLine;++j) { // z
500  const auto tag_y = lineBasis.getDofTag(j);
501  for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
502  const auto tag_x = lineBasis.getDofTag(i);
503 
504  if (tag_x(0) == 0 && tag_y(0) == 0 && tag_z(0) == 1) {
505  // edge: x vert, y vert, z edge
506  tags[idx][0] = 1; // edge dof
507  tags[idx][1] = edge_z[tag_x(1)][tag_y(1)]; // edge id
508  tags[idx][2] = tag_z(2); // local dof id
509  tags[idx][3] = tag_z(3); // total number of dofs in this vertex
510  } else if (tag_x(0) == 0 && tag_y(0) == 1 && tag_z(0) == 1) {
511  // face, x vert, y edge, z edge
512  tags[idx][0] = 2; // face dof
513  tags[idx][1] = face_yz[tag_x(1)]; // face id
514  tags[idx][2] = face_ndofs_per_direction + tag_y(2) + tag_y(3)*tag_z(2); // local dof id
515  tags[idx][3] = face_ndofs; // total number of dofs in this vertex
516  } else if (tag_x(0) == 1 && tag_y(0) == 0 && tag_z(0) == 1) {
517  // face, x edge, y vert, z edge
518  tags[idx][0] = 2; // face dof
519  tags[idx][1] = face_xz[tag_y(1)]; // face id
520  tags[idx][2] = face_ndofs_per_direction + tag_x(2) + tag_x(3)*tag_z(2); // local dof id
521  tags[idx][3] = face_ndofs; // total number of dofs in this vertex
522  } else {
523  // interior
524  tags[idx][0] = 3; // interior dof
525  tags[idx][1] = 0;
526  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
527  tags[idx][3] = intr_ndofs; // total number of dofs in this vertex
528  }
529  }
530  }
531  }
532 
533  INTREPID2_TEST_FOR_EXCEPTION( idx != this->basisCardinality_ , std::runtime_error,
534  ">>> ERROR (Basis_HCURL_HEX_In_FEM): " \
535  "counted tag index is not same as cardinality." );
536  }
537 
538  OrdinalTypeArray1DHost tagView(&tags[0][0], this->basisCardinality_*4);
539 
540  // Basis-independent function sets tag and enum data in tagToOrdinal_ and ordinalToTag_ arrays:
541  // tags are constructed on host
542  this->setOrdinalTagData(this->tagToOrdinal_,
543  this->ordinalToTag_,
544  tagView,
545  this->basisCardinality_,
546  tagSize,
547  posScDim,
548  posScOrd,
549  posDfOrd);
550  }
551 
552  // dofCoords on host and create its mirror view to device
553  Kokkos::DynRankView<typename ScalarViewType::value_type,typename SpT::array_layout,Kokkos::HostSpace>
554  dofCoordsHost("dofCoordsHost", this->basisCardinality_, this->basisCellTopology_.getDimension());
555 
556  // dofCoords on host and create its mirror view to device
557  Kokkos::DynRankView<typename ScalarViewType::value_type,typename SpT::array_layout,Kokkos::HostSpace>
558  dofCoeffsHost("dofCoeffsHost", this->basisCardinality_, this->basisCellTopology_.getDimension());
559 
560  Kokkos::DynRankView<typename ScalarViewType::value_type,SpT>
561  dofCoordsLine("dofCoordsLine", cardLine, 1),
562  dofCoordsBubble("dofCoordsBubble", cardBubble, 1);
563 
564  lineBasis.getDofCoords(dofCoordsLine);
565  auto dofCoordsLineHost = Kokkos::create_mirror_view(Kokkos::HostSpace(), dofCoordsLine);
566  Kokkos::deep_copy(dofCoordsLineHost, dofCoordsLine);
567 
568  bubbleBasis.getDofCoords(dofCoordsBubble);
569  auto dofCoordsBubbleHost = Kokkos::create_mirror_view(Kokkos::HostSpace(), dofCoordsBubble);
570  Kokkos::deep_copy(dofCoordsBubbleHost, dofCoordsBubble);
571 
572  {
573  ordinal_type idx = 0;
574 
575  // x component (lineBasis(z) lineBasis(y) bubbleBasis(x))
576  for (ordinal_type k=0;k<cardLine;++k) { // z
577  for (ordinal_type j=0;j<cardLine;++j) { // y
578  for (ordinal_type i=0;i<cardBubble;++i,++idx) { // x
579  dofCoordsHost(idx,0) = dofCoordsBubbleHost(i,0);
580  dofCoordsHost(idx,1) = dofCoordsLineHost(j,0);
581  dofCoordsHost(idx,2) = dofCoordsLineHost(k,0);
582  dofCoeffsHost(idx,0) = 1.0;
583  }
584  }
585  }
586 
587  // y component (lineBasis(z) bubbleBasis(y) lineBasis(x))
588  for (ordinal_type k=0;k<cardLine;++k) { // z
589  for (ordinal_type j=0;j<cardBubble;++j) { // y
590  for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
591  dofCoordsHost(idx,0) = dofCoordsLineHost(i,0);
592  dofCoordsHost(idx,1) = dofCoordsBubbleHost(j,0);
593  dofCoordsHost(idx,2) = dofCoordsLineHost(k,0);
594  dofCoeffsHost(idx,1) = 1.0;
595  }
596  }
597  }
598 
599  // z component (bubbleBasis(z) lineBasis(y) lineBasis(x))
600  for (ordinal_type k=0;k<cardBubble;++k) { // z
601  for (ordinal_type j=0;j<cardLine;++j) { // y
602  for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
603  dofCoordsHost(idx,0) = dofCoordsLineHost(i,0);
604  dofCoordsHost(idx,1) = dofCoordsLineHost(j,0);
605  dofCoordsHost(idx,2) = dofCoordsBubbleHost(k,0);
606  dofCoeffsHost(idx,2) = 1.0;
607  }
608  }
609  }
610  }
611 
612  this->dofCoords_ = Kokkos::create_mirror_view(typename SpT::memory_space(), dofCoordsHost);
613  Kokkos::deep_copy(this->dofCoords_, dofCoordsHost);
614 
615  this->dofCoeffs_ = Kokkos::create_mirror_view(typename SpT::memory_space(), dofCoeffsHost);
616  Kokkos::deep_copy(this->dofCoeffs_, dofCoeffsHost);
617  }
618 }
619 
620 #endif
Kokkos::View< ordinal_type *, typename ExecSpaceType::array_layout, Kokkos::HostSpace > OrdinalTypeArray1DHost
View type for 1d host array.
ordinal_type getCardinality() const
Returns cardinality of the basis.
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.
const OrdinalTypeArrayStride1DHost getDofTag(const ordinal_type dofOrd) const
DoF ordinal to DoF tag lookup.
static constexpr ordinal_type MaxOrder
The maximum reconstruction order.