46 #include "Teuchos_Comm.hpp" 
   47 #include "Teuchos_Assert.hpp" 
   49 #include "Panzer_Workset_Builder.hpp" 
   52 #include "Phalanx_KokkosDeviceTypes.hpp" 
   54 #include <unordered_set> 
   55 #include <unordered_map> 
   60 namespace partitioning_utilities
 
   65                       const std::vector<panzer::LocalOrdinal> & owned_parent_cells,
 
   68   using GO = panzer::GlobalOrdinal;
 
   69   using LO = panzer::LocalOrdinal;
 
   71   PANZER_FUNC_TIME_MONITOR_DIFF(
"panzer::partitioning_utilities::setupSubLocalMeshInfo",setupSLMI);
 
   85   const int num_owned_cells = owned_parent_cells.size();
 
   86   TEUCHOS_TEST_FOR_EXCEPT_MSG(num_owned_cells == 0, 
"panzer::partitioning_utilities::setupSubLocalMeshInfo : Input parent subcells must exist (owned_parent_cells)");
 
   89   TEUCHOS_TEST_FOR_EXCEPT_MSG(num_parent_owned_cells <= 0, 
"panzer::partitioning_utilities::setupSubLocalMeshInfo : Input parent info must contain owned cells");
 
   97   const int num_faces_per_cell = parent_info.
