//============================================================================= Epetra_Map* Epetra_Map::ReplaceCommWithSubset(const Epetra_Comm * theComm) const { // mfh 26 Mar 2013: The lazy way to do this is simply to recreate // the Map by calling its ordinary public constructor, using the // original Map's data. This only involves O(1) all-reduces over // the new communicator, which in the common case only includes a // small number of processes. Epetra_Map * NewMap=0; // Create the Map to return (unless theComm is NULL, in which case // we return zero). if(theComm) { // Map requires that the index base equal the global min GID. // Figuring out the global min GID requires a reduction over all // processes in the new communicator. It could be that some (or // even all) of these processes contain zero entries. (Recall // that this method, unlike removeEmptyProcesses(), may remove // an arbitrary subset of processes.) We deal with this by // doing a min over the min GID on each process if the process // has more than zero entries, or the global max GID, if that // process has zero entries. If no processes have any entries, // then the index base doesn't matter anyway. #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES if(GlobalIndicesInt()) { int MyMin, theIndexBase; MyMin = NumMyElements() > 0 ? MinMyGID() : MaxAllGID(); theComm->MinAll(&MyMin,&theIndexBase,1); NewMap = new Epetra_Map(-1,NumMyElements(),MyGlobalElements(),theIndexBase,*theComm); } else #endif #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES if(GlobalIndicesLongLong()) { long long MyMin, theIndexBase; MyMin = NumMyElements() > 0 ? MinMyGID64() : MaxAllGID64(); theComm->MinAll(&MyMin,&theIndexBase,1); NewMap = new Epetra_Map(-1,NumMyElements(),MyGlobalElements64(),theIndexBase,*theComm); } else #endif throw ReportError("Epetra_Map::ReplaceCommWithSubset ERROR, GlobalIndices type unknown.",-1); } return NewMap; }
inline static GT_ARRAY MyGlobalElements(MAP_TYPE A) { return Teuchos::arrayView(A->MyGlobalElements(), NumMyElements(A)); }
//============================================================================= Epetra_Map * Epetra_Map::RemoveEmptyProcesses() const { #ifdef HAVE_MPI const Epetra_MpiComm * MpiComm = dynamic_cast<const Epetra_MpiComm*>(&Comm()); // If the Comm isn't MPI, just treat this as a copy constructor if(!MpiComm) return new Epetra_Map(*this); MPI_Comm NewComm,MyMPIComm = MpiComm->Comm(); // Create the new communicator. MPI_Comm_split returns a valid // communicator on all processes. On processes where color == MPI_UNDEFINED, // ignore the result. Passing key == 0 tells MPI to order the // processes in the new communicator by their rank in the old // communicator. const int color = (NumMyElements() == 0) ? MPI_UNDEFINED : 1; // MPI_Comm_split must be called collectively over the original // communicator. We can't just call it on processes with color // one, even though we will ignore its result on processes with // color zero. int rv = MPI_Comm_split(MyMPIComm,color,0,&NewComm); if(rv!=MPI_SUCCESS) throw ReportError("Epetra_Map::RemoveEmptyProcesses: MPI_Comm_split failed.",-1); if(color == MPI_UNDEFINED) return 0; // We're not in the new map else { Epetra_MpiComm * NewEpetraComm = new Epetra_MpiComm(NewComm); // Use the copy constructor for a new map, but basically because it does nothing useful Epetra_Map * NewMap = new Epetra_Map(*this); // Get rid of the old BlockMapData, now make a new one from scratch... NewMap->CleanupData(); if(GlobalIndicesInt()) { #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES NewMap->BlockMapData_ = new Epetra_BlockMapData(NumGlobalElements(),0,IndexBase(),*NewEpetraComm,false); #endif } else { #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES NewMap->BlockMapData_ = new Epetra_BlockMapData(NumGlobalElements64(),0,IndexBase64(),*NewEpetraComm,true); #endif } // Now copy all of the relevent bits of BlockMapData... // NewMap->BlockMapData_->Comm_ = NewEpetraComm; NewMap->BlockMapData_->LID_ = BlockMapData_->LID_; #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES NewMap->BlockMapData_->MyGlobalElements_int_ = BlockMapData_->MyGlobalElements_int_; #endif #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES NewMap->BlockMapData_->MyGlobalElements_LL_ = BlockMapData_->MyGlobalElements_LL_; #endif NewMap->BlockMapData_->FirstPointInElementList_ = BlockMapData_->FirstPointInElementList_; NewMap->BlockMapData_->ElementSizeList_ = BlockMapData_->ElementSizeList_; NewMap->BlockMapData_->PointToElementList_ = BlockMapData_->PointToElementList_; NewMap->BlockMapData_->NumGlobalElements_ = BlockMapData_->NumGlobalElements_; NewMap->BlockMapData_->NumMyElements_ = BlockMapData_->NumMyElements_; NewMap->BlockMapData_->IndexBase_ = BlockMapData_->IndexBase_; NewMap->BlockMapData_->ElementSize_ = BlockMapData_->ElementSize_; NewMap->BlockMapData_->MinMyElementSize_ = BlockMapData_->MinMyElementSize_; NewMap->BlockMapData_->MaxMyElementSize_ = BlockMapData_->MaxMyElementSize_; NewMap->BlockMapData_->MinElementSize_ = BlockMapData_->MinElementSize_; NewMap->BlockMapData_->MaxElementSize_ = BlockMapData_->MaxElementSize_; NewMap->BlockMapData_->MinAllGID_ = BlockMapData_->MinAllGID_; NewMap->BlockMapData_->MaxAllGID_ = BlockMapData_->MaxAllGID_; NewMap->BlockMapData_->MinMyGID_ = BlockMapData_->MinMyGID_; NewMap->BlockMapData_->MaxMyGID_ = BlockMapData_->MaxMyGID_; NewMap->BlockMapData_->MinLID_ = BlockMapData_->MinLID_; NewMap->BlockMapData_->MaxLID_ = BlockMapData_->MaxLID_; NewMap->BlockMapData_->NumGlobalPoints_ = BlockMapData_->NumGlobalPoints_; NewMap->BlockMapData_->NumMyPoints_ = BlockMapData_->NumMyPoints_; NewMap->BlockMapData_->ConstantElementSize_ = BlockMapData_->ConstantElementSize_; NewMap->BlockMapData_->LinearMap_ = BlockMapData_->LinearMap_; NewMap->BlockMapData_->DistributedGlobal_ = NewEpetraComm->NumProc()==1 ? false : BlockMapData_->DistributedGlobal_; NewMap->BlockMapData_->OneToOneIsDetermined_ = BlockMapData_->OneToOneIsDetermined_; NewMap->BlockMapData_->OneToOne_ = BlockMapData_->OneToOne_; NewMap->BlockMapData_->GlobalIndicesInt_ = BlockMapData_->GlobalIndicesInt_; NewMap->BlockMapData_->GlobalIndicesLongLong_ = BlockMapData_->GlobalIndicesLongLong_; NewMap->BlockMapData_->LastContiguousGID_ = BlockMapData_->LastContiguousGID_; NewMap->BlockMapData_->LastContiguousGIDLoc_ = BlockMapData_->LastContiguousGIDLoc_; NewMap->BlockMapData_->LIDHash_ = BlockMapData_->LIDHash_ ? new Epetra_HashTable<int>(*BlockMapData_->LIDHash_) : 0; // Delay directory construction NewMap->BlockMapData_->Directory_ = 0; // Cleanup delete NewEpetraComm; return NewMap; } #else // MPI isn't compiled, so just treat this as a copy constructor return new Epetra_Map(*this); #endif }
//============================================================================== void Epetra_BlockMap::Print(ostream & os) const { int * FirstPointInElementList1 = 0; int * ElementSizeList1 = 0; if (!ConstantElementSize()) { FirstPointInElementList1 = FirstPointInElementList(); ElementSizeList1 = ElementSizeList(); } int MyPID = Comm().MyPID(); int NumProc = Comm().NumProc(); for (int iproc = 0; iproc < NumProc; iproc++) { if (MyPID == iproc) { if (MyPID == 0) { os << "\nNumber of Global Elements = "; os << NumGlobalElements64(); os << endl; os << "Number of Global Points = "; os << NumGlobalPoints64(); os << endl; os << "Maximum of all GIDs = "; os << MaxAllGID64(); os << endl; os << "Minimum of all GIDs = "; os << MinAllGID64(); os << endl; os << "Index Base = "; os << IndexBase(); os << endl; if (ConstantElementSize()) os << "Constant Element Size = "; os << ElementSize(); os << endl; } os << endl; os << "Number of Local Elements = "; os << NumMyElements(); os << endl; os << "Number of Local Points = "; os << NumMyPoints(); os << endl; os << "Maximum of my GIDs = "; os << MaxMyGID64(); os << endl; os << "Minimum of my GIDs = "; os << MinMyGID64(); os << endl; os << endl; os.width(14); os << " MyPID"; os << " "; os.width(14); os << " Local Index "; os << " "; os.width(14); os << " Global Index "; os << " "; if (!ConstantElementSize()) { os.width(14); os <<" FirstPointInElement "; os << " "; os.width(14); os <<" ElementSize "; os << " "; } os << endl; for (int i = 0; i < NumMyElements(); i++) { os.width(14); os << MyPID; os << " "; os.width(14); os << i; os << " "; os.width(14); if(BlockMapData_->GlobalIndicesLongLong_) { #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES long long * MyGlobalElements1 = MyGlobalElements64(); os << MyGlobalElements1[i]; os << " "; #else throw ReportError("Epetra_BlockMap::Print: ERROR, GlobalIndicesLongLong but no API for it.",-1); #endif } else if(BlockMapData_->GlobalIndicesInt_) { #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES int * MyGlobalElements1 = MyGlobalElements(); os << MyGlobalElements1[i]; os << " "; #else throw ReportError("Epetra_BlockMap::Print: ERROR, no GlobalIndicesLongLong but no API for it.",-1); #endif } if (!ConstantElementSize()) { os.width(14); os << FirstPointInElementList1[i]; os << " "; os.width(14); os << ElementSizeList1[i]; os << " "; } os << endl; } os << flush; } // Do a few global ops to give I/O a chance to complete Comm().Barrier(); Comm().Barrier(); Comm().Barrier(); } return; }