Intrepid2
Intrepid2_HDIV_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_HDIV_HEX_IN_FEM_DEF_HPP__
50 #define __INTREPID2_HDIV_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_HDIV_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()+(2*cardLine+cardBubble)*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  viewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts);
92  viewType outputLine(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts);
93  viewType outputBubble_A(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts);
94  viewType outputBubble_B(Kokkos::view_wrap(ptr3, vcprop), cardBubble, npts);
95 
96  // tensor product
97  ordinal_type idx = 0;
98  {
99  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
100  getValues(outputLine, input_x, workLine, vinvLine);
101 
102  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
103  getValues(outputBubble_A, input_y, workLine, vinvBubble);
104 
105  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
106  getValues(outputBubble_B, input_z, workLine, vinvBubble);
107 
108 
109  // x component (bubbleBasis(z) bubbleBasis(y) lineBasis(x))
110  const auto output_x = outputLine;
111  const auto output_y = outputBubble_A;
112  const auto output_z = outputBubble_B;
113 
114  for (ordinal_type k=0;k<cardBubble;++k) // z
115  for (ordinal_type j=0;j<cardBubble;++j) // y
116  for (ordinal_type i=0;i<cardLine;++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(outputBubble_A, input_x, workLine, vinvBubble);
126 
127  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
128  getValues(outputLine, input_y, workLine, vinvLine);
129 
130  //Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
131  // getValues(outputBubble_B, input_z, workLine, vinvBubble);
132 
133  // y component (lineBasis(z) bubbleBasis(y) lineBasis(x))
134  const auto output_x = outputBubble_A;
135  const auto output_y = outputLine;
136  const auto output_z = outputBubble_B;
137 
138  for (ordinal_type k=0;k<cardBubble;++k) // z
139  for (ordinal_type j=0;j<cardLine;++j) // y
140  for (ordinal_type i=0;i<cardBubble;++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(outputBubble_A, input_x, workLine, vinvBubble);
150 
151  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
152  getValues(outputBubble_B, input_y, workLine, vinvBubble);
153 
154  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
155  getValues(outputLine, input_z, workLine, vinvLine);
156 
157  // z component (bubbleBasis(z) bubbleBasis(y) lineBasis(x))
158  const auto output_x = outputBubble_A;
159  const auto output_y = outputBubble_B;
160  const auto output_z = outputLine;
161 
162  for (ordinal_type k=0;k<cardLine;++k) // z
163  for (ordinal_type j=0;j<cardBubble;++j) // y
164  for (ordinal_type i=0;i<cardBubble;++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_DIV: {
174  viewType workLine(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts);
175  // A line value
176  viewType outputBubble_A(Kokkos::view_wrap(ptr2, vcprop), cardBubble, npts);
177  // B line value
178  viewType outputBubble_B(Kokkos::view_wrap(ptr3, vcprop), cardBubble, npts);
179  // Line grad
180  viewType outputLine(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts, 1);
181 
182  // tensor product
183  ordinal_type idx = 0;
184 
185  { // x - component
186  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
187  getValues(outputLine, input_x, workLine, vinvLine, 1);
188 
189  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
190  getValues(outputBubble_A, input_y, workLine, vinvBubble);
191 
192  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
193  getValues(outputBubble_B, input_z, workLine, vinvBubble);
194 
195  // x component (bubbleBasis(z) bubbleBasis(y) lineBasis(x))
196  const auto output_dx = outputLine;
197  const auto output_y = outputBubble_A;
198  const auto output_z = outputBubble_B;
199 
200  for (ordinal_type k=0;k<cardBubble;++k) // z
201  for (ordinal_type j=0;j<cardBubble;++j) // y
202  for (ordinal_type i=0;i<cardLine;++i,++idx) // x
203  for (ordinal_type l=0;l<npts;++l)
204  output.access(idx,l) = output_dx.access(i,l,0)*output_y.access (j,l) *output_z.access(k,l);
205  }
206  { // y - component
207  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
208  getValues(outputBubble_A, input_x, workLine, vinvBubble);
209 
210  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
211  getValues(outputLine, input_y, workLine, vinvLine, 1);
212 
213  // Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
214  // getValues(outputBubble_B, input_z, workLine, vinvBubble);
215 
216  //(bubbleBasis(z) lineBasis(y) bubbleBasis(x))
217  const auto output_x = outputBubble_A;
218  const auto output_dy = outputLine;
219  const auto output_z = outputBubble_B;
220 
221  for (ordinal_type k=0;k<cardBubble;++k) // z
222  for (ordinal_type j=0;j<cardLine;++j) // y
223  for (ordinal_type i=0;i<cardBubble;++i,++idx) // x
224  for (ordinal_type l=0;l<npts;++l)
225  output.access(idx,l) = output_x.access(i,l)*output_dy.access(j,l,0)*output_z.access(k,l);
226  }
227  { // z - component
228  // Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
229  // getValues(outputBubble_A, input_x, workLine, vinvBubble);
230 
231  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
232  getValues(outputBubble_B, input_y, workLine, vinvBubble);
233 
234  Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
235  getValues(outputLine, input_z, workLine, vinvLine, 1);
236 
237  // (bubbleBasis(z) bubbleBasis(y) lineBasis(x))
238  const auto output_x = outputBubble_A;
239  const auto output_y = outputBubble_B;
240  const auto output_dz = outputLine;
241 
242  for (ordinal_type k=0;k<cardLine;++k) // z
243  for (ordinal_type j=0;j<cardBubble;++j) // y
244  for (ordinal_type i=0;i<cardBubble;++i,++idx) // x
245  for (ordinal_type l=0;l<npts;++l)
246  output.access(idx,l) = output_x.access(i,l)*output_y.access(j,l)*output_dz.access(k,l,0);
247  }
248  break;
249  }
250  default: {
251  INTREPID2_TEST_FOR_ABORT( true,
252  ">>> ERROR: (Intrepid2::Basis_HDIV_HEX_In_FEM::Serial::getValues) operator is not supported" );
253  }
254  }
255  }
256 
257  template<typename SpT, ordinal_type numPtsPerEval,
258  typename outputValueValueType, class ...outputValueProperties,
259  typename inputPointValueType, class ...inputPointProperties,
260  typename vinvValueType, class ...vinvProperties>
261  void
262  Basis_HDIV_HEX_In_FEM::
263  getValues( Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValues,
264  const Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPoints,
265  const Kokkos::DynRankView<vinvValueType, vinvProperties...> vinvLine,
266  const Kokkos::DynRankView<vinvValueType, vinvProperties...> vinvBubble,
267  const EOperator operatorType ) {
268  typedef Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValueViewType;
269  typedef Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPointViewType;
270  typedef Kokkos::DynRankView<vinvValueType, vinvProperties...> vinvViewType;
271  typedef typename ExecSpace<typename inputPointViewType::execution_space,SpT>::ExecSpaceType ExecSpaceType;
272 
273  // loopSize corresponds to cardinality
274  const auto loopSizeTmp1 = (inputPoints.extent(0)/numPtsPerEval);
275  const auto loopSizeTmp2 = (inputPoints.extent(0)%numPtsPerEval != 0);
276  const auto loopSize = loopSizeTmp1 + loopSizeTmp2;
277  Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
278 
279  typedef typename inputPointViewType::value_type inputPointType;
280 
281  const ordinal_type cardinality = outputValues.extent(0);
282  //get basis order based on basis cardinality.
283  ordinal_type order = 0;
284  ordinal_type cardBubble; // = std::cbrt(cardinality/3);
285  ordinal_type cardLine; // = cardBubble+1;
286  do {
287  cardBubble = Intrepid2::getPnCardinality<1>(order);
288  cardLine = Intrepid2::getPnCardinality<1>(++order);
289  } while((3*cardBubble*cardBubble*cardLine != cardinality) && (order != Parameters::MaxOrder));
290 
291  auto vcprop = Kokkos::common_view_alloc_prop(inputPoints);
292  typedef typename Kokkos::DynRankView< inputPointType, typename inputPointViewType::memory_space> workViewType;
293 
294  switch (operatorType) {
295  case OPERATOR_VALUE: {
296  auto workSize = Serial<OPERATOR_VALUE>::getWorkSizePerPoint(order);
297  workViewType work(Kokkos::view_alloc("Basis_HDIV_HEX_In_FEM::getValues::work", vcprop), workSize, inputPoints.extent(0));
298  typedef Functor<outputValueViewType,inputPointViewType,vinvViewType, workViewType,
299  OPERATOR_VALUE,numPtsPerEval> FunctorType;
300  Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinvLine, vinvBubble, work) );
301  break;
302  }
303  case OPERATOR_DIV: {
304  auto workSize = Serial<OPERATOR_DIV>::getWorkSizePerPoint(order);
305  workViewType work(Kokkos::view_alloc("Basis_HDIV_HEX_In_FEM::getValues::work", vcprop), workSize, inputPoints.extent(0));
306  typedef Functor<outputValueViewType,inputPointViewType,vinvViewType, workViewType,
307  OPERATOR_DIV,numPtsPerEval> FunctorType;
308  Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinvLine, vinvBubble, work) );
309  break;
310  }
311  default: {
312  INTREPID2_TEST_FOR_EXCEPTION( true , std::invalid_argument,
313  ">>> ERROR (Basis_HDIV_HEX_In_FEM): Operator type not implemented" );
314  // break; commented out since exception is thrown
315  }
316  }
317  }
318  }
319 
320  // -------------------------------------------------------------------------------------
321 
322  template<typename SpT, typename OT, typename PT>
324  Basis_HDIV_HEX_In_FEM( const ordinal_type order,
325  const EPointType pointType ) {
326 
327  INTREPID2_TEST_FOR_EXCEPTION( !(pointType == POINTTYPE_EQUISPACED ||
328  pointType == POINTTYPE_WARPBLEND), std::invalid_argument,
329  ">>> ERROR (Basis_HDIV_HEX_In_FEM): pointType must be either equispaced or warpblend.");
330 
331  // this should be created in host and vinv should be deep copied into device space
332  Basis_HGRAD_LINE_Cn_FEM<SpT,OT,PT> lineBasis( order, pointType );
333  Basis_HGRAD_LINE_Cn_FEM<SpT,OT,PT> bubbleBasis( order - 1, POINTTYPE_GAUSS );
334 
335  const ordinal_type
336  cardLine = lineBasis.getCardinality(),
337  cardBubble = bubbleBasis.getCardinality();
338 
339  this->vinvLine_ = Kokkos::DynRankView<typename scalarViewType::value_type,SpT>("Hcurl::Hex::In::vinvLine", cardLine, cardLine);
340  this->vinvBubble_ = Kokkos::DynRankView<typename scalarViewType::value_type,SpT>("Hcurl::Hex::In::vinvBubble", cardBubble, cardBubble);
341 
342  lineBasis.getVandermondeInverse(this->vinvLine_);
343  bubbleBasis.getVandermondeInverse(this->vinvBubble_);
344 
345  this->basisCardinality_ = 3*cardLine*cardBubble*cardBubble;
346  this->basisDegree_ = order;
347  this->basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<8> >() );
348  this->basisType_ = BASIS_FEM_FIAT;
349  this->basisCoordinates_ = COORDINATES_CARTESIAN;
350 
351  // initialize tags
352  {
353  // Basis-dependent initializations
354  const ordinal_type tagSize = 4; // size of DoF tag, i.e., number of fields in the tag
355  const ordinal_type posScDim = 0; // position in the tag, counting from 0, of the subcell dim
356  const ordinal_type posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal
357  const ordinal_type posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell
358 
359  // An array with local DoF tags assigned to the basis functions, in the order of their local enumeration
360  constexpr ordinal_type maxCardLine = Parameters::MaxOrder + 1;
361  ordinal_type tags[3*maxCardLine*maxCardLine*maxCardLine][4];
362 
363  const ordinal_type face_yz[2] = {3, 1};
364  const ordinal_type face_xz[2] = {0, 2};
365  const ordinal_type face_xy[2] = {4, 5};
366 
367  {
368  ordinal_type idx = 0;
369 
373 
374  // since there are x/y components in the interior
375  // dof sum should be computed before the information
376  // is assigned to tags
377  const ordinal_type
378  intr_ndofs_per_direction = (cardLine-2)*cardBubble*cardBubble,
379  intr_ndofs = 3*intr_ndofs_per_direction;
380 
381  // x component (bubbleBasis(z) bubbleBasis(y) lineBasis(x))
382  for (ordinal_type k=0;k<cardBubble;++k) { // z
383  const auto tag_z = bubbleBasis.getDofTag(k);
384  for (ordinal_type j=0;j<cardBubble;++j) { // y
385  const auto tag_y = bubbleBasis.getDofTag(j);
386  for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
387  const auto tag_x = lineBasis.getDofTag(i);
388 
389  if (tag_x(0) == 0 && tag_y(0) == 1 && tag_z(0) == 1) {
390  // face, x vert, y edge, z edge
391  tags[idx][0] = 2; // face dof
392  tags[idx][1] = face_yz[tag_x(1)]; // face id
393  tags[idx][2] = tag_y(2) + tag_y(3)*tag_z(2); // local dof id
394  tags[idx][3] = tag_y(3)*tag_z(3); // total number of dofs in this vertex
395  } else {
396  // interior
397  tags[idx][0] = 3; // interior dof
398  tags[idx][1] = 0;
399  tags[idx][2] = tag_x(2) + tag_x(3)*tag_y(2) + tag_x(3)*tag_y(3)*tag_z(2); // local dof id
400  tags[idx][3] = intr_ndofs; // total number of dofs in this vertex
401  }
402  }
403  }
404  }
405 
406  // y component (bubbleBasis(z) lineBasis(y) bubbleBasis(x))
407  for (ordinal_type k=0;k<cardBubble;++k) { // z
408  const auto tag_z = bubbleBasis.getDofTag(k);
409  for (ordinal_type j=0;j<cardLine;++j) { // y
410  const auto tag_y = lineBasis.getDofTag(j);
411  for (ordinal_type i=0;i<cardBubble;++i,++idx) { // x
412  const auto tag_x = bubbleBasis.getDofTag(i);
413 
414  if (tag_x(0) == 1 && tag_y(0) == 0 && tag_z(0) == 1) {
415  // face, x edge, y vert, z edge
416  tags[idx][0] = 2; // face dof
417  tags[idx][1] = face_xz[tag_y(1)]; // face id
418  tags[idx][2] = tag_x(2) + tag_x(3)*tag_z(2); // local dof id
419  tags[idx][3] = tag_x(3)*tag_z(3); // total number of dofs in this vertex
420  } else {
421  // interior
422  tags[idx][0] = 3; // interior dof
423  tags[idx][1] = 0;
424  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
425  tags[idx][3] = intr_ndofs; // total number of dofs in this vertex
426  }
427  }
428  }
429  }
430 
431  // z component (bubbleBasis(z) lineBasis(y) lineBasis(x))
432  for (ordinal_type k=0;k<cardLine;++k) { // y
433  const auto tag_z = lineBasis.getDofTag(k);
434  for (ordinal_type j=0;j<cardBubble;++j) { // z
435  const auto tag_y = bubbleBasis.getDofTag(j);
436  for (ordinal_type i=0;i<cardBubble;++i,++idx) { // x
437  const auto tag_x = bubbleBasis.getDofTag(i);
438 
439  if (tag_x(0) == 1 && tag_y(0) == 1 && tag_z(0) == 0) {
440  // face, x edge, y edge, z vert
441  tags[idx][0] = 2; // face dof
442  tags[idx][1] = face_xy[tag_z(1)]; // face id
443  tags[idx][2] = tag_x(2) + tag_x(3)*tag_y(2); // local dof id
444  tags[idx][3] = tag_x(3)*tag_y(3); // total number of dofs in this vertex
445  } else {
446  // interior
447  tags[idx][0] = 3; // interior dof
448  tags[idx][1] = 0;
449  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
450  tags[idx][3] = intr_ndofs; // total number of dofs in this vertex
451  }
452  }
453  }
454  }
455 
456  INTREPID2_TEST_FOR_EXCEPTION( idx != this->basisCardinality_ , std::runtime_error,
457  ">>> ERROR (Basis_HDIV_HEX_In_FEM): " \
458  "counted tag index is not same as cardinality." );
459  }
460 
461  ordinal_type_array_1d_host tagView(&tags[0][0], this->basisCardinality_*4);
462 
463  // Basis-independent function sets tag and enum data in tagToOrdinal_ and ordinalToTag_ arrays:
464  // tags are constructed on host
465  this->setOrdinalTagData(this->tagToOrdinal_,
466  this->ordinalToTag_,
467  tagView,
468  this->basisCardinality_,
469  tagSize,
470  posScDim,
471  posScOrd,
472  posDfOrd);
473  }
474 
475  // dofCoords on host and create its mirror view to device
476  Kokkos::DynRankView<typename scalarViewType::value_type,typename SpT::array_layout,Kokkos::HostSpace>
477  dofCoordsHost("dofCoordsHost", this->basisCardinality_, this->basisCellTopology_.getDimension());
478 
479  // dofCoeffs on host and create its mirror view to device
480  Kokkos::DynRankView<typename scalarViewType::value_type,typename SpT::array_layout,Kokkos::HostSpace>
481  dofCoeffsHost("dofCoeffsHost", this->basisCardinality_, this->basisCellTopology_.getDimension());
482 
483  Kokkos::DynRankView<typename scalarViewType::value_type,SpT>
484  dofCoordsLine("dofCoordsLine", cardLine, 1),
485  dofCoordsBubble("dofCoordsBubble", cardBubble, 1);
486 
487  lineBasis.getDofCoords(dofCoordsLine);
488  auto dofCoordsLineHost = Kokkos::create_mirror_view(Kokkos::HostSpace(), dofCoordsLine);
489  Kokkos::deep_copy(dofCoordsLineHost, dofCoordsLine);
490 
491  bubbleBasis.getDofCoords(dofCoordsBubble);
492  auto dofCoordsBubbleHost = Kokkos::create_mirror_view(Kokkos::HostSpace(), dofCoordsBubble);
493  Kokkos::deep_copy(dofCoordsBubbleHost, dofCoordsBubble);
494 
495  {
496  ordinal_type idx = 0;
497 
498  // x component (lineBasis(z) lineBasis(y) bubbleBasis(x))
499  for (ordinal_type k=0;k<cardBubble;++k) { // z
500  for (ordinal_type j=0;j<cardBubble;++j) { // y
501  for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
502  dofCoordsHost(idx,0) = dofCoordsLineHost(i,0);
503  dofCoordsHost(idx,1) = dofCoordsBubbleHost(j,0);
504  dofCoordsHost(idx,2) = dofCoordsBubbleHost(k,0);
505  dofCoeffsHost(idx,0) = 1.0;
506  }
507  }
508  }
509 
510  // y component (lineBasis(z) bubbleBasis(y) lineBasis(x))
511  for (ordinal_type k=0;k<cardBubble;++k) { // z
512  for (ordinal_type j=0;j<cardLine;++j) { // y
513  for (ordinal_type i=0;i<cardBubble;++i,++idx) { // x
514  dofCoordsHost(idx,0) = dofCoordsBubbleHost(i,0);
515  dofCoordsHost(idx,1) = dofCoordsLineHost(j,0);
516  dofCoordsHost(idx,2) = dofCoordsBubbleHost(k,0);
517  dofCoeffsHost(idx,1) = 1.0;
518  }
519  }
520  }
521 
522  // z component (bubbleBasis(z) lineBasis(y) lineBasis(x))
523  for (ordinal_type k=0;k<cardLine;++k) { // z
524  for (ordinal_type j=0;j<cardBubble;++j) { // y
525  for (ordinal_type i=0;i<cardBubble;++i,++idx) { // x
526  dofCoordsHost(idx,0) = dofCoordsBubbleHost(i,0);
527  dofCoordsHost(idx,1) = dofCoordsBubbleHost(j,0);
528  dofCoordsHost(idx,2) = dofCoordsLineHost(k,0);
529  dofCoeffsHost(idx,2) = 1.0;
530  }
531  }
532  }
533  }
534 
535  this->dofCoords_ = Kokkos::create_mirror_view(typename SpT::memory_space(), dofCoordsHost);
536  Kokkos::deep_copy(this->dofCoords_, dofCoordsHost);
537 
538  this->dofCoeffs_ = Kokkos::create_mirror_view(typename SpT::memory_space(), dofCoeffsHost);
539  Kokkos::deep_copy(this->dofCoeffs_, dofCoeffsHost);
540  }
541 }
542 
543 #endif
ordinal_type getCardinality() const
Returns cardinality of the basis.
Basis_HDIV_HEX_In_FEM(const ordinal_type order, const EPointType pointType=POINTTYPE_EQUISPACED)
Constructor.
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...
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.