Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_STK_LocalMeshUtilities.cpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Panzer: A partial differential equation assembly
5 // engine for strongly coupled complex multiphysics systems
6 // Copyright (2011) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Roger P. Pawlowski (rppawlo@sandia.gov) and
39 // Eric C. Cyr (eccyr@sandia.gov)
40 // ***********************************************************************
41 // @HEADER
42 
43 #include "Panzer_NodeType.hpp"
45 #include "Panzer_STK_Interface.hpp"
48 
49 #include "Panzer_HashUtils.hpp"
50 #include "Panzer_LocalMeshInfo.hpp"
52 #include "Panzer_FaceToElement.hpp"
53 
54 #include "Panzer_ConnManager.hpp"
55 #include "Panzer_FieldPattern.hpp"
60 
61 #include "Phalanx_KokkosDeviceTypes.hpp"
62 
63 #include "Teuchos_Assert.hpp"
64 
65 #include "Tpetra_Import.hpp"
66 #include "Tpetra_CrsMatrix.hpp"
67 #include "Tpetra_RowMatrixTransposer.hpp"
68 
69 #include <string>
70 #include <map>
71 #include <vector>
72 #include <unordered_set>
73 
74 namespace panzer_stk
75 {
76 
77 // No external access
78 namespace
79 {
80 
84 template <typename LO,typename GO>
85 void
86 buildCellGlobalIDs(panzer::ConnManager<LO,GO> & conn,
87  Kokkos::View<GO*> & globals)
88 {
89  // extract topologies, and build global connectivity...currently assuming only one topology
90  std::vector<shards::CellTopology> elementBlockTopologies;
91  conn.getElementBlockTopologies(elementBlockTopologies);
92  const shards::CellTopology & topology = elementBlockTopologies[0];
93 
94  // FIXME: We assume that all element blocks have the same topology.
95  for(const auto & other_topology : elementBlockTopologies){
96  TEUCHOS_ASSERT(other_topology.getKey() == topology.getKey());
97  }
98 
100  if(topology.getDimension() == 1){
101  cell_pattern = Teuchos::rcp(new panzer::EdgeFieldPattern(topology));
102  } else if(topology.getDimension() == 2){
103  cell_pattern = Teuchos::rcp(new panzer::FaceFieldPattern(topology));
104  } else if(topology.getDimension() == 3){
105  cell_pattern = Teuchos::rcp(new panzer::ElemFieldPattern(topology));
106  }
107 
108 // panzer::EdgeFieldPattern cell_pattern(elementBlockTopologies[0]);
109  conn.buildConnectivity(*cell_pattern);
110 
111  // calculate total number of local cells
112  std::vector<std::string> block_ids;
113  conn.getElementBlockIds(block_ids);
114 
115  std::size_t totalSize = 0;
116  for (std::size_t which_blk=0;which_blk<block_ids.size();which_blk++) {
117  // get the elem to face mapping
118  const std::vector<LO> & localIDs = conn.getElementBlock(block_ids[which_blk]);
119  totalSize += localIDs.size();
120  }
121  globals = Kokkos::View<GO*>("global_cells",totalSize);
122 
123  for (std::size_t id=0;id<totalSize; ++id) {
124  // sanity check
125  int n_conn = conn.getConnectivitySize(id);
126  TEUCHOS_ASSERT(n_conn==1);
127 
128  const GO * connectivity = conn.getConnectivity(id);
129  globals(id) = connectivity[0];
130  }
131 
132 // print_view_1D("buildCellGlobalIDs : globals",globals);
133 }
134 
138 template <typename LO,typename GO>
139 void
140 buildCellToNodes(panzer::ConnManager<LO,GO> & conn, Kokkos::View<GO**> & globals)
141 {
142  // extract topologies, and build global connectivity...currently assuming only one topology
143  std::vector<shards::CellTopology> elementBlockTopologies;
144  conn.getElementBlockTopologies(elementBlockTopologies);
145  const shards::CellTopology & topology = elementBlockTopologies[0];
146 
147  // FIXME: We assume that all element blocks have the same topology.
148  for(const auto & other_topology : elementBlockTopologies){
149  TEUCHOS_ASSERT(other_topology.getKey() == topology.getKey());
150  }
151 
152  panzer::NodalFieldPattern pattern(topology);
153  conn.buildConnectivity(pattern);
154 
155  // calculate total number of local cells
156  std::vector<std::string> block_ids;
157  conn.getElementBlockIds(block_ids);
158 
159  // compute total cells and maximum nodes
160  std::size_t totalCells=0, maxNodes=0;
161  for (std::size_t which_blk=0;which_blk<block_ids.size();which_blk++) {
162  // get the elem to face mapping
163  const std::vector<LO> & localIDs = conn.getElementBlock(block_ids[which_blk]);
164  if ( localIDs.size() == 0 )
165  continue;
166  LO thisSize = conn.getConnectivitySize(localIDs[0]);
167 
168  totalCells += localIDs.size();
169  maxNodes = maxNodes<Teuchos::as<std::size_t>(thisSize) ? Teuchos::as<std::size_t>(thisSize) : maxNodes;
170  }
171  globals = Kokkos::View<GO**>("cell_to_node",totalCells,maxNodes);
172 
173  // build connectivity array
174  for (std::size_t id=0;id<totalCells; ++id) {
175  const GO * connectivity = conn.getConnectivity(id);
176  LO nodeCnt = conn.getConnectivitySize(id);
177 
178  for(int n=0;n<nodeCnt;n++)
179  globals(id,n) = connectivity[n];
180  }
181 
182 // print_view("buildCellToNodes : globals",globals);
183 }
184 
185 template <typename LO,typename GO>
187 buildNodeMap(const Teuchos::RCP<const Teuchos::Comm<int> > & comm,
188  Kokkos::View<const GO**> cells_to_nodes)
189 {
190  using Teuchos::RCP;
191  using Teuchos::rcp;
192 
193  /*
194 
195  This function converts
196 
197  cells_to_nodes(local cell, local node) = global node index
198 
199  to a map describing which global nodes are found on this process
200 
201  Note that we have to ensure that that the global nodes found on this process are unique.
202 
203  */
204 
205  typedef Tpetra::Map<LO,GO,panzer::TpetraNodeType> map_type;
206 
207  // get locally unique global ids
208  std::set<GO> global_nodes;
209  for(unsigned int i=0;i<cells_to_nodes.extent(0);i++)
210  for(unsigned int j=0;j<cells_to_nodes.extent(1);j++)
211  global_nodes.insert(cells_to_nodes(i,j));
212 
213  // build local vector contribution
214  Kokkos::View<GO*> node_ids("global_nodes",global_nodes.size());
215  int i = 0;
216  for(auto itr=global_nodes.begin();itr!=global_nodes.end();++itr,++i)
217  node_ids(i) = *itr;
218 
219 // print_view("buildNodeMap : cells_to_nodes",cells_to_nodes);
220 // print_view_1D("buildNodeMap : node_ids",node_ids);
221 
222  return rcp(new map_type(-1,node_ids,0,comm));
223 }
224 
228 template <typename LO,typename GO>
230 buildNodeToCellMatrix(const Teuchos::RCP<const Teuchos::Comm<int> > & comm,
231  Kokkos::View<const GO*> owned_cells,
232  Kokkos::View<const GO**> owned_cells_to_nodes)
233 {
234  using Teuchos::RCP;
235  using Teuchos::rcp;
236 
237  typedef Tpetra::Map<LO,GO,panzer::TpetraNodeType> map_type;
238  typedef Tpetra::CrsMatrix<LO,LO,GO,panzer::TpetraNodeType> crs_type;
239  typedef Tpetra::Import<LO,GO,panzer::TpetraNodeType> import_type;
240 
241 
242  PANZER_FUNC_TIME_MONITOR_DIFF("panzer_stk::buildNodeToCellMatrix",BNTCM);
243 
244  TEUCHOS_ASSERT(owned_cells.extent(0)==owned_cells_to_nodes.extent(0));
245 
246  // build a unque node map to use with fill complete
247 
248  // This map identifies all nodes linked to cells on this process
249  auto node_map = buildNodeMap<LO,GO>(comm,owned_cells_to_nodes);
250 
251  // This map identifies nodes owned by this process
252  auto unique_node_map = Tpetra::createOneToOne(node_map);
253 
254  // This map identifies the cells owned by this process
255  RCP<map_type> cell_map = rcp(new map_type(-1,owned_cells,0,comm));
256 
257  // Create a CRS matrix that stores a pointless value for every global node that belongs to a global cell
258  // This is essentially another way to store cells_to_nodes
259  RCP<crs_type> cell_to_node;
260  {
261  PANZER_FUNC_TIME_MONITOR_DIFF("Build matrix",BuildMatrix);
262  // The matrix is indexed by (global cell, global node) = local node
263  cell_to_node = rcp(new crs_type(cell_map,0));
264 
265  // fill in the cell to node matrix
266  const unsigned int num_local_cells = owned_cells_to_nodes.extent(0);
267  const unsigned int num_nodes_per_cell = owned_cells_to_nodes.extent(1);
268  std::vector<LO> local_node_indexes(num_nodes_per_cell);
269  std::vector<GO> global_node_indexes(num_nodes_per_cell);
270  for(unsigned int i=0;i<num_local_cells;i++) {
271  const GO global_cell_index = owned_cells(i);
272  // std::vector<LO> vals(cells_to_nodes.extent(1));
273  // std::vector<GO> cols(cells_to_nodes.extent(1));
274  for(unsigned int j=0;j<num_nodes_per_cell;j++) {
275  // vals[j] = Teuchos::as<LO>(j);
276  // cols[j] = cells_to_nodes(i,j);
277  local_node_indexes[j] = Teuchos::as<LO>(j);
278  global_node_indexes[j] = owned_cells_to_nodes(i,j);
279  }
280 
281  // cell_to_node_mat->insertGlobalValues(cells(i),cols,vals);
282  cell_to_node->insertGlobalValues(global_cell_index,global_node_indexes,local_node_indexes);
283  }
284  cell_to_node->fillComplete(unique_node_map,cell_map);
285 
286  }
287 
288  // Transpose the cell_to_node array to create the node_to_cell array
289  RCP<crs_type> node_to_cell;
290  {
291  PANZER_FUNC_TIME_MONITOR_DIFF("Tranpose matrix",TransposeMatrix);
292  // Create an object designed to transpose the (global cell, global node) matrix to give
293  // a (global node, global cell) matrix
294  Tpetra::RowMatrixTransposer<LO,LO,GO,panzer::TpetraNodeType> transposer(cell_to_node);
295 
296  // Create the transpose crs matrix
297  auto trans = transposer.createTranspose();
298 
299  // We want to import the portion of the transposed matrix relating to all nodes on this process
300  // The importer must import nodes required by this process (node_map) from the unique nodes (nodes living on a process)
301  RCP<import_type> import = rcp(new import_type(unique_node_map,node_map));
302 
303  // Create the crs matrix to store (ghost node, global cell) array
304  // This CRS matrix will have overlapping rows for shared global nodes
305  node_to_cell = rcp(new crs_type(node_map,0));
306 
307  // Transfer data from the transpose array (associated with unique_node_map) to node_to_cell (associated with node_map)
308  node_to_cell->doImport(*trans,*import,Tpetra::INSERT);
309 
310  // Set the fill - basicially locks down the structured of the CRS matrix - required before doing some operations
311  //node_to_cell->fillComplete();
312  node_to_cell->fillComplete(cell_map,unique_node_map);
313  }
314 
315  // Return the node to cell array
316  return node_to_cell;
317 }
318 
321 template <typename GO>
322 Kokkos::View<const GO*>
323 buildGhostedCellOneRing(const Teuchos::RCP<const Teuchos::Comm<int> > & comm,
324  Kokkos::View<const GO*> cells,
325  Kokkos::View<const GO**> cells_to_nodes)
326 {
327 
328  PANZER_FUNC_TIME_MONITOR_DIFF("panzer_stk::buildGhostedCellOneRing",BGCOR);
329  typedef Tpetra::CrsMatrix<int,int,GO,panzer::TpetraNodeType> crs_type;
330 
331  // cells : (local cell index) -> global cell index
332  // cells_to_nodes : (local cell index, local node_index) -> global node index
333 
334  /*
335 
336  This function creates a list of global indexes relating to ghost cells
337 
338  It is a little misleading how it does this, but the idea is to use the indexing of a CRS matrix to identify
339  what global cells are connected to which global nodes. The values in the CRS matrix are meaningless, however,
340  the fact that they are filled allows us to ping what index combinations exist.
341 
342  To do this we are going to use cell 'nodes' which could also be cell 'vertices'. It is unclear.
343 
344  First we construct an array that stores that global node indexes make up the connectivity for a given global cell index (order doesn't matter)
345 
346  cell_to_node : cell_to_node[global cell index][global node index] = some value (not important, just has to exist)
347 
348  We are then going to transpose that array
349 
350  node_to_cell : node_to_cell[global node index][global cell index] = some value (not important, just has to exist)
351 
352  The coloring of the node_to_cell array tells us what global cells are connected to a given global node.
353 
354 
355  */
356 
357  // the node to cell matrix: Row = Global Node Id, Cell = Global Cell Id, Value = Cell Local Node Id
358  Teuchos::RCP<crs_type> node_to_cell = buildNodeToCellMatrix<int,GO>(comm,cells,cells_to_nodes);
359 
360  // the set of cells already known
361  std::unordered_set<GO> unique_cells;
362 
363  // mark all owned cells as already known, e.g. and not in the list of
364  // ghstd cells to be constructed
365  for(size_t i=0;i<cells.extent(0);i++) {
366  unique_cells.insert(cells(i));
367  }
368 
369  // The set of ghost cells that share a global node with an owned cell
370  std::set<GO> ghstd_cells_set;
371 
372  // Get a list of global node indexes associated with the cells owned by this process
373 // auto node_map = node_to_cell->getRangeMap()->getMyGlobalIndices();
374  auto node_map = node_to_cell->getMap()->getMyGlobalIndices();
375 
376  // Iterate through the global node indexes associated with this process
377  for(size_t i=0;i<node_map.extent(0);i++) {
378  const GO global_node_index = node_map(i);
379  size_t numEntries = node_to_cell->getNumEntriesInGlobalRow(node_map(i));
380  Teuchos::Array<GO> indices(numEntries);
381  Teuchos::Array<int> values(numEntries);
382 
383  // Copy the row for a global node index into a local vector
384  node_to_cell->getGlobalRowCopy(global_node_index,indices,values,numEntries);
385 
386  for(auto index : indices) {
387  // if this is a new index (not owned, not previously found ghstd index
388  // add it to the list of ghstd cells
389  if(unique_cells.find(index)==unique_cells.end()) {
390  ghstd_cells_set.insert(index);
391  unique_cells.insert(index); // make sure you don't find it again
392  }
393  }
394  }
395 
396  // build an array containing only the ghstd cells
397  int indx = 0;
398  Kokkos::View<GO*> ghstd_cells("ghstd_cells",ghstd_cells_set.size());
399  for(auto global_cell_index : ghstd_cells_set) {
400  ghstd_cells(indx) = global_cell_index;
401  indx++;
402  }
403 
404 // print_view_1D("ghstd_cells",ghstd_cells);
405 
406  return ghstd_cells;
407 }
408 
412 template <typename GO>
413 Kokkos::DynRankView<double,PHX::Device>
414 buildGhostedVertices(const Tpetra::Import<int,GO,panzer::TpetraNodeType> & importer,
415  Kokkos::DynRankView<const double,PHX::Device> owned_vertices)
416 {
417  using Teuchos::RCP;
418  using Teuchos::rcp;
419 
420  typedef Tpetra::MultiVector<double,int,GO,panzer::TpetraNodeType> mvec_type;
421  typedef typename mvec_type::dual_view_type dual_view_type;
422 
423  size_t owned_cell_cnt = importer.getSourceMap()->getNodeNumElements();
424  size_t ghstd_cell_cnt = importer.getTargetMap()->getNodeNumElements();
425  int vertices_per_cell = owned_vertices.extent(1);
426  int space_dim = owned_vertices.extent(2);
427 
428  TEUCHOS_ASSERT(owned_vertices.extent(0)==owned_cell_cnt);
429 
430  // build vertex multivector
431  RCP<mvec_type> owned_vertices_mv = rcp(new mvec_type(importer.getSourceMap(),vertices_per_cell*space_dim));
432  RCP<mvec_type> ghstd_vertices_mv = rcp(new mvec_type(importer.getTargetMap(),vertices_per_cell*space_dim));
433 
434  {
435  auto owned_vertices_view = owned_vertices_mv->template getLocalView<dual_view_type>();
436  for(size_t i=0;i<owned_cell_cnt;i++) {
437  int l = 0;
438  for(int j=0;j<vertices_per_cell;j++)
439  for(int k=0;k<space_dim;k++,l++)
440  owned_vertices_view(i,l) = owned_vertices(i,j,k);
441  }
442  }
443 
444  // communicate ghstd vertices
445  ghstd_vertices_mv->doImport(*owned_vertices_mv,importer,Tpetra::INSERT);
446 
447  // copy multivector into ghstd vertex structure
448  Kokkos::DynRankView<double,PHX::Device> ghstd_vertices("ghstd_vertices",ghstd_cell_cnt,vertices_per_cell,space_dim);
449  {
450  auto ghstd_vertices_view = ghstd_vertices_mv->template getLocalView<dual_view_type>();
451  for(size_t i=0;i<ghstd_cell_cnt;i++) {
452  int l = 0;
453  for(int j=0;j<vertices_per_cell;j++)
454  for(int k=0;k<space_dim;k++,l++)
455  ghstd_vertices(i,j,k) = ghstd_vertices_view(i,l);
456  }
457  }
458 
459  return ghstd_vertices;
460 } // end build ghstd vertices
461 
462 template<typename LO, typename GO>
463 void
464 setupLocalMeshBlockInfo(const panzer_stk::STK_Interface & mesh,
466  const panzer::LocalMeshInfo<LO,GO> & mesh_info,
467  const std::string & element_block_name,
469 {
470 
471  // This function identifies all cells in mesh_info that belong to element_block_name
472  // and creates a block_info from it.
473 
474  const int num_parent_owned_cells = mesh_info.num_owned_cells;
475 
476  // Make sure connectivity is setup for interfaces between cells
477  {
478  const shards::CellTopology & topology = *(mesh.getCellTopology(element_block_name));
480  if(topology.getDimension() == 1){
481  cell_pattern = Teuchos::rcp(new panzer::EdgeFieldPattern(topology));
482  } else if(topology.getDimension() == 2){
483  cell_pattern = Teuchos::rcp(new panzer::FaceFieldPattern(topology));
484  } else if(topology.getDimension() == 3){
485  cell_pattern = Teuchos::rcp(new panzer::ElemFieldPattern(topology));
486  }
487 
488  {
489  PANZER_FUNC_TIME_MONITOR("Build connectivity");
490  conn.buildConnectivity(*cell_pattern);
491  }
492  }
493 
494  std::vector<LO> owned_block_cells;
495  for(int parent_owned_cell=0;parent_owned_cell<num_parent_owned_cells;++parent_owned_cell){
496  const LO local_cell = mesh_info.local_cells(parent_owned_cell);
497  const bool is_in_block = conn.getBlockId(local_cell) == element_block_name;
498 
499  if(is_in_block){
500  owned_block_cells.push_back(parent_owned_cell);
501  }
502 
503  }
504 
505  if ( owned_block_cells.size() == 0 )
506  return;
507  block_info.num_owned_cells = owned_block_cells.size();
508  block_info.element_block_name = element_block_name;
509  block_info.cell_topology = mesh.getCellTopology(element_block_name);
510  {
511  PANZER_FUNC_TIME_MONITOR("panzer::partitioning_utilities::setupSubLocalMeshInfo");
512  panzer::partitioning_utilities::setupSubLocalMeshInfo<LO,GO>(mesh_info, owned_block_cells, block_info);
513  }
514 }
515 
516 
517 template<typename LO, typename GO>
518 void
519 setupLocalMeshSidesetInfo(const panzer_stk::STK_Interface & mesh,
520  panzer::ConnManager<LO,GO>& /* conn */,
521  const panzer::LocalMeshInfo<LO,GO> & mesh_info,
522  const std::string & element_block_name,
523  const std::string & sideset_name,
525 {
526 
527  // This function identifies all cells in mesh_info that belong to element_block_name
528  // and creates a block_info from it.
529 
530  const size_t face_subcell_dimension = mesh.getCellTopology(element_block_name)->getDimension()-1;
531 
532  Kokkos::DynRankView<double,PHX::Device> data_allocation;
533 
534  // This is a list of all entities that make up the 'side'
535  std::vector<stk::mesh::Entity> side_entities;
536 
537  // Grab the side entities associated with this sideset on the mesh
538  // Note: Throws exception if element block or sideset doesn't exist
539  try{
540 
541  mesh.getMySides(sideset_name, element_block_name, side_entities);
542 
543  } catch(STK_Interface::SidesetException & e) {
544  std::stringstream ss;
545  std::vector<std::string> sideset_names;
546  mesh.getSidesetNames(sideset_names);
547 
548  // build an error message
549  ss << e.what() << "\nChoose existing sideset:\n";
550  for(const auto & optional_sideset_name : sideset_names){
551  ss << "\t\"" << optional_sideset_name << "\"\n";
552  }
553 
554  TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(true,std::logic_error,ss.str());
555 
556  } catch(STK_Interface::ElementBlockException & e) {
557  std::stringstream ss;
558  std::vector<std::string> element_block_names;
559  mesh.getElementBlockNames(element_block_names);
560 
561  // build an error message
562  ss << e.what() << "\nChoose existing element block:\n";
563  for(const auto & optional_element_block_name : element_block_names){
564  ss << "\t\"" << optional_element_block_name << "\"\n";
565  }
566 
567  TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(true,std::logic_error,ss.str());
568 
569  } catch(std::logic_error & e) {
570  std::stringstream ss;
571  ss << e.what() << "\nUnrecognized logic error.\n";
572 
573  TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(true,std::logic_error,ss.str());
574 
575  }
576 
577  // We now have a list of sideset entities, lets unwrap them and create the sideset_info!
578 
579  // (subcell_dimension, subcell_index) -> list of cells
580  std::map<std::pair<size_t,size_t>, std::vector<size_t> > local_cell_indexes_by_subcell;
581 
582  // List of local subcell indexes indexed by element:
583  // For example: a Tet (element) would have
584  // - 4 triangular faces (subcell_index 0-3, subcell_dimension=2)
585  // - 6 edges (subcell_index 0-5, subcell_dimension=1)
586  // - 4 vertices (subcell_index 0-3, subcell_dimension=0)
587  // Another example: a Line (element) would have
588  // - 2 vertices (subcell_index 0-1, subcell_dimension=0)
589  std::vector<stk::mesh::Entity> elements;
590  std::vector<size_t> subcell_indexes;
591  std::vector<size_t> subcell_dimensions;
592  panzer_stk::workset_utils::getSideElementCascade(mesh, element_block_name, side_entities, subcell_dimensions, subcell_indexes, elements);
593  const LO num_elements = subcell_dimensions.size();
594 
595  // build local cell_ids, mapped by local side id
596  for(LO element_index=0; element_index<num_elements; ++element_index) {
597  const size_t subcell_dimension = subcell_dimensions[element_index];
598  const size_t subcell_index = subcell_indexes[element_index];
599  const size_t element_local_index = mesh.elementLocalId(elements[element_index]);
600 
601  // Add subcell to map
602  local_cell_indexes_by_subcell[std::pair<size_t,size_t>(subcell_dimension, subcell_index)].push_back(element_local_index);
603  }
604 
605  // We now have a list of all local cells 'touching' the side set, as well as the faces, edges, and vertices that define the 'touch'
606 
607  // For our purposes we only really want the cells and faces associated with the side
608 
609  // Each cell can have multiple faces on the sideset
610  std::unordered_set<LO> owned_parent_cells_set;
611  std::map<LO,std::vector<LO> > owned_parent_cell_index_map;
612  {
613  // We use a set to avoid duplicates
614  for(const auto & cell_subcell_pair : local_cell_indexes_by_subcell){
615  const std::pair<size_t,size_t> & subcell_definition = cell_subcell_pair.first;
616  const LO subcell_index = LO(subcell_definition.second);
617  if(subcell_definition.first == face_subcell_dimension){
618  const std::vector<size_t> & local_cell_indexes_for_subcell = cell_subcell_pair.second;
619  for(const size_t & local_cell_index : local_cell_indexes_for_subcell){
620 
621  // TODO: Super slow - fix this!!
622  for(LO i=0;i<LO(mesh_info.local_cells.extent(0)); ++i){
623  if(mesh_info.local_cells(i) == LO(local_cell_index)){
624  owned_parent_cell_index_map[i].push_back(subcell_index);
625  }
626  }
627  }
628  }
629  }
630 
631  for(const auto & pair : owned_parent_cell_index_map){
632  owned_parent_cells_set.insert(pair.first);
633  }
634 
635  }
636 
637  const LO num_owned_cells = owned_parent_cell_index_map.size();
638 
639  sideset_info.element_block_name = element_block_name;
640  sideset_info.sideset_name = sideset_name;
641  sideset_info.cell_topology = mesh.getCellTopology(element_block_name);
642 
643  sideset_info.num_owned_cells = num_owned_cells;
644 
645  struct face_t{
646  face_t(LO c0, LO c1, LO sc0, LO sc1)
647  {
648  cell_0=c0;
649  cell_1=c1;
650  subcell_index_0=sc0;
651  subcell_index_1=sc1;
652  }
653  LO cell_0;
654  LO cell_1;
655  LO subcell_index_0;
656  LO subcell_index_1;
657  };
658 
659 
660  // Figure out how many cells on the other side of the sideset are ghost or virtual
661  std::unordered_set<LO> ghstd_parent_cells_set, virtual_parent_cells_set;
662  std::vector<face_t> faces;
663  {
664  LO parent_virtual_cell_offset = mesh_info.num_owned_cells + mesh_info.num_ghstd_cells;
665  for(const auto & local_cell_index_pair : owned_parent_cell_index_map){
666  const LO local_cell = local_cell_index_pair.first;
667  const std::vector<LO> & subcell_indexes_vec = local_cell_index_pair.second;
668 
669  for(const LO & subcell_index : subcell_indexes_vec){
670 
671  const LO face = mesh_info.cell_to_faces(local_cell, subcell_index);
672  const LO face_other_side = (mesh_info.face_to_cells(face,0) == local_cell) ? 1 : 0;
673 
674  TEUCHOS_ASSERT(subcell_index == mesh_info.face_to_lidx(face, 1-face_other_side));
675 
676  const LO other_side_cell = mesh_info.face_to_cells(face, face_other_side);
677  const LO other_side_subcell_index = mesh_info.face_to_lidx(face, face_other_side);
678 
679  faces.push_back(face_t(local_cell, other_side_cell, subcell_index, other_side_subcell_index));
680 
681  if(other_side_cell >= parent_virtual_cell_offset){
682  virtual_parent_cells_set.insert(other_side_cell);
683  } else {
684  ghstd_parent_cells_set.insert(other_side_cell);
685  }
686  }
687  }
688  }
689 
690  std::vector<LO> all_cells;
691  all_cells.insert(all_cells.end(),owned_parent_cells_set.begin(),owned_parent_cells_set.end());
692  all_cells.insert(all_cells.end(),ghstd_parent_cells_set.begin(),ghstd_parent_cells_set.end());
693  all_cells.insert(all_cells.end(),virtual_parent_cells_set.begin(),virtual_parent_cells_set.end());
694 
695  sideset_info.num_ghstd_cells = ghstd_parent_cells_set.size();
696  sideset_info.num_virtual_cells = virtual_parent_cells_set.size();
697 
698  const LO num_real_cells = sideset_info.num_owned_cells + sideset_info.num_ghstd_cells;
699  const LO num_total_cells = num_real_cells + sideset_info.num_virtual_cells;
700  const LO num_vertices_per_cell = mesh_info.cell_vertices.extent(1);
701  const LO num_dims = mesh_info.cell_vertices.extent(2);
702 
703  sideset_info.global_cells = Kokkos::View<GO*>("global_cells", num_total_cells);
704  sideset_info.local_cells = Kokkos::View<LO*>("local_cells", num_total_cells);
705  sideset_info.cell_vertices = Kokkos::View<double***,PHX::Device>("cell_vertices", num_total_cells, num_vertices_per_cell, num_dims);
706  Kokkos::deep_copy(sideset_info.cell_vertices,0.);
707 
708  for(LO i=0; i<num_total_cells; ++i){
709  const LO parent_cell = all_cells[i];
710  sideset_info.local_cells(i) = mesh_info.local_cells(parent_cell);
711  sideset_info.global_cells(i) = mesh_info.global_cells(parent_cell);
712  for(LO j=0; j<num_vertices_per_cell; ++j){
713  for(LO k=0; k<num_dims; ++k){
714  sideset_info.cell_vertices(i,j,k) = mesh_info.cell_vertices(parent_cell,j,k);
715  }
716  }
717  }
718 
719  // Now we have to set the connectivity for the faces.
720 
721  const LO num_faces = faces.size();
722  const LO num_faces_per_cell = mesh_info.cell_to_faces.extent(1);
723 
724  sideset_info.face_to_cells = Kokkos::View<LO*[2]>("face_to_cells", num_faces);
725  sideset_info.face_to_lidx = Kokkos::View<LO*[2]>("face_to_lidx", num_faces);
726  sideset_info.cell_to_faces = Kokkos::View<LO**>("cell_to_faces", num_total_cells, num_faces_per_cell);
727 
728  // Default the system with invalid cell index - this will be most of the entries
729  Kokkos::deep_copy(sideset_info.cell_to_faces, -1);
730 
731  for(int face_index=0;face_index<num_faces;++face_index){
732  const face_t & face = faces[face_index];
733  const LO & cell_0 = face.cell_0;
734  const LO & cell_1 = face.cell_1;
735 
736  // TODO: Super expensive... need to find a better way
737  const LO sideset_cell_0 = std::distance(all_cells.begin(), std::find(all_cells.begin(), all_cells.end(), cell_0));
738  const LO sideset_cell_1 = std::distance(all_cells.begin(), std::find(all_cells.begin()+num_owned_cells, all_cells.end(), cell_1));
739 
740  sideset_info.face_to_cells(face_index,0) = sideset_cell_0;
741  sideset_info.face_to_cells(face_index,1) = sideset_cell_1;
742 
743  sideset_info.face_to_lidx(face_index,0) = face.subcell_index_0;
744  sideset_info.face_to_lidx(face_index,1) = face.subcell_index_1;
745 
746  sideset_info.cell_to_faces(sideset_cell_0,face.subcell_index_0) = face_index;
747  sideset_info.cell_to_faces(sideset_cell_1,face.subcell_index_1) = face_index;
748 
749  }
750 
751 }
752 
753 }
754 
755 template <typename LO, typename GO>
756 void
758  panzer::LocalMeshInfo<LO,GO> & mesh_info)
759 {
760  using Teuchos::RCP;
761  using Teuchos::rcp;
762 
763  //typedef Tpetra::CrsMatrix<int,LO,GO> crs_type;
764  typedef Tpetra::Map<LO,GO,panzer::TpetraNodeType> map_type;
765  typedef Tpetra::Import<LO,GO,panzer::TpetraNodeType> import_type;
766  //typedef Tpetra::MultiVector<double,LO,GO> mvec_type;
767  //typedef Tpetra::MultiVector<GO,LO,GO> ordmvec_type;
768 
769  // Make sure the STK interface is valid
771 
772  // This is required by some of the STK stuff
773  TEUCHOS_ASSERT(typeid(LO) == typeid(int));
774 
776 
777  TEUCHOS_FUNC_TIME_MONITOR_DIFF("panzer_stk::generateLocalMeshInfo",GenerateLocalMeshInfo);
778 
779  // This horrible line of code is required since the connection manager only takes rcps of a mesh
780  RCP<const panzer_stk::STK_Interface> mesh_rcp = Teuchos::rcpFromRef(mesh);
781  // We're allowed to do this since the connection manager only exists in this scope... even though it is also an RCP...
782 
783  // extract topology handle
785  panzer::ConnManager<LO,GO> & conn = *conn_rcp;
786 
787  // build cell to node map
788  Kokkos::View<GO**> owned_cell_to_nodes;
789  buildCellToNodes(conn, owned_cell_to_nodes);
790 
791  // build the local to global cell ID map
793  Kokkos::View<GO*> owned_cells;
794  buildCellGlobalIDs(conn, owned_cells);
795 
796  // get neighboring cells
798  Kokkos::View<const GO*> ghstd_cells = buildGhostedCellOneRing<GO>(comm,owned_cells,owned_cell_to_nodes);
799 
800  // build cell maps
802 
803  RCP<map_type> owned_cell_map = rcp(new map_type(-1,owned_cells, 0,comm));
804  RCP<map_type> ghstd_cell_map = rcp(new map_type(-1,ghstd_cells,0,comm));
805 
806  // build importer: cell importer, owned to ghstd
807  RCP<import_type> cellimport_own2ghst = rcp(new import_type(owned_cell_map,ghstd_cell_map));
808 
809  // read all the vertices associated with these elements, get ghstd contributions
811  std::vector<std::size_t> localCells(owned_cells.extent(0),-1);
812  for(size_t i=0;i<localCells.size();i++){
813  localCells[i] = i;
814  }
815 
816  // TODO: This all needs to be rewritten for when element blocks have different cell topologies
817  std::vector<std::string> element_block_names;
818  mesh.getElementBlockNames(element_block_names);
819 
820  const shards::CellTopology & cell_topology = *(mesh.getCellTopology(element_block_names[0]));
821 
822  const int space_dim = cell_topology.getDimension();
823  const int vertices_per_cell = cell_topology.getVertexCount();
824  const int faces_per_cell = cell_topology.getSubcellCount(space_dim-1);
825 
826  // Kokkos::View<double***> owned_vertices("owned_vertices",localCells.size(),vertices_per_cell,space_dim);
827  Kokkos::DynRankView<double,PHX::Device> owned_vertices("owned_vertices",localCells.size(),vertices_per_cell,space_dim);
828  mesh.getElementVerticesNoResize(localCells,owned_vertices);
829 
830  // this builds a ghstd vertex array
831  Kokkos::DynRankView<double,PHX::Device> ghstd_vertices = buildGhostedVertices(*cellimport_own2ghst,owned_vertices);
832 
833  // build edge to cell neighbor mapping
835 
836  std::unordered_map<GO,int> global_to_local;
837  global_to_local[-1] = -1; // this is the "no neighbor" flag
838  for(size_t i=0;i<owned_cells.extent(0);i++)
839  global_to_local[owned_cells(i)] = i;
840  for(size_t i=0;i<ghstd_cells.extent(0);i++)
841  global_to_local[ghstd_cells(i)] = i+Teuchos::as<int>(owned_cells.extent(0));
842 
843  // this class comes from Mini-PIC and Matt B
845  faceToElement->initialize(conn);
846  auto elems_by_face = faceToElement->getFaceToElementsMap();
847  auto face_to_lidx = faceToElement->getFaceToCellLocalIdxMap();
848 
849  const int num_owned_cells =owned_cells.extent(0);
850  const int num_ghstd_cells =ghstd_cells.extent(0);
851 
852 // print_view("elems_by_face",elems_by_face);
853 
854  // We also need to consider faces that connect to cells that do not exist, but are needed for boundary conditions
855  // We dub them virtual cell since there should be no geometry associated with them, or topology really
856  // They exist only for datastorage so that they are consistent with 'real' cells from an algorithm perspective
857 
858  // Each virtual face (face linked to a '-1' cell) requires a virtual cell (i.e. turn the '-1' into a virtual cell)
859  // Virtual cells are those that do not exist but are connected to an owned cell
860  // Note - in the future, ghosted cells will also need to connect to virtual cells at boundary conditions, but for the moment we will ignore this.
861 
862  // Iterate over all faces and identify the faces connected to a potential virtual cell
863  std::vector<int> all_boundary_faces;
864  const int num_faces = elems_by_face.extent(0);
865  for(int face=0;face<num_faces;++face){
866  if(elems_by_face(face,0) < 0 or elems_by_face(face,1) < 0){
867  all_boundary_faces.push_back(face);
868  }
869  }
870  const LO num_virtual_cells = all_boundary_faces.size();
871 
872  // total cells and faces include owned, ghosted, and virtual
873  const LO num_real_cells = num_owned_cells + num_ghstd_cells;
874  const LO num_total_cells = num_real_cells + num_virtual_cells;
875  const LO num_total_faces = elems_by_face.extent(0);
876 
877  // Create some global indexes associated with the virtual cells
878  // Note: We are assuming that virtual cells belong to ranks and are not 'shared' - this will change later on
879  Kokkos::View<GO*> virtual_cells = Kokkos::View<GO*>("virtual_cells",num_virtual_cells);
880  {
881  PANZER_FUNC_TIME_MONITOR_DIFF("Initial global index creation",InitialGlobalIndexCreation);
882 
883  const int num_ranks = comm->getSize();
884  const int rank = comm->getRank();
885 
886  std::vector<GO> owned_cell_distribution(num_ranks,0);
887  {
888  std::vector<GO> my_owned_cell_distribution(num_ranks,0);
889  my_owned_cell_distribution[rank] = num_owned_cells;
890 
891  Teuchos::reduceAll(*comm,Teuchos::REDUCE_SUM, num_ranks, my_owned_cell_distribution.data(),owned_cell_distribution.data());
892  }
893 
894  std::vector<GO> virtual_cell_distribution(num_ranks,0);
895  {
896  std::vector<GO> my_virtual_cell_distribution(num_ranks,0);
897  my_virtual_cell_distribution[rank] = num_virtual_cells;
898 
899  Teuchos::reduceAll(*comm,Teuchos::REDUCE_SUM, num_ranks, my_virtual_cell_distribution.data(),virtual_cell_distribution.data());
900  }
901 
902  GO num_global_real_cells=0;
903  for(int i=0;i<num_ranks;++i){
904  num_global_real_cells+=owned_cell_distribution[i];
905  }
906 
907  GO global_virtual_start_idx = num_global_real_cells;
908  for(int i=0;i<rank;++i){
909  global_virtual_start_idx += virtual_cell_distribution[i];
910  }
911 
912  for(int i=0;i<num_virtual_cells;++i){
913  virtual_cells(i) = global_virtual_start_idx + GO(i);
914  }
915 
916  }
917 
918  // Lookup cells connected to a face
919  Kokkos::View<LO*[2]> face_to_cells = Kokkos::View<LO*[2]>("face_to_cells",num_total_faces);
920 
921  // Lookup local face indexes given cell and left/right state (0/1)
922  Kokkos::View<LO*[2]> face_to_localidx = Kokkos::View<LO*[2]>("face_to_localidx",num_total_faces);
923 
924  // Lookup face index given a cell and local face index
925  Kokkos::View<LO**> cell_to_face = Kokkos::View<LO**>("cell_to_face",num_total_cells,faces_per_cell);
926 
927  // initialize with negative one cells that are not associated with a face
928  Kokkos::deep_copy(cell_to_face,-1);
929 
930  // Transfer information from 'faceToElement' datasets to local arrays
931  {
932  PANZER_FUNC_TIME_MONITOR_DIFF("Transer faceToElement to local",TransferFaceToElementLocal);
933 
934  int virtual_cell_index = num_real_cells;
935  for(size_t f=0;f<elems_by_face.extent(0);f++) {
936 
937  const GO global_c0 = elems_by_face(f,0);
938  const GO global_c1 = elems_by_face(f,1);
939 
940  // make sure that no bonus cells get in here
941  TEUCHOS_ASSERT(global_to_local.find(global_c0)!=global_to_local.end());
942  TEUCHOS_ASSERT(global_to_local.find(global_c1)!=global_to_local.end());
943 
944  auto c0 = global_to_local[global_c0];
945  auto lidx0 = face_to_lidx(f,0);
946  auto c1 = global_to_local[global_c1];
947  auto lidx1 = face_to_lidx(f,1);
948 
949  // Test for virtual cells
950 
951  // Left cell
952  if(c0 < 0){
953  // Virtual cell - create it!
954  c0 = virtual_cell_index++;
955 
956  // We need the subcell_index to line up between real and virtual cell
957  // This way the face has the same geometry... though the face normal
958  // will point in the wrong direction
959  lidx0 = lidx1;
960  }
961  cell_to_face(c0,lidx0) = f;
962 
963 
964  // Right cell
965  if(c1 < 0){
966  // Virtual cell - create it!
967  c1 = virtual_cell_index++;
968 
969  // We need the subcell_index to line up between real and virtual cell
970  // This way the face has the same geometry... though the face normal
971  // will point in the wrong direction
972  lidx1 = lidx0;
973  }
974  cell_to_face(c1,lidx1) = f;
975 
976  // Faces point from low cell index to high cell index
977  if(c0<c1){
978  face_to_cells(f,0) = c0;
979  face_to_localidx(f,0) = lidx0;
980  face_to_cells(f,1) = c1;
981  face_to_localidx(f,1) = lidx1;
982  } else {
983  face_to_cells(f,0) = c1;
984  face_to_localidx(f,0) = lidx1;
985  face_to_cells(f,1) = c0;
986  face_to_localidx(f,1) = lidx0;
987  }
988 
989  // We should avoid having two virtual cells linked together.
990  TEUCHOS_ASSERT(c0<num_real_cells or c1<num_real_cells)
991 
992  }
993  }
994 
995  // at this point all the data structures have been built, so now we can "do" DG.
996  // There are two of everything, an "owned" data structured corresponding to "owned"
997  // cells. And a "ghstd" data structure corresponding to ghosted cells
999  {
1000  PANZER_FUNC_TIME_MONITOR_DIFF("Assign Indices",AssignIndices);
1001  mesh_info.cell_to_faces = cell_to_face;
1002  mesh_info.face_to_cells = face_to_cells; // faces
1003  mesh_info.face_to_lidx = face_to_localidx;
1004 
1005  mesh_info.num_owned_cells = owned_cells.extent(0);
1006  mesh_info.num_ghstd_cells = ghstd_cells.extent(0);
1007  mesh_info.num_virtual_cells = virtual_cells.extent(0);
1008 
1009  mesh_info.global_cells = Kokkos::View<GO*>("global_cell_indices",num_total_cells);
1010  mesh_info.local_cells = Kokkos::View<LO*>("local_cell_indices",num_total_cells);
1011 
1012  for(int i=0;i<num_owned_cells;++i){
1013  mesh_info.global_cells(i) = owned_cells(i);
1014  mesh_info.local_cells(i) = i;
1015  }
1016 
1017  for(int i=0;i<num_ghstd_cells;++i){
1018  mesh_info.global_cells(i+num_owned_cells) = ghstd_cells(i);
1019  mesh_info.local_cells(i+num_owned_cells) = i+num_owned_cells;
1020  }
1021 
1022  for(int i=0;i<num_virtual_cells;++i){
1023  mesh_info.global_cells(i+num_real_cells) = virtual_cells(i);
1024  mesh_info.local_cells(i+num_real_cells) = i+num_real_cells;
1025  }
1026 
1027  mesh_info.cell_vertices = Kokkos::View<double***, PHX::Device>("cell_vertices",num_total_cells,vertices_per_cell,space_dim);
1028 
1029  // Initialize coordinates to zero
1030  Kokkos::deep_copy(mesh_info.cell_vertices, 0.);
1031 
1032  for(int i=0;i<num_owned_cells;++i){
1033  for(int j=0;j<vertices_per_cell;++j){
1034  for(int k=0;k<space_dim;++k){
1035  mesh_info.cell_vertices(i,j,k) = owned_vertices(i,j,k);
1036  }
1037  }
1038  }
1039 
1040  for(int i=0;i<num_ghstd_cells;++i){
1041  for(int j=0;j<vertices_per_cell;++j){
1042  for(int k=0;k<space_dim;++k){
1043  mesh_info.cell_vertices(i+num_owned_cells,j,k) = ghstd_vertices(i,j,k);
1044  }
1045  }
1046  }
1047 
1048  // This will backfire at some point, but we're going to make the virtual cell have the same geometry as the cell it interfaces with
1049  // This way we can define a virtual cell geometry without extruding the face outside of the domain
1050  {
1051  PANZER_FUNC_TIME_MONITOR_DIFF("Assign geometry traits",AssignGeometryTraits);
1052  for(int i=0;i<num_virtual_cells;++i){
1053 
1054  const LO virtual_cell = i+num_real_cells;
1055  bool exists = false;
1056  for(int local_face=0; local_face<faces_per_cell; ++local_face){
1057  const LO face = cell_to_face(virtual_cell, local_face);
1058  if(face >= 0){
1059  exists = true;
1060  const LO other_side = (face_to_cells(face, 0) == virtual_cell) ? 1 : 0;
1061  const LO real_cell = face_to_cells(face,other_side);
1062  TEUCHOS_ASSERT(real_cell < num_real_cells);
1063  for(int j=0;j<vertices_per_cell;++j){
1064  for(int k=0;k<space_dim;++k){
1065  mesh_info.cell_vertices(virtual_cell,j,k) = mesh_info.cell_vertices(real_cell,j,k);
1066  }
1067  }
1068  break;
1069  }
1070  }
1071  TEUCHOS_TEST_FOR_EXCEPT_MSG(!exists, "panzer_stk::generateLocalMeshInfo : Virtual cell is not linked to real cell");
1072  }
1073  }
1074  }
1075 
1076  // Setup element blocks and sidesets
1077  std::vector<std::string> sideset_names;
1078  mesh.getSidesetNames(sideset_names);
1079 
1080  for(const std::string & element_block_name : element_block_names){
1081  PANZER_FUNC_TIME_MONITOR_DIFF("Set up setupLocalMeshBlockInfo",SetupLocalMeshBlockInfo);
1082  panzer::LocalMeshBlockInfo<LO,GO> & block_info = mesh_info.element_blocks[element_block_name];
1083  setupLocalMeshBlockInfo(mesh, conn, mesh_info, element_block_name, block_info);
1084 
1085  // Setup sidesets
1086  for(const std::string & sideset_name : sideset_names){
1087  PANZER_FUNC_TIME_MONITOR_DIFF("Setup LocalMeshSidesetInfo",SetupLocalMeshSidesetInfo);
1088  panzer::LocalMeshSidesetInfo<LO,GO> & sideset_info = mesh_info.sidesets[element_block_name][sideset_name];
1089  setupLocalMeshSidesetInfo(mesh, conn, mesh_info, element_block_name, sideset_name, sideset_info);
1090  }
1091 
1092  }
1093 
1094 }
1095 
1096 }
1097 
1098 // Explicit instantiation
1099 template
1100 void
1101 panzer_stk::generateLocalMeshInfo<int,int>(const panzer_stk::STK_Interface & mesh,
1102  panzer::LocalMeshInfo<int,int> & mesh_info);
1103 
1104 #ifndef PANZER_ORDINAL64_IS_INT
1105 template
1106 void
1107 panzer_stk::generateLocalMeshInfo<int,panzer::Ordinal64>(const panzer_stk::STK_Interface & mesh,
1109 #endif
Teuchos::RCP< const shards::CellTopology > cell_topology
void getSidesetNames(std::vector< std::string > &name) const
void getElementVerticesNoResize(const std::vector< std::size_t > &localIds, ArrayT &vertices) const
void getElementBlockNames(std::vector< std::string > &names) const
virtual void getElementBlockIds(std::vector< std::string > &elementBlockIds) const =0
virtual std::string getBlockId(LocalOrdinal localElmtId) const =0
std::map< std::string, LocalMeshBlockInfo< LO, GO > > element_blocks
Kokkos::View< GO * > global_cells
Teuchos::RCP< const shards::CellTopology > cell_topology
virtual void getElementBlockTopologies(std::vector< shards::CellTopology > &elementBlockTopologies) const =0
void getMySides(const std::string &sideName, std::vector< stk::mesh::Entity > &sides) const
std::map< std::string, std::map< std::string, LocalMeshSidesetInfo< LO, GO > > > sidesets
Kokkos::View< LO * > local_cells
std::size_t elementLocalId(stk::mesh::Entity elmt) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
virtual LocalOrdinal getConnectivitySize(LocalOrdinal localElmtId) const =0
#define TEUCHOS_TEST_FOR_EXCEPT_MSG(throw_exception_test, msg)
virtual const GlobalOrdinal * getConnectivity(LocalOrdinal localElmtId) const =0
TEUCHOS_DEPRECATED void reduceAll(const Comm< Ordinal > &comm, const EReductionType reductType, const Packet &send, Packet *globalReduct)
Kokkos::View< LO *[2]> face_to_cells
virtual const std::vector< LocalOrdinal > & getElementBlock(const std::string &blockID) const =0
Kokkos::View< double ***, PHX::Device > cell_vertices
bool isInitialized() const
Has initialize been called on this mesh object?
Kokkos::View< LO ** > cell_to_faces
Kokkos::View< LO *[2]> face_to_lidx
virtual void buildConnectivity(const FieldPattern &fp)=0
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
get the comm associated with this mesh
void generateLocalMeshInfo(const panzer_stk::STK_Interface &mesh, panzer::LocalMeshInfo< LO, GO > &mesh_info)
#define TEUCHOS_ASSERT(assertion_test)
void getSideElementCascade(const panzer_stk::STK_Interface &mesh, const std::string &blockId, const std::vector< stk::mesh::Entity > &sides, std::vector< std::size_t > &localSubcellDim, std::vector< std::size_t > &localSubcellIds, std::vector< stk::mesh::Entity > &elements)
Teuchos::RCP< const shards::CellTopology > getCellTopology(const std::string &eBlock) const
#define TEUCHOS_FUNC_TIME_MONITOR_DIFF(FUNCNAME, DIFF)
#define TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(throw_exception_test, Exception, msg)