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 
51 namespace 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 SpT, 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,SpT>::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 SpT, 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<SpT,OT,PT> lineBasis( order, pointType );
266  const auto cardLine = lineBasis.getCardinality();
267 
268  this->vinv_ = Kokkos::DynRankView<typename ScalarViewType::value_type,SpT>("HVOL::HEX::Cn::vinv", cardLine, cardLine);
269  lineBasis.getVandermondeInverse(this->vinv_);
270 
271  this->basisCardinality_ = cardLine*cardLine*cardLine;
272  this->basisDegree_ = order;
273  this->basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<8> >() );
274  this->basisType_ = BASIS_FEM_FIAT;
275  this->basisCoordinates_ = COORDINATES_CARTESIAN;
276  this->functionSpace_ = FUNCTION_SPACE_HVOL;
277 
278  // initialize tags
279  {
280  // Basis-dependent initializations
281  const ordinal_type tagSize = 4; // size of DoF tag, i.e., number of fields in the tag
282  const ordinal_type posScDim = 0; // position in the tag, counting from 0, of the subcell dim
283  const ordinal_type posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal
284  const ordinal_type posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell
285 
286  // An array with local DoF tags assigned to the basis functions, in the order of their local enumeration
287  constexpr ordinal_type maxCardLine = Parameters::MaxOrder + 1;
288  ordinal_type tags[maxCardLine*maxCardLine*maxCardLine][4];
289 
290  {
291  ordinal_type idx = 0;
292  for (auto k=0;k<cardLine;++k) { // z
293  const auto tag_z = lineBasis.getDofTag(k);
294  for (ordinal_type j=0;j<cardLine;++j) { // y
295  const auto tag_y = lineBasis.getDofTag(j);
296  for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
297  const auto tag_x = lineBasis.getDofTag(i);
298 
299  // interior
300  tags[idx][0] = 3; // interior dof
301  tags[idx][1] = 0;
302  tags[idx][2] = tag_x(2) + tag_x(3)*tag_y(2) + tag_x(3)*tag_y(3)*tag_z(2); // local dof id
303  tags[idx][3] = tag_x(3)*tag_y(3)*tag_z(3); // total number of dofs in this vertex
304  }
305  }
306  }
307  }
308 
309  OrdinalTypeArray1DHost tagView(&tags[0][0], this->basisCardinality_*4);
310 
311  // Basis-independent function sets tag and enum data in tagToOrdinal_ and ordinalToTag_ arrays:
312  // tags are constructed on host
313  this->setOrdinalTagData(this->tagToOrdinal_,
314  this->ordinalToTag_,
315  tagView,
316  this->basisCardinality_,
317  tagSize,
318  posScDim,
319  posScOrd,
320  posDfOrd);
321  }
322 
323  // dofCoords on host and create its mirror view to device
324  Kokkos::DynRankView<typename ScalarViewType::value_type,typename SpT::array_layout,Kokkos::HostSpace>
325  dofCoordsHost("dofCoordsHost", this->basisCardinality_, this->basisCellTopology_.getDimension());
326 
327  Kokkos::DynRankView<typename ScalarViewType::value_type,SpT>
328  dofCoordsLine("dofCoordsLine", cardLine, 1);
329 
330  lineBasis.getDofCoords(dofCoordsLine);
331  auto dofCoordsLineHost = Kokkos::create_mirror_view(Kokkos::HostSpace(), dofCoordsLine);
332  Kokkos::deep_copy(dofCoordsLineHost, dofCoordsLine);
333  {
334  ordinal_type idx = 0;
335  for (auto k=0;k<cardLine;++k) { // z
336  for (ordinal_type j=0;j<cardLine;++j) { // y
337  for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
338  dofCoordsHost(idx,0) = dofCoordsLineHost(i,0);
339  dofCoordsHost(idx,1) = dofCoordsLineHost(j,0);
340  dofCoordsHost(idx,2) = dofCoordsLineHost(k,0);
341  }
342  }
343  }
344 
345  }
346 
347  this->dofCoords_ = Kokkos::create_mirror_view(typename SpT::memory_space(), dofCoordsHost);
348  Kokkos::deep_copy(this->dofCoords_, dofCoordsHost);
349  }
350 
351 }// namespace Intrepid2
352 
353 #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.
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,1] reference line cell, using Lagrange polynomials.
const OrdinalTypeArrayStride1DHost getDofTag(const ordinal_type dofOrd) const
DoF ordinal to DoF tag lookup.
static constexpr ordinal_type MaxOrder
The maximum reconstruction order.