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
52namespace 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 DT, 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,typename DT::execution_space>::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 DT, 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<DT,OT,PT> lineBasis( order, pointType );
367 Basis_HVOL_LINE_Cn_FEM<DT,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,DT>("Hcurl::Hex::In::vinvLine", cardLine, cardLine);
374 this->vinvBubble_ = Kokkos::DynRankView<typename ScalarViewType::value_type,DT>("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_LAGRANGIAN;
383 this->basisCoordinates_ = COORDINATES_CARTESIAN;
384 this->functionSpace_ = FUNCTION_SPACE_HCURL;
385 pointType_ = pointType;
386
387 // initialize tags
388 {
389 // Basis-dependent initializations
390 const ordinal_type tagSize = 4; // size of DoF tag, i.e., number of fields in the tag
391 const ordinal_type posScDim = 0; // position in the tag, counting from 0, of the subcell dim
392 const ordinal_type posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal
393 const ordinal_type posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell
394
395 // Note: the only reason why equispaced can't support higher order than Parameters::MaxOrder appears to be the fact that the tags below get stored into a fixed-length array.
396 // TODO: relax the maximum order requirement by setting up tags in a different container, perhaps directly into an OrdinalTypeArray1DHost (tagView, below). (As of this writing (1/25/22), looks like other nodal bases do this in a similar way -- those should be fixed at the same time; maybe search for Parameters::MaxOrder.)
397 INTREPID2_TEST_FOR_EXCEPTION( order > Parameters::MaxOrder, std::invalid_argument, "polynomial order exceeds the max supported by this class");
398
399 // An array with local DoF tags assigned to the basis functions, in the order of their local enumeration
400 constexpr ordinal_type maxCardLine = Parameters::MaxOrder + 1;
401 ordinal_type tags[3*maxCardLine*maxCardLine*maxCardLine][4];
402
403 const ordinal_type edge_x[2][2] = { {0, 4}, {2, 6} };
404 const ordinal_type edge_y[2][2] = { {3, 7}, {1, 5} };
405 const ordinal_type edge_z[2][2] = { {8,11}, {9,10} };
406
407 const ordinal_type face_yz[2] = {3, 1};
408 const ordinal_type face_xz[2] = {0, 2};
409 const ordinal_type face_xy[2] = {4, 5};
410
411 {
412 ordinal_type idx = 0;
413
417
418 // since there are x/y components in the interior
419 // dof sum should be computed before the information
420 // is assigned to tags
421 const ordinal_type
422 face_ndofs_per_direction = (cardLine-2)*cardBubble,
423 face_ndofs = 2*face_ndofs_per_direction,
424 intr_ndofs_per_direction = (cardLine-2)*(cardLine-2)*cardBubble,
425 intr_ndofs = 3*intr_ndofs_per_direction;
426
427 // x component (lineBasis(z) lineBasis(y) bubbleBasis(x))
428 for (ordinal_type k=0;k<cardLine;++k) { // z
429 const auto tag_z = lineBasis.getDofTag(k);
430 for (ordinal_type j=0;j<cardLine;++j) { // y
431 const auto tag_y = lineBasis.getDofTag(j);
432 for (ordinal_type i=0;i<cardBubble;++i,++idx) { // x
433 const auto tag_x = bubbleBasis.getDofTag(i);
434
435 if (tag_x(0) == 1 && tag_y(0) == 0 && tag_z(0) == 0) {
436 // edge: x edge, y vert, z vert
437 tags[idx][0] = 1; // edge dof
438 tags[idx][1] = edge_x[tag_y(1)][tag_z(1)]; // edge id
439 tags[idx][2] = tag_x(2); // local dof id
440 tags[idx][3] = tag_x(3); // total number of dofs in this edge
441 } else if (tag_x(0) == 1 && tag_y(0) == 0 && tag_z(0) == 1) {
442 // face, x edge, y vert, z edge
443 tags[idx][0] = 2; // face dof
444 tags[idx][1] = face_xz[tag_y(1)]; // face id
445 tags[idx][2] = tag_x(2) + tag_x(3)*tag_z(2); // local dof id
446 tags[idx][3] = face_ndofs; // total number of dofs in this face
447 } else if (tag_x(0) == 1 && tag_y(0) == 1 && tag_z(0) == 0) {
448 // face, x edge, y edge, z vert
449 tags[idx][0] = 2; // face dof
450 tags[idx][1] = face_xy[tag_z(1)]; // face id
451 tags[idx][2] = tag_x(2) + tag_x(3)*tag_y(2); // local dof id
452 tags[idx][3] = face_ndofs; // total number of dofs in this face
453 } else {
454 // interior
455 tags[idx][0] = 3; // interior dof
456 tags[idx][1] = 0;
457 tags[idx][2] = tag_x(2) + tag_x(3)*tag_y(2) + tag_x(3)*tag_y(3)*tag_z(2); // local dof id
458 tags[idx][3] = intr_ndofs; // total number of dofs in this vertex
459 }
460 }
461 }
462 }
463
464 // y component (lineBasis(z) bubbleBasis(y) lineBasis(x))
465 for (ordinal_type k=0;k<cardLine;++k) { // z
466 const auto tag_z = lineBasis.getDofTag(k);
467 for (ordinal_type j=0;j<cardBubble;++j) { // y
468 const auto tag_y = bubbleBasis.getDofTag(j);
469 for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
470 const auto tag_x = lineBasis.getDofTag(i);
471
472 if (tag_x(0) == 0 && tag_y(0) == 1 && tag_z(0) == 0) {
473 // edge: x vert, y edge, z vert
474 tags[idx][0] = 1; // edge dof
475 tags[idx][1] = edge_y[tag_x(1)][tag_z(1)]; // edge id
476 tags[idx][2] = tag_y(2); // local dof id
477 tags[idx][3] = tag_y(3); // total number of dofs in this vertex
478 } else if (tag_x(0) == 0 && tag_y(0) == 1 && tag_z(0) == 1) {
479 // face, x vert, y edge, z edge
480 tags[idx][0] = 2; // face dof
481 tags[idx][1] = face_yz[tag_x(1)]; // face id
482 tags[idx][2] = tag_y(2) + tag_y(3)*tag_z(2); // local dof id
483 tags[idx][3] = face_ndofs; // total number of dofs in this vertex
484 } else if (tag_x(0) == 1 && tag_y(0) == 1 && tag_z(0) == 0) {
485 // face, x edge, y edge, z vert
486 tags[idx][0] = 2; // face dof
487 tags[idx][1] = face_xy[tag_z(1)]; // face id
488 tags[idx][2] = face_ndofs_per_direction + tag_x(2) + tag_x(3)*tag_y(2); // local dof id
489 tags[idx][3] = face_ndofs; // total number of dofs in this vertex
490 } else {
491 // interior
492 tags[idx][0] = 3; // interior dof
493 tags[idx][1] = 0;
494 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
495 tags[idx][3] = intr_ndofs; // total number of dofs in this vertex
496 }
497 }
498 }
499 }
500
501 // z component (bubbleBasis(z) lineBasis(y) lineBasis(x))
502 for (ordinal_type k=0;k<cardBubble;++k) { // y
503 const auto tag_z = bubbleBasis.getDofTag(k);
504 for (ordinal_type j=0;j<cardLine;++j) { // z
505 const auto tag_y = lineBasis.getDofTag(j);
506 for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
507 const auto tag_x = lineBasis.getDofTag(i);
508
509 if (tag_x(0) == 0 && tag_y(0) == 0 && tag_z(0) == 1) {
510 // edge: x vert, y vert, z edge
511 tags[idx][0] = 1; // edge dof
512 tags[idx][1] = edge_z[tag_x(1)][tag_y(1)]; // edge id
513 tags[idx][2] = tag_z(2); // local dof id
514 tags[idx][3] = tag_z(3); // total number of dofs in this vertex
515 } else if (tag_x(0) == 0 && tag_y(0) == 1 && tag_z(0) == 1) {
516 // face, x vert, y edge, z edge
517 tags[idx][0] = 2; // face dof
518 tags[idx][1] = face_yz[tag_x(1)]; // face id
519 tags[idx][2] = face_ndofs_per_direction + tag_y(2) + tag_y(3)*tag_z(2); // local dof id
520 tags[idx][3] = face_ndofs; // total number of dofs in this vertex
521 } else if (tag_x(0) == 1 && tag_y(0) == 0 && tag_z(0) == 1) {
522 // face, x edge, y vert, z edge
523 tags[idx][0] = 2; // face dof
524 tags[idx][1] = face_xz[tag_y(1)]; // face id
525 tags[idx][2] = face_ndofs_per_direction + tag_x(2) + tag_x(3)*tag_z(2); // local dof id
526 tags[idx][3] = face_ndofs; // total number of dofs in this vertex
527 } else {
528 // interior
529 tags[idx][0] = 3; // interior dof
530 tags[idx][1] = 0;
531 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
532 tags[idx][3] = intr_ndofs; // total number of dofs in this vertex
533 }
534 }
535 }
536 }
537
538 INTREPID2_TEST_FOR_EXCEPTION( idx != this->basisCardinality_ , std::runtime_error,
539 ">>> ERROR (Basis_HCURL_HEX_In_FEM): " \
540 "counted tag index is not same as cardinality." );
541 }
542
543 OrdinalTypeArray1DHost tagView(&tags[0][0], this->basisCardinality_*4);
544
545 // Basis-independent function sets tag and enum data in tagToOrdinal_ and ordinalToTag_ arrays:
546 // tags are constructed on host
547 this->setOrdinalTagData(this->tagToOrdinal_,
548 this->ordinalToTag_,
549 tagView,
550 this->basisCardinality_,
551 tagSize,
552 posScDim,
553 posScOrd,
554 posDfOrd);
555 }
556
557 // dofCoords on host and create its mirror view to device
558 Kokkos::DynRankView<typename ScalarViewType::value_type,typename DT::execution_space::array_layout,Kokkos::HostSpace>
559 dofCoordsHost("dofCoordsHost", this->basisCardinality_, this->basisCellTopology_.getDimension());
560
561 // dofCoords on host and create its mirror view to device
562 Kokkos::DynRankView<typename ScalarViewType::value_type,typename DT::execution_space::array_layout,Kokkos::HostSpace>
563 dofCoeffsHost("dofCoeffsHost", this->basisCardinality_, this->basisCellTopology_.getDimension());
564
565 Kokkos::DynRankView<typename ScalarViewType::value_type,DT>
566 dofCoordsLine("dofCoordsLine", cardLine, 1),
567 dofCoordsBubble("dofCoordsBubble", cardBubble, 1);
568
569 lineBasis.getDofCoords(dofCoordsLine);
570 auto dofCoordsLineHost = Kokkos::create_mirror_view(Kokkos::HostSpace(), dofCoordsLine);
571 Kokkos::deep_copy(dofCoordsLineHost, dofCoordsLine);
572
573 bubbleBasis.getDofCoords(dofCoordsBubble);
574 auto dofCoordsBubbleHost = Kokkos::create_mirror_view(Kokkos::HostSpace(), dofCoordsBubble);
575 Kokkos::deep_copy(dofCoordsBubbleHost, dofCoordsBubble);
576
577 {
578 ordinal_type idx = 0;
579
580 // x component (lineBasis(z) lineBasis(y) bubbleBasis(x))
581 for (ordinal_type k=0;k<cardLine;++k) { // z
582 for (ordinal_type j=0;j<cardLine;++j) { // y
583 for (ordinal_type i=0;i<cardBubble;++i,++idx) { // x
584 dofCoordsHost(idx,0) = dofCoordsBubbleHost(i,0);
585 dofCoordsHost(idx,1) = dofCoordsLineHost(j,0);
586 dofCoordsHost(idx,2) = dofCoordsLineHost(k,0);
587 dofCoeffsHost(idx,0) = 1.0;
588 }
589 }
590 }
591
592 // y component (lineBasis(z) bubbleBasis(y) lineBasis(x))
593 for (ordinal_type k=0;k<cardLine;++k) { // z
594 for (ordinal_type j=0;j<cardBubble;++j) { // y
595 for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
596 dofCoordsHost(idx,0) = dofCoordsLineHost(i,0);
597 dofCoordsHost(idx,1) = dofCoordsBubbleHost(j,0);
598 dofCoordsHost(idx,2) = dofCoordsLineHost(k,0);
599 dofCoeffsHost(idx,1) = 1.0;
600 }
601 }
602 }
603
604 // z component (bubbleBasis(z) lineBasis(y) lineBasis(x))
605 for (ordinal_type k=0;k<cardBubble;++k) { // z
606 for (ordinal_type j=0;j<cardLine;++j) { // y
607 for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
608 dofCoordsHost(idx,0) = dofCoordsLineHost(i,0);
609 dofCoordsHost(idx,1) = dofCoordsLineHost(j,0);
610 dofCoordsHost(idx,2) = dofCoordsBubbleHost(k,0);
611 dofCoeffsHost(idx,2) = 1.0;
612 }
613 }
614 }
615 }
616
617 this->dofCoords_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoordsHost);
618 Kokkos::deep_copy(this->dofCoords_, dofCoordsHost);
619
620 this->dofCoeffs_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoeffsHost);
621 Kokkos::deep_copy(this->dofCoeffs_, dofCoeffsHost);
622 }
623}
624
625#endif
Basis_HCURL_HEX_In_FEM(const ordinal_type order, const EPointType pointType=POINTTYPE_EQUISPACED)
Constructor.
Implementation of the locally H(grad)-compatible FEM basis of variable order on the [-1,...
virtual void getDofCoords(ScalarViewType dofCoords) const override
Returns spatial locations (coordinates) of degrees of freedom on the reference cell.
Implementation of the locally HVOL-compatible FEM basis of variable order on the [-1,...
virtual void getDofCoords(ScalarViewType dofCoords) const override
Returns spatial locations (coordinates) of degrees of freedom on the reference cell.
const OrdinalTypeArrayStride1DHost getDofTag(const ordinal_type dofOrd) const
DoF ordinal to DoF tag lookup.
ordinal_type getCardinality() const
Returns cardinality of the basis.
static constexpr ordinal_type MaxOrder
The maximum reconstruction order.