]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
Implement filling of ConnectZones
authoreap <eap@opencascade.com>
Thu, 21 May 2015 11:51:06 +0000 (14:51 +0300)
committereap <eap@opencascade.com>
Thu, 21 May 2015 11:51:06 +0000 (14:51 +0300)
src/MEDCoupling/MEDCouplingSkyLineArray.cxx
src/MEDCoupling/MEDCouplingSkyLineArray.hxx
src/MEDPartitioner/MEDPARTITIONER_ConnectZone.cxx
src/MEDPartitioner/MEDPARTITIONER_ConnectZone.hxx
src/MEDPartitioner/MEDPARTITIONER_MeshCollection.cxx
src/MEDPartitioner/MEDPARTITIONER_MeshCollection.hxx
src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.cxx
src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.hxx
src/MEDPartitioner/MEDPARTITIONER_Topology.hxx

index 5b1293a9dc35ab77000a685ce41b1986afd779a7..6134472b6a04c7689d9f1d2b3993b23c5d840acf 100644 (file)
 
 #include "MEDCouplingSkyLineArray.hxx"
 
-#include <vector>
-
 using namespace ParaMEDMEM;
 
-MEDCouplingSkyLineArray::MEDCouplingSkyLineArray()
+MEDCouplingSkyLineArray::MEDCouplingSkyLineArray():
+  _index( DataArrayInt::New() ), _value( DataArrayInt::New() )
 {
 }
 
index 1e6eb99f4594ea933ab453922b823523dfbac0bf..0390488dcadb1d940481c829ef8e7b8bee766772 100644 (file)
 #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:
@@ -37,11 +34,20 @@ class DataArrayInt;
   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
index 155526dbfb2ffcada861f7702c3fb61710db8efe..3726e0a1e63c525831fde32a5f40b1d5f9a4de61 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <map>
 
+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 <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;
     }
@@ -84,7 +86,7 @@ ParaMEDMEM::MEDCouplingUMesh *MEDPARTITIONER::ConnectZone::getDistantMesh() cons
 
 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)
@@ -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<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;
 }
 
@@ -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<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;
@@ -241,43 +277,47 @@ void MEDPARTITIONER::ConnectZone::setFaceCorresp(int * faceCorresp, int nbface)
       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;
 }
-
-
-
-
-
-
-
index 83190cbee787d83fdabd968fc8b9820a21f180ed..d943e7df5a612af8fd51b852979cca2a80e4566d 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "MEDPARTITIONER.hxx"
 #include "MEDCouplingUMesh.hxx"
-#include "MEDPARTITIONER_SkyLineArray.hxx"
+#include "MEDCouplingSkyLineArray.hxx"
 
 #include <map>
 #include <string>
@@ -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 <int,int>, SkyLineArray * > _entity_corresp;
+    std::map < std::pair <int,int>, ParaMEDMEM::MEDCouplingSkyLineArray * > _entity_corresp;
   };
 }
 # endif
index a5a4efcb0830a5cfd6dd00b901ed3a85bc2aa53b..7c61dda916fa819fad36a3caa726cd1dc9e7afdd 100644 (file)
 //
 
 #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>
@@ -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<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"
@@ -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::ConnectZone*>& MEDPARTITIONER::MeshCollection::getCZ()
 {
-  return _connect_zones;
+  return _topology->getCZ();
 }
 
 MEDPARTITIONER::Topology* MEDPARTITIONER::MeshCollection::getTopology() const
index 3fae6277fbd008c36d90b468e24669a1038e2655..dbc243dfdab4045fb20a6b845e336a1963571ffb 100644 (file)
@@ -150,7 +150,10 @@ namespace MEDPARTITIONER
                         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,
@@ -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<MEDPARTITIONER::ConnectZone*> _connect_zones;
-
     //family ids storages
     std::vector<ParaMEDMEM::DataArrayInt*> _cell_family_ids;
     std::vector<ParaMEDMEM::DataArrayInt*> _face_family_ids;
index d445d303231ddda3e4119b76c1c9252f9b9ccaf3..9f66e154e4e908140d8bb8085d7e4b073ab1cf1f 100644 (file)
@@ -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<MEDPARTITIONER::ConnectZone*>& ParallelTopology::getCZ()
+{
+  return _connect_zones;
+}
+
 /*!
  * adding a face to the topology
  */
index bc81aa8a45df92c5ae4078027ea91b9b8854c286..5de3f4820fad6f10f060dbcbd1bb471faea0f57f 100644 (file)
@@ -147,6 +147,8 @@ namespace MEDPARTITIONER
 
     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);
 
@@ -161,10 +163,10 @@ namespace MEDPARTITIONER
     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
@@ -185,6 +187,10 @@ namespace MEDPARTITIONER
     int _nb_total_faces;
     int _nb_domain;
     int _mesh_dimension;
+
+    //links to connectzones
+    std::vector<MEDPARTITIONER::ConnectZone*> _connect_zones;
+
   };
 }
 #endif
index 9ea47e8891886302aa28ad7ab156c9e8a3bf1d48..a9790ebad0f7eccc9006121fc196da0168382307 100644 (file)
@@ -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<MEDPARTITIONER::ConnectZone*>& getCZ() = 0;
   };
 }