std::unordered_set<std::string> computeDefunctWellNames(const std::vector<std::vector<int> >& wells_on_proc, const Opm::EclipseStateConstPtr eclipseState, const CollectiveCommunication<MPI_Comm>& cc, int root) { std::vector<const Opm::Well*> wells = eclipseState->getSchedule()->getWells(); std::vector<int> my_well_indices; const int well_information_tag = 267553; if( root == cc.rank() ) { std::vector<MPI_Request> reqs(cc.size(), MPI_REQUEST_NULL); my_well_indices = wells_on_proc[root]; for ( int i=0; i < cc.size(); ++i ) { if(i==root) { continue; } MPI_Isend(const_cast<int*>(wells_on_proc[i].data()), wells_on_proc[i].size(), MPI_INT, i, well_information_tag, cc, &reqs[i]); } std::vector<MPI_Status> stats(reqs.size()); MPI_Waitall(reqs.size(), reqs.data(), stats.data()); } else { MPI_Status stat; MPI_Probe(root, well_information_tag, cc, &stat); int msg_size; MPI_Get_count(&stat, MPI_INT, &msg_size); my_well_indices.resize(msg_size); MPI_Recv(my_well_indices.data(), msg_size, MPI_INT, root, well_information_tag, cc, &stat); } // Compute defunct wells in parallel run. std::vector<int> defunct_wells(wells.size(), true); for(auto well_index : my_well_indices) { defunct_wells[well_index] = false; } // We need to use well names as only they are consistent. std::unordered_set<std::string> defunct_well_names; for(auto defunct = defunct_wells.begin(); defunct != defunct_wells.end(); ++defunct) { if ( *defunct ) { defunct_well_names.insert(wells[defunct-defunct_wells.begin()]->name()); } } return defunct_well_names; }
std::vector<int> zoltanGraphPartitionGridOnRoot(const CpGrid& cpgrid, const CollectiveCommunication<MPI_Comm>& cc, int root) { int rc; float ver; struct Zoltan_Struct *zz; int changes, numGidEntries, numLidEntries, numImport, numExport; ZOLTAN_ID_PTR importGlobalGids, importLocalGids, exportGlobalGids, exportLocalGids; int *importProcs, *importToPart, *exportProcs, *exportToPart; int argc=0; char** argv; rc = Zoltan_Initialize(argc, argv, &ver); zz = Zoltan_Create(cc); if ( rc != ZOLTAN_OK ) { OPM_THROW(std::runtime_error, "Could not initialize Zoltan!"); } Zoltan_Set_Param(zz, "DEBUG_LEVEL", "0"); Zoltan_Set_Param(zz, "LB_METHOD", "GRAPH"); Zoltan_Set_Param(zz, "LB_APPROACH", "PARTITION"); Zoltan_Set_Param(zz, "NUM_GID_ENTRIES", "1"); Zoltan_Set_Param(zz, "NUM_LID_ENTRIES", "1"); Zoltan_Set_Param(zz, "RETURN_LISTS", "ALL"); Zoltan_Set_Param(zz, "DEBUG_LEVEL", "3"); Zoltan_Set_Param(zz, "CHECK_GRAPH", "2"); Zoltan_Set_Param(zz, "PHG_EDGE_SIZE_THRESHOLD", ".35"); /* 0-remove all, 1-remove none */ bool pretendEmptyGrid = cc.rank()!=root; Dune::cpgrid::setCpGridZoltanGraphFunctions(zz, cpgrid, pretendEmptyGrid); rc = Zoltan_LB_Partition(zz, /* input (all remaining fields are output) */ &changes, /* 1 if partitioning was changed, 0 otherwise */ &numGidEntries, /* Number of integers used for a global ID */ &numLidEntries, /* Number of integers used for a local ID */ &numImport, /* Number of vertices to be sent to me */ &importGlobalGids, /* Global IDs of vertices to be sent to me */ &importLocalGids, /* Local IDs of vertices to be sent to me */ &importProcs, /* Process rank for source of each incoming vertex */ &importToPart, /* New partition for each incoming vertex */ &numExport, /* Number of vertices I must send to other processes*/ &exportGlobalGids, /* Global IDs of the vertices I must send */ &exportLocalGids, /* Local IDs of the vertices I must send */ &exportProcs, /* Process to which I send each of the vertices */ &exportToPart); /* Partition to which each vertex will belong */ int size = cpgrid.numCells(); int rank = cc.rank(); std::vector<int> parts=std::vector<int>(size, rank); for ( int i=0; i < numExport; ++i ) { parts[exportLocalGids[i]] = exportProcs[i]; } cc.broadcast(&parts[0], parts.size(), root); Zoltan_LB_Free_Part(&exportGlobalGids, &exportLocalGids, &exportProcs, &exportToPart); Zoltan_LB_Free_Part(&importGlobalGids, &importLocalGids, &importProcs, &importToPart); Zoltan_Destroy(&zz); return parts; }