Intrepid2
Intrepid2_HVOL_HEX_Cn_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
48#ifndef __INTREPID2_HVOL_HEX_CN_FEMDEF_HPP__
49#define __INTREPID2_HVOL_HEX_CN_FEMDEF_HPP__
50
51namespace Intrepid2 {
52
53 // -------------------------------------------------------------------------------------
54 namespace Impl {
55
56 template<EOperator opType>
57 template<typename OutputViewType,
58 typename inputViewType,
59 typename workViewType,
60 typename vinvViewType>
61 KOKKOS_INLINE_FUNCTION
62 void
63 Basis_HVOL_HEX_Cn_FEM::Serial<opType>::
64 getValues( OutputViewType output,
65 const inputViewType input,
66 workViewType work,
67 const vinvViewType vinv,
68 const ordinal_type operatorDn ) {
69 ordinal_type opDn = operatorDn;
70
71 const ordinal_type cardLine = vinv.extent(0);
72 const ordinal_type npts = input.extent(0);
73
74 typedef Kokkos::pair<ordinal_type,ordinal_type> range_type;
75 const auto input_x = Kokkos::subview(input, Kokkos::ALL(), range_type(0,1));
76 const auto input_y = Kokkos::subview(input, Kokkos::ALL(), range_type(1,2));
77 const auto input_z = Kokkos::subview(input, Kokkos::ALL(), range_type(2,3));
78
79 const ordinal_type dim_s = get_dimension_scalar(work);
80 auto ptr0 = work.data();
81 auto ptr1 = work.data()+cardLine*npts*dim_s;
82 auto ptr2 = work.data()+2*cardLine*npts*dim_s;
83 auto ptr3 = work.data()+3*cardLine*npts*dim_s;
84
85 typedef typename Kokkos::DynRankView<typename workViewType::value_type, typename workViewType::memory_space> viewType;
86 auto vcprop = Kokkos::common_view_alloc_prop(work);
87
88 switch (opType) {
89 case OPERATOR_VALUE: {
90 viewType work_line(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts);
91 viewType output_x(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts);
92 viewType output_y(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts);
93 viewType output_z(Kokkos::view_wrap(ptr3, vcprop), cardLine, npts);
94
95 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
96 getValues(output_x, input_x, work_line, vinv);
97
98 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
99 getValues(output_y, input_y, work_line, vinv);
100
101 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
102 getValues(output_z, input_z, work_line, vinv);
103
104 // tensor product
105 ordinal_type idx = 0;
106 for (ordinal_type k=0;k<cardLine;++k) // z
107 for (ordinal_type j=0;j<cardLine;++j) // y
108 for (ordinal_type i=0;i<cardLine;++i,++idx) // x
109 for (ordinal_type l=0;l<npts;++l)
110 output.access(idx,l) = output_x.access(i,l)*output_y.access(j,l)*output_z.access(k,l);
111 break;
112 }
113 case OPERATOR_GRAD:
114 case OPERATOR_D1:
115 case OPERATOR_D2:
116 case OPERATOR_D3:
117 case OPERATOR_D4:
118 case OPERATOR_D5:
119 case OPERATOR_D6:
120 case OPERATOR_D7:
121 case OPERATOR_D8:
122 case OPERATOR_D9:
123 case OPERATOR_D10:
124 opDn = getOperatorOrder(opType);
125 case OPERATOR_Dn: {
126 const ordinal_type dkcard = opDn + 1;
127
128 ordinal_type d = 0;
129 for (ordinal_type l1=0;l1<dkcard;++l1)
130 for (ordinal_type l0=0;l0<(l1+1);++l0) {
131 const ordinal_type mult_x = (opDn - l1);
132 const ordinal_type mult_y = l1 - l0;
133 const ordinal_type mult_z = l0;
134
135 //std::cout << " l0, l1 = " << l0 << " " << l1 << std::endl;
136 //std::cout << " x , y , z = " << mult_x << " " << mult_y << " " << mult_z << std::endl;
137
138 if (mult_x < 0) {
139 // pass
140 } else {
141 viewType work_line(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts);
142 decltype(work_line) output_x, output_y, output_z;
143
144 if (mult_x) {
145 output_x = viewType(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts, 1);
146 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
147 getValues(output_x, input_x, work_line, vinv, mult_x);
148 } else {
149 output_x = viewType(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts);
150 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
151 getValues(output_x, input_x, work_line, vinv);
152 }
153
154 if (mult_y) {
155 output_y = viewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts, 1);
156 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
157 getValues(output_y, input_y, work_line, vinv, mult_y);
158 } else {
159 output_y = viewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts);
160 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
161 getValues(output_y, input_y, work_line, vinv);
162 }
163
164 if (mult_z) {
165 output_z = viewType(Kokkos::view_wrap(ptr3, vcprop), cardLine, npts, 1);
166 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
167 getValues(output_z, input_z, work_line, vinv, mult_z);
168 } else {
169 output_z = viewType(Kokkos::view_wrap(ptr3, vcprop), cardLine, npts);
170 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
171 getValues(output_z, input_z, work_line, vinv);
172 }
173
174 // tensor product (extra dimension of ouput x,y and z are ignored)
175 ordinal_type idx = 0;
176 for (ordinal_type k=0;k<cardLine;++k) // z
177 for (ordinal_type j=0;j<cardLine;++j) // y
178 for (ordinal_type i=0;i<cardLine;++i,++idx) // x
179 for (ordinal_type l=0;l<npts;++l)
180 output.access(idx,l,d) = output_x.access(i,l,0)*output_y.access(j,l,0)*output_z.access(k,l,0);
181 ++d;
182 }
183 }
184 break;
185 }
186 default: {
187 INTREPID2_TEST_FOR_ABORT( true ,
188 ">>> ERROR (Basis_HVOL_HEX_Cn_FEM): Operator type not implemented");
189 break;
190 }
191 }
192 }
193
194 template<typename DT, ordinal_type numPtsPerEval,
195 typename outputValueValueType, class ...outputValueProperties,
196 typename inputPointValueType, class ...inputPointProperties,
197 typename vinvValueType, class ...vinvProperties>
198 void
199 Basis_HVOL_HEX_Cn_FEM::
200 getValues( Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValues,
201 const Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPoints,
202 const Kokkos::DynRankView<vinvValueType, vinvProperties...> vinv,
203 const EOperator operatorType ) {
204 typedef Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValueViewType;
205 typedef Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPointViewType;
206 typedef Kokkos::DynRankView<vinvValueType, vinvProperties...> vinvViewType;
207 typedef typename ExecSpace<typename inputPointViewType::execution_space,typename DT::execution_space>::ExecSpaceType ExecSpaceType;
208
209 // loopSize corresponds to cardinality
210 const auto loopSizeTmp1 = (inputPoints.extent(0)/numPtsPerEval);
211 const auto loopSizeTmp2 = (inputPoints.extent(0)%numPtsPerEval != 0);
212 const auto loopSize = loopSizeTmp1 + loopSizeTmp2;
213 Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
214
215 typedef typename inputPointViewType::value_type inputPointType;
216
217 const ordinal_type cardinality = outputValues.extent(0);
218 const ordinal_type cardLine = std::cbrt(cardinality);
219 const ordinal_type workSize = 4*cardLine;
220
221 auto vcprop = Kokkos::common_view_alloc_prop(inputPoints);
222 typedef typename Kokkos::DynRankView< inputPointType, typename inputPointViewType::memory_space> workViewType;
223 workViewType work(Kokkos::view_alloc("Basis_HVOL_HEX_Cn_FEM::getValues::work", vcprop), workSize, inputPoints.extent(0));
224
225 switch (operatorType) {
226 case OPERATOR_VALUE: {
227 typedef Functor<outputValueViewType,inputPointViewType,vinvViewType,workViewType,
228 OPERATOR_VALUE,numPtsPerEval> FunctorType;
229 Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) );
230 break;
231 }
232 case OPERATOR_GRAD:
233 case OPERATOR_D1:
234 case OPERATOR_D2:
235 case OPERATOR_D3:
236 case OPERATOR_D4:
237 case OPERATOR_D5:
238 case OPERATOR_D6:
239 case OPERATOR_D7:
240 case OPERATOR_D8:
241 case OPERATOR_D9:
242 case OPERATOR_D10: {
243 typedef Functor<outputValueViewType,inputPointViewType,vinvViewType,workViewType,
244 OPERATOR_Dn,numPtsPerEval> FunctorType;
245 Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work,
246 getOperatorOrder(operatorType)) );
247 break;
248 }
249 default: {
250 INTREPID2_TEST_FOR_EXCEPTION( true , std::invalid_argument,
251 ">>> ERROR (Basis_HVOL_HEX_Cn_FEM): Operator type not implemented" );
252 // break; commented out since exception is thrown
253 }
254 }
255 }
256 }
257
258 // -------------------------------------------------------------------------------------
259 template<typename DT, typename OT, typename PT>
261 Basis_HVOL_HEX_Cn_FEM( const ordinal_type order,
262 const EPointType pointType ) {
263
264 // this should be in host
265 Basis_HVOL_LINE_Cn_FEM<DT,OT,PT> lineBasis( order, pointType );
266 const auto cardLine = lineBasis.getCardinality();
267
268 this->pointType_ = pointType;
269 this->vinv_ = Kokkos::DynRankView<typename ScalarViewType::value_type,DT>("HVOL::HEX::Cn::vinv", cardLine, cardLine);
270 lineBasis.getVandermondeInverse(this->vinv_);
271
272 this->basisCardinality_ = cardLine*cardLine*cardLine;
273 this->basisDegree_ = order;
274 this->basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<8> >() );
275 this->basisType_ = BASIS_FEM_LAGRANGIAN;
276 this->basisCoordinates_ = COORDINATES_CARTESIAN;
277 this->functionSpace_ = FUNCTION_SPACE_HVOL;
278
279 // initialize tags
280 {
281 // Basis-dependent initializations
282 const ordinal_type tagSize = 4; // size of DoF tag, i.e., number of fields in the tag
283 const ordinal_type posScDim = 0; // position in the tag, counting from 0, of the subcell dim
284 const ordinal_type posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal
285 const ordinal_type posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell
286
287 // An array with local DoF tags assigned to the basis functions, in the order of their local enumeration
288 constexpr ordinal_type maxCardLine = Parameters::MaxOrder + 1;
289 ordinal_type tags[maxCardLine*maxCardLine*maxCardLine][4];
290
291 {
292 ordinal_type idx = 0;
293 for (auto k=0;k<cardLine;++k) { // z
294 const auto tag_z = lineBasis.getDofTag(k);
295 for (ordinal_type j=0;j<cardLine;++j) { // y
296 const auto tag_y = lineBasis.getDofTag(j);
297 for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
298 const auto tag_x = lineBasis.getDofTag(i);
299
300 // interior
301 tags[idx][0] = 3; // interior dof
302 tags[idx][1] = 0;
303 tags[idx][2] = tag_x(2) + tag_x(3)*tag_y(2) + tag_x(3)*tag_y(3)*tag_z(2); // local dof id
304 tags[idx][3] = tag_x(3)*tag_y(3)*tag_z(3); // total number of dofs in this vertex
305 }
306 }
307 }
308 }
309
310 OrdinalTypeArray1DHost tagView(&tags[0][0], this->basisCardinality_*4);
311
312 // Basis-independent function sets tag and enum data in tagToOrdinal_ and ordinalToTag_ arrays:
313 // tags are constructed on host
314 this->setOrdinalTagData(this->tagToOrdinal_,
315 this->ordinalToTag_,
316 tagView,
317 this->basisCardinality_,
318 tagSize,
319 posScDim,
320 posScOrd,
321 posDfOrd);
322 }
323
324 // dofCoords on host and create its mirror view to device
325 Kokkos::DynRankView<typename ScalarViewType::value_type,typename DT::execution_space::array_layout,Kokkos::HostSpace>
326 dofCoordsHost("dofCoordsHost", this->basisCardinality_, this->basisCellTopology_.getDimension());
327
328 Kokkos::DynRankView<typename ScalarViewType::value_type,DT>
329 dofCoordsLine("dofCoordsLine", cardLine, 1);
330
331 lineBasis.getDofCoords(dofCoordsLine);
332 auto dofCoordsLineHost = Kokkos::create_mirror_view(Kokkos::HostSpace(), dofCoordsLine);
333 Kokkos::deep_copy(dofCoordsLineHost, dofCoordsLine);
334 {
335 ordinal_type idx = 0;
336 for (auto k=0;k<cardLine;++k) { // z
337 for (ordinal_type j=0;j<cardLine;++j) { // y
338 for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
339 dofCoordsHost(idx,0) = dofCoordsLineHost(i,0);
340 dofCoordsHost(idx,1) = dofCoordsLineHost(j,0);
341 dofCoordsHost(idx,2) = dofCoordsLineHost(k,0);
342 }
343 }
344 }
345
346 }
347
348 this->dofCoords_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoordsHost);
349 Kokkos::deep_copy(this->dofCoords_, dofCoordsHost);
350 }
351
352}// namespace Intrepid2
353
354#endif
KOKKOS_INLINE_FUNCTION ordinal_type getOperatorOrder(const EOperator operatorType)
Returns order of an operator.
Basis_HVOL_HEX_Cn_FEM(const ordinal_type order, const EPointType pointType=POINTTYPE_EQUISPACED)
Constructor.
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.