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.