From: eap Date: Thu, 21 May 2015 11:51:06 +0000 (+0300) Subject: Implement filling of ConnectZones X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=3d11d61f3ab2bab011defa48817449e9a00f1a76;p=tools%2Fmedcoupling.git Implement filling of ConnectZones --- diff --git a/src/MEDCoupling/MEDCouplingSkyLineArray.cxx b/src/MEDCoupling/MEDCouplingSkyLineArray.cxx index 5b1293a9d..6134472b6 100644 --- a/src/MEDCoupling/MEDCouplingSkyLineArray.cxx +++ b/src/MEDCoupling/MEDCouplingSkyLineArray.cxx @@ -19,11 +19,10 @@ #include "MEDCouplingSkyLineArray.hxx" -#include - using namespace ParaMEDMEM; -MEDCouplingSkyLineArray::MEDCouplingSkyLineArray() +MEDCouplingSkyLineArray::MEDCouplingSkyLineArray(): + _index( DataArrayInt::New() ), _value( DataArrayInt::New() ) { } diff --git a/src/MEDCoupling/MEDCouplingSkyLineArray.hxx b/src/MEDCoupling/MEDCouplingSkyLineArray.hxx index 1e6eb99f4..0390488dc 100644 --- a/src/MEDCoupling/MEDCouplingSkyLineArray.hxx +++ b/src/MEDCoupling/MEDCouplingSkyLineArray.hxx @@ -21,14 +21,11 @@ #define __PARAMEDMEM_MEDCOUPLINGSKYLINEARRAY_HXX__ #include "MEDCoupling.hxx" -#include "MEDCouplingMesh.hxx" #include "MEDCouplingMemArray.hxx" #include "MEDCouplingAutoRefCountObjectPtr.hxx" -#include namespace ParaMEDMEM { -class DataArrayInt; class MEDCOUPLING_EXPORT MEDCouplingSkyLineArray { private: @@ -37,11 +34,20 @@ class DataArrayInt; public: MEDCouplingSkyLineArray(); MEDCouplingSkyLineArray( const MEDCouplingSkyLineArray &myArray ); - MEDCouplingSkyLineArray( const MEDCouplingAutoRefCountObjectPtr& index, const MEDCouplingAutoRefCountObjectPtr& value ); + MEDCouplingSkyLineArray( const MEDCouplingAutoRefCountObjectPtr& index, + const MEDCouplingAutoRefCountObjectPtr& value ); ~MEDCouplingSkyLineArray(); - - int getNumberOf() const { return _index->getNbOfElems(); } - int getLength() const { return _value->getNbOfElems(); } + + void set( const MEDCouplingAutoRefCountObjectPtr& index, + const MEDCouplingAutoRefCountObjectPtr& value ); + + int getNumberOf() const { return _index->getNbOfElems()-1; } + int getLength() const { return _value->getNbOfElems(); } + const int* getIndex() const { return _index->begin(); } + const int* getValue() const { return _value->begin(); } + + MEDCouplingAutoRefCountObjectPtr getIndexArray() const { return _index; } + MEDCouplingAutoRefCountObjectPtr getValueArray() const { return _value; } }; } # endif diff --git a/src/MEDPartitioner/MEDPARTITIONER_ConnectZone.cxx b/src/MEDPartitioner/MEDPARTITIONER_ConnectZone.cxx index 155526dbf..3726e0a1e 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_ConnectZone.cxx +++ b/src/MEDPartitioner/MEDPARTITIONER_ConnectZone.cxx @@ -21,6 +21,8 @@ #include +using namespace ParaMEDMEM; + MEDPARTITIONER::ConnectZone::ConnectZone(): _name("") ,_description("") @@ -35,7 +37,7 @@ MEDPARTITIONER::ConnectZone::~ConnectZone() { delete _node_corresp; delete _face_corresp; - for(std::map < std::pair ,SkyLineArray * >::iterator iter=_entity_corresp.begin(); iter!=_entity_corresp.end();iter++) + for(std::map < std::pair ,MEDCouplingSkyLineArray * >::iterator iter=_entity_corresp.begin(); iter!=_entity_corresp.end();iter++) { delete iter->second; } @@ -84,7 +86,7 @@ ParaMEDMEM::MEDCouplingUMesh *MEDPARTITIONER::ConnectZone::getDistantMesh() cons bool MEDPARTITIONER::ConnectZone::isEntityCorrespPresent(int localEntity, int distantEntity) const { - typedef std::map, SkyLineArray*>::const_iterator map_iter; + typedef std::map, MEDCouplingSkyLineArray*>::const_iterator map_iter; for(map_iter iter=_entity_corresp.begin(); iter != _entity_corresp.end(); iter++) { if ((iter->first).first==localEntity && (iter->first).second==distantEntity) @@ -108,6 +110,11 @@ int MEDPARTITIONER::ConnectZone::getNodeNumber() const return _node_corresp->getNumberOf(); } +const ParaMEDMEM::MEDCouplingSkyLineArray * MEDPARTITIONER::ConnectZone::getNodeCorresp() const +{ + return _node_corresp; +} + const int *MEDPARTITIONER::ConnectZone::getFaceCorrespIndex() const { return _face_corresp->getIndex(); @@ -123,55 +130,73 @@ int MEDPARTITIONER::ConnectZone::getFaceNumber() const return _face_corresp->getNumberOf(); } +const ParaMEDMEM::MEDCouplingSkyLineArray * MEDPARTITIONER::ConnectZone::getFaceCorresp() const +{ + return _face_corresp; +} + const int *MEDPARTITIONER::ConnectZone::getEntityCorrespIndex(int localEntity, - int distantEntity) const + int distantEntity) const { - typedef std::map, SkyLineArray*>::const_iterator map_iter; + typedef std::map, MEDCouplingSkyLineArray*>::const_iterator map_iter; for(map_iter iter=_entity_corresp.begin();iter!=_entity_corresp.end();iter++) - { - if ((iter->first).first==localEntity && (iter->first).second==distantEntity) - return iter->second->getIndex(); - } + { + if ((iter->first).first==localEntity && (iter->first).second==distantEntity) + return iter->second->getIndex(); + } return 0; } const int *MEDPARTITIONER::ConnectZone::getEntityCorrespValue(int localEntity, - int distantEntity) const + int distantEntity) const { - typedef std::map, SkyLineArray*>::const_iterator map_iter; + typedef std::map, MEDCouplingSkyLineArray*>::const_iterator map_iter; for (map_iter iter=_entity_corresp.begin();iter!=_entity_corresp.end();iter++) - { - if ((iter->first).first==localEntity && (iter->first).second==distantEntity) - return iter->second->getValue(); - } + { + if ((iter->first).first==localEntity && (iter->first).second==distantEntity) + return iter->second->getValue(); + } return 0; } int MEDPARTITIONER::ConnectZone::getEntityCorrespNumber(int localEntity, - int distantEntity) const + int distantEntity) const { - typedef std::map, SkyLineArray*>::const_iterator map_iter; + typedef std::map, MEDCouplingSkyLineArray*>::const_iterator map_iter; for(map_iter iter=_entity_corresp.begin();iter!=_entity_corresp.end();iter++) - { - if((iter->first).first==localEntity && (iter->first).second==distantEntity) - return iter->second->getNumberOf(); - } + { + if((iter->first).first==localEntity && (iter->first).second==distantEntity) + return iter->second->getNumberOf(); + } return 0; } int MEDPARTITIONER::ConnectZone::getEntityCorrespLength(int localEntity, - int distantEntity) const + int distantEntity) const +{ + typedef std::map, MEDCouplingSkyLineArray*>::const_iterator map_iter; + + for (map_iter iter=_entity_corresp.begin(); iter != _entity_corresp.end(); iter++) + { + if ((iter->first).first==localEntity && (iter->first).second==distantEntity) + return iter->second->getLength(); + } + return 0; +} + +const ParaMEDMEM::MEDCouplingSkyLineArray * +MEDPARTITIONER::ConnectZone::getEntityCorresp(int localEntity, int distantEntity) const { - typedef std::map, SkyLineArray*>::const_iterator map_iter; - + typedef std::map, MEDCouplingSkyLineArray*>::const_iterator map_iter; + for (map_iter iter=_entity_corresp.begin(); iter != _entity_corresp.end(); iter++) - { - if ((iter->first).first==localEntity && (iter->first).second==distantEntity) - return iter->second->getLength(); - } + { + if ((iter->first).first==localEntity && (iter->first).second==distantEntity) + return iter->second; + } return 0; } @@ -207,33 +232,44 @@ void MEDPARTITIONER::ConnectZone::setDistantMesh(ParaMEDMEM::MEDCouplingUMesh * /*! transforms an int array containing * the node-node connections - * to a SkyLineArray + * to a MEDCouplingSkyLineArray */ -void MEDPARTITIONER::ConnectZone::setNodeCorresp(int * nodeCorresp, int nbnode) +void MEDPARTITIONER::ConnectZone::setNodeCorresp(const int * nodeCorresp, int nbnode) { - std::vector index(nbnode+1),value(2*nbnode); + MEDCouplingAutoRefCountObjectPtr indexArr( DataArrayInt::New() ); + MEDCouplingAutoRefCountObjectPtr valueArr( DataArrayInt::New() ); + indexArr->alloc( nbnode+1 ); + valueArr->alloc( 2*nbnode ); + int * index = indexArr->getPointer(); + int * value = valueArr->getPointer(); for (int i=0; i index(nbface+1),value(2*nbface); + MEDCouplingAutoRefCountObjectPtr indexArr( DataArrayInt::New() ); + MEDCouplingAutoRefCountObjectPtr valueArr( DataArrayInt::New() ); + indexArr->alloc( nbface+1 ); + valueArr->alloc( 2*nbface ); + int * index = indexArr->getPointer(); + int * value = valueArr->getPointer(); for (int i=0; i index(nbentity+1),value(2*nbentity); + MEDCouplingAutoRefCountObjectPtr indexArr( DataArrayInt::New() ); + MEDCouplingAutoRefCountObjectPtr valueArr( DataArrayInt::New() ); + indexArr->alloc( nbentity+1 ); + valueArr->alloc( 2*nbentity ); + int * index = indexArr->getPointer(); + int * value = valueArr->getPointer(); for (int i=0; i, ParaMEDMEM::MEDCouplingSkyLineArray * >::iterator it; + it = _entity_corresp.insert + ( std::make_pair( std::make_pair(localEntity,distantEntity), nullArray )).first; + if ( it->second != nullArray ) delete it->second; + it->second = array; } - - - - - - - diff --git a/src/MEDPartitioner/MEDPARTITIONER_ConnectZone.hxx b/src/MEDPartitioner/MEDPARTITIONER_ConnectZone.hxx index 83190cbee..d943e7df5 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_ConnectZone.hxx +++ b/src/MEDPartitioner/MEDPARTITIONER_ConnectZone.hxx @@ -22,7 +22,7 @@ #include "MEDPARTITIONER.hxx" #include "MEDCouplingUMesh.hxx" -#include "MEDPARTITIONER_SkyLineArray.hxx" +#include "MEDCouplingSkyLineArray.hxx" #include #include @@ -47,9 +47,11 @@ namespace MEDPARTITIONER const int *getNodeCorrespIndex() const; const int *getNodeCorrespValue() const; int getNodeNumber() const; + const ParaMEDMEM::MEDCouplingSkyLineArray * getNodeCorresp() const; const int *getFaceCorrespIndex() const; const int *getFaceCorrespValue() const; int getFaceNumber() const; + const ParaMEDMEM::MEDCouplingSkyLineArray * getFaceCorresp() const; const int *getEntityCorrespIndex(int localEntity, int distantEntity) const; const int *getEntityCorrespValue(int localEntity, @@ -58,6 +60,8 @@ namespace MEDPARTITIONER int distantEntity) const; int getEntityCorrespLength(int localEntity, int distantEntity) const; + const ParaMEDMEM::MEDCouplingSkyLineArray * getEntityCorresp(int localEntity, + int distantEntity) const; void setName(const std::string& name) ; void setDescription(const std::string& description) ; void setDistantDomainNumber(int distantDomainNumber) ; @@ -65,14 +69,14 @@ namespace MEDPARTITIONER void setLocalMesh(ParaMEDMEM::MEDCouplingUMesh * localMesh) ; void setDistantMesh(ParaMEDMEM::MEDCouplingUMesh * distantMesh) ; - void setNodeCorresp(int * nodeCorresp, int nbnode); - void setNodeCorresp(MEDPARTITIONER::SkyLineArray* array); - void setFaceCorresp(int * faceCorresp, int nbface); - void setFaceCorresp(MEDPARTITIONER::SkyLineArray* array); + void setNodeCorresp(const int * nodeCorresp, int nbnode); + void setNodeCorresp(ParaMEDMEM::MEDCouplingSkyLineArray* array); + void setFaceCorresp(const int * faceCorresp, int nbface); + void setFaceCorresp(ParaMEDMEM::MEDCouplingSkyLineArray* array); void setEntityCorresp(int localEntity, int distantEntity, - int * entityCorresp, int nbentity); + const int * entityCorresp, int nbentity); void setEntityCorresp(int localEntity, int distantEntity, - MEDPARTITIONER::SkyLineArray *array); + ParaMEDMEM::MEDCouplingSkyLineArray *array); private : std::string _name; std::string _description; @@ -82,10 +86,10 @@ namespace MEDPARTITIONER ParaMEDMEM::MEDCouplingUMesh * _local_mesh; ParaMEDMEM::MEDCouplingUMesh * _distant_mesh; - SkyLineArray * _node_corresp; - SkyLineArray * _face_corresp; + ParaMEDMEM::MEDCouplingSkyLineArray * _node_corresp; + ParaMEDMEM::MEDCouplingSkyLineArray * _face_corresp; - std::map < std::pair , SkyLineArray * > _entity_corresp; + std::map < std::pair , ParaMEDMEM::MEDCouplingSkyLineArray * > _entity_corresp; }; } # endif diff --git a/src/MEDPartitioner/MEDPARTITIONER_MeshCollection.cxx b/src/MEDPartitioner/MEDPARTITIONER_MeshCollection.cxx index a5a4efcb0..7c61dda91 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_MeshCollection.cxx +++ b/src/MEDPartitioner/MEDPARTITIONER_MeshCollection.cxx @@ -18,30 +18,29 @@ // #include "MEDPARTITIONER_MeshCollection.hxx" + +#include "MEDPARTITIONER_ConnectZone.hxx" +#include "MEDPARTITIONER_Graph.hxx" #include "MEDPARTITIONER_MeshCollectionDriver.hxx" -#include "MEDPARTITIONER_MeshCollectionMedXmlDriver.hxx" #include "MEDPARTITIONER_MeshCollectionMedAsciiDriver.hxx" +#include "MEDPARTITIONER_MeshCollectionMedXmlDriver.hxx" #include "MEDPARTITIONER_ParaDomainSelector.hxx" -#include "MEDPARTITIONER_Topology.hxx" #include "MEDPARTITIONER_ParallelTopology.hxx" +#include "MEDPARTITIONER_Topology.hxx" +#include "MEDPARTITIONER_UserGraph.hxx" +#include "MEDPARTITIONER_Utils.hxx" #ifdef HAVE_MPI #include "MEDPARTITIONER_JointFinder.hxx" #endif -#include "MEDPARTITIONER_Graph.hxx" -#include "MEDPARTITIONER_UserGraph.hxx" -#include "MEDPARTITIONER_Utils.hxx" - -#include "MEDLoaderBase.hxx" -#include "MEDLoader.hxx" +#include "MEDCouplingAutoRefCountObjectPtr.hxx" +#include "MEDCouplingFieldDouble.hxx" #include "MEDCouplingMemArray.hxx" -#include "MEDCouplingUMesh.hxx" #include "MEDCouplingNormalizedUnstructuredMesh.hxx" -#include "MEDCouplingFieldDouble.hxx" -#include "PointLocator3DIntersectorP0P0.hxx" - -#include "MEDCouplingAutoRefCountObjectPtr.hxx" +#include "MEDCouplingUMesh.hxx" +#include "MEDLoader.hxx" +#include "MEDLoaderBase.hxx" #ifdef HAVE_MPI #include @@ -183,6 +182,11 @@ MEDPARTITIONER::MeshCollection::MeshCollection(MeshCollection& initialCollection } } + // find faces common with neighbor domains and put them in groups + buildBoundaryFaces(); + + //building the connect zones necessary for writing joints + buildConnectZones( nodeMapping, initialCollection.getTopology()->nbDomain() ); } /*! @@ -936,6 +940,281 @@ void MEDPARTITIONER::MeshCollection::remapDoubleField(int inew, int iold, } } +namespace +{ + using namespace ParaMEDMEM; + //================================================================================ + /*! + * \brief Sort correspondence ids of one domain and permute ids of the other accordingly + * \param [in,out] ids1 - ids of one domain + * \param [in,out] ids2 - ids of another domain + * \param [in] removeEqual - to remove equal ids + * \return DataArrayInt* - array of ids joined back + */ + //================================================================================ + + DataArrayInt* sortCorrespondences( DataArrayInt* ids1, + DataArrayInt* ids2, + bool removeEqual = false) + { + // sort + MEDCouplingAutoRefCountObjectPtr< DataArrayInt > renumN2O = ids1->buildPermArrPerLevel(); + ids1->renumberInPlaceR( renumN2O->begin() ); + ids2->renumberInPlaceR( renumN2O->begin() ); + + if ( removeEqual ) + { + ids1 = ids1->buildUnique(); + ids2 = ids2->buildUnique(); + } + + // join + DataArrayInt* ids12 = DataArrayInt::Meld( ids1, ids2 ); // two components + ids12->rearrange( 1 ); // make one component + return ids12; + } +} + +//================================================================================ +/*! + * \brief Fill up ConnectZone's stored in _topology with nodal correspondences + * \param [in] nodeMapping - mapping between old nodes and new nodes + * (iolddomain,ioldnode)->(inewdomain,inewnode) + */ +//================================================================================ + +void MEDPARTITIONER::MeshCollection::buildConnectZones( const NodeMapping& nodeMapping, + int nbInitialDomains) +{ + if ( !MyGlobals::_Create_Joints || _topology->nbDomain() < 2 ) + return; + + if ( isParallelMode() ) + { + _topology->getCZ().clear(); + return; // not implemented for parallel mode + } + + // at construction, _topology creates cell correspondences basing on Graph information, + // and here we + // 1) add node correspondences, + // 2) split cell correspondences by cell geometry types + // 3) sort ids to be in ascending order + + const int nb_domains = _topology->nbDomain(); + + // ================================== + // 1) add node correspondences + // ================================== + + std::vector< std::vector< std::vector< int > > > nodeCorresp( nb_domains ); + for ( int idomain = 0; idomain < nb_domains; ++idomain ) + { + nodeCorresp[ idomain ].resize( nb_domains ); + } + + NodeMapping::const_iterator nmIt1, nmIt2 = nodeMapping.begin(); + for ( nmIt1 = nmIt2; nmIt1 != nodeMapping.end(); nmIt1 = nmIt2 ) + { + // look for an "old" node mapped into several "new" nodes in different domains + int nbSameOld = 0; + while ( ++nmIt2 != nodeMapping.end() && nmIt2->first == nmIt1->first ) + nbSameOld += ( nmIt2->second != nmIt1->second ); + + if ( nbSameOld > 0 ) + { + NodeMapping::const_iterator nmEnd = nmIt2; + for ( ; true; ++nmIt1 ) + { + nmIt2 = nmIt1; + if ( ++nmIt2 == nmEnd ) + break; + int dom1 = nmIt1->second.first; + int node1 = nmIt1->second.second; + for ( ; nmIt2 != nmEnd; ++nmIt2 ) + { + int dom2 = nmIt2->second.first; + int node2 = nmIt2->second.second; + if ( dom1 != dom2 ) + { + nodeCorresp[ dom1 ][ dom2 ].push_back( node1 ); + nodeCorresp[ dom1 ][ dom2 ].push_back( node2 ); + nodeCorresp[ dom2 ][ dom1 ].push_back( node2 ); + nodeCorresp[ dom2 ][ dom1 ].push_back( node1 ); + } + } + } + } + } + + // add nodeCorresp to czVec + + std::vector& czVec = _topology->getCZ(); + + for ( int idomain = 0; idomain < nb_domains; ++idomain ) + { + for ( int idomainNear = 0; idomainNear < nb_domains; ++idomainNear ) + { + std::vector< int > & corresp = nodeCorresp[ idomain ][ idomainNear ]; + if ( corresp.empty() ) + continue; + + MEDPARTITIONER::ConnectZone* cz = 0; + for ( size_t i = 0; i < czVec.size() && !cz; ++i ) + if ( czVec[i] && + czVec[i]->getLocalDomainNumber () == idomain && + czVec[i]->getDistantDomainNumber() == idomainNear ) + cz = czVec[i]; + + if ( !cz ) + { + MEDPARTITIONER::ConnectZone* cz = new MEDPARTITIONER::ConnectZone(); + cz->setName( "Nodal Connect Zone defined by MEDPARTITIONER" ); + cz->setLocalDomainNumber ( idomain ); + cz->setDistantDomainNumber( idomainNear ); + } + + cz->setNodeCorresp( &corresp[0], corresp.size()/2 ); + } + } + + // ========================================================== + // 2) split cell correspondences by cell geometry types + // ========================================================== + + for ( size_t i = 0; i < czVec.size(); ++i ) + { + MEDPARTITIONER::ConnectZone* cz = czVec[i]; + if ( !cz || + cz->getEntityCorrespNumber( 0,0 ) == 0 || + cz->getLocalDomainNumber () > _mesh.size() || + cz->getDistantDomainNumber() > _mesh.size() ) + continue; + ParaMEDMEM::MEDCouplingUMesh* mesh1 = _mesh[ cz->getLocalDomainNumber () ]; + ParaMEDMEM::MEDCouplingUMesh* mesh2 = _mesh[ cz->getDistantDomainNumber() ]; + + // separate ids of two domains + const ParaMEDMEM::MEDCouplingSkyLineArray *corrArray = cz->getEntityCorresp( 0, 0 ); + MEDCouplingAutoRefCountObjectPtr ids12 = corrArray->getValueArray(); + MEDCouplingAutoRefCountObjectPtr ids1, ids2; + ids1 = ids12->selectByTupleId2( 0, corrArray->getLength()+1, 2 ); + ids2 = ids12->selectByTupleId2( 1, corrArray->getLength()+1, 2 ); + + // check nb cell types + std::set types1, types2; + types1 = mesh1->getTypesOfPart( ids1->begin(), ids1->end() ); + types2 = mesh2->getTypesOfPart( ids2->begin(), ids2->end() ); + if ( types1.size() < 1 || types2.size() < 1 ) + continue; // parallel mode? + + MEDPARTITIONER::ConnectZone* cz21 = 0; // zone 2 -> 1 + for ( size_t j = 0; j < czVec.size() && !cz21; ++j ) + if ( czVec[j] && + czVec[j]->getLocalDomainNumber () == cz->getDistantDomainNumber() && + czVec[j]->getDistantDomainNumber() == cz->getLocalDomainNumber() ) + cz21 = czVec[j]; + + if ( types1.size() == 1 && types2.size() == 1 ) // split not needed, only sort + { + ids12 = sortCorrespondences( ids1, ids2 ); + cz->setEntityCorresp( *types1.begin(), *types2.begin(), + ids12->begin(), ids12->getNbOfElems() / 2 ); + + if ( cz21 )// set 2->1 correspondence + { + ids12 = sortCorrespondences( ids2, ids1 ); + cz21->setEntityCorresp( *types2.begin(), *types1.begin(), + ids12->begin(), ids12->getNbOfElems() / 2 ); + } + } + else // split and sort + { + typedef std::pair< std::vector< int >, std::vector< int > > T2Vecs; + T2Vecs idsByType[ INTERP_KERNEL::NORM_MAXTYPE ][ INTERP_KERNEL::NORM_MAXTYPE ]; + int t1, t2; + + const int nbIds = ids1->getNbOfElems(); + const int * p1 = ids1->begin(), * p2 = ids2->begin(); + for ( int i = 0; i < nbIds; ++i ) + { + t1 = mesh1->getTypeOfCell( p1[ i ]); + t2 = mesh2->getTypeOfCell( p2[ i ]); + T2Vecs & ids = idsByType[ t1 ][ t2 ]; + ids.first .push_back( p1[ i ]); + ids.second.push_back( p1[ i ]); + } + + const int maxType = int( INTERP_KERNEL::NORM_MAXTYPE ); + for ( t1 = 0; t1 < maxType; ++t1 ) + for ( t2 = 0; t2 < maxType; ++t2 ) + { + T2Vecs & ids = idsByType[ t1 ][ t2 ]; + if ( ids.first.empty() ) continue; + p1 = & ids.first[0]; + p2 = & ids.second[0]; + ids1->desallocate(); + ids1->pushBackValsSilent( p1, p1+ids.first.size() ); + ids2->desallocate(); + ids2->pushBackValsSilent( p2, p2+ids.first.size() ); + ids12 = sortCorrespondences( ids1, ids2 ); + + cz->setEntityCorresp( t1, t2, ids12->begin(), ids12->getNbOfElems() / 2 ); + + if ( cz21 )// set 2->1 correspondence + { + ids12 = sortCorrespondences( ids2, ids1 ); + cz21->setEntityCorresp( t2, t1, ids12->begin(), ids12->getNbOfElems() / 2 ); + break; + } + } + }// split and sort + + cz->setEntityCorresp( 0, 0, 0, 0 ); // erase ids computed by _topology + if ( cz21 ) + cz21->setEntityCorresp( 0, 0, 0, 0 ); + + } // loop on czVec + + + // ========================================== + // 3) sort node ids to be in ascending order + // ========================================== + + const bool removeEqual = ( nbInitialDomains > 1 ); + + for ( size_t i = 0; i < czVec.size(); ++i ) + { + MEDPARTITIONER::ConnectZone* cz = czVec[i]; + if ( !cz || cz->getNodeNumber() == 0 ) + continue; + if ( cz->getDistantDomainNumber() < cz->getLocalDomainNumber() ) + continue; // treat a pair of domains once + + MEDPARTITIONER::ConnectZone* cz21 = 0; // zone 2 -> 1 + for ( size_t j = 0; j < czVec.size() && !cz21; ++j ) + if ( czVec[j] && + czVec[j]->getLocalDomainNumber () == cz->getDistantDomainNumber() && + czVec[j]->getDistantDomainNumber() == cz->getLocalDomainNumber() ) + cz21 = czVec[j]; + + // separate ids of two domains + const ParaMEDMEM::MEDCouplingSkyLineArray *corrArray = cz->getNodeCorresp(); + MEDCouplingAutoRefCountObjectPtr ids12 = corrArray->getValueArray(); + MEDCouplingAutoRefCountObjectPtr ids1, ids2; + ids1 = ids12->selectByTupleId2( 0, corrArray->getLength()+1, 2 ); + ids2 = ids12->selectByTupleId2( 1, corrArray->getLength()+1, 2 ); + + ids12 = sortCorrespondences( ids1, ids2, removeEqual ); + cz->setNodeCorresp( ids12->begin(), ids12->getNbOfElems() / 2 ); + + if ( cz21 )// set 2->1 correspondence + { + ids12 = sortCorrespondences( ids2, ids1, false ); + cz->setNodeCorresp( ids12->begin(), ids12->getNbOfElems() / 2 ); + } + } +} + //================================================================================ /*! * \brief Find faces common with neighbor domains and put them in "JOINT_n_p_Faces" @@ -943,8 +1222,11 @@ void MEDPARTITIONER::MeshCollection::remapDoubleField(int inew, int iold, */ //================================================================================ -void MEDPARTITIONER::MeshCollection::buildConnectZones() +void MEDPARTITIONER::MeshCollection::buildBoundaryFaces() { + if (_topology->nbDomain() < 2 || !_subdomain_boundary_creates ) + return; + if ( getMeshDimension() < 2 ) return; @@ -1441,9 +1723,6 @@ MEDPARTITIONER::MeshCollection::~MeshCollection() */ void MEDPARTITIONER::MeshCollection::write(const std::string& filename) { - //building the connect zones necessary for writing joints - if (_topology->nbDomain()>1 && _subdomain_boundary_creates ) - buildConnectZones(); //suppresses link with driver so that it can be changed for writing delete _driver; _driver=0; @@ -1540,7 +1819,7 @@ ParaMEDMEM::MEDCouplingUMesh* MEDPARTITIONER::MeshCollection::getFaceMesh(int id std::vector& MEDPARTITIONER::MeshCollection::getCZ() { - return _connect_zones; + return _topology->getCZ(); } MEDPARTITIONER::Topology* MEDPARTITIONER::MeshCollection::getTopology() const diff --git a/src/MEDPartitioner/MEDPARTITIONER_MeshCollection.hxx b/src/MEDPartitioner/MEDPARTITIONER_MeshCollection.hxx index 3fae6277f..dbc243dfd 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_MeshCollection.hxx +++ b/src/MEDPartitioner/MEDPARTITIONER_MeshCollection.hxx @@ -150,7 +150,10 @@ namespace MEDPARTITIONER std::vector > >& new2oldIds); //constructing connect zones - void buildConnectZones(); + void buildConnectZones( const NodeMapping& nodeMapping, int nbInitialDomains ); + + // Find faces common with neighbor domains and put them in groups + void buildBoundaryFaces(); private: void castIntField(std::vector& meshesCastFrom, @@ -201,9 +204,6 @@ namespace MEDPARTITIONER //index of a non empty mesh within _mesh (in parallel mode all of meshes can be empty) int _i_non_empty_mesh; - //links to connectzones - std::vector _connect_zones; - //family ids storages std::vector _cell_family_ids; std::vector _face_family_ids; diff --git a/src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.cxx b/src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.cxx index d445d3032..9f66e154e 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.cxx +++ b/src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.cxx @@ -316,22 +316,78 @@ ParallelTopology::ParallelTopology(Graph* graph, Topology* oldTopology, int nb_d if (MyGlobals::_Verbose>300) for (int idomain=0; idomain<_nb_domain; idomain++) - std::cout << "proc " << MyGlobals::_Rank << " : nbCells in new domain " << idomain << " : " << _nb_cells[idomain] << std::endl; + std::cout << "proc " << MyGlobals::_Rank << " : nbCells in new domain " << idomain << " : " << _nb_cells[idomain] << std::endl; + + // JOINTs + + if ( MyGlobals::_Create_Joints && nb_domain > 1 ) + { + std::vector< std::vector< std::vector< int > > > cellCorresp( nb_domain ); + for ( int idomain = 0; idomain < nb_domain; ++idomain ) + { + cellCorresp[ idomain ].resize( nb_domain ); + } + const SkyLineArray* skylinegraph = graph->getGraph(); + const int* index = skylinegraph->getIndex(); + const int* value = skylinegraph->getValue(); + const int nbCells = skylinegraph->getNumberOf(); + for ( int iGlob = 0; iGlob < nbCells; ++iGlob ) + { + int iGlobDom = part[ iGlob ]; + for ( int i = index[ iGlob ]; i < index[ iGlob+1 ]; i++ ) + { + int iGlobNear = value[ i ]; + if ( iGlob > iGlobNear ) + continue; // treat ( iGlob, iGlobNear ) pair once + int iGlobNearDom = part[ iGlobNear ]; + if ( iGlobDom != iGlobNearDom ) + { + int iLoc = convertGlobalCell( iGlob ).second; + int iLocNear = convertGlobalCell( iGlobNear ).second; + cellCorresp[ iGlobDom ][ iGlobNearDom ].push_back( iLoc ); + cellCorresp[ iGlobDom ][ iGlobNearDom ].push_back( iLocNear ); + cellCorresp[ iGlobNearDom ][ iGlobDom ].push_back( iLocNear ); + cellCorresp[ iGlobNearDom ][ iGlobDom ].push_back( iLoc ); + } + } + } + for ( int idomain = 0; idomain < nb_domain; ++idomain ) + { + for ( int idomainNear = 0; idomainNear < nb_domain; ++idomainNear ) + { + std::vector< int > & corresp = cellCorresp[ idomain ][ idomainNear ]; + if ( corresp.empty() ) + continue; + MEDPARTITIONER::ConnectZone* cz = new MEDPARTITIONER::ConnectZone(); + cz->setName( "Connect Zone defined by MEDPARTITIONER" ); + cz->setDistantDomainNumber( idomainNear ); + cz->setLocalDomainNumber ( idomain ); + cz->setEntityCorresp( 0,0, &corresp[0], corresp.size()/2 ); + _connect_zones.push_back( cz ); + } + } + } } ParallelTopology::~ParallelTopology() { -} + for ( size_t i = 0; i < _connect_zones.size(); ++i ) + { + delete _connect_zones[i]; + _connect_zones[i] = 0; + } + _connect_zones.clear(); +} /*!Converts a list of global node numbers * to a distributed array with local cell numbers. - * + * * If a node in the list is represented on several domains, * only the first value is returned * */ void ParallelTopology::convertGlobalNodeList(const int* node_list, int nbnode, int* local, int* ip) { - if (_node_glob_to_loc.empty()) + if (_node_glob_to_loc.empty()) throw INTERP_KERNEL::Exception("Node mapping has not yet been built"); for (int i=0; i< nbnode; i++) { @@ -600,6 +656,11 @@ int ParallelTopology::convertGlobalNode(int iglobal, int idomain) return -1; } +std::vector& ParallelTopology::getCZ() +{ + return _connect_zones; +} + /*! * adding a face to the topology */ diff --git a/src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.hxx b/src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.hxx index bc81aa8a4..5de3f4820 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.hxx +++ b/src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.hxx @@ -147,6 +147,8 @@ namespace MEDPARTITIONER int convertGlobalNode(int iglobal, int idomain); + std::vector& getCZ(); + //adding a face to the topology void appendFace(int idomain, int ilocal, int iglobal); @@ -161,10 +163,10 @@ namespace MEDPARTITIONER typedef INTERP_KERNEL::HashMultiMap > TGlob2DomainLoc; TGlob2DomainLoc _glob_to_loc; - std::vector > _loc_to_glob; - INTERP_KERNEL::HashMultiMap > _node_glob_to_loc; + TGlob2DomainLoc _node_glob_to_loc; //mapping local -> global + std::vector > _loc_to_glob; std::vector > _node_loc_to_glob; // global numbers in parallel mode @@ -185,6 +187,10 @@ namespace MEDPARTITIONER int _nb_total_faces; int _nb_domain; int _mesh_dimension; + + //links to connectzones + std::vector _connect_zones; + }; } #endif diff --git a/src/MEDPartitioner/MEDPARTITIONER_Topology.hxx b/src/MEDPartitioner/MEDPARTITIONER_Topology.hxx index 9ea47e889..a9790ebad 100644 --- a/src/MEDPartitioner/MEDPARTITIONER_Topology.hxx +++ b/src/MEDPartitioner/MEDPARTITIONER_Topology.hxx @@ -105,6 +105,8 @@ namespace MEDPARTITIONER virtual int convertGlobalFace(int iglobal, int idomain) = 0; /*! converting a global node number to a local representation */ virtual int convertGlobalNode(int iglobal, int idomain) = 0; + /*! getting a reference to connect zones vector */ + virtual std::vector& getCZ() = 0; }; }