Intrepid2
Intrepid2_LagrangianInterpolationDef.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_LAGRANGIANINTERPOLATIONDEF_HPP__
49 #define __INTREPID2_LAGRANGIANINTERPOLATIONDEF_HPP__
50 
52 #include "Intrepid2_ArrayTools.hpp"
54 
55 
56 namespace Intrepid2 {
57 
58 
59 namespace FunctorsLagrangianTools {
60 template<typename CoordsViewType,
61 typename ortViewType,
62 typename t2oViewType,
63 typename subcellParamViewType,
64 typename intViewType,
65 typename ScalarViewType>
67  typedef typename ScalarViewType::value_type value_type;
68 
69  CoordsViewType dofCoords_;
70  const ortViewType orts_;
71  const t2oViewType tagToOrdinal_;
72  const subcellParamViewType edgeParam_, faceParam_;
73  const intViewType edgesInternalDofOrdinals_, facesInternalDofOrdinals_;
74  const ScalarViewType edgesInternalDofCoords_;
75  const ScalarViewType facesInternalDofCoords_;
76  ScalarViewType edgeWorkView_, faceWorkView_;
77  const ordinal_type cellDim_, numEdges_, numFaces_;
78  const intViewType edgeTopoKey_, numEdgesInternalDofs_;
79  const intViewType faceTopoKey_, numFacesInternalDofs_;
80 
81  computeDofCoords( CoordsViewType dofCoords,
82  const ortViewType orts,
83  const t2oViewType tagToOrdinal,
84  const subcellParamViewType edgeParam,
85  const subcellParamViewType faceParam,
86  const ScalarViewType edgesInternalDofCoords,
87  const ScalarViewType facesInternalDofCoords,
88  const ordinal_type cellDim,
89  const ordinal_type numEdges,
90  const ordinal_type numFaces,
91  const intViewType edgeTopoKey,
92  const intViewType numEdgesInternalDofs,
93  const intViewType faceTopoKey,
94  const intViewType numFacesInternalDofs
95  )
96  : dofCoords_(dofCoords),
97  orts_(orts),
98  tagToOrdinal_(tagToOrdinal),
99  edgeParam_(edgeParam),
100  faceParam_(faceParam),
101  edgesInternalDofCoords_(edgesInternalDofCoords),
102  facesInternalDofCoords_(facesInternalDofCoords),
103  cellDim_(cellDim),
104  numEdges_(numEdges),
105  numFaces_(numFaces),
106  edgeTopoKey_(edgeTopoKey),
107  numEdgesInternalDofs_(numEdgesInternalDofs),
108  faceTopoKey_(faceTopoKey),
109  numFacesInternalDofs_(numFacesInternalDofs)
110  {
111  if(numEdges > 0)
112  edgeWorkView_ = ScalarViewType("edgeWorkView", dofCoords.extent(0), edgesInternalDofCoords.extent(1), cellDim);
113  if(numFaces > 0)
114  faceWorkView_ = ScalarViewType("faceWorkView", dofCoords.extent(0), facesInternalDofCoords.extent(1), cellDim);
115  }
116 
117  KOKKOS_INLINE_FUNCTION
118  void operator()(const ordinal_type cell) const {
119  typedef Kokkos::pair<ordinal_type,ordinal_type> range_type;
120 
121 
122  if(numEdges_ > 0) {
123  //compute coordinates associated to edge DoFs
124  ordinal_type eOrt[12];
125  orts_(cell).getEdgeOrientation(eOrt, numEdges_);
126  for (ordinal_type iedge=0; iedge < numEdges_; ++iedge) {
127  ordinal_type numInternalDofs = numEdgesInternalDofs_(iedge);
128  auto dofRange = range_type(0, numInternalDofs);
129  auto edgeInternalDofCoords = Kokkos::subview(edgesInternalDofCoords_, iedge, dofRange, Kokkos::ALL());
130  auto cellDofCoordsOriented = Kokkos::subview(edgeWorkView_,cell, dofRange, range_type(0,cellDim_));
131 
132  //map edge DoFs coords into parent element coords
133  Impl::OrientationTools::mapSubcellCoordsToRefCell(cellDofCoordsOriented, edgeInternalDofCoords, edgeParam_, edgeTopoKey_(iedge), iedge, eOrt[iedge]);
134 
135  for (ordinal_type j=0;j<numInternalDofs;++j) {
136  auto idof = tagToOrdinal_(1, iedge, j);
137  for (ordinal_type d=0;d<cellDim_;++d)
138  dofCoords_(cell,idof,d) = cellDofCoordsOriented(j,d);
139  }
140  }
141  }
142 
143  if(numFaces_ > 0) {
144  //compute coordinates associated to face DoFs
145  ordinal_type fOrt[12];
146  orts_(cell).getFaceOrientation(fOrt, numFaces_);
147  //map face dofs coords into parent element coords
148  for (ordinal_type iface=0; iface < numFaces_; ++iface) {
149  ordinal_type ort = fOrt[iface];
150  ordinal_type numInternalDofs = numFacesInternalDofs_(iface);
151  auto dofRange = range_type(0, numInternalDofs);
152  auto faceInternalDofCoords = Kokkos::subview(facesInternalDofCoords_, iface, dofRange, Kokkos::ALL());
153  auto cellDofCoordsOriented = Kokkos::subview(faceWorkView_,cell, dofRange, range_type(0,cellDim_));
154 
155  Impl::OrientationTools::mapSubcellCoordsToRefCell(cellDofCoordsOriented, faceInternalDofCoords, faceParam_, faceTopoKey_(iface), iface, ort);
156  for (ordinal_type j=0;j<numInternalDofs;++j) {
157  auto idof = tagToOrdinal_(2, iface, j);
158  for (ordinal_type d=0;d<cellDim_;++d)
159  dofCoords_(cell,idof,d) = cellDofCoordsOriented(j,d);
160  }
161  }
162  }
163  }
164 };
165 } // FunctorsLagrangianTools namespace
166 
167 
168 template<typename DeviceType>
169 template<typename BasisType,
170 class ...coordsProperties,
171 typename ortValueType, class ...ortProperties>
172 void
174  Kokkos::DynRankView<typename BasisType::scalarType, coordsProperties...> dofCoords,
175  const BasisType* basis,
176  const Kokkos::DynRankView<ortValueType, ortProperties...> orts) {
177 
178  using HostSpaceType = Kokkos::DefaultHostExecutionSpace;
179  using scalarType = typename BasisType::scalarType;
180  using ScalarViewType = Kokkos::DynRankView<scalarType, DeviceType>;
181  using ScalarViewTypeHost = Kokkos::DynRankView<scalarType, HostSpaceType>;
182  using intViewType = Kokkos::DynRankView<ordinal_type, DeviceType>;
183 
184  const auto topo = basis->getBaseCellTopology();
185  const std::string name(basis->getName());
186 
187  ordinal_type numEdges = (basis->getDofCount(1, 0) > 0) ? topo.getEdgeCount() : 0;
188  ordinal_type numFaces = (basis->getDofCount(2, 0) > 0) ? topo.getFaceCount() : 0;
189 
190  std::vector<Teuchos::RCP<Basis<DeviceType,scalarType,scalarType> > > edgeBases, faceBases;
191 
192  for(int i=0;i<numEdges;++i)
193  edgeBases.push_back(basis->getSubCellRefBasis(1,i));
194  for(int i=0;i<numFaces;++i)
195  faceBases.push_back(basis->getSubCellRefBasis(2,i));
196 
197  auto tagToOrdinal = Kokkos::create_mirror_view_and_copy(typename DeviceType::memory_space(), basis->getAllDofOrdinal());
198 
199  const ordinal_type dim = topo.getDimension();
200 
201  ScalarViewType refDofCoords("refDofCoords", dofCoords.extent(1), dofCoords.extent(2));
202  basis->getDofCoords(refDofCoords);
203  RealSpaceTools<DeviceType>::clone(dofCoords,refDofCoords);
204 
205  if((numFaces == 0) && (numEdges == 0))
206  return;
207 
208  //*** Pre-compute needed quantities related to edge DoFs that do not depend on the cell ***
209  intViewType edgeTopoKey("edgeTopoKey",numEdges);
210  intViewType sOrt("eOrt", numEdges);
211  intViewType numEdgesInternalDofs("numEdgesInternalDofs", numEdges);
212  ScalarViewType edgesInternalDofCoords;
213  intViewType edgesInternalDofOrdinals;
214 
215  ordinal_type maxNumEdgesInternalDofs=0;
216  ordinal_type edgeBasisMaxCardinality=0;
217 
218  auto hostNumEdgesInternalDofs = Kokkos::create_mirror_view(numEdgesInternalDofs);
219  for (ordinal_type iedge=0; iedge < numEdges; ++iedge) {
220  ordinal_type numInternalDofs = edgeBases[iedge]->getDofCount(1,0);
221  hostNumEdgesInternalDofs(iedge) = numInternalDofs;
222  maxNumEdgesInternalDofs = std::max(maxNumEdgesInternalDofs,numInternalDofs);
223  ordinal_type edgeBasisCardinality = edgeBases[iedge]->getCardinality();
224  edgeBasisMaxCardinality = std::max(edgeBasisMaxCardinality, edgeBasisCardinality);
225  }
226  Kokkos::deep_copy(numEdgesInternalDofs,hostNumEdgesInternalDofs);
227 
228  edgesInternalDofCoords = ScalarViewType("edgeInternalDofCoords", numEdges, maxNumEdgesInternalDofs,1);
229  edgesInternalDofOrdinals = intViewType("edgeInternalDofCoords", numEdges, maxNumEdgesInternalDofs);
230  auto hostEdgesInternalDofCoords = Kokkos::create_mirror_view(edgesInternalDofCoords);
231  auto hostEdgesInternalDofOrdinals = Kokkos::create_mirror_view(edgesInternalDofOrdinals);
232  auto hostEdgeTopoKey = Kokkos::create_mirror_view(edgeTopoKey);
233  for (ordinal_type iedge=0; iedge < numEdges; ++iedge) {
234  auto hostEdgeBasisPtr = edgeBases[iedge]->getHostBasis();
235  hostEdgeTopoKey(iedge) = hostEdgeBasisPtr->getBaseCellTopology().getBaseKey();
236  ordinal_type edgeBasisCardinality = hostEdgeBasisPtr->getCardinality();
237  ScalarViewTypeHost edgeDofCoords("edgeDofCoords", edgeBasisCardinality, 1);
238  hostEdgeBasisPtr->getDofCoords(edgeDofCoords);
239  for(ordinal_type i=0; i<hostNumEdgesInternalDofs(iedge); ++i) {
240  hostEdgesInternalDofOrdinals(iedge, i) = hostEdgeBasisPtr->getDofOrdinal(1, 0, i);
241  hostEdgesInternalDofCoords(iedge, i,0) = edgeDofCoords(hostEdgesInternalDofOrdinals(iedge, i),0);
242  }
243  }
244  Kokkos::deep_copy(edgesInternalDofCoords,hostEdgesInternalDofCoords);
245  Kokkos::deep_copy(edgeTopoKey,hostEdgeTopoKey);
246 
247  auto edgeParam = RefSubcellParametrization<DeviceType>::get(1, topo.getKey());
248 
249  //*** Pre-compute needed quantities related to face DoFs that do not depend on the cell ***
250  intViewType faceTopoKey("faceTopoKey",numFaces);
251  intViewType fOrt("fOrt", numFaces);
252  intViewType numFacesInternalDofs("numFacesInternalDofs", numFaces);
253  ScalarViewType facesInternalDofCoords;
254  intViewType facesInternalDofOrdinals;
255 
256  ordinal_type maxNumFacesInternalDofs=0;
257  ordinal_type faceBasisMaxCardinality=0;
258 
259  auto hostNumFacesInternalDofs = Kokkos::create_mirror_view(numFacesInternalDofs);
260  for (ordinal_type iface=0; iface < numFaces; ++iface) {
261  ordinal_type numInternalDofs = faceBases[iface]->getDofCount(2,0);
262  hostNumFacesInternalDofs(iface) = numInternalDofs;
263  maxNumFacesInternalDofs = std::max(maxNumFacesInternalDofs,numInternalDofs);
264  ordinal_type faceBasisCardinality = faceBases[iface]->getCardinality();
265  faceBasisMaxCardinality = std::max(faceBasisMaxCardinality, faceBasisCardinality);
266  }
267  Kokkos::deep_copy(numFacesInternalDofs,hostNumFacesInternalDofs);
268 
269  facesInternalDofCoords = ScalarViewType("faceInternalDofCoords", numFaces, maxNumFacesInternalDofs, 2);
270  facesInternalDofOrdinals = intViewType("faceInternalDofCoords", numFaces, maxNumFacesInternalDofs);
271 
272  auto hostFacesInternalDofCoords = Kokkos::create_mirror_view(facesInternalDofCoords);
273  auto hostFacesInternalDofOrdinals = Kokkos::create_mirror_view(facesInternalDofOrdinals);
274  auto hostFaceTopoKey = Kokkos::create_mirror_view(faceTopoKey);
275  for (ordinal_type iface=0; iface < numFaces; ++iface) {
276  auto hostFaceBasisPtr = faceBases[iface]->getHostBasis();
277  hostFaceTopoKey(iface) = hostFaceBasisPtr->getBaseCellTopology().getBaseKey();
278  ordinal_type faceBasisCardinality = hostFaceBasisPtr->getCardinality();
279  ScalarViewTypeHost faceDofCoords("faceDofCoords", faceBasisCardinality, 2);
280  hostFaceBasisPtr->getDofCoords(faceDofCoords);
281  for(ordinal_type i=0; i<hostNumFacesInternalDofs(iface); ++i) {
282  hostFacesInternalDofOrdinals(iface, i) = hostFaceBasisPtr->getDofOrdinal(2, 0, i);
283  for(ordinal_type d=0; d <2; ++d)
284  hostFacesInternalDofCoords(iface, i,d) = faceDofCoords(hostFacesInternalDofOrdinals(iface, i),d);
285  }
286  }
287  Kokkos::deep_copy(facesInternalDofCoords,hostFacesInternalDofCoords);
288  Kokkos::deep_copy(faceTopoKey,hostFaceTopoKey);
289 
290  typename RefSubcellParametrization<DeviceType>::ConstViewType faceParam;
291  if(dim > 2)
292  faceParam = RefSubcellParametrization<DeviceType>::get(2, topo.getKey());
293 
294 
295  //*** Loop over cells ***
296 
297  const Kokkos::RangePolicy<typename DeviceType::execution_space> policy(0, dofCoords.extent(0));
298  using FunctorType = FunctorsLagrangianTools::computeDofCoords<decltype(dofCoords),
299  decltype(orts),
300  decltype(tagToOrdinal),
301  decltype(edgeParam),
302  intViewType,
303  ScalarViewType>;
304  Kokkos::parallel_for(policy,
305  FunctorType(dofCoords,
306  orts, tagToOrdinal, edgeParam, faceParam,
307  edgesInternalDofCoords, facesInternalDofCoords,
308  dim, numEdges, numFaces,
309  edgeTopoKey, numEdgesInternalDofs,
310  faceTopoKey, numFacesInternalDofs));
311 }
312 
313 
314 template<typename DeviceType>
315 template<typename BasisType,
316 class ...coeffsProperties,
317 typename ortValueType, class ...ortProperties>
318 void
320  Kokkos::DynRankView<typename BasisType::scalarType, coeffsProperties...> dofCoeffs,
321  const BasisType* basis,
322  const Kokkos::DynRankView<ortValueType, ortProperties...> orts) {
323 
324  using ScalarViewType = Kokkos::DynRankView<typename BasisType::scalarType, DeviceType>;
325  ScalarViewType refDofCoeffs;
326  if(dofCoeffs.rank() == 3) //vector basis
327  refDofCoeffs = ScalarViewType("refDofCoeffs", dofCoeffs.extent(1), dofCoeffs.extent(2));
328  else //scalar basis
329  refDofCoeffs = ScalarViewType("refDofCoeffs",dofCoeffs.extent(1));
330  basis->getDofCoeffs(refDofCoeffs);
331 
332  OrientationTools<DeviceType>::modifyBasisByOrientationInverse(dofCoeffs, refDofCoeffs, orts, basis, true);
333 }
334 
335 
336 template<typename DeviceType>
337 template<typename basisCoeffsViewType,
338 typename funcViewType,
339 typename BasisType,
340 typename ortViewType>
341 void
343  const funcViewType functionValsAtDofCoords,
344  const BasisType* cellBasis,
345  const ortViewType orts){
346  using scalarType = typename BasisType::scalarType;
347  using ScalarViewType = Kokkos::DynRankView<scalarType, DeviceType>;
348  auto dofCoeffs = (functionValsAtDofCoords.rank() == 3) ?
349  ScalarViewType("dofCoeffs", basisCoeffs.extent(0), cellBasis->getCardinality(), functionValsAtDofCoords.extent(2)) :
350  ScalarViewType("dofCoeffs", basisCoeffs.extent(0), cellBasis->getCardinality());
351  auto dofCoeffs0 = Kokkos::subview(dofCoeffs, 0, Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL());
352  cellBasis->getDofCoeffs(dofCoeffs0);
353  RealSpaceTools<DeviceType>::clone(dofCoeffs,dofCoeffs0);
354  Kokkos::DynRankView<typename basisCoeffsViewType::value_type, DeviceType> basisCoeffsRef("basisCoeffsRef", basisCoeffs.extent(0), basisCoeffs.extent(1));
355  ArrayTools<DeviceType>::dotMultiplyDataData(basisCoeffsRef,functionValsAtDofCoords,dofCoeffs);
356  OrientationTools<DeviceType>::modifyBasisByOrientationInverse(basisCoeffs, basisCoeffsRef, orts, cellBasis, true);
357 }
358 
359 } // Intrepid2 namespace
360 
361 #endif
362 
Header file for the abstract base class Intrepid2::DefaultCubatureFactory.
static void getBasisCoeffs(basisCoeffsViewType basisCoeffs, const funcViewType functionAtDofCoords, const BasisType *cellBasis, const ortViewType orts)
Computes the basis weights of the function interpolation.
static KOKKOS_INLINE_FUNCTION void mapSubcellCoordsToRefCell(coordsViewType cellCoords, const subcellCoordsViewType subCellCoords, const ParamViewType subcellParametrization, const unsigned subcellTopoKey, const ordinal_type subCellOrd, const ordinal_type ort)
Maps points defined on the subCell manifold into the parent Cell accounting for orientation.
static ConstViewType get(const ordinal_type subcellDim, const unsigned parentCellKey)
Returns a Kokkos view with the coefficients of the parametrization maps for the edges or faces of a r...
static void clone(Kokkos::DynRankView< outputValueType, outputProperties...> output, const Kokkos::DynRankView< inputValueType, inputProperties...> input)
Clone input array.
static void dotMultiplyDataData(Kokkos::DynRankView< outputDataValueType, outputDataProperties...> outputData, const Kokkos::DynRankView< inputDataLeftValueType, inputDataLeftProperties...> inputDataLeft, const Kokkos::DynRankView< inputDataRightValueType, inputDataRightProperties...> inputDataRight)
There are two use cases: (1) dot product of a rank-2, 3 or 4 container inputDataRight with dimensions...
static void getOrientedDofCoords(Kokkos::DynRankView< typename BasisType::scalarType, coordsProperties...> dofCoords, const BasisType *cellBasis, const Kokkos::DynRankView< ortValueType, ortProperties...> cellOrientations)
Computes the coordinates associated with the basis DOFs for the reference oriented element...
Header file for the Intrepid2::FunctionSpaceTools class.
static void getOrientedDofCoeffs(Kokkos::DynRankView< typename BasisType::scalarType, coeffsProperties...> dofCoeffs, const BasisType *cellBasis, const Kokkos::DynRankView< ortValueType, ortProperties...> cellOrientations)
Computes the coefficients associated with the basis DOFs for the reference oriented element...
Header file for Intrepid2::ArrayTools class providing utilities for array operations.
static void modifyBasisByOrientationInverse(Kokkos::DynRankView< outputValueType, outputProperties...> output, const Kokkos::DynRankView< inputValueType, inputProperties...> input, const OrientationViewType orts, const BasisType *basis, const bool transpose=false)
Modify basis due to orientation, applying the inverse of the operator applied in modifyBasisByOrienta...