cell_to_faces.extent(1);
 
  101   std::vector<LO> ghstd_parent_cells;
 
  102   std::vector<LO> virtual_parent_cells;
 
  104     PANZER_FUNC_TIME_MONITOR_DIFF(
"Construct parent cell vector",ParentCell);
 
  107     std::unordered_set<LO> owned_parent_cells_set(owned_parent_cells.begin(), owned_parent_cells.end());
 
  114     const int virtual_parent_cell_offset = num_parent_owned_cells + num_parent_ghstd_cells;
 
  116     std::unordered_set<LO> ghstd_parent_cells_set;
 
  117     std::unordered_set<LO> virtual_parent_cells_set;
 
  118     for(
int i=0;i<num_owned_cells;++i){
 
  119       const LO parent_cell_index = owned_parent_cells[i];
 
  120       for(
int local_face_index=0;local_face_index<num_faces_per_cell;++local_face_index){
 
  121         const LO parent_face = parent_info.
cell_to_faces(parent_cell_index, local_face_index);
 
  129         const LO neighbor_parent_side = (parent_info.
face_to_cells(parent_face,0) == parent_cell_index) ? 1 : 0;
 
  132         const LO neighbor_parent_cell = parent_info.
face_to_cells(parent_face, neighbor_parent_side);
 
  138         if(neighbor_parent_cell >= virtual_parent_cell_offset){
 
  139           virtual_parent_cells_set.insert(neighbor_parent_cell);
 
  140         } 
else if(neighbor_parent_cell >= num_parent_owned_cells){
 
  143           ghstd_parent_cells_set.insert(neighbor_parent_cell);
 
  147           if(owned_parent_cells_set.find(neighbor_parent_cell) == owned_parent_cells_set.end()){
 
  149             ghstd_parent_cells_set.insert(neighbor_parent_cell);
 
  158     ghstd_parent_cells.assign(ghstd_parent_cells_set.begin(), ghstd_parent_cells_set.end());
 
  159     virtual_parent_cells.assign(virtual_parent_cells_set.begin(), virtual_parent_cells_set.end());
 
  163   const int num_ghstd_cells = ghstd_parent_cells.size();
 
  164   const int num_virtual_cells = virtual_parent_cells.size();
 
  165   const int num_real_cells = num_owned_cells + num_ghstd_cells;
 
  166   const int num_total_cells = num_real_cells + num_virtual_cells;
 
  168   std::vector<std::pair<LO, LO> > all_parent_cells(num_total_cells);
 
  169   for (std::size_t i=0; i< owned_parent_cells.size(); ++i)
 
  170     all_parent_cells[i] = std::pair<LO, LO>(owned_parent_cells[i], i);
 
  172   for (std::size_t i=0; i< ghstd_parent_cells.size(); ++i) {
 
  173     LO insert = owned_parent_cells.size()+i;
 
  174     all_parent_cells[insert] = std::pair<LO, LO>(ghstd_parent_cells[i], insert);
 
  177   for (std::size_t i=0; i< virtual_parent_cells.size(); ++i) {
 
  178     LO insert = owned_parent_cells.size()+ ghstd_parent_cells.size()+i;
 
  179     all_parent_cells[insert] = std::pair<LO, LO>(virtual_parent_cells[i], insert);
 
  193   const int num_vertices_per_cell = parent_info.
cell_vertices.extent(1);
 
  197   sub_info.
global_cells = Kokkos::View<GO*>(
"global_cells", num_total_cells);
 
  198   sub_info.
local_cells = Kokkos::View<LO*>(
"local_cells", num_total_cells);
 
  199   sub_info.
cell_vertices = Kokkos::View<double***, PHX::Device>(
"cell_vertices", num_total_cells, num_vertices_per_cell, num_dims);
 
  200   for(
int cell=0;cell<num_total_cells;++cell){
 
  201     const LO parent_cell = all_parent_cells[cell].first;
 
  204     for(
int vertex=0;vertex<num_vertices_per_cell;++vertex){
 
  205       for(
int dim=0;dim<num_dims;++dim){
 
  218     face_t(LO c0, LO c1, LO sc0, LO sc1)
 
  233   std::vector<face_t> faces;
 
  235     PANZER_FUNC_TIME_MONITOR_DIFF(
"Create faces",CreateFaces);
 
  237     std::unordered_map<LO,std::unordered_map<LO, std::pair<LO,LO> > > faces_set;
 
  239     std::sort(all_parent_cells.begin(), all_parent_cells.end());
 
  241     for(
int owned_cell=0;owned_cell<num_owned_cells;++owned_cell){
 
  242       const LO owned_parent_cell = owned_parent_cells[owned_cell];
 
  243       for(
int local_face=0;local_face<num_faces_per_cell;++local_face){
 
  244         const LO parent_face = parent_info.
cell_to_faces(owned_parent_cell,local_face);
 
  251         const LO neighbor_side = (parent_info.
face_to_cells(parent_face,0) == owned_parent_cell) ? 1 : 0;
 
  253         const LO neighbor_parent_cell = parent_info.
face_to_cells(parent_face, neighbor_side);
 
  254         const LO neighbor_subcell_index = parent_info.
face_to_lidx(parent_face, neighbor_side);
 
  257         std::pair<LO, LO> search_point(neighbor_parent_cell, 0);
 
  258         auto itr = std::lower_bound(all_parent_cells.begin(), all_parent_cells.end(), search_point);
 
  260         TEUCHOS_TEST_FOR_EXCEPT_MSG(itr == all_parent_cells.end(), 
"panzer_stk::setupSubLocalMeshInfo : Neighbor cell was not found in owned, ghosted, or virtual cells");
 
  262         const LO neighbor_cell = itr->second;
 
  264         LO cell_0, cell_1, subcell_index_0, subcell_index_1;
 
  265         if(owned_cell < neighbor_cell){
 
  267           subcell_index_0 = local_face;
 
  268           cell_1 = neighbor_cell;
 
  269           subcell_index_1 = neighbor_subcell_index;
 
  272           subcell_index_1 = local_face;
 
  273           cell_0 = neighbor_cell;
 
  274           subcell_index_0 = neighbor_subcell_index;
 
  278         faces_set[cell_0][subcell_index_0] = std::pair<LO,LO>(cell_1, subcell_index_1);
 
  282     for(
const auto & cell_pair : faces_set){
 
  283       const LO cell_0 = cell_pair.first;
 
  284       for(
const auto & subcell_pair : cell_pair.second){
 
  285         const LO subcell_index_0 = subcell_pair.first;
 
  286         const LO cell_1 = subcell_pair.second.first;
 
  287         const LO subcell_index_1 = subcell_pair.second.second;
 
  288         faces.push_back(face_t(cell_0,cell_1,subcell_index_0,subcell_index_1));
 
  293   const int num_faces = faces.size();
 
  295   sub_info.
face_to_cells = Kokkos::View<LO*[2]>(
"face_to_cells", num_faces);
 
  296   sub_info.
face_to_lidx = Kokkos::View<LO*[2]>(
"face_to_lidx", num_faces);
 
  297   sub_info.
cell_to_faces = Kokkos::View<LO**>(
"cell_to_faces", num_total_cells, num_faces_per_cell);
 
  302   for(
int face_index=0;face_index<num_faces;++face_index){
 
  303     const face_t & face = faces[face_index];
 
  308     sub_info.
cell_to_faces(face.cell_0,face.subcell_index_0) = face_index;
 
  309     sub_info.
cell_to_faces(face.cell_1,face.subcell_index_1) = face_index;
 
  311     sub_info.
face_to_lidx(face_index,0) = face.subcell_index_0;
 
  312     sub_info.
face_to_lidx(face_index,1) = face.subcell_index_1;
 
  322               const int splitting_size,
 
  323               std::vector<panzer::LocalMeshPartition> & partitions)
 
  326   using LO = panzer::LocalOrdinal;
 
  335   std::vector<LO> partition_cells;
 
  336   partition_cells.resize(base_partition_size);
 
  342     LO partition_size = base_partition_size;
 
  350     if(partition_size != base_partition_size)
 
  351       partition_cells.resize(partition_size);
 
  354     for(LO i=0; i<partition_size; ++i)
 
  355       partition_cells[i] = cell_count+i;
 
  364     cell_count += partition_size;
 
  374                             std::vector<panzer::LocalMeshPartition> & partitions)
 
  383   const std::string & element_block_name = description.
getElementBlock();
 
  391     const auto & sideset_map = mesh_info.
sidesets.at(element_block_name);
 
  393     const std::string & sideset_name = description.
getSideset();
 
  396     if(sideset_map.find(sideset_name) == sideset_map.end())
 
  404     for(
auto & partition : partitions){
 
  405       partition.sideset_name = sideset_name;
 
  406       partition.element_block_name = element_block_name;
 
  430     for(
auto & partition : partitions){
 
  431       partition.element_block_name = element_block_name;
 
Backwards compatibility mode that ignores the worksetSize in the WorksetDescriptor. 
 
std::map< std::string, std::map< std::string, LocalMeshSidesetInfo > > sidesets
 
Kokkos::View< double ***, PHX::Device > cell_vertices
 
const std::string & getSideset(const int block=0) const 
Get sideset name. 
 
Kokkos::View< panzer::LocalOrdinal * > local_cells
 
Teuchos::RCP< const shards::CellTopology > cell_topology
 
const std::string & getElementBlock(const int block=0) const 
Get element block name. 
 
void generateLocalMeshPartitions(const panzer::LocalMeshInfo &mesh_info, const panzer::WorksetDescriptor &description, std::vector< panzer::LocalMeshPartition > &partitions)
 
bool useSideset() const 
This descriptor is for a side set. 
 
Kokkos::View< panzer::GlobalOrdinal * > global_cells
 
panzer::LocalOrdinal num_owned_cells
 
Kokkos::View< panzer::LocalOrdinal *[2]> face_to_cells
 
panzer::LocalOrdinal num_virtual_cells
 
Teuchos::RCP< const shards::CellTopology > cell_topology
 
#define TEUCHOS_TEST_FOR_EXCEPT_MSG(throw_exception_test, msg)
 
panzer::LocalOrdinal num_ghstd_cells
 
std::map< std::string, LocalMeshBlockInfo > element_blocks
 
Kokkos::View< panzer::LocalOrdinal *[2]> face_to_lidx
 
Kokkos::View< panzer::LocalOrdinal ** > cell_to_faces
 
void splitMeshInfo(const panzer::LocalMeshInfoBase &mesh_info, const int splitting_size, std::vector< panzer::LocalMeshPartition > &partitions)
 
#define TEUCHOS_ASSERT(assertion_test)
 
int getWorksetSize() const 
Get the requested workset size (default -2 (workset size is set elsewhere), -1 (largest possible work...
 
void setupSubLocalMeshInfo(const panzer::LocalMeshInfoBase &parent_info, const std::vector< panzer::LocalOrdinal > &owned_parent_cells, panzer::LocalMeshInfoBase &sub_info)
 
bool requiresPartitioning() const 
Do we need to partition the local mesh prior to generating worksets. 
 
Workset size is set to the total number of local elements in the MPI process.