#include "MEDCouplingSkyLineArray.hxx"
-#include <vector>
-
using namespace ParaMEDMEM;
-MEDCouplingSkyLineArray::MEDCouplingSkyLineArray()
+MEDCouplingSkyLineArray::MEDCouplingSkyLineArray():
+ _index( DataArrayInt::New() ), _value( DataArrayInt::New() )
{
}
#define __PARAMEDMEM_MEDCOUPLINGSKYLINEARRAY_HXX__
#include "MEDCoupling.hxx"
-#include "MEDCouplingMesh.hxx"
#include "MEDCouplingMemArray.hxx"
#include "MEDCouplingAutoRefCountObjectPtr.hxx"
-#include <vector>
namespace ParaMEDMEM
{
-class DataArrayInt;
class MEDCOUPLING_EXPORT MEDCouplingSkyLineArray
{
private:
public:
MEDCouplingSkyLineArray();
MEDCouplingSkyLineArray( const MEDCouplingSkyLineArray &myArray );
- MEDCouplingSkyLineArray( const MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& index, const MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& value );
+ MEDCouplingSkyLineArray( const MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& index,
+ const MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& value );
~MEDCouplingSkyLineArray();
-
- int getNumberOf() const { return _index->getNbOfElems(); }
- int getLength() const { return _value->getNbOfElems(); }
+
+ void set( const MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& index,
+ const MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& 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<DataArrayInt> getIndexArray() const { return _index; }
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> getValueArray() const { return _value; }
};
}
# endif
#include <map>
+using namespace ParaMEDMEM;
+
MEDPARTITIONER::ConnectZone::ConnectZone():
_name("")
,_description("")
{
delete _node_corresp;
delete _face_corresp;
- for(std::map < std::pair <int, int>,SkyLineArray * >::iterator iter=_entity_corresp.begin(); iter!=_entity_corresp.end();iter++)
+ for(std::map < std::pair <int, int>,MEDCouplingSkyLineArray * >::iterator iter=_entity_corresp.begin(); iter!=_entity_corresp.end();iter++)
{
delete iter->second;
}
bool MEDPARTITIONER::ConnectZone::isEntityCorrespPresent(int localEntity, int distantEntity) const
{
- typedef std::map<std::pair<int,int>, SkyLineArray*>::const_iterator map_iter;
+ typedef std::map<std::pair<int,int>, 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 _node_corresp->getNumberOf();
}
+const ParaMEDMEM::MEDCouplingSkyLineArray * MEDPARTITIONER::ConnectZone::getNodeCorresp() const
+{
+ return _node_corresp;
+}
+
const int *MEDPARTITIONER::ConnectZone::getFaceCorrespIndex() const
{
return _face_corresp->getIndex();
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<std::pair<int,int>, SkyLineArray*>::const_iterator map_iter;
+ typedef std::map<std::pair<int,int>, 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<std::pair<int,int>, SkyLineArray*>::const_iterator map_iter;
+ typedef std::map<std::pair<int,int>, 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<std::pair<int,int>, SkyLineArray*>::const_iterator map_iter;
+ typedef std::map<std::pair<int,int>, 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<std::pair<int,int>, 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<std::pair<int,int>, SkyLineArray*>::const_iterator map_iter;
-
+ typedef std::map<std::pair<int,int>, 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;
}
/*! 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<int> index(nbnode+1),value(2*nbnode);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> indexArr( DataArrayInt::New() );
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> valueArr( DataArrayInt::New() );
+ indexArr->alloc( nbnode+1 );
+ valueArr->alloc( 2*nbnode );
+ int * index = indexArr->getPointer();
+ int * value = valueArr->getPointer();
for (int i=0; i<nbnode; i++)
{
index[i]=2*i;
- value[2*i]=nodeCorresp[2*i];
+ value[2*i ]=nodeCorresp[2*i];
value[2*i+1]=nodeCorresp[2*i+1];
}
index[nbnode]=2*nbnode;
- _node_corresp = new SkyLineArray(index,value);
+ setNodeCorresp( new MEDCouplingSkyLineArray( indexArr, valueArr ));
}
-void MEDPARTITIONER::ConnectZone::setNodeCorresp(SkyLineArray* array)
+void MEDPARTITIONER::ConnectZone::setNodeCorresp(MEDCouplingSkyLineArray* array)
{
+ if ( _node_corresp ) delete _node_corresp;
_node_corresp = array;
}
/*! transforms an int array containing
* the face-face connections
- * to a SkyLineArray
+ * to a MEDCouplingSkyLineArray
*/
-void MEDPARTITIONER::ConnectZone::setFaceCorresp(int * faceCorresp, int nbface)
+void MEDPARTITIONER::ConnectZone::setFaceCorresp(const int * faceCorresp, int nbface)
{
- std::vector<int> index(nbface+1),value(2*nbface);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> indexArr( DataArrayInt::New() );
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> valueArr( DataArrayInt::New() );
+ indexArr->alloc( nbface+1 );
+ valueArr->alloc( 2*nbface );
+ int * index = indexArr->getPointer();
+ int * value = valueArr->getPointer();
for (int i=0; i<nbface; i++)
{
index[i]=2*i;
value[2*i+1]=faceCorresp[2*i+1];
}
index[nbface]=2*nbface;
- _face_corresp = new MEDPARTITIONER::SkyLineArray(index,value);
+ setFaceCorresp( new MEDCouplingSkyLineArray( indexArr, valueArr ));
}
-void MEDPARTITIONER::ConnectZone::setFaceCorresp(SkyLineArray* array)
+void MEDPARTITIONER::ConnectZone::setFaceCorresp(MEDCouplingSkyLineArray* array)
{
+ if ( _face_corresp ) delete _face_corresp;
_face_corresp = array;
}
/*! transforms an int array containing
* the entity-entity connections
- * to a SkyLineArray
+ * to a MEDCouplingSkyLineArray
*
- * the resulting SkyLineArray is put in the map
+ * the resulting MEDCouplingSkyLineArray is put in the map
*/
void MEDPARTITIONER::ConnectZone::setEntityCorresp(int localEntity, int distantEntity,
- int *entityCorresp, int nbentity)
+ const int *entityCorresp, int nbentity)
{
- std::vector<int> index(nbentity+1),value(2*nbentity);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> indexArr( DataArrayInt::New() );
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> valueArr( DataArrayInt::New() );
+ indexArr->alloc( nbentity+1 );
+ valueArr->alloc( 2*nbentity );
+ int * index = indexArr->getPointer();
+ int * value = valueArr->getPointer();
for (int i=0; i<nbentity; i++)
{
index[i]=2*i;
- value[2*i]=entityCorresp[2*i];
+ value[2*i ]=entityCorresp[2*i];
value[2*i+1]=entityCorresp[2*i+1];
}
index[nbentity]=2*nbentity;
- _entity_corresp[std::make_pair(localEntity,distantEntity)] = new SkyLineArray(index,value);
+ setEntityCorresp( localEntity, distantEntity, new MEDCouplingSkyLineArray(indexArr,valueArr));
}
void MEDPARTITIONER::ConnectZone::setEntityCorresp(int localEntity, int distantEntity,
- SkyLineArray *array)
+ MEDCouplingSkyLineArray *array)
{
- _entity_corresp[std::make_pair(localEntity,distantEntity)]=array;
+ ParaMEDMEM::MEDCouplingSkyLineArray * nullArray = 0;
+ std::map < std::pair <int,int>, 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;
}
-
-
-
-
-
-
-
#include "MEDPARTITIONER.hxx"
#include "MEDCouplingUMesh.hxx"
-#include "MEDPARTITIONER_SkyLineArray.hxx"
+#include "MEDCouplingSkyLineArray.hxx"
#include <map>
#include <string>
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,
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) ;
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;
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 <int,int>, SkyLineArray * > _entity_corresp;
+ std::map < std::pair <int,int>, ParaMEDMEM::MEDCouplingSkyLineArray * > _entity_corresp;
};
}
# endif
//
#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 <mpi.h>
}
}
+ // 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() );
}
/*!
}
}
+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<MEDPARTITIONER::ConnectZone*>& 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<DataArrayInt> ids12 = corrArray->getValueArray();
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids1, ids2;
+ ids1 = ids12->selectByTupleId2( 0, corrArray->getLength()+1, 2 );
+ ids2 = ids12->selectByTupleId2( 1, corrArray->getLength()+1, 2 );
+
+ // check nb cell types
+ std::set<INTERP_KERNEL::NormalizedCellType> 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<DataArrayInt> ids12 = corrArray->getValueArray();
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> 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"
*/
//================================================================================
-void MEDPARTITIONER::MeshCollection::buildConnectZones()
+void MEDPARTITIONER::MeshCollection::buildBoundaryFaces()
{
+ if (_topology->nbDomain() < 2 || !_subdomain_boundary_creates )
+ return;
+
if ( getMeshDimension() < 2 )
return;
*/
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;
std::vector<MEDPARTITIONER::ConnectZone*>& MEDPARTITIONER::MeshCollection::getCZ()
{
- return _connect_zones;
+ return _topology->getCZ();
}
MEDPARTITIONER::Topology* MEDPARTITIONER::MeshCollection::getTopology() const
std::vector<std::vector<std::vector<int> > >& 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<ParaMEDMEM::MEDCouplingUMesh*>& meshesCastFrom,
//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<MEDPARTITIONER::ConnectZone*> _connect_zones;
-
//family ids storages
std::vector<ParaMEDMEM::DataArrayInt*> _cell_family_ids;
std::vector<ParaMEDMEM::DataArrayInt*> _face_family_ids;
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++)
{
return -1;
}
+std::vector<MEDPARTITIONER::ConnectZone*>& ParallelTopology::getCZ()
+{
+ return _connect_zones;
+}
+
/*!
* adding a face to the topology
*/
int convertGlobalNode(int iglobal, int idomain);
+ std::vector<MEDPARTITIONER::ConnectZone*>& getCZ();
+
//adding a face to the topology
void appendFace(int idomain, int ilocal, int iglobal);
typedef INTERP_KERNEL::HashMultiMap<int,std::pair<int,int> > TGlob2DomainLoc;
TGlob2DomainLoc _glob_to_loc;
- std::vector<std::vector<int> > _loc_to_glob;
- INTERP_KERNEL::HashMultiMap<int,std::pair<int,int> > _node_glob_to_loc;
+ TGlob2DomainLoc _node_glob_to_loc;
//mapping local -> global
+ std::vector<std::vector<int> > _loc_to_glob;
std::vector<std::vector <int> > _node_loc_to_glob;
// global numbers in parallel mode
int _nb_total_faces;
int _nb_domain;
int _mesh_dimension;
+
+ //links to connectzones
+ std::vector<MEDPARTITIONER::ConnectZone*> _connect_zones;
+
};
}
#endif
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<MEDPARTITIONER::ConnectZone*>& getCZ() = 0;
};
}