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
63 template<
typename LO,
typename GO>
66 const std::vector<LO> & owned_parent_cells,
69 PANZER_FUNC_TIME_MONITOR_DIFF(
"panzer::partitioning_utilities::setupSubLocalMeshInfo",setupSLMI);
83 const int num_owned_cells = owned_parent_cells.size();
84 TEUCHOS_TEST_FOR_EXCEPT_MSG(num_owned_cells == 0,
"panzer::partitioning_utilities::setupSubLocalMeshInfo : Input parent subcells must exist (owned_parent_cells)");
87 TEUCHOS_TEST_FOR_EXCEPT_MSG(num_parent_owned_cells <= 0,
"panzer::partitioning_utilities::setupSubLocalMeshInfo : Input parent info must contain owned cells");
95 const int num_faces_per_cell = parent_info.
cell_to_faces.extent(1);
99 std::vector<LO> ghstd_parent_cells;
100 std::vector<LO> virtual_parent_cells;
102 PANZER_FUNC_TIME_MONITOR_DIFF(
"Construct parent cell vector",ParentCell);
105 std::unordered_set<LO> owned_parent_cells_set(owned_parent_cells.begin(), owned_parent_cells.end());
112 const int virtual_parent_cell_offset = num_parent_owned_cells + num_parent_ghstd_cells;
114 std::unordered_set<LO> ghstd_parent_cells_set;
115 std::unordered_set<LO> virtual_parent_cells_set;
116 for(
int i=0;i<num_owned_cells;++i){
117 const LO parent_cell_index = owned_parent_cells[i];
118 for(
int local_face_index=0;local_face_index<num_faces_per_cell;++local_face_index){
119 const LO parent_face = parent_info.
cell_to_faces(parent_cell_index, local_face_index);
127 const LO neighbor_parent_side = (parent_info.
face_to_cells(parent_face,0) == parent_cell_index) ? 1 : 0;
130 const LO neighbor_parent_cell = parent_info.
face_to_cells(parent_face, neighbor_parent_side);
136 if(neighbor_parent_cell >= virtual_parent_cell_offset){
137 virtual_parent_cells_set.insert(neighbor_parent_cell);
138 }
else if(neighbor_parent_cell >= num_parent_owned_cells){
141 ghstd_parent_cells_set.insert(neighbor_parent_cell);
145 if(owned_parent_cells_set.find(neighbor_parent_cell) == owned_parent_cells_set.end()){
147 ghstd_parent_cells_set.insert(neighbor_parent_cell);
156 ghstd_parent_cells.assign(ghstd_parent_cells_set.begin(), ghstd_parent_cells_set.end());
157 virtual_parent_cells.assign(virtual_parent_cells_set.begin(), virtual_parent_cells_set.end());
161 const int num_ghstd_cells = ghstd_parent_cells.size();
162 const int num_virtual_cells = virtual_parent_cells.size();
163 const int num_real_cells = num_owned_cells + num_ghstd_cells;
164 const int num_total_cells = num_real_cells + num_virtual_cells;
166 std::vector<std::pair<LO, LO> > all_parent_cells(num_total_cells);
167 for (std::size_t i=0; i< owned_parent_cells.size(); ++i)
168 all_parent_cells[i] = std::pair<LO, LO>(owned_parent_cells[i], i);
170 for (std::size_t i=0; i< ghstd_parent_cells.size(); ++i) {
171 LO insert = owned_parent_cells.size()+i;
172 all_parent_cells[insert] = std::pair<LO, LO>(ghstd_parent_cells[i], insert);
175 for (std::size_t i=0; i< virtual_parent_cells.size(); ++i) {
176 LO insert = owned_parent_cells.size()+ ghstd_parent_cells.size()+i;
177 all_parent_cells[insert] = std::pair<LO, LO>(virtual_parent_cells[i], insert);
191 const int num_vertices_per_cell = parent_info.
cell_vertices.extent(1);
195 sub_info.
global_cells = Kokkos::View<GO*>(
"global_cells", num_total_cells);
196 sub_info.
local_cells = Kokkos::View<LO*>(
"local_cells", num_total_cells);
197 sub_info.
cell_vertices = Kokkos::View<double***, PHX::Device>(
"cell_vertices", num_total_cells, num_vertices_per_cell, num_dims);
198 for(
int cell=0;cell<num_total_cells;++cell){
199 const LO parent_cell = all_parent_cells[cell].first;
202 for(
int vertex=0;vertex<num_vertices_per_cell;++vertex){
203 for(
int dim=0;dim<num_dims;++dim){
216 face_t(LO c0, LO c1, LO sc0, LO sc1)
231 std::vector<face_t> faces;
233 PANZER_FUNC_TIME_MONITOR_DIFF(
"Create faces",CreateFaces);
235 std::unordered_map<LO,std::unordered_map<LO, std::pair<LO,LO> > > faces_set;
237 std::sort(all_parent_cells.begin(), all_parent_cells.end());
239 for(
int owned_cell=0;owned_cell<num_owned_cells;++owned_cell){
240 const LO owned_parent_cell = owned_parent_cells[owned_cell];
241 for(
int local_face=0;local_face<num_faces_per_cell;++local_face){
242 const LO parent_face = parent_info.
cell_to_faces(owned_parent_cell,local_face);
249 const LO neighbor_side = (parent_info.
face_to_cells(parent_face,0) == owned_parent_cell) ? 1 : 0;
251 const LO neighbor_parent_cell = parent_info.
face_to_cells(parent_face, neighbor_side);
252 const LO neighbor_subcell_index = parent_info.
face_to_lidx(parent_face, neighbor_side);
255 std::pair<LO, LO> search_point(neighbor_parent_cell, 0);
256 auto itr = std::lower_bound(all_parent_cells.begin(), all_parent_cells.end(), search_point);
258 TEUCHOS_TEST_FOR_EXCEPT_MSG(itr == all_parent_cells.end(),
"panzer_stk::setupSubLocalMeshInfo : Neighbor cell was not found in owned, ghosted, or virtual cells");
260 const LO neighbor_cell = itr->second;
262 LO cell_0, cell_1, subcell_index_0, subcell_index_1;
263 if(owned_cell < neighbor_cell){
265 subcell_index_0 = local_face;
266 cell_1 = neighbor_cell;
267 subcell_index_1 = neighbor_subcell_index;
270 subcell_index_1 = local_face;
271 cell_0 = neighbor_cell;
272 subcell_index_0 = neighbor_subcell_index;
276 faces_set[cell_0][subcell_index_0] = std::pair<LO,LO>(cell_1, subcell_index_1);
280 for(
const auto & cell_pair : faces_set){
281 const LO cell_0 = cell_pair.first;
282 for(
const auto & subcell_pair : cell_pair.second){
283 const LO subcell_index_0 = subcell_pair.first;
284 const LO cell_1 = subcell_pair.second.first;
285 const LO subcell_index_1 = subcell_pair.second.second;
286 faces.push_back(face_t(cell_0,cell_1,subcell_index_0,subcell_index_1));
291 const int num_faces = faces.size();
293 sub_info.
face_to_cells = Kokkos::View<LO*[2]>(
"face_to_cells", num_faces);
294 sub_info.
face_to_lidx = Kokkos::View<LO*[2]>(
"face_to_lidx", num_faces);
295 sub_info.
cell_to_faces = Kokkos::View<LO**>(
"cell_to_faces", num_total_cells, num_faces_per_cell);
300 for(
int face_index=0;face_index<num_faces;++face_index){
301 const face_t & face = faces[face_index];
306 sub_info.
cell_to_faces(face.cell_0,face.subcell_index_0) = face_index;
307 sub_info.
cell_to_faces(face.cell_1,face.subcell_index_1) = face_index;
309 sub_info.
face_to_lidx(face_index,0) = face.subcell_index_0;
310 sub_info.
face_to_lidx(face_index,1) = face.subcell_index_1;
322 template<
typename LO,
typename GO>
325 const int splitting_size,
338 if(splitting_size < 0){
341 std::vector<LO> partition_cells;
344 partition_cells.push_back(i);
348 if(partition_cells.size() > 0){
355 std::vector<LO> partition_cells;
356 partition_cells.reserve(splitting_size);
361 LO partition_start_index = 0;
362 for(LO partition=0;partition<num_partitions;++partition){
365 const LO partition_end_index = std::min(partition_start_index + splitting_size, num_owned_cells);
367 partition_cells.resize(partition_end_index - partition_start_index,-1);
368 for(
int i=partition_start_index;i<partition_end_index;++i){
369 partition_cells[i] = i;
373 if(partition_cells.size() > 0){
378 partition_start_index = partition_end_index;
385 template<
typename LO,
typename GO>
397 template <
typename LO,
typename GO>
411 const std::string & element_block_name = description.
getElementBlock();
419 const auto & sideset_map = mesh_info.
sidesets.at(element_block_name);
421 const std::string & sideset_name = description.
getSideset();
424 if(sideset_map.find(sideset_name) == sideset_map.end())
430 panzer::partitioning_utilities::splitMeshInfo<LO,GO>(sideset_info, description.
getWorksetSize(), partitions);
432 for(
auto & partition : partitions){
434 partition.element_block_name = element_block_name;
435 partition.cell_topology = sideset_info.cell_topology;
461 for(
auto & partition : partitions){
462 partition.element_block_name = element_block_name;
475 const std::vector<int> & owned_parent_cells,
478 #ifndef PANZER_ORDINAL64_IS_INT
482 const std::vector<int> & owned_parent_cells,
490 std::vector<panzer::LocalMeshPartition<int,int> > & partitions);
492 #ifndef PANZER_ORDINAL64_IS_INT
497 std::vector<panzer::LocalMeshPartition<int,panzer::Ordinal64> > & partitions);
Backwards compatibility mode that ignores the worksetSize in the WorksetDescriptor.
const std::string & getSideset(const int block=0) const
Get sideset name.
std::map< std::string, LocalMeshBlockInfo< LO, GO > > element_blocks
Kokkos::View< GO * > global_cells
const std::string & getElementBlock(const int block=0) const
Get element block name.
Teuchos::RCP< const shards::CellTopology > cell_topology
bool useSideset() const
This descriptor is for a side set.
void setupSubLocalMeshInfo(const panzer::LocalMeshInfoBase< LO, GO > &parent_info, const std::vector< LO > &owned_parent_cells, panzer::LocalMeshInfoBase< LO, GO > &sub_info)
void splitMeshInfo(const panzer::LocalMeshInfoBase< LO, GO > &mesh_info, const int splitting_size, std::vector< panzer::LocalMeshPartition< LO, GO > > &partitions)
std::map< std::string, std::map< std::string, LocalMeshSidesetInfo< LO, GO > > > sidesets
Kokkos::View< LO * > local_cells
#define TEUCHOS_TEST_FOR_EXCEPT_MSG(throw_exception_test, msg)
Kokkos::View< LO *[2]> face_to_cells
Kokkos::View< double ***, PHX::Device > cell_vertices
Kokkos::View< LO ** > cell_to_faces
Kokkos::View< LO *[2]> face_to_lidx
void partitionMeshInfo(const panzer::LocalMeshInfoBase< LO, GO > &, const size_t, std::vector< panzer::LocalMeshPartition< LO, GO >> &)
void generateLocalMeshPartitions(const panzer::LocalMeshInfo< LO, GO > &mesh_info, const panzer::WorksetDescriptor &description, std::vector< panzer::LocalMeshPartition< LO, GO > > &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...
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.