Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_IntrepidFieldPattern.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Panzer: A partial differential equation assembly
4 // engine for strongly coupled complex multiphysics systems
5 //
6 // Copyright 2011 NTESS and the Panzer contributors.
7 // SPDX-License-Identifier: BSD-3-Clause
8 // *****************************************************************************
9 // @HEADER
10 
12 
13 #include "Teuchos_Assert.hpp"
14 #include "Intrepid2_CellTools.hpp"
15 #include "Shards_CellTopology.hpp"
16 
17 namespace panzer {
18 
20  Intrepid2FieldPattern(const Teuchos::RCP< Intrepid2::Basis<PHX::Device,double,double> > &intrepidBasis)
21  : intrepidBasis_(intrepidBasis) {
22  const auto dofOrd = intrepidBasis_->getAllDofOrdinal(); // rank 3 view
23  const auto dofTag = intrepidBasis_->getAllDofTags(); // rank 2 view
24 
25  const int
26  iend = dofOrd.extent(0),
27  jend = dofOrd.extent(1);
28 
29  subcellIndicies_.resize(iend);
30  for (int i=0;i<iend;++i) {
31  subcellIndicies_[i].resize(jend);
32  for (int j=0;j<jend;++j) {
33  const int ord = dofOrd(i, j, 0);
34  if (ord >= 0) {
35  const int ndofs = dofTag(ord, 3);
36  subcellIndicies_[i][j].resize(ndofs);
37  for (int k=0;k<ndofs;++k)
38  subcellIndicies_[i][j][k] = dofOrd(i, j, k);
39  } else {
40  // if ordinal does not exist empty container.
41  subcellIndicies_[i][j].clear();
42  }
43  }
44  }
45  }
46 
47  int
49  getSubcellCount(int dim) const
50  {
51  const shards::CellTopology ct = intrepidBasis_->getBaseCellTopology();
52  return ct.getSubcellCount(dim);
53  }
54 
55  const std::vector<int> &
56  Intrepid2FieldPattern::getSubcellIndices(int dim, int cellIndex) const
57  {
58  if ((dim < static_cast<int>(subcellIndicies_.size() )) and
59  (cellIndex < static_cast<int>(subcellIndicies_[dim].size())))
60  return subcellIndicies_[dim][cellIndex];
61 
62  return empty_;
63  }
64 
65  void
67  getSubcellClosureIndices(int dim,int cellIndex,std::vector<int> & indices) const
68  {
69  // wipe out previous values
70  indices.clear();
71 
72  if (dim == 0) {
73  indices = getSubcellIndices(dim,cellIndex);
74  } else {
75  // construct full topology
76  const shards::CellTopology ct = intrepidBasis_->getBaseCellTopology();
77 
78  std::set<std::pair<unsigned,unsigned> > closure;
79  Intrepid2FieldPattern::buildSubcellClosure(ct,dim,cellIndex,closure);
80 
81  // grab basis indices on the closure of the sub cell
82  std::set<std::pair<unsigned,unsigned> >::const_iterator itr;
83  for (itr=closure.begin();itr!=closure.end();++itr) {
84  // grab indices for this sub cell
85  const std::vector<int> & subcellIndices = getSubcellIndices(itr->first,itr->second);
86 
87  // concatenate the two vectors
88  indices.insert(indices.end(),subcellIndices.begin(),subcellIndices.end());
89  }
90  }
91  }
92 
93  int
96  {
97  return intrepidBasis_->getBaseCellTopology().getDimension();
98  }
99 
100  shards::CellTopology
103  {
104  // TODO BWR Probably should change the name of this call...
105  // TODO BWR However this is a virtual function
106  return intrepidBasis_->getBaseCellTopology();
107  }
108 
109  void
111  getSubcellNodes(const shards::CellTopology & cellTopo,unsigned dim,unsigned subCell,
112  std::vector<unsigned> & nodes)
113  {
114  if(dim==0) {
115  nodes.push_back(subCell);
116  return;
117  }
118 
119  // get all nodes on requested sub cell
120  unsigned subCellNodeCount = cellTopo.getNodeCount(dim,subCell);
121  for(unsigned node=0;node<subCellNodeCount;++node)
122  nodes.push_back(cellTopo.getNodeMap(dim,subCell,node));
123 
124  // sort them so they are ordered correctly for "includes" call
125  std::sort(nodes.begin(),nodes.end());
126  }
127 
128  void
130  findContainedSubcells(const shards::CellTopology & cellTopo,unsigned dim,
131  const std::vector<unsigned> & nodes,
132  std::set<std::pair<unsigned,unsigned> > & subCells)
133  {
134  unsigned subCellCount = cellTopo.getSubcellCount(dim);
135  for(unsigned subCellOrd=0;subCellOrd<subCellCount;++subCellOrd) {
136  // get all nodes in sub cell
137  std::vector<unsigned> subCellNodes;
138  getSubcellNodes(cellTopo,dim,subCellOrd,subCellNodes);
139 
140  // if subCellNodes \subset nodes => add (dim,subCellOrd) to subCells
141  bool isSubset = std::includes( nodes.begin(), nodes.end(),
142  subCellNodes.begin(), subCellNodes.end());
143  if(isSubset)
144  subCells.insert(std::make_pair(dim,subCellOrd));
145 
146  }
147 
148  // stop recursion base case
149  if (dim==0) return;
150 
151  // find subcells in next sub dimension
152  findContainedSubcells(cellTopo,dim-1,nodes,subCells);
153  }
154 
155  void
157  buildSubcellClosure(const shards::CellTopology & cellTopo,unsigned dim,unsigned subCell,
158  std::set<std::pair<unsigned,unsigned> > & closure)
159  {
160  switch(dim) {
161  case 0:
162  closure.insert(std::make_pair(0,subCell));
163  break;
164  case 1:
165  closure.insert(std::make_pair(0,cellTopo.getNodeMap(dim,subCell,0)));
166  closure.insert(std::make_pair(0,cellTopo.getNodeMap(dim,subCell,1)));
167  closure.insert(std::make_pair(1,subCell));
168  break;
169  case 2:
170  {
171  unsigned cnt = (shards::CellTopology(cellTopo.getCellTopologyData(dim,subCell))).getSubcellCount(dim-1);
172  for(unsigned i=0;i<cnt;i++) {
173  int edge = mapCellFaceEdge(cellTopo.getCellTopologyData(),subCell,i);
174  buildSubcellClosure(cellTopo,dim-1,edge,closure);
175  }
176  closure.insert(std::make_pair(2,subCell));
177  }
178  break;
179  default:
180  // beyond a two dimension surface this thing crashes!
181  TEUCHOS_ASSERT(false);
182  };
183  }
184 
185  bool
188  {
189  // we no longer use CoordsInterface
190  return true;
191  }
192 
198  void
200  getInterpolatoryCoordinates(Kokkos::DynRankView<double,PHX::Device> & coords) const
201  {
202  // this may not be efficient if coords is allocated every time this function is called
203  coords = Kokkos::DynRankView<double,PHX::Device>("coords",intrepidBasis_->getCardinality(),getDimension());
204  intrepidBasis_->getDofCoords(coords);
205  }
206 
212  void
214  getInterpolatoryCoordinates(const Kokkos::DynRankView<double,PHX::Device> & cellNodes,
215  Kokkos::DynRankView<double,PHX::Device> & coords,
216  Teuchos::RCP<const shards::CellTopology> meshCellTopology) const
217  {
218  TEUCHOS_ASSERT(cellNodes.rank()==3);
219 
220  int numCells = cellNodes.extent(0);
221 
222  // grab the local coordinates
223  Kokkos::DynRankView<double,PHX::Device> localCoords;
224  getInterpolatoryCoordinates(localCoords);
225 
226  // resize the coordinates field container
227  coords = Kokkos::DynRankView<double,PHX::Device>("coords",numCells,localCoords.extent(0),getDimension());
228 
229  if(numCells>0) {
230  Intrepid2::CellTools<PHX::Device> cellTools;
231  // For backwards compatability, allow the FE basis to supply the mesh cell topology (via the FEM base cell topo)
232  // This will occur if no meshCellTopology is provided (defaults to Teuchos::null)
233  // If provided, use the mesh topology directly
234  if (meshCellTopology==Teuchos::null) {
235  cellTools.mapToPhysicalFrame(coords,localCoords,cellNodes,intrepidBasis_->getBaseCellTopology());
236  } else {
237  cellTools.mapToPhysicalFrame(coords,localCoords,cellNodes,*meshCellTopology);
238  }
239  }
240  }
241 
244  { return intrepidBasis_; }
245 
246 }
virtual const std::vector< int > & getSubcellIndices(int dim, int cellIndex) const
static void buildSubcellClosure(const shards::CellTopology &cellTopo, unsigned dim, unsigned subCell, std::set< std::pair< unsigned, unsigned > > &closure)
virtual shards::CellTopology getCellTopology() const
bool supportsInterpolatoryCoordinates() const
Does this field pattern support interpolatory coordinates?
Intrepid2FieldPattern(const Teuchos::RCP< Intrepid2::Basis< PHX::Device, double, double > > &intrepidBasis)
static void getSubcellNodes(const shards::CellTopology &cellTopo, unsigned dim, unsigned subCell, std::vector< unsigned > &nodes)
virtual void getSubcellClosureIndices(int dim, int cellIndex, std::vector< int > &indices) const
Teuchos::RCP< Intrepid2::Basis< PHX::Device, double, double > > getIntrepidBasis() const
Returns the underlying Intrepid2::Basis object.
std::vector< std::vector< std::vector< int > > > subcellIndicies_
static void findContainedSubcells(const shards::CellTopology &cellTopo, unsigned dim, const std::vector< unsigned > &nodes, std::set< std::pair< unsigned, unsigned > > &subCells)
void getInterpolatoryCoordinates(Kokkos::DynRankView< double, PHX::Device > &coords) const
#define TEUCHOS_ASSERT(assertion_test)
virtual int getSubcellCount(int dim) const
Teuchos::RCP< Intrepid2::Basis< PHX::Device, double, double > > intrepidBasis_