int NonlocalMaterialWTP :: unpackMigratingElementDependencies(Domain *d, ProcessCommunicator &pc) { int myrank = d->giveEngngModel()->giveRank(); int iproc = pc.giveRank(); int _globnum; if ( iproc == myrank ) { return 1; // skip local partition } // query process communicator to use ProcessCommunicatorBuff *pcbuff = pc.giveProcessCommunicatorBuff(); ProcessCommDataStream pcDataStream(pcbuff); // unpack element data do { pcbuff->unpackInt(_globnum); if ( _globnum == NonlocalMaterialWTP_END_DATA ) { break; } pcbuff->unpackIntArray(nonlocElementDependencyMap [ _globnum ]); } while ( 1 ); return 1; }
int NonlocalMaterialWTP :: packMigratingElementDependencies(Domain *d, ProcessCommunicator &pc) { int myrank = d->giveEngngModel()->giveRank(); int iproc = pc.giveRank(); if ( iproc == myrank ) { return 1; // skip local partition } // query process communicator to use ProcessCommunicatorBuff *pcbuff = pc.giveProcessCommunicatorBuff(); ProcessCommDataStream pcDataStream(pcbuff); int ielem, nelem = d->giveNumberOfElements(); int _globnum; Element *elem; for ( ielem = 1; ielem <= nelem; ielem++ ) { // begin loop over elements elem = d->giveElement(ielem); if ( ( elem->giveParallelMode() == Element_local ) && ( lb->giveElementPartition(ielem) == iproc ) ) { // pack local element (node numbers shuld be global ones!!!) // pack type _globnum = elem->giveGlobalNumber(); pcbuff->packInt(_globnum); pcbuff->packIntArray(nonlocElementDependencyMap [ _globnum ]); } } // end loop over elements // pack end-of-element-record pcbuff->packInt(NonlocalMaterialWTP_END_DATA); return 1; }
int NonlocalMaterialWTP :: packRemoteElements(Domain *d, ProcessCommunicator &pc) { int myrank = d->giveEngngModel()->giveRank(); int iproc = pc.giveRank(); int nnodes, inode; DofManager *node, *dofman; Element *elem; if ( iproc == myrank ) { return 1; // skip local partition } // query process communicator to use ProcessCommunicatorBuff *pcbuff = pc.giveProcessCommunicatorBuff(); ProcessCommDataStream pcDataStream(pcbuff); // here we have to pack also nodes that are shared by packed elements !!! // assemble set of nodes needed by those elements // these have to be send (except those that are shared) std :: set< int >nodesToSend; for ( int ie: toSendList [ iproc ] ) { //ie = d->elementGlobal2Local(gie); elem = d->giveElement(ie); nnodes = elem->giveNumberOfDofManagers(); for ( int i = 1; i <= nnodes; i++ ) { node = elem->giveDofManager(i); if ( ( node->giveParallelMode() == DofManager_local ) || ( node->isShared() && !node->givePartitionList()->contains(iproc) ) ) { nodesToSend.insert( node->giveGlobalNumber() ); } } } // pack nodes that become null nodes on remote partition for ( int in: nodesToSend ) { inode = d->dofmanGlobal2Local(in); dofman = d->giveDofManager(inode); pcbuff->packString( dofman->giveInputRecordName() ); dofman->saveContext(& pcDataStream, CM_Definition | CM_State | CM_UnknownDictState); } pcbuff->packString(""); for ( int ie: toSendList [ iproc ] ) { //ie = d->elementGlobal2Local(gie); elem = d->giveElement(ie); // pack local element (node numbers shuld be global ones!!!) // pack type pcbuff->packString( elem->giveInputRecordName() ); elem->saveContext(& pcDataStream, CM_Definition | CM_DefinitionGlobal | CM_State); } pcbuff->packString(""); return 1; }
int NonlocalMaterialWTP :: unpackRemoteElements(Domain *d, ProcessCommunicator &pc) { int myrank = d->giveEngngModel()->giveRank(); int iproc = pc.giveRank(); std :: string _type; DofManager *dofman; IntArray _partitions; if ( iproc == myrank ) { return 1; // skip local partition } // query process communicator to use ProcessCommunicatorBuff *pcbuff = pc.giveProcessCommunicatorBuff(); ProcessCommDataStream pcDataStream(pcbuff); // unpack dofman data do { pcbuff->unpackString(_type); if ( _type.size() == 0 ) { break; } dofman = classFactory.createDofManager(_type.c_str(), 0, d); dofman->restoreContext(& pcDataStream, CM_Definition | CM_State | CM_UnknownDictState); dofman->setParallelMode(DofManager_null); if ( d->dofmanGlobal2Local( dofman->giveGlobalNumber() ) ) { // record already exist delete dofman; } else { d->giveTransactionManager()->addDofManTransaction(DomainTransactionManager :: DTT_ADD, dofman->giveGlobalNumber(), dofman); } } while ( 1 ); // unpack element data Element *elem; _partitions.resize(1); _partitions.at(1) = iproc; do { pcbuff->unpackString(_type); if ( _type.size() == 0 ) { break; } elem = classFactory.createElement(_type.c_str(), 0, d); elem->restoreContext(& pcDataStream, CM_Definition | CM_State); elem->setParallelMode(Element_remote); elem->setPartitionList(_partitions); d->giveTransactionManager()->addElementTransaction(DomainTransactionManager :: DTT_ADD, elem->giveGlobalNumber(), elem); } while ( 1 ); return 1; }
int LoadBalancer :: unpackMigratingData(Domain *d, ProcessCommunicator &pc) { // create temp space for dofManagers and elements // merging should be made by domain ? // maps of new dofmanagers and elements indexed by global number // we can put local dofManagers and elements into maps (should be done before unpacking) // int nproc=this->giveEngngModel()->giveNumberOfProcesses(); int myrank = d->giveEngngModel()->giveRank(); int iproc = pc.giveRank(); int _mode, _globnum, _type; bool _newentry; classType _etype; IntArray _partitions, local_partitions; //LoadBalancer::DofManMode dmode; DofManager *dofman; DomainTransactionManager *dtm = d->giveTransactionManager(); // ************************************************** // Unpack migrating data to remote partition // ************************************************** if ( iproc == myrank ) { return 1; // skip local partition } // query process communicator to use ProcessCommunicatorBuff *pcbuff = pc.giveProcessCommunicatorBuff(); ProcessCommDataStream pcDataStream(pcbuff); pcbuff->unpackInt(_type); // unpack dofman data while ( _type != LOADBALANCER_END_DATA ) { _etype = ( classType ) _type; pcbuff->unpackInt(_mode); switch ( _mode ) { case LoadBalancer :: DM_Remote: // receiving new local dofManager pcbuff->unpackInt(_globnum); /* * _newentry = false; * if ( ( dofman = dtm->giveDofManager(_globnum) ) == NULL ) { * // data not available -> create a new one * _newentry = true; * dofman = CreateUsrDefDofManagerOfType(_etype, 0, d); * } */ _newentry = true; dofman = CreateUsrDefDofManagerOfType(_etype, 0, d); dofman->setGlobalNumber(_globnum); // unpack dofman state (this is the local dofman, not available on remote) dofman->restoreContext(& pcDataStream, CM_Definition | CM_DefinitionGlobal | CM_State | CM_UnknownDictState); // unpack list of new partitions pcbuff->unpackIntArray(_partitions); dofman->setPartitionList(& _partitions); dofman->setParallelMode(DofManager_local); // add transaction if new entry allocated; otherwise existing one has been modified via returned dofman if ( _newentry ) { dtm->addTransaction(DomainTransactionManager :: DTT_ADD, DomainTransactionManager :: DCT_DofManager, _globnum, dofman); } //dmanMap[_globnum] = dofman; break; case LoadBalancer :: DM_Shared: // receiving new shared dofManager, that was local on sending partition // should be received only once (from partition where was local) pcbuff->unpackInt(_globnum); /* * _newentry = false; * if ( ( dofman = dtm->giveDofManager(_globnum) ) == NULL ) { * // data not available -> mode should be SharedUpdate * _newentry = true; * dofman = CreateUsrDefDofManagerOfType(_etype, 0, d); * } */ _newentry = true; dofman = CreateUsrDefDofManagerOfType(_etype, 0, d); dofman->setGlobalNumber(_globnum); // unpack dofman state (this is the local dofman, not available on remote) dofman->restoreContext(& pcDataStream, CM_Definition | CM_DefinitionGlobal | CM_State | CM_UnknownDictState); // unpack list of new partitions pcbuff->unpackIntArray(_partitions); dofman->setPartitionList(& _partitions); dofman->setParallelMode(DofManager_shared); #ifdef __VERBOSE_PARALLEL fprintf(stderr, "[%d] received Shared new dofman [%d]\n", myrank, _globnum); #endif // add transaction if new entry allocated; otherwise existing one has been modified via returned dofman if ( _newentry ) { dtm->addTransaction(DomainTransactionManager :: DTT_ADD, DomainTransactionManager :: DCT_DofManager, _globnum, dofman); } //dmanMap[_globnum] = dofman; break; default: OOFEM_ERROR2("LoadBalancer::unpackMigratingData: unexpected dof manager type (%d)", _type); } // get next type record pcbuff->unpackInt(_type); } ; // while (_type != LOADBALANCER_END_DATA); // unpack element data Element *elem; int nrecv = 0; do { pcbuff->unpackInt(_type); if ( _type == LOADBALANCER_END_DATA ) { break; } _etype = ( classType ) _type; elem = CreateUsrDefElementOfType(_etype, 0, d); elem->restoreContext(& pcDataStream, CM_Definition | CM_State); elem->initForNewStep(); dtm->addTransaction(DomainTransactionManager :: DTT_ADD, DomainTransactionManager :: DCT_Element, elem->giveGlobalNumber(), elem); nrecv++; //recvElemList.push_back(elem); } while ( 1 ); OOFEM_LOG_RELEVANT("[%d] LoadBalancer:: receiving %d migrating elements from %d\n", myrank, nrecv, iproc); return 1; }
int LoadBalancer :: packMigratingData(Domain *d, ProcessCommunicator &pc) { int myrank = d->giveEngngModel()->giveRank(); int iproc = pc.giveRank(); int idofman, ndofman; classType dtype; DofManager *dofman; LoadBalancer :: DofManMode dmode; // ************************************************** // Pack migrating data to remote partition // ************************************************** // pack dofManagers if ( iproc == myrank ) { return 1; // skip local partition } // query process communicator to use ProcessCommunicatorBuff *pcbuff = pc.giveProcessCommunicatorBuff(); ProcessCommDataStream pcDataStream(pcbuff); // loop over dofManagers ndofman = d->giveNumberOfDofManagers(); for ( idofman = 1; idofman <= ndofman; idofman++ ) { dofman = d->giveDofManager(idofman); dmode = this->giveDofManState(idofman); dtype = dofman->giveClassID(); // sync data to remote partition // if dofman already present on remote partition then there is no need to sync //if ((this->giveDofManPartitions(idofman)->findFirstIndexOf(iproc))) { if ( ( this->giveDofManPartitions(idofman)->findFirstIndexOf(iproc) ) && ( !dofman->givePartitionList()->findFirstIndexOf(iproc) ) ) { pcbuff->packInt(dtype); pcbuff->packInt(dmode); pcbuff->packInt( dofman->giveGlobalNumber() ); // pack dofman state (this is the local dofman, not available on remote) /* this is a potential performance leak, sending shared dofman to a partition, * in which is already shared does not require to send context (is already there) * here for simplicity it is always send */ dofman->saveContext(& pcDataStream, CM_Definition | CM_DefinitionGlobal | CM_State | CM_UnknownDictState); // send list of new partitions pcbuff->packIntArray( * ( this->giveDofManPartitions(idofman) ) ); } } // pack end-of-dofman-section record pcbuff->packInt(LOADBALANCER_END_DATA); int ielem, nelem = d->giveNumberOfElements(), nsend = 0; Element *elem; for ( ielem = 1; ielem <= nelem; ielem++ ) { // begin loop over elements elem = d->giveElement(ielem); if ( ( elem->giveParallelMode() == Element_local ) && ( this->giveElementPartition(ielem) == iproc ) ) { // pack local element (node numbers shuld be global ones!!!) // pack type pcbuff->packInt( elem->giveClassID() ); // nodal numbers shuld be packed as global !! elem->saveContext(& pcDataStream, CM_Definition | CM_DefinitionGlobal | CM_State); nsend++; } } // end loop over elements // pack end-of-element-record pcbuff->packInt(LOADBALANCER_END_DATA); OOFEM_LOG_RELEVANT("[%d] LoadBalancer:: sending %d migrating elements to %d\n", myrank, nsend, iproc); return 1; }