]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
partition of meshes MEDCoupling with MEDCouplingFieldDouble BR_MEDPartitioner_dev
authorcvw <cvw>
Tue, 3 Jan 2012 15:25:20 +0000 (15:25 +0000)
committercvw <cvw>
Tue, 3 Jan 2012 15:25:20 +0000 (15:25 +0000)
25 files changed:
src/MEDPartitioner/MEDPARTITIONER.hxx
src/MEDPartitioner/MEDPARTITIONER_ConnectZone.cxx
src/MEDPartitioner/MEDPARTITIONER_ConnectZone.hxx
src/MEDPartitioner/MEDPARTITIONER_JointFinder.cxx
src/MEDPartitioner/MEDPARTITIONER_JointFinder.hxx
src/MEDPartitioner/MEDPARTITIONER_MESHCollection.cxx
src/MEDPartitioner/MEDPARTITIONER_MESHCollection.hxx
src/MEDPartitioner/MEDPARTITIONER_MESHCollectionDriver.cxx
src/MEDPartitioner/MEDPARTITIONER_MESHCollectionDriver.hxx
src/MEDPartitioner/MEDPARTITIONER_MESHCollectionMedAsciiDriver.cxx
src/MEDPartitioner/MEDPARTITIONER_MESHCollectionMedXMLDriver.cxx
src/MEDPartitioner/MEDPARTITIONER_METISGraph.cxx
src/MEDPartitioner/MEDPARTITIONER_METISGraph.hxx
src/MEDPartitioner/MEDPARTITIONER_ParaDomainSelector.cxx
src/MEDPartitioner/MEDPARTITIONER_ParaDomainSelector.hxx
src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.cxx
src/MEDPartitioner/MEDPARTITIONER_ParallelTopology.hxx
src/MEDPartitioner/MEDPARTITIONER_SkyLineArray.cxx
src/MEDPartitioner/MEDPARTITIONER_SkyLineArray.hxx
src/MEDPartitioner/MEDPARTITIONER_Topology.hxx
src/MEDPartitioner/MEDPARTITIONER_utils.cxx [new file with mode: 0644]
src/MEDPartitioner/MEDPARTITIONER_utils.hxx
src/MEDPartitioner/Makefile.am
src/MEDPartitioner/medpartitioner.cxx
src/MEDPartitioner/medpartitioner_para.cxx

index 80e64b033676137c0c306ad9e0a762ee582c6bac..e18a0da3a3717bdfd19d646e0aa5c34407c34276 100755 (executable)
@@ -1,4 +1,4 @@
- //  Copyright (C) 2007-2010  CEA/DEN, EDF R&D
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D
 //
 //  This library is free software; you can redistribute it and/or
 //  modify it under the terms of the GNU Lesser General Public
index 91e267ad6234c902dffc57a29908e8976dbb2ae9..0404107140c6c344c27279b9e60d0f486cdfc860 100644 (file)
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
-// few STL include files
-//
-#include <map>
-
 // few Med Memory include files
-#include "MEDMEM_define.hxx"
 #include "MEDCouplingUMesh.hxx"
 #include "MEDPARTITIONER_SkyLineArray.hxx"
 #include "MEDPARTITIONER_ConnectZone.hxx"
 
+// few STL include files
+#include <map>
+
 using namespace MEDPARTITIONER;
 
 CONNECTZONE::CONNECTZONE():
index fd50e772e28a259df0c7f81a1d34c56240fbb4db..feff431fe7350aa2fd4219a69b86824cce58fb00 100644 (file)
 # define __MEDPARTITIONER_CONNECTZONE_HXX__
 
 #include "MEDPARTITIONER.hxx"
+#include "MEDPARTITIONER_SkyLineArray.hxx"
 
 // few STL include files
 #include <map>
 #include <string>
 
-// few Med Memory include files
-// #include "MEDMEM_STRING.hxx"
-// #include "MEDMEM_define.hxx"
-// #include "MEDMEM_Mesh.hxx"
-#include "MEDPARTITIONER_SkyLineArray.hxx"
-
 namespace MEDPARTITIONER {
 class MEDPARTITIONER_EXPORT CONNECTZONE
 {
index 8a6ab8b780abb736708f6d105f433f7742b792ce..348764b84b8a93b261abbd593261a115b17b8be6 100644 (file)
@@ -3,6 +3,7 @@
 #include "MEDPARTITIONER_Topology.hxx"
 #include "MEDPARTITIONER_ParaDomainSelector.hxx"
 #include "MEDCouplingUMesh.hxx"
+#include "MEDPARTITIONER_utils.hxx"
 #include "BBTree.txx"
 
 
@@ -14,103 +15,137 @@ JointFinder::JointFinder(const MESHCollection& mc):_mesh_collection(mc), _topolo
 {
 }
 
+JointFinder::~JointFinder()
+{
+  //if (MyGlobals::_is0verbose>100) cout<<"TODO ~JointFinder"<<endl;
+}
+
 void JointFinder::findCommonDistantNodes()
 {
   int nbdomain=_topology->nbDomain();
   _distant_node_cell.resize(nbdomain);
   _node_node.resize(nbdomain);
-  for (int i=0; i<nbdomain;i++) 
-    {
-      _distant_node_cell[i].resize(nbdomain);
-      _node_node[i].resize(nbdomain);
-    }
+  for (int i=0; i<nbdomain; i++) 
+  {
+    _distant_node_cell[i].resize(nbdomain);
+    _node_node[i].resize(nbdomain);
+  }
   int nbproc=_domain_selector->nbProcs();
-  std::vector<BBTree<3>* > bbtree(nbdomain); 
-  std::vector<ParaMEDMEM::DataArrayInt*> rev(nbdomain);
-  std::vector<ParaMEDMEM::DataArrayInt*>revIndx(nbdomain);
+  std::vector<BBTree<3>* > bbtree(nbdomain,(BBTree<3>*) 0); 
+  std::vector<ParaMEDMEM::DataArrayInt*> rev(nbdomain,(DataArrayInt*) 0);
+  std::vector<ParaMEDMEM::DataArrayInt*> revIndx(nbdomain,(DataArrayInt*) 0);
   int meshDim;
   int spaceDim;
   
-  for (int mydomain=0;mydomain<nbdomain;mydomain++)
+  //init rev and revIndx and bbtree for my domain (of me:proc n)
+  for (int mydomain=0; mydomain<nbdomain; mydomain++)
+  {
+    if(!_domain_selector->isMyDomain(mydomain)) continue;
+    const ParaMEDMEM::MEDCouplingUMesh* myMesh=_mesh_collection.getMesh(mydomain);
+    meshDim=myMesh->getMeshDimension();
+    spaceDim= myMesh->getSpaceDimension();
+    rev[mydomain] = ParaMEDMEM::DataArrayInt::New();
+    revIndx[mydomain] = ParaMEDMEM::DataArrayInt::New();
+    myMesh->getReverseNodalConnectivity(rev[mydomain],revIndx[mydomain]);
+    double* bbx=new double[2*spaceDim*myMesh->getNumberOfNodes()];
+    for (int i=0; i<myMesh->getNumberOfNodes()*spaceDim; i++)
+    {
+      const double* coords=myMesh->getCoords()->getConstPointer();
+      bbx[2*i]=(coords[i])-1e-12;
+      bbx[2*i+1]=bbx[2*i]+2e-12;
+    }
+    bbtree[mydomain]=new BBTree<3> (bbx,0,0,myMesh->getNumberOfNodes(),-1e-12);
+    delete[] bbx;
+  }
+
+  //send my domains to other proc an receive other domains from other proc
+  for (int isource=0; isource<nbdomain; isource++)
+  {
+    for (int itarget=0; itarget<nbdomain; itarget++)
     {
-      if(! _domain_selector->isMyDomain(mydomain)) continue;
-      const ParaMEDMEM::MEDCouplingUMesh* myMesh=_mesh_collection.getMesh(mydomain);
+      const ParaMEDMEM::MEDCouplingUMesh* sourceMesh=_mesh_collection.getMesh(isource);
+      if (_domain_selector->isMyDomain(isource)&&_domain_selector->isMyDomain(itarget)) continue;
+      if (_domain_selector->isMyDomain(isource))
+      {
+        //preparing data for treatment on target proc
+        int targetProc = _domain_selector->getProcessorID(itarget);
+    
+        std::vector<double> vec(spaceDim*sourceMesh->getNumberOfNodes());
+        //cvw cout<<"\nproc "<<_domain_selector->rank()<<" : numberOfNodes "<<sourceMesh->getNumberOfNodes()<<endl;
+        std::copy(sourceMesh->getCoords()->getConstPointer(),sourceMesh->getCoords()->getConstPointer()+sourceMesh->getNumberOfNodes()*spaceDim,&vec[0]);
+        sendDoubleVec(vec,targetProc);
+    
+        //retrieving target data for storage in commonDistantNodes array
+        std::vector<int> localCorrespondency;
+        recvIntVec(localCorrespondency, targetProc);
+        //cvw cout<<"\nproc "<<_domain_selector->rank()<<" : nodeCellCorrespondency ";
+        for (int i=0; i<localCorrespondency.size()/2; i++)
+        {
+          _distant_node_cell[isource][itarget].insert(std::make_pair(localCorrespondency[2*i],localCorrespondency[2*i+1]));
+          //cvw cout<<" "<<localCorrespondency[2*i]<<"/"<<localCorrespondency[2*i+1];
+        }
+    
+      }
+      if (_domain_selector->isMyDomain(itarget))
+      {
+        //receiving data from source proc
+        int sourceProc = isource%nbproc;
+        std::vector<double> recvVec;
+        recvDoubleVec(recvVec,sourceProc);
+        std::map<int,int> commonNodes; // (local nodes, distant nodes) list
+        //cvw cout<<"\nproc "<<_domain_selector->rank()<<" : commonNodes ";
+        for (int inode=0; inode<(recvVec.size()/meshDim); inode++)
+        {
+          double* bbox=new double[2*spaceDim];
+          for (int i=0; i<spaceDim; i++)
+          {
+            bbox[2*i]=recvVec[inode*spaceDim+i]-1e-12;
+            bbox[2*i+1]=bbox[2*i]+2e-12;
+          }
+          std::vector<int> inodes;
+          bbtree[itarget]->getIntersectingElems(bbox,inodes);
+          delete[] bbox;
       
-      meshDim=myMesh->getMeshDimension();
-      spaceDim= myMesh->getSpaceDimension();
-      rev[mydomain] = ParaMEDMEM::DataArrayInt::New();
-      revIndx[mydomain] = ParaMEDMEM::DataArrayInt::New();
-      myMesh->getReverseNodalConnectivity(rev[mydomain],revIndx[mydomain]);
-      double* bbx=new double[2*spaceDim*myMesh->getNumberOfNodes()];
-      for (int i=0; i<myMesh->getNumberOfNodes()*spaceDim;i++)
+          if (inodes.size()>0) 
+          {
+            commonNodes.insert(std::make_pair(inodes[0],inode));
+            //cvw cout<<" "<<inodes[0]<<"/"<<inode;
+          }
+          
+        }
+        std::vector<int> nodeCellCorrespondency;
+        for (std::map<int,int>::iterator iter=commonNodes.begin(); iter!=commonNodes.end(); iter++)
         {
-          const double* coords=myMesh->getCoords()->getConstPointer();
-          bbx[2*i]=(coords[i])-1e-12;
-          bbx[2*i+1]=bbx[2*i]+2e-12;
+          _node_node[itarget][isource].push_back(std::make_pair(iter->first, iter->second));//storing node pairs in a vector
+          const int* revIndxPtr=revIndx[itarget]->getConstPointer();
+          const int* revPtr=rev[itarget]->getConstPointer();
+          for (int icell=revIndxPtr[iter->first]; icell<revIndxPtr[iter->first+1]; icell++)
+          {
+            nodeCellCorrespondency.push_back(iter->second); //
+            int globalCell=_topology->convertCellToGlobal(itarget,revPtr[icell]);
+            nodeCellCorrespondency.push_back(globalCell);
+            //nodeCellCorrespondency.push_back(revPtr[icell]); //need to set at global numerotation 
+            //cout<<"processor "<<MyGlobals::_rank<<" : isource "<<isource<<" itarget "<<itarget<<
+            //      " node "<<iter->second<<" cellLoc "<<revPtr[icell]<<" cellGlob "<<globalCell<<endl;
+          }
+        }
+        //std::cout<<"proc "<<_domain_selector->rank()<<" : JointFinder sendIntVec "<<_domain_selector->rank()<<std::endl;  //cvwdebug
+        sendIntVec(nodeCellCorrespondency, sourceProc); //itarget proc send to other (otherLocalNode-itargetGlobalCell)
         }
-      bbtree[mydomain]=new BBTree<3> (bbx,0,0,myMesh->getNumberOfNodes(),-1e-12);
+      }
+    }
+    //free  rev(nbdomain) revIndx(nbdomain) bbtree(nbdomain)
+    for (int i=0; i<nbdomain; i++)
+    {
+      if (rev[i]!=0) rev[i]->decrRef();
+      if (revIndx[i]!=0) revIndx[i]->decrRef();
+      if (bbtree[i]!=0) delete bbtree[i];
     }
 
-  for (int isource=0;isource<nbdomain;isource++)
-    for (int itarget=0;itarget<nbdomain;itarget++)
-       {
-            const ParaMEDMEM::MEDCouplingUMesh* sourceMesh=_mesh_collection.getMesh(isource);
-        
-            if (_domain_selector->isMyDomain(isource)&&_domain_selector->isMyDomain(itarget)) continue;
-            if (_domain_selector->isMyDomain(isource))
-              {
-                //preparing data for treatment on target proc
-                int targetProc = _domain_selector->getProcessorID(itarget);
-            
-                std::vector<double> vec(spaceDim*sourceMesh->getNumberOfNodes());
-                std::copy(sourceMesh->getCoords()->getConstPointer(),sourceMesh->getCoords()->getConstPointer()+sourceMesh->getNumberOfNodes()*spaceDim,&vec[0]);
-                _domain_selector->sendDoubleVec (vec,targetProc);
-            
-                //retrieving target data for storage in commonDistantNodes array
-                std::vector<int> localCorrespondency;
-                _domain_selector->recvIntVec(localCorrespondency, targetProc);
-                for (int i=0; i<localCorrespondency.size()/2;i++)
-                  _distant_node_cell[isource][itarget].insert(std::make_pair(localCorrespondency[2*i],localCorrespondency[2*i+1]));      
-            
-              }
-            if (_domain_selector->isMyDomain(itarget))    
-              {
-                //receiving data from source proc
-                int sourceProc = isource%nbproc;
-                std::vector<double> recvVec;
-                _domain_selector->recvDoubleVec(recvVec,sourceProc);
-                std::map<int,int> commonNodes; // (local nodes, distant nodes) list
-                for (int inode=0; inode<(recvVec.size()/meshDim);inode++)
-                  {
-                    double* bbox=new double[2*spaceDim];
-                    for (int i=0; i<spaceDim;i++)
-                      {
-                        bbox[2*i]=recvVec[inode*spaceDim+i]-1e-12;
-                        bbox[2*i+1]=bbox[2*i]+2e-12;
-                      }
-                    std::vector<int> inodes;
-                    bbtree[itarget]->getIntersectingElems(bbox,inodes);
-                    delete[] bbox;
-                
-                    if (inodes.size()>0) commonNodes.insert(std::make_pair(inodes[0],inode));
-                  }
-                std::vector<int> nodeCellCorrespondency;
-                for (std::map<int,int>::iterator iter=commonNodes.begin();iter!=commonNodes.end();iter++)
-                  {
-                    _node_node[itarget][isource].push_back(std::make_pair(iter->first, iter->second));//storing node pairs in a vector
-                    const int*revIndxPtr=revIndx[itarget]->getConstPointer();
-                    const int*revPtr=rev[itarget]->getConstPointer();
-                    for (int icell=revIndxPtr[iter->first];icell<revIndxPtr[iter->first+1];icell++)
-                      {
-                        nodeCellCorrespondency.push_back(iter->second);
-                        nodeCellCorrespondency.push_back(revPtr[icell]);
-                      }
-                  }
-                _domain_selector->sendIntVec(nodeCellCorrespondency, sourceProc);
-              }
-          }
-    
+    if (MyGlobals::_verbose>100) 
+      std::cout<<"proc "<<_domain_selector->rank()<<" : end JointFinder::findCommonDistantNodes"<<std::endl;
 }
+
 std::vector<std::vector<std::multimap<int,int> > > & JointFinder::getDistantNodeCell()
 {
   return _distant_node_cell;
@@ -120,3 +155,40 @@ std::vector<std::vector<std::vector<std::pair<int,int> > > >& JointFinder::getNo
 {
   return _node_node;
 }
+
+void JointFinder::print()
+//it is for debug on small arrays under mpi 2,3 cpus
+{
+   int nbdomain=_topology->nbDomain();
+   //MPI_Barrier(MPI_COMM_WORLD);
+   if (MyGlobals::_is0verbose>0) 
+     cout<<"\nJointFinder print node-node (nn)iproc|itarget|isource|i|inodefirst-inodesecond\n\n"<<
+           "JointFinder print distantNode=cell (nc)iproc|itarget|isource|inode=icell\n\n";
+   for (int isource=0; isource<nbdomain; isource++)
+   {
+     for (int itarget=0; itarget<nbdomain; itarget++)
+     {
+       for (int i=0; i<_node_node[itarget][isource].size(); i++)
+         cout<<" nn"<<_domain_selector->rank()<<itarget<<"|"<<isource<<"|"<<i<<"|"<<
+               _node_node[itarget][isource][i].first<<"-"<<
+               _node_node[itarget][isource][i].second;
+     }
+   }
+   cout<<endl;
+   //MPI_Barrier(MPI_COMM_WORLD);
+   
+   //cout<<"proc "<<_domain_selector->rank()<<" : JointFinder _distant_node_cell itarget/isource/inode=icell"<<endl;
+   for (int isource=0; isource<nbdomain; isource++)
+   {
+     for (int itarget=0; itarget<nbdomain; itarget++)
+     {
+       std::multimap<int,int>::iterator it;
+       for (it=_distant_node_cell[isource][itarget].begin() ; it!=_distant_node_cell[isource][itarget].end(); it++)
+       {
+         cout<<" nc"<<_domain_selector->rank()<<"|"<<itarget<<"|"<<isource<<"|"<<(*it).first<<"="<<(*it).second;
+       }
+     }
+   }
+   cout<<endl;
+   //MPI_Barrier(MPI_COMM_WORLD);
+}
index 558f06b39835b7f69edd4a4a6ff10ca6d4df8743..45860c96502dc7293f19dd36f79494be25c64584 100644 (file)
@@ -29,14 +29,17 @@ class JointFinder
 {
 public:
   JointFinder(const MESHCollection& mc);
+  ~JointFinder();
   void findCommonDistantNodes();
+  void print();
   std::vector<std::vector<std::multimap<int,int> > >& getDistantNodeCell();
   std::vector<std::vector<std::vector<std::pair<int,int> > > >& getNodeNode();
+  std::vector<std::vector<std::multimap<int,int> > > _distant_node_cell;
 private:
   const MESHCollection& _mesh_collection;
   const ParaDomainSelector* _domain_selector;
   const Topology* _topology;
-  std::vector<std::vector<std::multimap<int,int> > > _distant_node_cell;
+  //std::vector<std::vector<std::multimap<int,int> > > _distant_node_cell;
   std::vector<std::vector<std::vector<std::pair<int,int> > > > _node_node;
 };
 };
index 79076e87356ee80552b86cabd813cc16f17ab865..eaab9f5217eb41fd4fd20818f9faf458002eb4a2 100644 (file)
@@ -17,8 +17,6 @@
 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
  
-#include "MEDMEM_Exception.hxx"
-
 #include "MEDCouplingUMesh.hxx"
 #include "MEDCouplingNormalizedUnstructuredMesh.hxx"
 #include "MEDCouplingMemArray.hxx"
 #include "MEDPARTITIONER_MESHCollectionMedAsciiDriver.hxx"
 #include "MEDPARTITIONER_JointFinder.hxx"
 #include "MEDPARTITIONER_UserGraph.hxx"
+#include "MEDLoader.hxx"
+#include "MEDCouplingFieldDouble.hxx"
 
+#ifdef HAVE_MPI2
+#include <mpi.h>
+#endif
 
 #ifdef ENABLE_METIS
 #include "MEDPARTITIONER_METISGraph.hxx"
@@ -73,7 +76,8 @@ MESHCollection::MESHCollection()
     _driver_type(MEDPARTITIONER::MedXML),
     _subdomain_boundary_creates(false),
     _family_splitting(false),
-    _create_empty_groups(false)
+    _create_empty_groups(false),
+    _joint_finder(0)
 {
 }
 
@@ -88,7 +92,11 @@ MESHCollection::MESHCollection()
  * \param topology topology containing the cell mappings
  */
 
-MESHCollection::MESHCollection(MESHCollection& initialCollection, Topology* topology, bool family_splitting, bool create_empty_groups)
+MESHCollection::MESHCollection(
+      MESHCollection& initialCollection, 
+      Topology* topology, 
+      bool family_splitting, 
+      bool create_empty_groups) //cvwat04
   : _name(initialCollection._name),
     _topology(topology),
     _owns_topology(false),
@@ -98,139 +106,174 @@ MESHCollection::MESHCollection(MESHCollection& initialCollection, Topology* topo
     _driver_type(MEDPARTITIONER::MedXML),
     _subdomain_boundary_creates(false),
     _family_splitting(family_splitting),
-    _create_empty_groups(create_empty_groups)
+    _create_empty_groups(create_empty_groups),
+    _joint_finder(0)
 {
-  
   std::vector<std::vector<std::vector<int> > > new2oldIds(initialCollection.getTopology()->nbDomain());
-   castCellMeshes(initialCollection, new2oldIds);
+  if (MyGlobals::_verbose>10) std::cout<<"proc "<<MyGlobals::_rank<<" : castCellMeshes"<<std::endl;
+  castCellMeshes(initialCollection, new2oldIds);
 
   //defining the name for the collection and the underlying meshes
   setName(initialCollection.getName());
 
-  /////////////////:
-  // treating faces
+  /////////////////
+  //treating faces
   /////////////////
 
+  if (MyGlobals::_is0verbose) std::cout<<"treating faces"<<std::endl;
   NodeMapping nodeMapping;
+  //nodeMapping contains the mapping between old nodes and new nodes
+  // (iolddomain,ioldnode)->(inewdomain,inewnode)
   createNodeMapping(initialCollection, nodeMapping);
+  //cvw std::cout<<"castMeshes"<<std::endl;
   std::vector<std::vector<std::vector<int> > > new2oldFaceIds;
-  castMeshes(initialCollection.getFaceMesh(), this->getFaceMesh(),initialCollection, nodeMapping, new2oldFaceIds);
+  castFaceMeshes(initialCollection, nodeMapping, new2oldFaceIds);
 
   ////////////////////
   //treating families
   ////////////////////
 
-  _faceFamilyIds.resize(topology->nbDomain());
-  _cellFamilyIds.resize(topology->nbDomain());
-  //allocating family ids arrays
-  for (int inew=0; inew<topology->nbDomain();inew++)
-    {
-      if(isParallelMode() && !_domain_selector->isMyDomain(inew)) continue;
-      _cellFamilyIds[inew]=ParaMEDMEM::DataArrayInt::New();
-      int nbCells=_mesh[inew]->getNumberOfCells();
-      int* ptrCellIds=new int[nbCells];
-      for (int i=0; i< nbCells;i++) ptrCellIds[i]=0;
-      _cellFamilyIds[inew]->useArray(ptrCellIds,true, ParaMEDMEM::CPP_DEALLOC,nbCells,1);
-
-      int nbFaces=_faceMesh[inew]->getNumberOfCells();
-      _faceFamilyIds[inew]=ParaMEDMEM::DataArrayInt::New();
-      int* ptrFaceIds=new int[nbFaces];
-      for (int i=0; i<nbFaces;i++) ptrFaceIds[i]=0;
-      _faceFamilyIds[inew]->useArray(ptrFaceIds,true, ParaMEDMEM::CPP_DEALLOC,nbFaces,1); 
-    }
-
-  //casting cell and face  families on new meshes
-  castIntField(initialCollection.getMesh(), this->getMesh(),initialCollection.getCellFamilyIds(),_cellFamilyIds);
-  castIntField(initialCollection.getFaceMesh(), this->getFaceMesh(),initialCollection.getFaceFamilyIds(),_faceFamilyIds);
-
-
-  ///////////////////////
-  ////treating groups
-  //////////////////////
+  if (MyGlobals::_is0verbose) 
+    if (isParallelMode()) std::cout<<"ParallelMode on "<<topology->nbDomain()<<" Domains"<<std::endl;
+    else std::cout<<"NOT ParallelMode on "<<topology->nbDomain()<<" Domains"<<std::endl;
+    
+  if (MyGlobals::_is0verbose>10) std::cout<<"treating cell and face families"<<std::endl;
+  
+  castIntField2(initialCollection.getMesh(),
+                this->getMesh(),
+                initialCollection.getCellFamilyIds(),
+                "cellFamily");
+  castIntField2(initialCollection.getFaceMesh(), 
+                this->getFaceMesh(),
+                initialCollection.getFaceFamilyIds(),
+                "faceFamily");
+
+  //////////////////
+  //treating groups
+  //////////////////
+  if (MyGlobals::_is0verbose) std::cout<<"treating groups"<<std::endl;
   _familyInfo=initialCollection.getFamilyInfo();
   _groupInfo=initialCollection.getGroupInfo();
-
+  
+  //////////////////
+  //treating fields
+  //////////////////
+  if (MyGlobals::_is0verbose) std::cout<<"treating fields"<<std::endl;
+  //cvwat08
+  castAllFields(initialCollection,"cellFieldDouble");
+  //castAllFields(initialCollection,"faceFieldsIds");
 }
 
 /*!
-Creates the meshes using the topology underlying he mesh collection and the mesh data coming from the ancient collection
+Creates the meshes using the topology underlying he mesh collection and the mesh data 
+coming from the ancient collection
 \param initialCollection collection from which the data is extracted to create the new meshes
  */
 
-void MESHCollection::castCellMeshes(MESHCollection& initialCollection, std::vector<std::vector<std::vector<int> > >& new2oldIds)
+void MESHCollection::castCellMeshes(
+      MESHCollection& initialCollection,
+      std::vector<std::vector<std::vector<int> > >& new2oldIds)
 {
-  if (_topology==0) throw INTERP_KERNEL::Exception("Topology has not been defined on call to castCellMeshes");
-  _mesh.resize(_topology->nbDomain());
+  if (_topology==0) throw INTERP_KERNEL::Exception(LOCALIZED("Topology has not been defined on call to castCellMeshes"));
   
-  //splitting the initial domains into smaller bits
+  int nbNewDomain=_topology->nbDomain();
+  int nbOldDomain=initialCollection.getTopology()->nbDomain();
   
+  _mesh.resize(nbNewDomain);
+  int rank=MyGlobals::_rank;
+  //if (MyGlobals::_verbose>10) std::cout<<"proc "<<rank<<" : castCellMeshes splitting"<<std::endl;
+  //splitting the initial domains into smaller bits
   std::vector<std::vector<ParaMEDMEM::MEDCouplingUMesh*> > splitMeshes;
-  splitMeshes.resize(_topology->nbDomain());
-  for (int inew=0; inew<_topology->nbDomain();inew++)
-    {
-      splitMeshes[inew].resize(initialCollection.getTopology()->nbDomain());
-      std::fill(&(splitMeshes[inew][0]),&(splitMeshes[inew][0])+splitMeshes[inew].size(),(ParaMEDMEM::MEDCouplingUMesh*)0);
-    }
+  splitMeshes.resize(nbNewDomain);
+  for (int inew=0; inew<nbNewDomain; inew++)
+  {
+    splitMeshes[inew].resize(nbOldDomain, (ParaMEDMEM::MEDCouplingUMesh*)0);
+    /*std::fill( &(splitMeshes[inew][0]), 
+               &(splitMeshes[inew][0])+splitMeshes[inew].size(), 
+               (ParaMEDMEM::MEDCouplingUMesh*)0 );*/
+  }
   
-  for (int iold=0; iold<initialCollection.getTopology()->nbDomain();iold++)
+  for (int iold=0; iold<nbOldDomain; iold++)
+  {
+    if (!isParallelMode() || initialCollection._domain_selector->isMyDomain(iold))
     {
-      if (!isParallelMode() || initialCollection._domain_selector->isMyDomain(iold))
-        {
-          int size=(initialCollection._mesh)[iold]->getNumberOfCells();
-          std::vector<int> globalids(size);
-          initialCollection.getTopology()->getCellList(iold, &globalids[0]);
-          std::vector<int> ilocalnew(size);
-          std::vector<int> ipnew(size);
-          _topology->convertGlobalCellList(&globalids[0],size,&ilocalnew[0],&ipnew[0]);
-          new2oldIds[iold].resize(_topology->nbDomain());
-          for (int i=0; i<ilocalnew.size();i++)
-            {
-              new2oldIds[iold][ipnew[i]].push_back(i);
-            }
-          for (int inew=0;inew<_topology->nbDomain();inew++)
-            {
-              splitMeshes[inew][iold]=(ParaMEDMEM::MEDCouplingUMesh*)(initialCollection.getMesh())[iold]->buildPartOfMySelf(&new2oldIds[iold][inew][0],&new2oldIds[iold][inew][0]+new2oldIds[iold][inew].size(),true);
-            }
-        }
+      int size=(initialCollection._mesh)[iold]->getNumberOfCells();
+      std::vector<int> globalids(size);
+      initialCollection.getTopology()->getCellList(iold, &globalids[0]);
+      std::vector<int> ilocalnew(size); //local
+      std::vector<int> ipnew(size);     //idomain old
+      //cvw work locally
+      _topology->convertGlobalCellList(&globalids[0],size,&ilocalnew[0],&ipnew[0]);
+      
+      new2oldIds[iold].resize(nbNewDomain);
+      for (int i=0; i<ilocalnew.size(); i++)
+      {
+        new2oldIds[iold][ipnew[i]].push_back(i);
+      }
+      for (int inew=0; inew<nbNewDomain; inew++)
+      {
+        splitMeshes[inew][iold]=(ParaMEDMEM::MEDCouplingUMesh*)
+            (initialCollection.getMesh())[iold]->buildPartOfMySelf(
+                &new2oldIds[iold][inew][0],
+                &new2oldIds[iold][inew][0]+new2oldIds[iold][inew].size(),
+                true);
+        if (MyGlobals::_verbose>400)
+          std::cout<<"proc "<<rank<<" : a splitMesh iold inew NbCells "<<iold<<" "<<inew<<" "
+                   <<splitMeshes[inew][iold]->getNumberOfCells()<<std::endl;
+      }
     }
+  }
 
   if (isParallelMode())
-    {
-      for (int iold=0; iold<initialCollection.getTopology()->nbDomain();iold++)
-        for(int inew=0;inew<_topology->nbDomain();inew++)
-          {
-            if (initialCollection._domain_selector->isMyDomain(iold) && _domain_selector->isMyDomain(inew)) continue;
-          
-            if(initialCollection._domain_selector->isMyDomain(iold))
-              _domain_selector->sendMesh(*(splitMeshes[inew][iold]),_domain_selector->getProcessorID(inew));
-            
-            if (_domain_selector->isMyDomain(inew))
-              _domain_selector->recvMesh(splitMeshes[inew][iold],_domain_selector->getProcessorID(iold));
-            
-          }
-    }
+  {
+    //if (MyGlobals::_verbose>300) std::cout<<"proc "<<rank<<" : castCellMeshes send/receive"<<std::endl;
+    for (int iold=0; iold<nbOldDomain; iold++)
+      for(int inew=0; inew<nbNewDomain; inew++)
+      {
+        if (initialCollection._domain_selector->isMyDomain(iold) && _domain_selector->isMyDomain(inew)) continue;
+
+        if(initialCollection._domain_selector->isMyDomain(iold))
+          _domain_selector->sendMesh(*(splitMeshes[inew][iold]),_domain_selector->getProcessorID(inew));
+
+        if (_domain_selector->isMyDomain(inew))
+          _domain_selector->recvMesh(splitMeshes[inew][iold],_domain_selector->getProcessorID(iold));
+
+      }
+  }
   
   //fusing the split meshes
-  for (int inew=0; inew<_topology->nbDomain()  ;inew++)
-    {
-      std::vector<const ParaMEDMEM::MEDCouplingUMesh*> meshes;
-     
-      for (int i=0; i< splitMeshes[inew].size();i++)
-        if (splitMeshes[inew][i]!=0) meshes.push_back(splitMeshes[inew][i]);
+  if (MyGlobals::_verbose>200) std::cout<<"proc "<<rank<<" : castCellMeshes fusing"<<std::endl;
+  for (int inew=0; inew<nbNewDomain ;inew++)
+  {
+    std::vector<const ParaMEDMEM::MEDCouplingUMesh*> meshes;
+    
+    for (int i=0; i< splitMeshes[inew].size();i++)
+      if (splitMeshes[inew][i]!=0) 
+        if (splitMeshes[inew][i]->getNumberOfCells()>0)
+          meshes.push_back(splitMeshes[inew][i]);
 
-      if (!isParallelMode()||_domain_selector->isMyDomain(inew))
-        {
-          _mesh[inew]=ParaMEDMEM::MEDCouplingUMesh::MergeUMeshes(meshes);
-          bool areNodesMerged;
-          int nbNodesMerged;
-          ParaMEDMEM::DataArrayInt* array=_mesh[inew]->mergeNodes(1e-12,areNodesMerged,nbNodesMerged);
-          array->decrRef(); // array is not used in this case
-          _mesh[inew]->zipCoords();
-        }
-      for (int i=0; i< splitMeshes[inew].size();i++)
-        if (splitMeshes[inew][i]!=0) splitMeshes[inew][i]->decrRef();
-    }  
-  
+    if (!isParallelMode()||_domain_selector->isMyDomain(inew))
+    {
+      if (meshes.size()==0) 
+      {
+        _mesh[inew]=createEmptyMEDCouplingUMesh();
+        //throw INTERP_KERNEL::Exception(LOCALIZED("castCellMeshes fusing : no meshes"));
+        cout<<"WARNING : castCellMeshes fusing : no meshes try another number of processors"<<endl;
+      }
+      else
+      {
+        _mesh[inew]=ParaMEDMEM::MEDCouplingUMesh::MergeUMeshes(meshes);
+        bool areNodesMerged;
+        int nbNodesMerged;
+        ParaMEDMEM::DataArrayInt* array=_mesh[inew]->mergeNodes(1e-12,areNodesMerged,nbNodesMerged);
+        array->decrRef(); // array is not used in this case
+        _mesh[inew]->zipCoords();
+      }
+    }
+    for (int i=0; i< splitMeshes[inew].size(); i++)
+      if (splitMeshes[inew][i]!=0) splitMeshes[inew][i]->decrRef();
+  }  
+  if (MyGlobals::_verbose>300) std::cout<<"proc "<<rank<<" : castCellMeshes end fusing"<<std::endl;
 }
 
 /*!
@@ -239,7 +282,8 @@ void MESHCollection::castCellMeshes(MESHCollection& initialCollection, std::vect
 */
 void MESHCollection::createNodeMapping( MESHCollection& initialCollection, NodeMapping& nodeMapping)
 {
-
+  using std::vector;
+  using std::make_pair;
   //  NodeMapping reverseNodeMapping;
   for (int iold=0; iold<initialCollection.getTopology()->nbDomain();iold++)
     {
@@ -253,7 +297,7 @@ void MESHCollection::createNodeMapping( MESHCollection& initialCollection, NodeM
           bbox=new double[nvertices*6];
           ParaMEDMEM::DataArrayDouble* coords = initialCollection.getMesh(iold)->getCoords();
           double* coordsPtr=coords->getPointer();
-              
+
           for (int i=0; i<nvertices*3;i++)
             {
               bbox[i*2]=coordsPtr[i]-1e-6;
@@ -261,8 +305,8 @@ void MESHCollection::createNodeMapping( MESHCollection& initialCollection, NodeM
             }
           tree=new BBTree<3>(bbox,0,0,nvertices,1e-9);
         }
-              
-      for (int inew=0; inew<_topology->nbDomain(); inew++)
+
+      for (int inew=0; inew<_topology->nbDomain(); inew++) //cvwat12
         {
           //sending meshes for parallel computation
           if (isParallelMode() && _domain_selector->isMyDomain(inew) && !_domain_selector->isMyDomain(iold))  
@@ -275,24 +319,22 @@ void MESHCollection::createNodeMapping( MESHCollection& initialCollection, NodeM
               for (int inode=0; inode<mesh->getNumberOfNodes();inode++)
                 {
                   double* coordsPtr=coords->getPointer()+inode*3;
-                  std::vector<int> elems;
+                  vector<int> elems;
                   tree->getElementsAroundPoint(coordsPtr,elems);
-                  if (elems.size()==0) continue;         
+                  if (elems.size()==0) continue;
                   nodeMapping.insert(make_pair(make_pair(iold,elems[0]),make_pair(inew,inode)));
-                 }
+                }
+              mesh->decrRef();
             }
           else if (!isParallelMode() || (_domain_selector->isMyDomain(inew) && _domain_selector->isMyDomain(iold)))
             {
-              ParaMEDMEM::DataArrayDouble* coords = getMesh(inew)->getCoords();           
-            
+              ParaMEDMEM::DataArrayDouble* coords = getMesh(inew)->getCoords();
               for (int inode=0; inode<_mesh[inew]->getNumberOfNodes();inode++)
                 {
-                  
                   double* coordsPtr=coords->getPointer()+inode*3;
-     
-                  std::vector<int> elems;
+                  vector<int> elems;
                   tree->getElementsAroundPoint(coordsPtr,elems);
-                  if (elems.size()==0) continue;              
+                  if (elems.size()==0) continue;
                   nodeMapping.insert(make_pair(make_pair(iold,elems[0]),make_pair(inew,inode)));
                 }
             }
@@ -306,40 +348,95 @@ void MESHCollection::createNodeMapping( MESHCollection& initialCollection, NodeM
 
 }
 
+//getNodeIds(meshCell, meshFace, nodeIds)
+//inodeCell=nodeIds[inodeFace]
+//(put the biggest mesh in One)
+//if no corresponding node then inodeCell==-1
+void getNodeIds(ParaMEDMEM::MEDCouplingUMesh& meshOne, ParaMEDMEM::MEDCouplingUMesh& meshTwo, vector<int>& nodeIds)
+{
+  using std::vector;
+  if (!&meshOne || !&meshTwo) return;  //empty or not existing
+  double* bbox;
+  BBTree<3>* tree;
+  int nv1=meshOne.getNumberOfNodes();
+  bbox=new double[nv1*6];
+  ParaMEDMEM::DataArrayDouble* coords=meshOne.getCoords();
+  double* coordsPtr=coords->getPointer();
+  for (int i=0; i<nv1*3; i++)
+  {
+    bbox[i*2]=coordsPtr[i]-1e-6;
+    bbox[i*2+1]=coordsPtr[i]+1e-6;
+  }
+  tree=new BBTree<3>(bbox,0,0,nv1,1e-9);
+  
+  int nv2=meshTwo.getNumberOfNodes();
+  nodeIds.resize(nv2,-1);
+  coords=meshTwo.getCoords();
+  for (int inode=0; inode<nv2; inode++)
+  {
+    double* coordsPtr=coords->getPointer()+inode*3;
+    vector<int> elems;
+    tree->getElementsAroundPoint(coordsPtr,elems);
+    if (elems.size()==0) continue;
+    nodeIds[inode]=elems[0];
+  }
+  delete tree;
+  delete[] bbox;
+}
+
 /*!
   creates the face meshes on the new domains from the faces on the old domain and the node mapping
   faces at the interface are duplicated
 */
-
-void MESHCollection::castMeshes(std::vector<ParaMEDMEM::MEDCouplingUMesh*>& meshesCastFrom,std::vector<ParaMEDMEM::MEDCouplingUMesh*>& meshesCastTo, MESHCollection& initialCollection,const NodeMapping& nodeMapping, std::vector<std::vector<std::vector<int> > >& new2oldIds)
+void MESHCollection::castFaceMeshes(MESHCollection& initialCollection,
+                    const std::multimap<std::pair<int,int>, std::pair<int,int> >& nodeMapping,
+                    std::vector<std::vector<std::vector<int> > >& new2oldIds)
 {
 
   //splitMeshes structure will contain the partition of 
   //the old faces on the new ones
-  // splitMeshes[4][2] contains the faces from old domain 2
-  // that have to be added to domain 4
-
+  //splitMeshes[4][2] contains the faces from old domain 2
+  //that have to be added to domain 4
+  
+  using std::vector;
+  using std::map;
+  using std::multimap;
+  using std::pair;
+  using std::make_pair;
+  
+  vector<ParaMEDMEM::MEDCouplingUMesh*>& meshesCastFrom=initialCollection.getFaceMesh();
+  vector<ParaMEDMEM::MEDCouplingUMesh*>& meshesCastTo=this->getFaceMesh();
+  
   vector< vector<ParaMEDMEM::MEDCouplingUMesh*> > splitMeshes;
   int newSize=_topology->nbDomain();
-  splitMeshes.resize ( newSize );
+  int fromSize=meshesCastFrom.size();
+  
+  splitMeshes.resize(newSize);
+  for (int inew=0;inew<newSize;inew++) splitMeshes[inew].resize(fromSize);
+  new2oldIds.resize(fromSize);
+  for (int iold=0;iold<fromSize;iold++) new2oldIds[iold].resize(newSize);
+  
+  //init null pointer for empty meshes
   for (int inew=0;inew<newSize;inew++)
+  {
+    for (int iold=0;iold<fromSize;iold++)
     {
-      splitMeshes[inew].resize(meshesCastFrom.size());
+       splitMeshes[inew][iold]=0; //null for empty meshes
+       new2oldIds[iold][inew].clear();
     }
-
-
-  new2oldIds.resize(meshesCastFrom.size());
+  }
 
   //loop over the old domains to analyse the faces and decide 
   //on which new domain they belong
-
-  for (int iold=0; iold<meshesCastFrom.size();iold++)
+  
+  for (int iold=0; iold<fromSize;iold++)
+  {
+    if (isParallelMode() && !_domain_selector->isMyDomain(iold)) continue;
+    if (meshesCastFrom[iold] != 0)
     {
-      if (isParallelMode() && !_domain_selector->isMyDomain(iold)) continue;
-      new2oldIds[iold].resize(newSize);
-      for (int ielem=0;ielem<meshesCastFrom[iold]->getNumberOfCells();ielem++)
-        {
-          std::vector<int> nodes;
+      for (int ielem=0; ielem<meshesCastFrom[iold]->getNumberOfCells(); ielem++)
+      {
+          vector<int> nodes;
           meshesCastFrom[iold]->getNodeIdsOfCell(ielem,nodes);
           
           map <int,int> faces;
@@ -350,140 +447,472 @@ void MESHCollection::castMeshes(std::vector<ParaMEDMEM::MEDCouplingUMesh*>& mesh
           //are incremented for each target node
           //the face is considered as going to target domains if the counter of the domain 
           //is equal to the number of nodes
-          for (int inode=0;inode<nodes.size();inode++)
-            {
+          for (int inode=0; inode<nodes.size(); inode++)
+          {
               typedef multimap<pair<int,int>,pair<int,int> >::const_iterator MI;
               int mynode=nodes[inode];
 
               pair <MI,MI> myRange = nodeMapping.equal_range(make_pair(iold,mynode));
               for (MI iter=myRange.first; iter!=myRange.second; iter++)
-                {
+              {
                   int inew=iter->second.first;
                   if (faces.find(inew)==faces.end())
                     faces[inew]=1;
                   else
                     faces[inew]++;
-                }
-            }
+              }
+          }
           
-          for (map<int,int>::iterator iter=faces.begin();
-               iter!=faces.end();
-               iter++)
-            {
+          for (map<int,int>::iterator iter=faces.begin(); iter!=faces.end(); iter++)
+          {
               if (iter->second==nodes.size())
+                //cvw eligible but may be have to be face of a cell of this->getMesh()[inew]?
+                //it is not sure here...
+                //done before writeMedfile on option?... see filterFaceOnCell()
                 new2oldIds[iold][iter->first].push_back(ielem);
-            }
-        }        
+          }
+      }
       
       //creating the splitMeshes from the face ids
       for (int inew=0;inew<_topology->nbDomain();inew++)
-        {
-          splitMeshes[inew][iold]=(ParaMEDMEM::MEDCouplingUMesh*)(meshesCastFrom[iold]->buildPartOfMySelf(&new2oldIds[iold][inew][0],&new2oldIds[iold][inew][0]+new2oldIds[iold][inew].size(),true));
-          splitMeshes[inew][iold]->zipCoords();
-        }
+      {
+          if (meshesCastFrom[iold]->getNumberOfCells() > 0) //cvw
+          {
+            splitMeshes[inew][iold]=
+              (ParaMEDMEM::MEDCouplingUMesh*) 
+              ( meshesCastFrom[iold]->buildPartOfMySelf(
+                  &new2oldIds[iold][inew][0],
+                  &new2oldIds[iold][inew][0]+new2oldIds[iold][inew].size(),
+                  true) 
+              );
+            splitMeshes[inew][iold]->zipCoords();
+          }
+          else
+          {
+            //std::cout<<"one empty mesh from "<<iold<<std::endl; //cvw
+            splitMeshes[inew][iold]=createEmptyMEDCouplingUMesh();
+          }
+      }
     }
-      
+    else
+    {
+      std::cout<<"proc "<<MyGlobals::_rank<<" : castFaceMeshes empty mesh from iodDomain "<<iold<<std::endl;
+    }
+  }
+  
   // send/receive stuff
   if (isParallelMode())
-  for (int iold=0; iold<meshesCastFrom.size();iold++)
+  {
+  ParaMEDMEM::MEDCouplingUMesh *empty=createEmptyMEDCouplingUMesh();
+  for (int iold=0; iold<fromSize; iold++)
     for (int inew=0; inew<newSize; inew++)
       {
+        /*std::cout<<"iold inew "<<iold<<" "<<inew<<" "<<
+                   _domain_selector->isMyDomain(iold)<<" "<<
+                   _domain_selector->isMyDomain(inew)<<std::endl;*/
         if (_domain_selector->isMyDomain(iold) && !_domain_selector->isMyDomain(inew))
-          _domain_selector->sendMesh(*(splitMeshes[inew][iold]), _domain_selector->getProcessorID(inew));
+          if (splitMeshes[inew][iold] != 0) {
+           //cvw std::cout<<"send NOT empty mesh "<<splitMeshes[inew][iold]->getName()<<" "<<inew<<"<-"<<iold<<std::endl;
+           _domain_selector->sendMesh(*(splitMeshes[inew][iold]), _domain_selector->getProcessorID(inew));
+          }
+          else {
+           //std::cout<<"send empty mesh "<<inew<<"<-"<<iold<<std::endl;
+           _domain_selector->sendMesh(*(empty), _domain_selector->getProcessorID(inew));
+          }
         if (!_domain_selector->isMyDomain(iold) && _domain_selector->isMyDomain(inew))
-           _domain_selector->recvMesh(splitMeshes[inew][iold], _domain_selector->getProcessorID(iold));
+          _domain_selector->recvMesh(splitMeshes[inew][iold], _domain_selector->getProcessorID(iold));
       }
-
-
+  empty->decrRef();
+  }
+  
   //recollecting the bits of splitMeshes to fuse them into one
+  if (MyGlobals::_verbose>300) std::cout<<"proc "<<MyGlobals::_rank<<" : fuse splitMeshes"<<std::endl;
   meshesCastTo.resize(newSize);
-  for (int inew=0; inew < newSize;inew++)
+  for (int inew=0; inew < newSize; inew++)
     {
       vector<const ParaMEDMEM::MEDCouplingUMesh*> myMeshes;
-      for (int iold=0; iold < meshesCastFrom.size();iold++)
+      for (int iold=0; iold<fromSize; iold++)
         {
-          if (splitMeshes[inew][iold] !=0)
-            myMeshes.push_back(splitMeshes[inew][iold]);          
+          ParaMEDMEM::MEDCouplingUMesh *umesh=splitMeshes[inew][iold];
+          if (umesh!=0)
+           if (umesh->getNumberOfCells()>0) {
+             myMeshes.push_back(umesh);
+           }
+           //else {
+           //  std::cout<<"one empty mesh "<<inew<<" "<<iold<<std::endl;
+           //}
         }
-      meshesCastTo[inew]=ParaMEDMEM::MEDCouplingUMesh::MergeUMeshes(myMeshes);
+      
+      if (myMeshes.size()>0)
+      {
+        meshesCastTo[inew]=ParaMEDMEM::MEDCouplingUMesh::MergeUMeshes(myMeshes);
+      }
+      else
+      {
+        //std::cout<<"one empty meshes to merge "<<inew<<std::endl;
+        //ParaMEDMEM::MEDCouplingUMesh *empty=ParaMEDMEM::MEDCouplingUMesh::New(); //empty one
+        //empty->setName("emptyMesh");
+        //empty->setMeshDimension(3);
+        //empty->allocateCells(0);
+        ParaMEDMEM::MEDCouplingUMesh *empty=createEmptyMEDCouplingUMesh();
+        meshesCastTo[inew]=empty;
+      }
       //      meshesCastTo[inew]->zipCoords();
-      for (int iold=0; iold < meshesCastFrom.size();iold++)
+      for (int iold=0; iold<fromSize; iold++)
         if (splitMeshes[inew][iold]!=0) splitMeshes[inew][iold]->decrRef();
     }
+  //if (MyGlobals::_verbose>1) std::cout<<"proc "<<MyGlobals::_rank<<" : end fuse"<<std::endl;
 }
 
-void MESHCollection::castIntField(std::vector<ParaMEDMEM::MEDCouplingUMesh*>& meshesCastFrom,std::vector<ParaMEDMEM::MEDCouplingUMesh*>& meshesCastTo,  std::vector<ParaMEDMEM::DataArrayInt*>& arrayFrom,  std::vector<ParaMEDMEM::DataArrayInt*>& arrayTo)
+void MESHCollection::remapIntField(
+      const ParaMEDMEM::MEDCouplingUMesh& sourceMesh,
+      const ParaMEDMEM::MEDCouplingUMesh& targetMesh,
+      const int* fromArray,
+      int* toArray)
 {
-  vector<vector<const ParaMEDMEM::DataArrayInt*> > splitIds;
-  splitIds.resize(meshesCastTo.size());
-  // send / recv operations
-  for (int inew=0; inew < meshesCastTo.size();inew++)    
-    for (int iold=0; iold < meshesCastFrom.size();iold++)
+  using std::vector;
+  if (sourceMesh.getNumberOfCells()<=0) return; //empty mesh could exist
+  //cvw std::cout<<"remapIntField "<<sourceMesh.getNumberOfCells()<<" "<<targetMesh.getNumberOfCells()<<std::endl;
+  ParaMEDMEM::DataArrayDouble* sourceCoords=sourceMesh.getBarycenterAndOwner();
+  ParaMEDMEM::DataArrayDouble* targetCoords=targetMesh.getBarycenterAndOwner();
+   
+  ParaMEDMEM::MEDCouplingUMesh* tmpMesh=ParaMEDMEM::MEDCouplingUMesh::New();
+  tmpMesh->setCoords(sourceCoords);
+  vector<int> c;
+  vector<int> cI;
+  tmpMesh->getNodeIdsNearPoints(targetCoords->getConstPointer(),targetMesh.getNumberOfCells(),1e-10,c,cI);
+  if (cI.size()!= targetMesh.getNumberOfCells()+1) 
+    throw INTERP_KERNEL::Exception(LOCALIZED("Error in source/target projection"));
+  for (int itargetnode=0; itargetnode<targetMesh.getNumberOfCells();itargetnode++)    
+    {
+      if (cI[itargetnode]==cI[itargetnode+1]) continue;
+      int isourcenode=c[cI[itargetnode]];
+      toArray[itargetnode]=fromArray[isourcenode];
+    } 
+  sourceCoords->decrRef();
+  targetCoords->decrRef();
+  tmpMesh->decrRef();
+}
+
+void MESHCollection::castIntField2(  //cvwat08
+      std::vector<ParaMEDMEM::MEDCouplingUMesh*>& meshesCastFrom,
+      std::vector<ParaMEDMEM::MEDCouplingUMesh*>& meshesCastTo,
+      std::vector<ParaMEDMEM::DataArrayInt*>& arrayFrom,
+      std::string nameArrayTo)
+{
+  using std::vector;
+  
+  int ioldMax=meshesCastFrom.size();
+  int inewMax=meshesCastTo.size();
+  // send-recv operations
+  for (int inew=0; inew<inewMax; inew++)
+  {
+    for (int iold=0; iold<ioldMax; iold++)
+    {
+      //sending arrays for distant domains
+      if (isParallelMode() && _domain_selector->isMyDomain(iold) && !_domain_selector->isMyDomain(inew))
+      {
+        //send mesh
+        _domain_selector->sendMesh(*meshesCastFrom[iold],_domain_selector->getProcessorID(inew));
+        //send vector
+        int size=arrayFrom[iold]->getNumberOfTuples(); //cvw may be -1!
+        vector<int>sendIds;
+        if (MyGlobals::_verbose>400) std::cout<<"proc "<<_domain_selector->rank()<<" : castIntField sendIntVec size "<<size<<std::endl;
+        if (size>0) //no empty
+        {
+          sendIds.resize(size);
+          std::copy(arrayFrom[iold]->getPointer(),arrayFrom[iold]->getPointer()+size,&sendIds[0]);
+        }
+        else //empty
+        {
+          size=0;
+          sendIds.resize(size);
+        }
+        //std::cout<<"proc "<<_domain_selector->rank()<<" : castIntField sendIntVec "<<size<<std::endl;
+        sendIntVec(sendIds, _domain_selector->getProcessorID(inew));
+      }
+      //receiving arrays from distant domains
+      if (isParallelMode() && !_domain_selector->isMyDomain(iold) && _domain_selector->isMyDomain(inew))
+      {
+        //receive mesh
+        vector<int> recvIds;
+        ParaMEDMEM::MEDCouplingUMesh* recvMesh;
+        _domain_selector->recvMesh(recvMesh,_domain_selector->getProcessorID(iold));
+        //receive vector
+        if (MyGlobals::_verbose>400) std::cout<<"proc "<<_domain_selector->rank()<<" : castIntField recIntVec "<<std::endl;
+        recvIntVec(recvIds, _domain_selector->getProcessorID(iold));
+        remapIntField2(inew,iold,*recvMesh,*meshesCastTo[inew],&recvIds[0],nameArrayTo);
+        recvMesh->decrRef(); //cww is it correct?
+      }
+    }
+  }
+  
+  //local contributions and aggregation
+  for (int inew=0; inew<inewMax; inew++)    
+  {
+    for (int iold=0; iold<ioldMax; iold++)
+      if (!isParallelMode() || ( _domain_selector->isMyDomain(iold) && _domain_selector->isMyDomain(inew)))
+      {
+        remapIntField2(inew,iold,*meshesCastFrom[iold],*meshesCastTo[inew],arrayFrom[iold]->getConstPointer(),nameArrayTo);
+      }
+  }
+}
+
+void MESHCollection::remapIntField2(int inew,int iold,
+      const ParaMEDMEM::MEDCouplingUMesh& sourceMesh,
+      const ParaMEDMEM::MEDCouplingUMesh& targetMesh,
+      const int* fromArray,
+      string nameArrayTo)
+//here we store ccI for next use in future call of castAllFields and remapDoubleField2
+{
+  using std::vector;
+  //cout<<"remapIntField2 "<<cle2ToStr(nameArrayTo,inew,iold)<<endl;
+  if (sourceMesh.getNumberOfCells()<=0) return; //empty mesh could exist
+  //cvw std::cout<<"remapIntField "<<sourceMesh.getNumberOfCells()<<" "<<targetMesh.getNumberOfCells()<<std::endl;
+  ParaMEDMEM::DataArrayDouble* sourceCoords=sourceMesh.getBarycenterAndOwner();
+  ParaMEDMEM::DataArrayDouble* targetCoords=targetMesh.getBarycenterAndOwner();
+   
+  ParaMEDMEM::MEDCouplingUMesh* tmpMesh=ParaMEDMEM::MEDCouplingUMesh::New();
+  tmpMesh->setCoords(sourceCoords);
+  vector<int> c;
+  vector<int> cI;
+  vector<int> ccI; //memorize intersection target<-source(inew,iold)
+  string str,cle;
+  str=nameArrayTo+"_toArray";
+  cle=cle1ToStr(str,inew);
+  int* toArray;
+  int targetSize=targetMesh.getNumberOfCells();
+  //first time iold : create and initiate 
+  if (_mapDataArrayInt.find(cle)==_mapDataArrayInt.end())
+  {
+    if (MyGlobals::_is0verbose>100) cout<<"create "<<cle<<" size "<<targetSize<<endl;
+    ParaMEDMEM::DataArrayInt* p=DataArrayInt::New();
+    p->alloc(targetSize,1);
+    p->fillWithZero();
+    toArray=p->getPointer();
+    _mapDataArrayInt[cle]=p;
+  }
+  else //other times iold: refind and complete
+  {
+    toArray=_mapDataArrayInt.find(cle)->second->getPointer();
+  }
+  tmpMesh->getNodeIdsNearPoints(targetCoords->getConstPointer(),targetSize,1e-10,c,cI);
+  if (cI.size()!=targetSize+1) 
+    throw INTERP_KERNEL::Exception(LOCALIZED("Error in source/target projection"));
+  for (int itargetnode=0; itargetnode<targetSize; itargetnode++)    
+  {
+    if (cI[itargetnode]==cI[itargetnode+1]) continue;
+    int isourcenode=c[cI[itargetnode]];
+    toArray[itargetnode]=fromArray[isourcenode];
+    //memorize intersection 
+    ccI.push_back(itargetnode); //next we'll do toArray[ccI[i]]=fromArray[ccI[i+1]]
+    ccI.push_back(isourcenode);
+  }
+  //ccI.push_back(sourceMesh.getNumberOfCells()); //additionnal information at end??
+  
+  //memories intersection for future same job on fields (if no existing cle=no intersection)
+  str=cle2ToStr(nameArrayTo+"_ccI",inew,iold);
+  if (MyGlobals::_verbose>700) cout<<"proc "<<MyGlobals::_rank<<" : map memorize '"<<str<<"'\n";
+  _mapDataArrayInt[str]=createDataArrayIntFromVector(ccI, 2);
+  sourceCoords->decrRef();
+  targetCoords->decrRef();
+  tmpMesh->decrRef();
+}
+
+void MESHCollection::castAllFields(MESHCollection& initialCollection, string nameArrayTo) //cvwat08
+{
+  using std::vector;
+  if (nameArrayTo!="cellFieldDouble") 
+    throw INTERP_KERNEL::Exception(LOCALIZED("Error castAllField only on cellFieldDouble"));
+
+  string nameTo="typeData=6"; //resume the type of field casted 
+  // send-recv operations
+  int ioldMax=initialCollection.getMesh().size();
+  int inewMax=this->getMesh().size();
+  int iFieldMax=initialCollection.getFieldDescriptions().size();
+  if (MyGlobals::_verbose>10) cout<<"castAllFields with:\n"<<reprVectorOfString(initialCollection.getFieldDescriptions())<<endl;
+  //std::vector<std::string> initialCollection.getFieldDescriptions()
+  //getFieldDescriptions() is a string description of field coherent and tested and set BEFORE.
+  //see collection.prepareFieldDescriptions()
+  for (int ifield=0; ifield<iFieldMax; ifield++)
+  {
+    string descriptionField=initialCollection.getFieldDescriptions()[ifield];
+    if (descriptionField.find(nameTo)==string::npos) continue; //only nameTo accepted in Fields name description
+    for (int inew=0; inew<inewMax; inew++)
+    {
+      for (int iold=0; iold<ioldMax; iold++)
       {
-        vector<int> recvIntVec;
         //sending arrays for distant domains
         if (isParallelMode() && _domain_selector->isMyDomain(iold) && !_domain_selector->isMyDomain(inew))
-          {
-            _domain_selector->sendMesh(*meshesCastFrom[iold],_domain_selector->getProcessorID(inew));
-            int size=arrayFrom[iold]->getNumberOfTuples();
-            vector<int>sendIds(size);
-            std::copy(arrayFrom[iold]->getPointer(),arrayFrom[iold]->getPointer()+size,&sendIds[0]);
-            _domain_selector->sendIntVec(sendIds, _domain_selector->getProcessorID(inew));
-          }
+        {
+          int target=_domain_selector->getProcessorID(inew);
+          ParaMEDMEM::DataArrayDouble* field=initialCollection.getField(descriptionField,iold); //cvwat14
+          //getField look for and read it if not done, and assume decrRef() in ~MESHCollection;
+          if (MyGlobals::_verbose>10) 
+            std::cout<<"proc "<<_domain_selector->rank()<<" : castAllFields sendDouble"<<std::endl;
+          sendDataArrayDouble(field, target);
+        }
         //receiving arrays from distant domains
-        if (isParallelMode()&&!_domain_selector->isMyDomain(iold) && _domain_selector->isMyDomain(inew))
-          {
-            vector<int> recvIds;
-            ParaMEDMEM::MEDCouplingUMesh* recvMesh;
-            _domain_selector->recvMesh(recvMesh,_domain_selector->getProcessorID(iold));
-            _domain_selector->recvIntVec(recvIds, _domain_selector->getProcessorID(iold));
-            remapIntField(*recvMesh,*meshesCastTo[inew],&recvIds[0],arrayTo[inew]->getPointer());
-          }
+        if (isParallelMode() && !_domain_selector->isMyDomain(iold) && _domain_selector->isMyDomain(inew))
+        {
+          int source=_domain_selector->getProcessorID(iold);
+          //receive vector
+          if (MyGlobals::_verbose>10) 
+            std::cout<<"proc "<<_domain_selector->rank()<<" : castAllFields recvDouble"<<std::endl;
+          ParaMEDMEM::DataArrayDouble* field=recvDataArrayDouble(source);
+          remapDoubleField3(inew,iold,field,nameArrayTo,descriptionField);
+        }
+      }
+    }
+  
+    //local contributions and aggregation
+    for (int inew=0; inew<inewMax; inew++)
+    {
+    for (int iold=0; iold<ioldMax; iold++)
+      if (!isParallelMode() || ( _domain_selector->isMyDomain(iold) && _domain_selector->isMyDomain(inew)))
+      {
+        ParaMEDMEM::DataArrayDouble* field=initialCollection.getField(descriptionField,iold); //cvwat14
+        remapDoubleField3(inew,iold,field,nameArrayTo,descriptionField);
       }
+    }
+  }
+}
 
-  //local contributions and aggregation
-  for (int inew=0; inew < meshesCastTo.size();inew++)    
+void MESHCollection::remapDoubleField3(int inew, int iold, 
+                                       ParaMEDMEM::DataArrayDouble* fromArray,
+                                       string nameArrayTo,
+                                       string descriptionField)
+//here we use 'cellFamily_ccI inew iold' set in remapIntField2
+{
+  using std::vector;
+  if (nameArrayTo!="cellFieldDouble") 
+    throw INTERP_KERNEL::Exception(LOCALIZED("Error remapDoubleField3 only on cellFieldDouble"));
+  string cle=cle2ToStr("cellFamily_ccI",inew,iold);
+  
+  map<string,ParaMEDMEM::DataArrayInt*>::iterator it1;
+  it1=_mapDataArrayInt.find(cle);
+  if (it1==_mapDataArrayInt.end())
+  {
+    cerr<<"proc "<<MyGlobals::_rank<<" : remapDoubleField3 cle '"<<cle<<"' not found"<<endl;
+    cerr<<" trying remap of field double on cells : "<<descriptionField<<endl;
+    return;
+  }
+  //create ccI in remapIntField2
+  ParaMEDMEM::DataArrayInt* ccI=it1->second;
+  if (MyGlobals::_verbose>300) cout<<"proc "<<MyGlobals::_rank<<" : remapDoubleField3 "<<cle<<" size "<<ccI->getNbOfElems()<<endl;
+  //cout<<descriptionField<<endl;
+  
+  int nbcell=this->getMesh()[inew]->getNumberOfCells(); //number of cell of mesh
+  int nbcomp=fromArray->getNumberOfComponents();
+  int nbPtGauss=strToInt(extractFromDescription(descriptionField, "nbPtGauss="));
+  
+  //int nbk=fromArray->getNumberOfTuples();
+  
+  //cle=reprGenericDescription(descriptionField)+" "+intToStr(inew);
+  string tag="inewFieldDouble="+intToStr(inew);
+  cle=descriptionField+serializeFromString(tag);
+  //cout<<"descriptionField in remapDoubleField3 : "<<descriptionField<<endl;
+  int fromArrayNbOfElem=fromArray->getNbOfElems();
+  int fromArrayNbOfComp=fromArray->getNumberOfComponents();
+  int fromArrayNbOfCell=fromArrayNbOfElem/fromArrayNbOfComp/nbPtGauss;
+  
+  if (MyGlobals::_verbose>1000)
+  {
+    cout<<"proc "<<MyGlobals::_rank<<" nbcell "<<nbcell<<" nbcomp "<<nbcomp<<" nbPtGauss "<<nbPtGauss<<
+          " fromArray nbOfElems "<<fromArrayNbOfElem<<
+          " nbTuples "<<fromArray->getNumberOfTuples()<<
+          " nbcells "<<fromArrayNbOfCell<<
+          " nbComponents "<<fromArray->getNumberOfComponents()<<endl;
+  }
+
+  ParaMEDMEM::DataArrayDouble* field=0;
+  map<string,ParaMEDMEM::DataArrayDouble*>::iterator it2;
+  it2=_mapDataArrayDouble.find(cle);
+  if (it2==_mapDataArrayDouble.end())
+  {
+    if (MyGlobals::_verbose>300) cout<<"proc "<<MyGlobals::_rank<<" : remapDoubleField3 cle '"<<cle<<"' not found and create it"<<endl;
+    field=DataArrayDouble::New();
+    _mapDataArrayDouble[cle]=field;
+    field->alloc(nbcell*nbPtGauss,nbcomp);
+    field->fillWithZero();
+  }
+  else
+  {
+    field=it2->second;
+    if (field->getNumberOfTuples()!=nbcell*nbPtGauss || field->getNumberOfComponents()!=nbcomp)
     {
-      for (int iold=0; iold < meshesCastFrom.size();iold++)
-        if (!isParallelMode() || ( _domain_selector->isMyDomain(iold) && _domain_selector->isMyDomain(inew)))
-            {
-              remapIntField(*meshesCastFrom[iold],*meshesCastTo[inew],arrayFrom[iold]->getConstPointer(),arrayTo[inew]->getPointer());
-            }     
+      cerr<<"proc "<<MyGlobals::_rank<<" : remapDoubleField3 pb of size "<<
+            " trying remap of field double on cells : \n"<<descriptionField<<endl;
+      return;
+    }
+  }
+  //cout<<"proc "<<MyGlobals::_rank<<" : remapDoubleField3 "<<cle<<" size "<<ccI->getNbOfElems()<<endl;
+  
+  if (nbPtGauss==1)
+  {
+    field->setPartOfValuesAdv(fromArray,ccI);
+  }
+  else
+  {
+    //replaced by setPartOfValuesAdv if nbPtGauss==1
+    int iMax=ccI->getNbOfElems();
+    int* pccI=ccI->getPointer();
+    double* pField=field->getPointer();
+    double* pFrom=fromArray->getPointer();
+    int itarget, isource, delta=nbPtGauss*nbcomp;
+    for (int i=0; i<iMax; i=i+2)  //cell
+    {
+      itarget=pccI[i];
+      isource=pccI[i+1];
+      if ((itarget<0) || (itarget>=nbcell) || (isource<0) || (isource>=fromArrayNbOfCell))
+            throw INTERP_KERNEL::Exception(LOCALIZED("Error field override"));
+      int ita=itarget*delta;
+      int iso=isource*delta;
+      for (int k=0; k<delta; k++) pField[ita+k]=pFrom[iso+k]; //components and gausspoints
     }
+  }
 }
 
-void MESHCollection::remapIntField(const ParaMEDMEM::MEDCouplingUMesh& sourceMesh,
-                              const ParaMEDMEM::MEDCouplingUMesh& targetMesh,
-                              const int* fromArray,
-                              int* toArray)
+/*
+void MESHCollection::remapFields(
+      const ParaMEDMEM::MEDCouplingUMesh& sourceMesh,
+      const ParaMEDMEM::MEDCouplingUMesh& targetMesh,
+      mapOfFields* fromFields,
+      mapOfFields* toFields)
+      //const int* fromArray,int* toArray)
 {
+  using std::vector;
+  if (sourceMesh.getNumberOfCells()<=0) return; //empty mesh could exist
+  //cvw std::cout<<"remapIntField "<<sourceMesh.getNumberOfCells()<<" "<<targetMesh.getNumberOfCells()<<std::endl;
   ParaMEDMEM::DataArrayDouble* sourceCoords=sourceMesh.getBarycenterAndOwner();
   ParaMEDMEM::DataArrayDouble* targetCoords=targetMesh.getBarycenterAndOwner();
    
   ParaMEDMEM::MEDCouplingUMesh* tmpMesh=ParaMEDMEM::MEDCouplingUMesh::New();
   tmpMesh->setCoords(sourceCoords);
-  vector<int>c;
+  vector<int> c;
   vector<int> cI;
   tmpMesh->getNodeIdsNearPoints(targetCoords->getConstPointer(),targetMesh.getNumberOfCells(),1e-10,c,cI);
-  if (cI.size()!= targetMesh.getNumberOfCells()+1) throw INTERP_KERNEL::Exception("Error in source/target projection");
+  if (cI.size()!= targetMesh.getNumberOfCells()+1) 
+    throw INTERP_KERNEL::Exception(LOCALIZED("Error in source/target projection"));
+
   for (int itargetnode=0; itargetnode<targetMesh.getNumberOfCells();itargetnode++)    
     {
       if (cI[itargetnode]==cI[itargetnode+1]) continue;
       int isourcenode=c[cI[itargetnode]];
       toArray[itargetnode]=fromArray[isourcenode];
-    } 
+    }
+  
   sourceCoords->decrRef();
   targetCoords->decrRef();
   tmpMesh->decrRef();
-    
-    
 }
+*/
+
 /*! constructing the MESH collection from a distributed file
  *
  * \param filename name of the master file containing the list of all the MED files
  */
-MESHCollection::MESHCollection(const string& filename)
+MESHCollection::MESHCollection(const std::string& filename)
   : _topology(0),
     _owns_topology(true),
     _driver(0),
@@ -492,7 +921,8 @@ MESHCollection::MESHCollection(const string& filename)
     _driver_type(MEDPARTITIONER::Undefined),
     _subdomain_boundary_creates(false),
     _family_splitting(false),
-    _create_empty_groups(false)
+    _create_empty_groups(false),
+    _joint_finder(0)
 {
   // char filenamechar[256];
   // strcpy(filenamechar,filename.c_str());
@@ -501,22 +931,22 @@ MESHCollection::MESHCollection(const string& filename)
       _driver=new MESHCollectionMedXMLDriver(this);
       _driver->read (filename.c_str());
       _driver_type = MedXML;
-
     }
-  catch(MEDMEM::MEDEXCEPTION){
-    delete _driver;
-    try
-      {
-        _driver=new MESHCollectionMedAsciiDriver(this);
-        _driver->read (filename.c_str());
-        _driver_type=MedAscii;
-      }
-    catch(MEDMEM::MEDEXCEPTION&)
-      {
-        delete _driver;
-        throw MEDMEM::MEDEXCEPTION("file does not comply with any recognized format");
-      }
-  }
+  catch(...) 
+    {  // Handle all exceptions
+      if ( _driver ) delete _driver; _driver=0;
+      try
+        {
+          _driver=new MESHCollectionMedAsciiDriver(this);
+          _driver->read (filename.c_str());
+          _driver_type=MedAscii;
+        }
+      catch(...)
+        {
+          if ( _driver ) delete _driver; _driver=0;
+          throw INTERP_KERNEL::Exception(LOCALIZED("file does not comply with any recognized format"));
+        }
+    }
   for ( int idomain = 0; idomain < _mesh.size(); ++idomain )
     if ( _mesh[idomain] && _mesh[idomain]->getNumberOfNodes() > 0 )
       _i_non_empty_mesh = idomain;
@@ -527,46 +957,166 @@ MESHCollection::MESHCollection(const string& filename)
  * \param filename  - name of the master file containing the list of all the MED files
  * \param domainSelector - selector of domains to load
  */
-MESHCollection::MESHCollection(const string& filename, ParaDomainSelector& domainSelector)
+MESHCollection::MESHCollection(const std::string& filename, ParaDomainSelector& domainSelector) //cvwat01
   : _topology(0),
     _owns_topology(true),
     _driver(0),
-    _domain_selector( domainSelector.nbProcs() > 1 ? & domainSelector : 0 ),
+    //cvw _domain_selector( domainSelector.nbProcs() > 1 ? & domainSelector : 0 ),
+    _domain_selector( &domainSelector ),
     _i_non_empty_mesh(-1),
     _driver_type(MEDPARTITIONER::Undefined),
     _subdomain_boundary_creates(false),
     _family_splitting(false),
-    _create_empty_groups(false)
+    _create_empty_groups(false),
+    _joint_finder(0)
 {
-  try
+  std::string myfile=filename;
+  std::size_t found=myfile.find(".xml");
+  if (found!=std::string::npos) //file .xml
+  {
+    try
     {
-      _driver=new MESHCollectionMedXMLDriver(this);
+      _driver=new MESHCollectionMedXMLDriver(this); //cvwat02
       _driver->read ( (char*)filename.c_str(), _domain_selector );
       _driver_type = MedXML;
     }
-  catch(MEDMEM::MEDEXCEPTION&)
+    catch(...)
+    {  // Handle all exceptions
+      if ( _driver ) delete _driver; _driver=0;
+      throw INTERP_KERNEL::Exception(LOCALIZED("file .xml does not comply with any recognized format"));
+    }
+  }
+  else 
+  {
+    found=myfile.find(".med");
+    if (found!=std::string::npos) //file .med single
+    {
+      //make a temporary file .xml and retry MedXMLDriver
+      std::string xml="\
+<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n \
+<root>\n \
+  <version maj=\"2\" min=\"3\" ver=\"1\"/>\n \
+  <description what=\"\" when=\"\"/>\n \
+  <content>\n \
+    <mesh name=\"$meshName\"/>\n \
+  </content>\n \
+  <splitting>\n \
+    <subdomain number=\"1\"/>\n \
+    <global_numbering present=\"no\"/>\n \
+  </splitting>\n \
+  <files>\n \
+    <subfile id=\"1\">\n \
+      <name>$fileName</name>\n \
+      <machine>localhost</machine>\n \
+    </subfile>\n \
+  </files>\n \
+  <mapping>\n \
+    <mesh name=\"$meshName\">\n \
+      <chunk subdomain=\"1\">\n \
+        <name>$meshName</name>\n \
+      </chunk>\n \
+    </mesh>\n \
+  </mapping>\n \
+</root>\n";
+      std::vector<std::string> meshNames=MEDLoader::GetMeshNames(myfile.c_str());
+      xml.replace(xml.find("$fileName"),9,myfile);
+      xml.replace(xml.find("$meshName"),9,meshNames[0]);
+      xml.replace(xml.find("$meshName"),9,meshNames[0]);
+      xml.replace(xml.find("$meshName"),9,meshNames[0]);
+      //std::cout<<xml<<std::endl;
+      std::string nameFileXml=myfile;
+      nameFileXml.replace(nameFileXml.find(".med"),4,".xml");
+      nameFileXml="medpartitioner_"+nameFileXml;
+      if (_domain_selector->rank()==0) //only on to write it
+      {
+        std::ofstream f(nameFileXml.c_str());
+        f<<xml;
+        f.close();
+      }
+#ifdef HAVE_MPI2
+      MPI_Barrier(MPI_COMM_WORLD); //wait for creation of nameFileXml
+#endif
+      try
+      {
+        _driver=new MESHCollectionMedXMLDriver(this);
+        _driver->read ( (char*)nameFileXml.c_str(), _domain_selector );
+        _driver_type = MedXML;
+      }
+      catch(...)
+      {  // Handle all exceptions
+        if ( _driver ) delete _driver; _driver=0;
+        throw INTERP_KERNEL::Exception(LOCALIZED("file medpartitioner_xxx.xml does not comply with any recognized format"));
+      }
+    }
+    else //no extension
     {
-      delete _driver;
       try
         {
           _driver=new MESHCollectionMedAsciiDriver(this);
           _driver->read ( (char*)filename.c_str(), _domain_selector );
           _driver_type=MedAscii;
         }
-      catch(MEDMEM::MEDEXCEPTION&)
+      catch(...)
         {
-          delete _driver;
-          throw MEDMEM::MEDEXCEPTION("file does not comply with any recognized format");
+          if ( _driver ) delete _driver; _driver=0;
+          throw INTERP_KERNEL::Exception(LOCALIZED("file name with no extension does not comply with any recognized format"));
         }
     }
+  }
+  
+  /*done in MESHCollectionMedXMLDriver read
   if ( isParallelMode() )
     // to know nb of cells on each proc to compute global cell ids from locally global
-    _domain_selector->gatherNbOf( getMesh() );
+    _domain_selector->gatherNbOf( getMesh() );*/
 
   // find non-empty domain mesh
   for ( int idomain = 0; idomain < _mesh.size(); ++idomain )
     if ( _mesh[idomain] && _mesh[idomain]->getNumberOfNodes() > 0 )
       _i_non_empty_mesh = idomain;
+  
+  try
+  {
+    //check for all proc/file compatibility of _fieldDescriptions
+    //*MyGlobals::_fileNames=allgathervVectorOfString(*MyGlobals::_fileNames);
+    _fieldDescriptions=allgathervVectorOfString(MyGlobals::_fieldDescriptions); //cvwat07
+  }
+  catch(INTERP_KERNEL::Exception& e)
+  {
+    cerr<<"proc "<<MyGlobals::_rank<<" : INTERP_KERNEL_Exception : "<<e.what()<<endl;
+    throw INTERP_KERNEL::Exception(LOCALIZED("Something wrong verifying coherency of files med ands fields"));
+  }
+  
+  try
+  {
+    //check for all proc/file compatibility of _familyInfo //cvwat05
+    vector<string> v2=allgathervVectorOfString(vectorizeFromMapOfStringInt(_familyInfo));
+    _familyInfo=devectorizeToMapOfStringInt(v2);
+  }
+  catch(INTERP_KERNEL::Exception& e)
+  {
+    cerr<<"proc "<<MyGlobals::_rank<<" : INTERP_KERNEL_Exception : "<<e.what()<<endl;
+    throw INTERP_KERNEL::Exception(LOCALIZED("Something wrong merging all familyInfo"));
+  }
+
+  try
+  {
+   //check for all proc/file compatibility of _groupInfo
+    vector<string> v2=allgathervVectorOfString(
+                      vectorizeFromMapOfStringVectorOfString(_groupInfo));
+    _groupInfo=deleteDuplicatesInMapOfStringVectorOfString(
+               devectorizeToMapOfStringVectorOfString(v2));
+  }
+  catch(INTERP_KERNEL::Exception& e)
+  {
+    cerr<<"proc "<<MyGlobals::_rank<<" : INTERP_KERNEL_Exception : "<<e.what()<<endl;
+    throw INTERP_KERNEL::Exception(LOCALIZED("Something wrong merging all groupInfo"));
+  }
+
+  
+  //std::vector< std::string > _meshes=MEDLoader::GetMeshNames(filename);
+  //std::vector< std::string > _fields=MEDLoader::GetAllFieldNamesOnMesh(filename,meshname[0]);
+  //cout<<"number of fields "<<_fields.size()<<endl;
+  
 }
 
 /*! constructing the MESH collection from a sequential MED-file
@@ -574,7 +1124,7 @@ MESHCollection::MESHCollection(const string& filename, ParaDomainSelector& domai
  * \param filename MED file
  * \param meshname name of the mesh that is to be read
  */
-MESHCollection::MESHCollection(const string& filename, const string& meshname)
+MESHCollection::MESHCollection(const std::string& filename, const std::string& meshname)
   : _name(meshname),
     _topology(0),
     _owns_topology(true),
@@ -584,20 +1134,21 @@ MESHCollection::MESHCollection(const string& filename, const string& meshname)
     _driver_type(MEDPARTITIONER::MedXML),
     _subdomain_boundary_creates(false),
     _family_splitting(false),
-    _create_empty_groups(false)
+    _create_empty_groups(false),
+    _joint_finder(0)
 {
   //char filenamechar[256];
   //char meshnamechar[256];
-  //  strcpy(filenamechar,filename.c_str());
+  //strcpy(filenamechar,filename.c_str());
   //strcpy(meshnamechar,meshname.c_str());
   try // avoid memory leak in case of inexistent filename
     {
       retrieveDriver()->readSeq (filename.c_str(),meshname.c_str());
     }
-  catch ( MED_EXCEPTION& e )
+  catch (...)
     {
       if ( _driver ) delete _driver; _driver=0;
-      throw e;
+      throw INTERP_KERNEL::Exception(LOCALIZED("problem reading .med files"));
     }
   if ( _mesh[0] && _mesh[0]->getNumberOfNodes() > 0 )
     _i_non_empty_mesh = 0;
@@ -606,22 +1157,29 @@ MESHCollection::MESHCollection(const string& filename, const string& meshname)
 MESHCollection::~MESHCollection()
 {
   for (int i=0; i<_mesh.size();i++)
-    {
-      if (_mesh[i]!=0)  _mesh[i]->decrRef(); 
-      if (_cellFamilyIds[i]!=0) _cellFamilyIds[i]->decrRef();
-    }
+    if (_mesh[i]!=0) _mesh[i]->decrRef(); 
+  
+  for (int i=0; i<_cellFamilyIds.size();i++)
+    if (_cellFamilyIds[i]!=0) _cellFamilyIds[i]->decrRef();
   
   for (int i=0; i<_faceMesh.size();i++)
-    {
-      if (_faceMesh[i]!=0)  _faceMesh[i]->decrRef();
-      if (_faceFamilyIds[i]!=0) _faceFamilyIds[i]->decrRef();
-    }
+    if (_faceMesh[i]!=0) _faceMesh[i]->decrRef();
+  
+  for (int i=0; i<_faceFamilyIds.size();i++)
+    if (_faceFamilyIds[i]!=0) _faceFamilyIds[i]->decrRef();
+  
+  for (map<string, ParaMEDMEM::DataArrayInt*>::iterator it=_mapDataArrayInt.begin() ; it!=_mapDataArrayInt.end(); it++ )
+    if ((*it).second!=0) (*it).second->decrRef();
+  
+  for (map<string, ParaMEDMEM::DataArrayDouble*>::iterator it=_mapDataArrayDouble.begin() ; it!=_mapDataArrayDouble.end(); it++ )
+    if ((*it).second!=0) (*it).second->decrRef();
   
   if (_driver !=0) {delete _driver; _driver=0;}
   if (_topology!=0 && _owns_topology) {delete _topology; _topology=0;}
+  
+  if (_joint_finder!=0) {delete _joint_finder; _joint_finder=0;}
 }
 
-
 /*! constructing the MESH collection from a file
  * 
  * The method creates as many MED-files as there are domains in the 
@@ -632,13 +1190,13 @@ MESHCollection::~MESHCollection()
  * \param filename name of the master file that will contain the list of the MED files
  * 
  */
-void MESHCollection::write(const string& filename)
+void MESHCollection::write(const std::string& filename)
 {
   //building the connect zones necessary for writing joints
   //   if (_topology->nbDomain()>1)
   //     buildConnectZones();
   //suppresses link with driver so that it can be changed for writing
-  if (_driver!=0)delete _driver;
+  if (_driver!=0) delete _driver;
   _driver=0;
 
   //char filenamechar[256];
@@ -661,10 +1219,9 @@ MESHCollectionDriver* MESHCollection::retrieveDriver()
           _driver=new MESHCollectionMedAsciiDriver(this);
           break;
         default:
-          throw MEDMEM::MEDEXCEPTION("Unrecognized driver");
+          throw INTERP_KERNEL::Exception(LOCALIZED("Unrecognized driver"));
         }
     }
-
   return _driver;
 }
 
@@ -672,67 +1229,250 @@ MESHCollectionDriver* MESHCollection::retrieveDriver()
 /*! gets an existing driver
  * 
  */
-MESHCollectionDriver* MESHCollection::getDriver() const
-{
+MESHCollectionDriver* MESHCollection::getDriver() const {
   return _driver;
 }
+
 // /*! retrieves the mesh dimension*/
-int MESHCollection::getMeshDimension() const
-{
+int MESHCollection::getMeshDimension() const {
   return _i_non_empty_mesh < 0 ? -1 : _mesh[_i_non_empty_mesh]->getMeshDimension();
 }
 
-vector<ParaMEDMEM::MEDCouplingUMesh*>& MESHCollection::getMesh() 
-{
+std::vector<ParaMEDMEM::MEDCouplingUMesh*>& MESHCollection::getMesh() {
   return _mesh;
 }
-vector<ParaMEDMEM::MEDCouplingUMesh*>& MESHCollection::getFaceMesh() 
-{
+
+std::vector<ParaMEDMEM::MEDCouplingUMesh*>& MESHCollection::getFaceMesh() {
   return _faceMesh;
 }
-ParaMEDMEM::MEDCouplingUMesh* MESHCollection::getMesh(int idomain) const
-{
+
+ParaMEDMEM::MEDCouplingUMesh* MESHCollection::getMesh(int idomain) const {
   return _mesh[idomain];
 }
 
-ParaMEDMEM::MEDCouplingUMesh* MESHCollection::getFaceMesh(int idomain)
-{
+ParaMEDMEM::MEDCouplingUMesh* MESHCollection::getFaceMesh(int idomain) {
   return _faceMesh[idomain];
 }
-vector<MEDPARTITIONER::CONNECTZONE*>& MESHCollection::getCZ()
-{
+
+std::vector<MEDPARTITIONER::CONNECTZONE*>& MESHCollection::getCZ() {
   return _connect_zones;
 }
 
-Topology* MESHCollection::getTopology() const 
-{
+Topology* MESHCollection::getTopology() const {
   return _topology;
 }
 
-void MESHCollection::setTopology(Topology* topo)
-{
+void MESHCollection::setTopology(Topology* topo) {
   if (_topology!=0)
     {
-      throw MEDMEM::MEDEXCEPTION("Erreur : topology is already set");
+      throw INTERP_KERNEL::Exception(LOCALIZED("topology is already set"));
     }
   else
     _topology = topo;
 }
 
-
 /*! Method creating the cell graph
  * 
  * \param array returns the pointer to the structure that contains the graph 
  * \param edgeweight returns the pointer to the table that contains the edgeweights
  *        (only used if indivisible regions are required)
  */
-
-void MESHCollection::buildCellGraph(MEDPARTITIONER::MEDSKYLINEARRAY* & array,int *& edgeweights )
+void MESHCollection::buildCellGraph(MEDPARTITIONER::MEDSKYLINEARRAY* & array, int *& edgeweights ) //cvwat09
 {
-
+  using std::multimap;
+  using std::vector;
+  using std::make_pair;
+  using std::pair;
+  
   multimap< int, int > node2cell;
   multimap< int, int > cell2cell;
+  multimap< int, int > cell2node;
+
+  vector<vector<multimap<int,int> > > commonDistantNodes;
+  int nbdomain=_topology->nbDomain();
+  if (isParallelMode())
+  {
+    _joint_finder=new JointFinder(*this);
+    _joint_finder->findCommonDistantNodes();
+    commonDistantNodes=_joint_finder->getDistantNodeCell();
+  }
+
+  if (MyGlobals::_verbose>500) _joint_finder->print();
+  
+  //looking for reverse nodal connectivity i global numbering
+  for (int idomain=0; idomain<nbdomain; idomain++)
+  {
+    if (isParallelMode() && !_domain_selector->isMyDomain(idomain)) continue;
+    
+    /*obsolete
+    int offsetCell=0, offsetNode=0;
+    if (isParallelMode())
+    {
+      offsetCell=_domain_selector->getDomainCellShift(idomain);
+      offsetNode=_domain_selector->getDomainNodeShift(idomain);
+    }*/
+    
+    ParaMEDMEM::DataArrayInt* index=ParaMEDMEM::DataArrayInt::New();
+    ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
+    int nbNodes=_mesh[idomain]->getNumberOfNodes();
+    //cout<<"proc "<<MyGlobals::_rank<<" idomain "<<idomain<<" nbNodes "<<nbNodes<<" offsetCell "<<offsetCell<<" offsetNode "<<offsetNode<<endl;
+    _mesh[idomain]->getReverseNodalConnectivity(revConn,index);
+    //problem saturation over 1 000 000 nodes for 1 proc
+    if (MyGlobals::_verbose>100) cout<<"proc "<<MyGlobals::_rank<<" getReverseNodalConnectivity done on "<<nbNodes<<" nodes"<<endl;
+    int* index_ptr=index->getPointer();
+    int* revConnPtr=revConn->getPointer();
+    //if (MyGlobals::_verbose>100) cout<<"proc "<<MyGlobals::_rank<<" create node2cell on local nodes with global numerotation idomain|inode|icell\n";
+    for (int i=0; i<nbNodes; i++)
+    {
+      for (int icell=index_ptr[i]; icell<index_ptr[i+1]; icell++)
+      {
+        /*cvw local
+        node2cell.insert(make_pair(i, revConnPtr[icell]));
+        cout<<" "<<idomain<<"|"<<i<<"|"<<revConnPtr[icell];
+        cell2node.insert(make_pair(revConnPtr[icell], i));
+        */
+        int globalNode=_topology->convertNodeToGlobal(idomain,i);
+        int globalCell=_topology->convertCellToGlobal(idomain,revConnPtr[icell]);
+        node2cell.insert(make_pair(globalNode, globalCell));
+        //cvw cout<<" "<<idomain<<"|"<<i<<"#"<< globalNode<<"|"<<revConnPtr[icell]<<"#"<<globalCell;
+        cell2node.insert(make_pair(globalCell, globalNode));
+      }
+    }
+    revConn->decrRef();
+    index->decrRef();
+    //vector<vector<multimap<int,int> > > dNC=getDistantNodeCell()
+    for (int iother=0; iother<nbdomain; iother++)
+    {
+      std::multimap<int,int>::iterator it;
+      int isource=idomain;
+      int itarget=iother;
+      for (it=_joint_finder->_distant_node_cell[isource][itarget].begin(); 
+           it!=_joint_finder->_distant_node_cell[isource][itarget].end(); it++)
+      {
+        int globalNode=_topology->convertNodeToGlobal(idomain,(*it).first);
+        int globalCell=(*it).second;
+        node2cell.insert(make_pair(globalNode, globalCell));
+        //cout<<"processor "<<MyGlobals::_rank<<" : isource "<<isource<<" itarget "<<itarget<<
+        //      " "<<(*it).first<<"~"<<globalNode<<"~"<<globalCell<<endl;
+        cell2node.insert(make_pair(globalCell, globalNode));
+      }
+    }
+  }  //endfor idomain
+
+  //creating graph arcs (cell to cell relations)
+  //arcs are stored in terms of (index,value) notation
+  // 0 3 5 6 6
+  // 1 2 3 2 3 3 
+  // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
+  // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
+  //warning here one node have less than or equal effective number of cell with it
+  //but cell could have more than effective nodes
+  //because other equals nodes in other domain (with other global inode)
+  if (MyGlobals::_verbose>100) cout<<"proc "<<MyGlobals::_rank<<" creating graph arcs on nbNodes "<<_topology->nbNodes()<<endl;
+  for (int inode=0; inode<_topology->nbNodes(); inode++)  //on all nodes
+  {
+    typedef multimap<int,int>::const_iterator MI;
+    pair <MI,MI> myRange=node2cell.equal_range(inode);
+    for (MI cell1=myRange.first; cell1!=myRange.second; cell1++)  //on cells with inode
+    {
+      pair <MI,MI> myNodes1=cell2node.equal_range(cell1->second);  //nodes of one cell
+      for (MI cell2=myRange.first; cell2!=myRange.second; cell2++)  //on one of these cell
+      {
+        if (cell1->second!=cell2->second)  //in cells of my domain
+        {
+          pair <MI,MI> myNodes2=cell2node.equal_range(cell2->second); //on nodes of this cell
+          int nbcn=0; //number of common nodes between cells: at least 3 for cells
+          for (MI it1=myNodes1.first; it1!=myNodes1.second; ++it1)
+          {
+            for (MI it2=myNodes2.first; it2!=myNodes2.second; ++it2)
+            {
+              if ((*it1).second==(*it2).second)
+              {
+                nbcn=nbcn+1 ; break;
+              }
+            }
+          }
+          if (nbcn>=3)  //cvw TODO if 2d cells set at 2
+            cell2cell.insert(make_pair(cell1->second,cell2->second));
+            //note here there is some global numerotation of cell which come from other domain (not mydomain)
+            //cout<<" "<<MyGlobals::_rank<<"!"<<cell1->second<<"!"<<cell2->second; //cvw
+        }
+      }
+    }
+  }
+  
+  if (MyGlobals::_verbose>100) cout<<"proc "<<MyGlobals::_rank<<" create skylinearray"<<endl;
+  //filling up index and value to create skylinearray structure
+  vector <int> index,value;
+  index.push_back(0);
+  int idep=0;
+  
+  for (int idomain=0; idomain<nbdomain; idomain++)
+  {
+    if (isParallelMode() && !_domain_selector->isMyDomain(idomain)) continue;
+    int nbCells=_mesh[idomain]->getNumberOfCells();
+    for (int icell=0; icell<nbCells; icell++)
+    {
+      int size=0;
+      int globalCell=_topology->convertCellToGlobal(idomain,icell);
+      multimap<int,int>::iterator it;
+      pair<multimap<int,int>::iterator,multimap<int,int>::iterator> ret;
+      ret=cell2cell.equal_range(globalCell);
+      //cout<<" "<<MyGlobals::_rank<<"$"<<icell<<"$"<<globalCell;
+      for (it=ret.first; it!=ret.second; ++it)
+      {
+        //cout<<" "<<MyGlobals::_rank<<"$"<<icell<<"$"<<globalCell<<"$"<<(*it).second<<endl;
+        int ival=(*it).second; //no adding one existing yet
+        for (int i=idep ; i<idep+size ; i++)
+        {
+          if (value[i]==ival)
+          {
+            ival=-1; break;
+          }
+        }
+        if (ival!=-1)
+        {
+          value.push_back(ival);
+          //cout<<"|"<<ival;
+          size++;
+        }
+      }
+      //cout<<" ";
+      idep=index[index.size()-1]+size;
+      index.push_back(idep);
+    }
+  }
+  
+  array=new MEDPARTITIONER::MEDSKYLINEARRAY(index,value);
+
+  if (MyGlobals::_verbose>100)
+  {
+    std::cout<<"\nproc "<<_domain_selector->rank()<<" : end MESHCollection::buildCellGraph "<<
+               index.size()-1<<" "<<value.size()<<std::endl;
+    if (index.size()>1)
+    {
+      for (int i=0; i<10; ++i) cout<<index[i]<<" ";
+      cout<<"... "<<index[index.size()-1]<<endl;
+      for (int i=0; i<15; ++i) cout<<value[i]<<" ";
+      int ll=index[index.size()-1]-1;
+      cout<<"... ("<<ll<<") "<<value[ll-1]<<" "<<value[ll]<<endl;
+    }
+  }
+  
+}
 
+/*
+void MESHCollection::buildCellGraph_old(MEDPARTITIONER::MEDSKYLINEARRAY* & array,int *& edgeweights ) //cvwat09
+{
+  using std::multimap;
+  using std::vector;
+  using std::make_pair;
+  using std::pair;
+  
+  multimap< int, int > node2cell;
+  multimap< int, int > cell2cell;
+  
   vector<vector<multimap<int,int> > > commonDistantNodes;
   int nbdomain=_topology->nbDomain();
   if (isParallelMode())
@@ -743,14 +1483,14 @@ void MESHCollection::buildCellGraph(MEDPARTITIONER::MEDSKYLINEARRAY* & array,int
     }
 
   //looking for reverse nodal connectivity i global numbering
-  for (int idomain=0; idomain<nbdomain;idomain++)
+  for (int idomain=0; idomain<nbdomain; idomain++)
     {
       if (isParallelMode() && !_domain_selector->isMyDomain(idomain)) continue;
       int offset=0, procOffset=0;
       if (isParallelMode())
         {
-          offset=_domain_selector->getDomainShift(idomain);
-          procOffset=_domain_selector->getProcShift()+1;
+          offset=_domain_selector->getDomainCellShift(idomain);
+          procOffset=_domain_selector->getProcShift();
         }
       ParaMEDMEM::DataArrayInt* index=ParaMEDMEM::DataArrayInt::New();
       ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
@@ -774,8 +1514,10 @@ void MESHCollection::buildCellGraph(MEDPARTITIONER::MEDSKYLINEARRAY* & array,int
       int* globalRevConnPtr=globalRevConn->getPointer();
       for (int i=0; i<_mesh[idomain]->getNumberOfNodes();i++)
         {
-          for (int icell=index_ptr[i]; icell<index_ptr[i+1];icell++)
-            node2cell.insert(make_pair(globalNodeIds[i],globalRevConnPtr[icell]+procOffset));
+          for (int icell=index_ptr[i]; icell<index_ptr[i+1]; icell++)
+          {
+            node2cell.insert(make_pair(globalNodeIds[i], globalRevConnPtr[icell]+procOffset));
+          }
         }
       if (isParallelMode())
         {
@@ -787,10 +1529,8 @@ void MESHCollection::buildCellGraph(MEDPARTITIONER::MEDSKYLINEARRAY* & array,int
                     {
                       int ilocnode=iter->first;
                       int icell=iter->second;
-                      
-                      node2cell.insert(make_pair(globalNodeIds[ilocnode],icell+offset));     
+                      node2cell.insert(make_pair(globalNodeIds[ilocnode],icell+offset));
                     }
-                  // }
             }
         }
 
@@ -807,33 +1547,41 @@ void MESHCollection::buildCellGraph(MEDPARTITIONER::MEDSKYLINEARRAY* & array,int
   // means 6 arcs (0,1), (0,2), (0,3), (1,2), (1,3), (2,3)
   // in present version arcs are not doubled but reflexive (1,1) arcs are present for each cell
  
+  //warning here one node have effective number of cell with it
+  //but cell could have more than effective nodes 
+  //is it normal??? because other equals nodes in other domain (with other inode)???
+  
   int mincell,maxcell;
   if (isParallelMode())
     {
-      mincell=_domain_selector->getProcShift()+1;
+      mincell=_domain_selector->getProcShift();
       maxcell=mincell;
       for (int i=0; i<nbdomain;i++)
         if (_domain_selector->isMyDomain(i)) maxcell+=_mesh[i]->getNumberOfCells();
-    
     }
   else
     {
       mincell=0;
       maxcell=_topology->nbCells();
     }
-  for (int inode=0; inode<_topology->nbNodes();inode++)
+  for (int inode=0; inode<_topology->nbNodes(); inode++)  //on all nodes
     {
       typedef multimap<int,int>::const_iterator MI;
       pair <MI,MI> myRange = node2cell.equal_range(inode);
-      for (MI cell1=myRange.first; cell1!=myRange.second; cell1++)
+      
+      
+      for (MI cell1=myRange.first; cell1!=myRange.second; cell1++)  //on cells with inode
         {
-          for (MI cell2 = myRange.first; cell2!=myRange.second; cell2++)
+          for (MI cell2 = myRange.first; cell2!=myRange.second; cell2++)  //on one of these cell
             {
-              if (cell1->second!=cell2->second&&cell1->second>=mincell&&cell1->second<maxcell) cell2cell.insert(make_pair(cell1->second,cell2->second));
+              if (cell1->second!=cell2->second && cell1->second>=mincell && cell1->second<maxcell)  //in cells of my domain
+              {
+                cell2cell.insert(make_pair(cell1->second,cell2->second));
+              }
             }
         }
     }
-
+  //cout<<"proc "<<MyGlobals::_rank<<" end create skylinearray"<<endl;
   //filling up index and value to create skylinearray structure
 
   multimap<int,int>::const_iterator iter;
@@ -841,26 +1589,34 @@ void MESHCollection::buildCellGraph(MEDPARTITIONER::MEDSKYLINEARRAY* & array,int
   iter=cell2cell.begin();
   vector <int> index,value;
   index.push_back(0);
+  int idep=0;
   while (iter != cell2cell.end())
+  {
+    multimap<int,int>::const_iterator next_iter = cell2cell.upper_bound(iter->first);
+    int size=0;
+    for (multimap<int,int>::const_iterator current_iter=iter; current_iter!=next_iter; current_iter++)
     {
-      multimap<int,int>::const_iterator next_iter = cell2cell.upper_bound(iter->first);
-      int size=0;
-      for (multimap<int,int>::const_iterator current_iter=iter; current_iter!=next_iter; current_iter++)
+      int ival=current_iter->second; //no adding one existing yet
+      for (int i=idep ; i<idep+size ; i++)
+      {
+        if (value[i]==ival)
         {
-          value.push_back(current_iter->second);
-          size++;
+          ival=-1;
+          break;
         }
-      index.push_back(index[index.size()-1]+size);
-
-      
-      iter=next_iter;
+      }
+      if (ival!=-1)
+      {
+        value.push_back(ival);
+        size++;
+      }
     }
-
+    idep=index[index.size()-1]+size;
+    index.push_back(idep);
+    iter=next_iter;
+  }
   array=new MEDPARTITIONER::MEDSKYLINEARRAY(index,value);
-
-  cout<< "end of graph creation"<<endl;
-}
-
+}*/
 
 /*! Creates the partition corresponding to the cell graph and the partition number
  * 
@@ -868,36 +1624,45 @@ void MESHCollection::buildCellGraph(MEDPARTITIONER::MEDSKYLINEARRAY* & array,int
  * 
  * returns a topology based on the new graph
  */
-Topology* MESHCollection::createPartition(int nbdomain, 
+Topology* MESHCollection::createPartition(int nbdomain, //cvwat06
                                           Graph::splitter_type split, 
-                                          const string& options_string,
+                                          const std::string& options_string,
                                           int* user_edge_weights,
                                           int* user_vertices_weights)
 {
-  if (nbdomain <1) throw MEDMEM::MEDEXCEPTION("Number of subdomains must be >0");
+  using std::cout;
+  using std::endl;
+  
+  if (MyGlobals::_verbose>10) cout<<"proc "<<MyGlobals::_rank<<" : MESHCollection::createPartition : Building cell graph"<<endl;
+  
+  if (nbdomain <1) throw INTERP_KERNEL::Exception(LOCALIZED("Number of subdomains must be > 0"));
   MEDPARTITIONER::MEDSKYLINEARRAY* array=0;
   int* edgeweights=0;
 
-  cout<<"Building cell graph";
+  //cout<<"Building cell graph... ";
   //   if ( _domain_selector )
   //     buildCellGraphParallel(array,edgeweights);
   //   else
-  buildCellGraph(array,edgeweights);
+  buildCellGraph(array,edgeweights); //cvwat09
+  //MPI_Barrier(MPI_COMM_WORLD);
+  //cout<<"proc "<<MyGlobals::_rank<<" :end barrier CellGraph done"<<endl;
   Graph* cellGraph;
   switch (split)
     {
     case Graph::METIS:
 #ifdef ENABLE_METIS
+      if (MyGlobals::_verbose>10) cout<<"METISGraph"<<endl;
       cellGraph=(Graph*)(new METISGraph(array,edgeweights));
 #else
-      throw MEDMEM::MEDEXCEPTION("METIS Graph is not available. Check your products, please.");
+      throw INTERP_KERNEL::Exception(LOCALIZED("METIS Graph is not available. Check your products, please."));
 #endif
       break;
     case Graph::SCOTCH:
 #ifdef ENABLE_SCOTCH
+      if (MyGlobals::_verbose>10) cout<<"SCOTCHGraph"<<endl;
       cellGraph=(Graph*)(new SCOTCHGraph(array,edgeweights));
 #else
-      throw MEDMEM::MEDEXCEPTION("SCOTCH Graph is not available. Check your products, please.");
+      throw INTERP_KERNEL::Exception(LOCALIZED("SCOTCH Graph is not available. Check your products, please."));
 #endif
       break;
     }
@@ -908,21 +1673,18 @@ Topology* MESHCollection::createPartition(int nbdomain,
   if (user_vertices_weights!=0)
     cellGraph->setVerticesWeights(user_vertices_weights);
 
-  cout<<"Partitioning graph";
-  cellGraph->partGraph(nbdomain,options_string,_domain_selector);
-
-  
+  if (MyGlobals::_is0verbose>10) cout<<"partitioning graph on "<<nbdomain<<" domains"<<endl;
+  cellGraph->partGraph(nbdomain, options_string, _domain_selector);  //cvwat10
 
-  cout<<"Building new topology";
+  if (MyGlobals::_is0verbose>10) cout<<"building new topology"<<endl;
   //cellGraph is a shared pointer 
-  Topology* topology = new ParallelTopology (cellGraph, nbdomain, getMeshDimension());
+  Topology* topology=new ParallelTopology (cellGraph, getTopology(), nbdomain, getMeshDimension());
 
   //cleaning
   if (edgeweights!=0) delete[] edgeweights;
   // if (array!=0) delete array;
-  cout<<"End of partition creation";
   delete cellGraph;
-
+  if (MyGlobals::_verbose>11) cout<<"proc "<<MyGlobals::_rank<<" : end MESHCollection::createPartition"<<endl;
   return topology;
 }
 
@@ -934,6 +1696,8 @@ Topology* MESHCollection::createPartition(int nbdomain,
  */
 Topology* MESHCollection::createPartition(const int* partition)
 {
+  using std::set;
+  
   MEDPARTITIONER::MEDSKYLINEARRAY* array=0;
   int* edgeweights=0;
 
@@ -949,7 +1713,7 @@ Topology* MESHCollection::createPartition(const int* partition)
   cellGraph=(Graph*)(new UserGraph(array, partition, _topology->nbCells()));
   
   //cellGraph is a shared pointer 
-  Topology* topology = new ParallelTopology (cellGraph, nbdomain, getMeshDimension());
+  Topology* topology = new ParallelTopology (cellGraph, getTopology(), nbdomain, getMeshDimension());
   
   //  if (array!=0) delete array;
   delete cellGraph;
@@ -960,9 +1724,248 @@ void MESHCollection::setDomainNames(const std::string& name)
 {
   for (int i=0; i<_topology->nbDomain(); i++)
     {
-      ostringstream oss;
+      std::ostringstream oss;
       oss<<name<<"_"<<i;
       if (!isParallelMode() || _domain_selector->isMyDomain(i))
       _mesh[i]->setName(oss.str().c_str());
     }
 }
+
+ParaMEDMEM::DataArrayDouble* MESHCollection::getField(std::string descriptionField, int iold)
+//getField look for and read it if not done, and assume decrRef() in ~MESHCollection;
+//something like MEDCouplingFieldDouble *f2=MEDLoader::ReadFieldCell(name.c_str(),f1->getMesh()->getName(),0,f1->getName(),0,1);
+ {
+  int rank=MyGlobals::_rank;
+  string tag="ioldFieldDouble="+intToStr(iold);
+  string descriptionIold=descriptionField+serializeFromString(tag);
+  if (_mapDataArrayDouble.find(descriptionIold)!=_mapDataArrayDouble.end())
+  {
+    if (MyGlobals::_verbose>300) cout<<"proc "<<rank<<" : YET READ getField : "<<descriptionIold<<endl;
+    DataArrayDouble* res=_mapDataArrayDouble[descriptionIold];
+    //cout<<res->reprZip()<<endl;
+    return res;
+  }
+  if (MyGlobals::_verbose>200) cout<<"proc "<<rank<<" : TO BE READ getField : "<<descriptionIold<<endl;
+  string description, fileName, meshName, fieldName;
+  int idomain, typeField, DT, IT, entity;
+  idomain=iold;
+  fileName=MyGlobals::_fileNames[iold];
+  if (MyGlobals::_verbose>10) 
+    cout<<"proc "<<MyGlobals::_rank<<" : in "<<fileName<<" "<<iold<<" "<<descriptionIold<<endl;
+  //cout<<"\n\n"<<"ON_CELLS "<<ON_CELLS<<" ON_NODES "<<ON_NODES<<" ON_GAUSS_PT "<<ON_GAUSS_PT<<" ON_GAUSS_NE "<<ON_GAUSS_NE<<endl;;
+  //typeField ON_CELLS 0 ON_NODES 1 ON_GAUSS_PT 2 ON_GAUSS_NE 3;
+  //fieldDescriptionToData(descriptionField, &idomain, &fileName, &meshName, &fieldName, &typeField, &DT, &IT);
+  fieldShortDescriptionToData(descriptionIold, fieldName, typeField, entity, DT, IT);
+  meshName=MyGlobals::_meshNames[iold];
+  
+  //MEDCouplingFieldDouble* f2=MEDLoader::ReadFieldCell(
+  //         fileName.c_str(), meshName.c_str(), meshDimRelToMax, fieldName.c_str(), DT, IT);
+  MEDCouplingFieldDouble* f2=MEDLoader::ReadField((ParaMEDMEM::TypeOfField) typeField,
+           fileName.c_str(), meshName.c_str(), 0, fieldName.c_str(), DT, IT);
+  
+  DataArrayDouble* res=f2->getArray();
+  //to know names of components
+  vector <string> browse=browseFieldDouble(f2);
+  //done yet 
+  //double time=f2->getTime(IT,DT);
+  //browse.push_back("time="+doubleToStr(time));
+  string localFieldInformation=descriptionIold+serializeFromVectorOfString(browse);
+  if (MyGlobals::_verbose>10) cout<<"proc "<<MyGlobals::_rank<<" : localFieldInformation : "<<localFieldInformation<<endl;
+  MyGlobals::_generalInformations.push_back(localFieldInformation);
+  res->incrRef();  //free field, keep res
+  f2->decrRef();
+  _mapDataArrayDouble[descriptionIold]=res; 
+  
+  //duplicate it! because f2->decRef!!
+  //DataArrayDouble* res=f2->getArray()->deepCpy();
+  //f2->decrRef();
+  //cout<<res->reprZip()<<endl;
+  //have to put it in map for next needs.. decRef later...~MESHCollection
+  return res;
+}
+
+void MESHCollection::prepareFieldDescriptions()
+//to have unique valid fields names/pointers/descriptions for partitionning
+//filter _fieldDescriptions to be in all procs compliant and equal
+{
+  int nbfiles=MyGlobals::_fileNames.size(); //nb domains
+  vector<string> r2;
+  //from allgatherv then vector(procs) of serialised vector(fields) of vector(description) data
+  for (int i=0; i<_fieldDescriptions.size(); i++)
+  {
+    vector<string> r1=deserializeToVectorOfString(_fieldDescriptions[i]);
+    for (int i=0; i<r1.size(); i++) r2.push_back(r1[i]);
+  }
+  //here vector(procs*fields) of serialised vector(description) data
+  _fieldDescriptions=r2;
+  int nbfields=_fieldDescriptions.size(); //on all domains
+  if ((nbfields%nbfiles)!=0)
+  {
+    if (MyGlobals::_rank==0)
+    {
+      cerr<<"\nERROR : incoherent number of fields references in all files .med\n"<<endl
+          <<"fileMedNames :"<<endl
+          <<reprVectorOfString(MyGlobals::_fileNames)
+          <<"fieldDescriptions :"<<endl
+          <<reprVectorOfString(MyGlobals::_fieldDescriptions); //cvwat07
+    }
+    throw INTERP_KERNEL::Exception(LOCALIZED("incoherent number of fields references in all files .med\n"));
+  }
+  _fieldDescriptions.resize(nbfields/nbfiles);
+  for (int i=0; i<_fieldDescriptions.size(); i++)
+  {
+    string str=_fieldDescriptions[i];
+    str=eraseTagSerialized(str,"idomain=");
+    str=eraseTagSerialized(str,"fileName=");
+    _fieldDescriptions[i]=str;
+  }
+}
+
+//returns true if inodes of a face are in inodes of a cell
+bool isFaceOncell(vector< int >& inodesFace,vector< int >&  inodesCell)
+{
+  int ires=0;
+  int nbok=inodesFace.size();
+  for (int i=0; i<nbok; i++)
+  {
+    int ii=inodesFace[i];
+    if (ii<0) cout<<"isFaceOncell problem inodeface<0"<<endl;
+    for (int j=0; j<inodesCell.size(); j++)
+    {
+      if (ii==inodesCell[j])
+      {
+        ires=ires+1; break; //inode of face found
+      }
+    }
+    if (ires<i+1) break; //inode of face not found do not continue...
+  }
+  return (ires==nbok);
+}
+
+void MESHCollection::filterFaceOnCell()
+{
+  //meshesCells=_mesh;
+  //meshesFaces=_faceMesh;
+  for (int inew=0; inew<_topology->nbDomain(); inew++)
+  {
+    if (isParallelMode() && _domain_selector->isMyDomain(inew))
+    {
+      if (MyGlobals::_verbose>200) 
+        std::cout<<"proc "<<MyGlobals::_rank<<" : filterFaceOnCell on inewDomain "<<inew<<
+                   " nbOfFaces "<<_faceMesh[inew]->getNumberOfCells()<<endl;
+      ParaMEDMEM::MEDCouplingUMesh* mcel=_mesh[inew];
+      ParaMEDMEM::MEDCouplingUMesh* mfac=_faceMesh[inew];
+      
+      //to have cellnode=f(facenode)... inodeCell=nodeIds[inodeFace]
+      vector<int> nodeIds;
+      //cout<<"proc "<<MyGlobals::_rank<<" : nodeIds beg "<<inew<<" "<<mcel<<" "<<mfac<<endl;
+      getNodeIds(*mcel, *mfac, nodeIds);
+      if (nodeIds.size()==0) continue;  //one empty mesh nothing to do
+      
+      DataArrayInt *revNodalCel=DataArrayInt::New();
+      DataArrayInt *revNodalIndxCel=DataArrayInt::New();
+      mcel->getReverseNodalConnectivity(revNodalCel,revNodalIndxCel);
+      int *revC=revNodalCel->getPointer();
+      int *revIndxC=revNodalIndxCel->getPointer();
+      
+      vector< int > faceOnCell;
+      vector< int > faceNotOnCell;
+      int nbface=mfac->getNumberOfCells();
+      for (int iface=0; iface<nbface; iface++)
+      {
+        bool ok;
+        vector< int > inodesFace;
+        mfac->getNodeIdsOfCell(iface, inodesFace);
+        int nbnodFace=inodesFace.size();
+        //set inodesFace in mcel
+        for (int i=0; i<nbnodFace; i++) inodesFace[i]=nodeIds[inodesFace[i]];
+        int inod=inodesFace[0];
+        if (inod<0) cout<<"filterFaceOnCell problem 1"<<endl;
+        int nbcell=revIndxC[inod+1]-revIndxC[inod];
+        for (int j=0; j<nbcell; j++) //look for each cell with inod
+        {
+          int icel=revC[revIndxC[inod]+j];
+          vector< int > inodesCell;
+          mcel->getNodeIdsOfCell(icel, inodesCell);
+          ok=isFaceOncell(inodesFace, inodesCell);
+          if (ok) break;
+        }
+        if (ok)
+        {
+          faceOnCell.push_back(iface);
+          //if (MyGlobals::_is0verbose) cout<<"face on cell "<<iface<<" "<<faceOnCell.size()-1<<endl;
+        }
+        else
+        {
+          faceNotOnCell.push_back(iface);
+          if (MyGlobals::_is0verbose) cout<<"face NOT on cell "<<iface<<" "<<faceOnCell.size()-1<<endl;
+        }
+      }
+      
+      revNodalCel->decrRef();
+      revNodalIndxCel->decrRef();
+      
+      string cle;
+      cle=cle1ToStr("filterFaceOnCell",inew);
+      _mapDataArrayInt[cle]=createDataArrayIntFromVector(faceOnCell);
+      cle=cle1ToStr("filterNotFaceOnCell",inew);
+      _mapDataArrayInt[cle]=createDataArrayIntFromVector(faceNotOnCell);
+      
+      /*ParaMEDMEM::DataArrayInt* index=ParaMEDMEM::DataArrayInt::New();
+      ParaMEDMEM::DataArrayInt* revConn=ParaMEDMEM::DataArrayInt::New();
+      _mesh[idomain]->getReverseNodalConnectivity(revConn,index);
+      int* index_ptr=index->getPointer();*/
+      
+      /*if (MyGlobals::_is0verbose)
+      {
+        cout<<"proc "<<MyGlobals::_rank<<" : nodeIds end "<<inew<<" "<<nodeIds.size()<<endl;
+        for (int i=0; i<nodeIds.size(); i++) cout<<" "<<nodeIds[i];
+        cout<<endl;
+      }*/
+
+    }
+  }
+}
+
+/*
+void MESHCollection::buildBoundaryOnCellMeshes()
+//no used... yet
+{
+  //cout<<"buildBoundaryOnCellMeshes"<<endl;
+  //meshesCells=_mesh;
+  //meshesFaces=_faceMesh;
+  for (int inew=0; inew<_topology->nbDomain(); inew++)
+  {
+    if (isParallelMode() && _domain_selector->isMyDomain(inew))
+    {
+      if (MyGlobals::_verbose>1) std::cout<<"proc "<<MyGlobals::_rank<<" : filterFaceOnCell on "<<inew<<" "<<_faceMesh[inew]->getNumberOfCells()<<endl;
+      ParaMEDMEM::MEDCouplingUMesh* mcel=_mesh[inew];
+      //ParaMEDMEM::MEDCouplingUMesh& mfac=_faceMesh[inew];
+      
+      DataArrayInt *desc=DataArrayInt::New();
+      DataArrayInt *descIndx=DataArrayInt::New();
+      DataArrayInt *revDesc=DataArrayInt::New();
+      DataArrayInt *revDescIndx=DataArrayInt::New();
+      //
+      MEDCouplingUMesh *meshDM1=mcel->buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
+      revDesc->decrRef();
+      desc->decrRef();
+      descIndx->decrRef();
+      int nbOfCells=meshDM1->getNumberOfCells();
+      const int *revDescIndxC=revDescIndx->getConstPointer();
+      std::vector<int> boundaryCells;
+      for(int i=0; i<nbOfCells; i++)
+        if(revDescIndxC[i+1]-revDescIndxC[i]==1)
+          boundaryCells.push_back(i);
+      revDescIndx->decrRef();
+      bool keepCoords=true;
+      MEDCouplingUMesh *ret=(MEDCouplingUMesh *)meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
+      meshDM1->decrRef();
+      //don't know what to do with result yet..
+      //_faceMesh[inew]->decrRef();
+      //_faceMesh[inew]=ret;
+    }
+  }
+}
+*/
+
index 331d33339bf0cc525a2a0dd1cdbc7fc04c2596fb..e30a9b6398675ade160b6e273997115c3caf6672 100644 (file)
@@ -22,6 +22,8 @@
 #include "MEDPARTITIONER.hxx"
 
 #include "MEDPARTITIONER_Graph.hxx"
+#include "MEDCouplingUMesh.hxx"
+
 //#include "MEDPARTITIONER_FaceModel.hxx"
 //#include "boost/shared_ptr.hpp"
 #include <vector>
@@ -89,62 +91,40 @@ namespace MEDPARTITIONER
 
     //creation of a user specified partition
     Topology* createPartition(const int* partition);
-
-   //  //retrieving list of types
-//       void getTypeList(int* cell_list,int nb_cells,MED_EN::medEntityMesh entity,
-//                      MED_EN::medGeometryElement* type_list) const ;
-
-//     //getting list of coordinates
-//     void getCoordinates(int* node_list,int nb_nodes, double* coordinates) const ;
-
-//     //getting connectivities
-//     void getNodeConnectivity( const int*  cell_list,int nb_cells,MED_EN::medEntityMesh,MED_EN::medGeometryElement type, int* type_connectivity) const ;
-//     void getPolygonNodeConnectivity(const int* cell_list,int nb_cells,MED_EN::medEntityMesh entity,
-//                                     vector<int>& type_connectivity, vector<int>& connectivity_index) const;
-//     void getPolyhedraNodeConnectivity(const int* cell_list,int nb_cells,MED_EN::medEntityMesh entity,
-//                                       vector<int>& type_connectivity, vector<int>& connectivity_index, vector<int>& face_connectivity_index) const;
-
-//     void getFaceConnectivity( const int*  cell_list,int nb_cells,MED_EN::medEntityMesh,MED_EN::medGeometryElement type, int* type_connectivity) const ;
-
-//     //void getFaceConnectivity( const int*  cell_list,int nb_cells,MED_EN::medGeometryElement type, int* type_connectivity) const ;
-
-//     //getting mesh dimension
+    
+     //getting mesh dimension
      int getMeshDimension() const ;
 
-//     //getting space dimension
-//     int getSpaceDimension() const ;
-
-//     //getting system of coordinates
-//     std::string getSystem() const;
+     //getting a reference to mesh vector
+     std::vector<ParaMEDMEM::MEDCouplingUMesh*>& getMesh();
+     std::vector<ParaMEDMEM::MEDCouplingUMesh*>& getFaceMesh();
+     std::vector<std::vector<ParaMEDMEM::MEDCouplingUMesh*> >& getGroupMeshes();
 
-//     //getting name of the mesh
-//     std::string getMeshName() const;
-
-//     //return constituent entity
-//     MED_EN::medEntityMesh getSubEntity() const;
-
-//     //getting a reference to mesh vector
-     std::vector<ParaMEDMEM::MEDCouplingUMesh*>& getMesh() ;
-     std::vector<ParaMEDMEM::MEDCouplingUMesh*>& getFaceMesh() ;
-     std::vector<std::vector<ParaMEDMEM::MEDCouplingUMesh*> >&getGroupMeshes();
      ParaMEDMEM::MEDCouplingUMesh* getMesh(int idomain) const;
      ParaMEDMEM::MEDCouplingUMesh* getFaceMesh(int idomain);
      std::vector<ParaMEDMEM::MEDCouplingUMesh*>& getGroupMeshes(int idomain);
 
      std::vector<ParaMEDMEM::DataArrayInt*>& getCellFamilyIds() {return _cellFamilyIds;}
      std::vector<ParaMEDMEM::DataArrayInt*>& getFaceFamilyIds() {return _faceFamilyIds;}
-
-     std::map<std::string,int>& getFamilyInfo(){return _familyInfo;}
-     std::map<std::string, std::vector<std::string> >& getGroupInfo(){return _groupInfo;}
-//     //getting a reference to connect zones vector
+     
+     std::map<std::string, ParaMEDMEM::DataArrayInt*>& getMapDataArrayInt() {return _mapDataArrayInt;}
+     std::map<std::string, ParaMEDMEM::DataArrayDouble*>& getMapDataArrayDouble() {return _mapDataArrayDouble;}
+
+     std::map<std::string,int>& getFamilyInfo() {return _familyInfo;}
+     std::map<std::string, std::vector<std::string> >& getGroupInfo() {return _groupInfo;}
+
+     ParaMEDMEM::DataArrayDouble* getField(std::string descriptionField, int iold);
+     std::vector<std::string>&  getFieldDescriptions() {return _fieldDescriptions;}
+     void prepareFieldDescriptions();
+     void filterFaceOnCell();
+     
+    //getting a reference to connect zones vector
     std::vector<MEDPARTITIONER::CONNECTZONE*>& getCZ();
 
     //getting a pointer to topology
     Topology* getTopology() const ;
     ParaDomainSelector* getParaDomainSelector() const{return _domain_selector;}
-  //settig a new topology
+    //settig a new topology
     void setTopology(Topology* topology);
 
     //getting/setting the name of the global mesh (as opposed 
@@ -158,48 +138,66 @@ namespace MEDPARTITIONER
     void setDescription(const std::string& name) { _description=name;}
 
     //creates the node mapping between an old collection and the present one
-    void createNodeMapping( MESHCollection& initialCollection, std::multimap<std::pair<int,int>,std::pair<int,int> >& nodeMapping);
+    void createNodeMapping(MESHCollection& initialCollection, 
+                           std::multimap<std::pair<int,int>,std::pair<int,int> >& nodeMapping);
 
-    void castCellMeshes(MESHCollection& initialCollection, std::vector<std::vector<std::vector<int> > >& new2oldIds);
+    void castCellMeshes(MESHCollection& initialCollection, 
+                        std::vector<std::vector<std::vector<int> > >& new2oldIds);
+    
     //creates faces on the new collection
-    void castFaceMeshes( MESHCollection& initialCollection,const std::multimap<std::pair<int,int>,std::pair<int,int> >& nodeMapping);
+    void castFaceMeshes(MESHCollection& initialCollection,
+                    const std::multimap<std::pair<int,int>, std::pair<int,int> >& nodeMapping,
+                    std::vector<std::vector<std::vector<int> > >& new2oldIds);
 
-    //creates faces on the new collection
-    void castMeshes(std::vector<ParaMEDMEM::MEDCouplingUMesh*>& meshCastFrom,std::vector<ParaMEDMEM::MEDCouplingUMesh*>& meshCastTo,   MESHCollection& initialCollection,const std::multimap<std::pair<int,int>,std::pair<int,int> >& nodeMapping, std::vector<std::vector<std::vector<int> > >& old2newIds);
-    
   private:
 
-    
-    void castIntField(std::vector<ParaMEDMEM::MEDCouplingUMesh*>& meshesCastFrom,std::vector<ParaMEDMEM::MEDCouplingUMesh*>& meshesCastTo,  std::vector<ParaMEDMEM::DataArrayInt*>& arrayFrom,  std::vector<ParaMEDMEM::DataArrayInt*>& arrayTo);
+    void castIntField2(std::vector<ParaMEDMEM::MEDCouplingUMesh*>& meshesCastFrom,
+                       std::vector<ParaMEDMEM::MEDCouplingUMesh*>& meshesCastTo,
+                       std::vector<ParaMEDMEM::DataArrayInt*>& arrayFrom,
+                       std::string nameArrayTo);
+
+    void castAllFields(MESHCollection& initialCollection,
+                       std::string nameArrayTo);
 
     void findCommonDistantNodes(std::vector<std::vector<std::multimap<int,int> > >& commonDistantNodes);
 
-void remapIntField(const ParaMEDMEM::MEDCouplingUMesh& sourceMesh,
-                              const ParaMEDMEM::MEDCouplingUMesh& targetMesh,
-                              const int* fromArray,
-                               int* toArray);
+    void remapIntField(const ParaMEDMEM::MEDCouplingUMesh& sourceMesh,
+                       const ParaMEDMEM::MEDCouplingUMesh& targetMesh,
+                       const int* fromArray,
+                       int* toArray);
+    
+    void remapIntField2(int inew, int iold, 
+                       const ParaMEDMEM::MEDCouplingUMesh& sourceMesh,
+                       const ParaMEDMEM::MEDCouplingUMesh& targetMesh,
+                       const int* fromArray,
+                       std::string nameArrayTo);
+
+    void remapDoubleField3(int inew, int iold,
+                           ParaMEDMEM::DataArrayDouble* fromArray,
+                           std::string nameArrayTo,
+                           std::string descriptionField);
 
     //!link to mesh_collection topology
-    Topology*                         _topology;
+    Topology* _topology;
 
     //!control over topology
-    bool                              _owns_topology;
+    bool _owns_topology;
 
     //!link to graph
-    //    Graph*          _cell_graph;
+    //Graph* _cell_graph;
 
     //! Driver for read/write operations
-    MESHCollectionDriver*             _driver;
+    MESHCollectionDriver* _driver;
 
     //! Parallelizer - mark of parallel execution mode
-    ParaDomainSelector*               _domain_selector;
+    ParaDomainSelector* _domain_selector;
 
     //!links to meshes
-    std::vector<ParaMEDMEM::MEDCouplingUMesh*>        _mesh;
-    std::vector<ParaMEDMEM::MEDCouplingUMesh*>        _faceMesh;
+    std::vector<ParaMEDMEM::MEDCouplingUMesh*> _mesh;
+    std::vector<ParaMEDMEM::MEDCouplingUMesh*> _faceMesh;
    
- //!index of a non empty mesh within _mesh (in parallel mode all of meshes can be empty)
-    int                               _i_non_empty_mesh;
   //!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;
@@ -207,34 +205,41 @@ void remapIntField(const ParaMEDMEM::MEDCouplingUMesh& sourceMesh,
     //!family ids storages
     std::vector<ParaMEDMEM::DataArrayInt*> _cellFamilyIds;
     std::vector<ParaMEDMEM::DataArrayInt*> _faceFamilyIds;
-
+    
+    //!DataArrayInt* storages
+    std::map<std::string, ParaMEDMEM::DataArrayInt*> _mapDataArrayInt;
+    //!DataArrayDouble* storages
+    std::map<std::string, ParaMEDMEM::DataArrayDouble*> _mapDataArrayDouble;
+    
+    std::vector<std::string> _fieldDescriptions; //fields to be partitioned
+    
     //!group family conversion
-    std::map<std::string,int> _familyInfo;
+    std::map<std::string, int> _familyInfo;
     std::map<std::string, std::vector<std::string> > _groupInfo;
   
     //!list of groups that are not to be splitted
-    std::vector<std::string>          _indivisible_regions;
+    std::vector<std::string> _indivisible_regions;
 
     //!name of global mesh
-    std::string                            _name;
+    std::string _name;
 
     //!description of global mesh
-    std::string                            _description;
+    std::string _description;
 
     //! specifies the driver associated to the collection
-    DriverType                        _driver_type;
+    DriverType _driver_type;
 
     /*! flag specifying that the splitter should create boundary constituent entity
       so that they are written in joints*/
-    bool                              _subdomain_boundary_creates;
+    bool _subdomain_boundary_creates;
 
         /*! flag specifying that families must be preserved by the
                 splitting*/
-    bool                              _family_splitting;
+    bool _family_splitting;
 
         /*! flag specifying that groups must be created on all domains, 
                 even if they are empty*/
-    bool                              _create_empty_groups;
+    bool _create_empty_groups;
 
     JointFinder* _joint_finder;
   };
index 2de4dc7b6457f51ca7f50f244c23e4a772bbc5e1..78b1e5edfd137bdb8661f4494b0090a4c984734d 100644 (file)
 
 #include <sys/time.h>
 #include "MEDCouplingUMesh.hxx"
+#include "MEDCouplingFieldDouble.hxx"
 #include "MEDLoader.hxx"
 #include "MEDFileMesh.hxx"
-#include "MEDMEM_Exception.hxx"
+
 extern "C" {
 #include "med.h"
 }
@@ -42,8 +43,10 @@ extern "C" {
 #include "MEDPARTITIONER_MESHCollectionDriver.hxx"
 #include "MEDPARTITIONER_MESHCollection.hxx"
 #include "MEDPARTITIONER_ParaDomainSelector.hxx"
+#include "MEDPARTITIONER_utils.hxx"
 
 using namespace MEDPARTITIONER;
+using namespace std;
 
 //template inclusion
 //#include "MEDPARTITIONER_MESHCollectionDriver.H"
@@ -78,11 +81,9 @@ MESHCollectionDriver::MESHCollectionDriver(MESHCollection* collection):_collecti
  * */
 int MESHCollectionDriver::readSeq(const char* filename, const char* meshname)
 {
-  //const char* LOC = "MEDPARTITIONER::MESHCollectionDriver::readSeq()";
-  //  BEGIN_OF_MED(LOC);
-
-  _filename.resize(1);
-  _filename[0]=string(filename);
+  cout<<"readSeq"<<endl;
+  MyGlobals::_fileNames.resize(1);
+  MyGlobals::_fileNames[0]=string(filename);
 
   ParaMEDMEM::MEDFileUMesh* mfm=ParaMEDMEM::MEDFileUMesh::New(filename,meshname);
   //puts the only mesh in the mesh vector
@@ -111,6 +112,7 @@ int MESHCollectionDriver::readSeq(const char* filename, const char* meshname)
 
 
   (_collection->getCZ()).clear();
+  /*cvw 
   vector<int*> cellglobal,nodeglobal,faceglobal;
   cellglobal.resize(1);
   nodeglobal.resize(1);
@@ -122,11 +124,12 @@ int MESHCollectionDriver::readSeq(const char* filename, const char* meshname)
   //connectzone argument is 0
   ParallelTopology* aPT = new ParallelTopology
     ((_collection->getMesh()), (_collection->getCZ()), cellglobal, nodeglobal, faceglobal);
+  */
+  
+  ParallelTopology* aPT = new ParallelTopology((_collection->getMesh()));
   _collection->setTopology(aPT);
   _collection->setName(meshname);
   _collection->setDomainNames(meshname);
-
-  //  END_OF_MED(LOC);
   return 0;
 }
 
@@ -137,35 +140,141 @@ int MESHCollectionDriver::readSeq(const char* filename, const char* meshname)
  */
 //================================================================================
 
-
-void MESHCollectionDriver::readSubdomain(vector<int*>& cellglobal,
+void MESHCollectionDriver::readSubdomain(vector<int*>& cellglobal, //cvwat03
                                          vector<int*>& faceglobal,
                                          vector<int*>& nodeglobal, int idomain)
 {
-  string meshname=_meshname[idomain];
-  string file=_filename[idomain];
+  string meshname=MyGlobals::_meshNames[idomain];
+  string file=MyGlobals::_fileNames[idomain];
 
-  cout << "Reading "<<_meshname[idomain]<<" in "<<_filename[idomain]<<endl;
+  //cout << "Reading "<<meshname<<" in "<<file<<endl; //cvw
 
   ParaMEDMEM::MEDFileUMesh* mfm=ParaMEDMEM::MEDFileUMesh::New(file.c_str(),meshname.c_str());
- (_collection->getMesh())[idomain]=mfm->getLevel0Mesh(false);
-  (_collection->getFaceMesh())[idomain]=mfm->getLevelM1Mesh(false);
+  vector<int> nonEmpty=mfm->getNonEmptyLevels();
+  
+  try 
+  { 
+    (_collection->getMesh())[idomain]=mfm->getLevel0Mesh(false); 
+    //reading families groups
+    ParaMEDMEM::DataArrayInt* cellIds(mfm->getFamilyFieldAtLevel(0)->deepCpy());
+    (_collection->getCellFamilyIds())[idomain]=cellIds;
+  }
+  catch(...)
+  { 
+    (_collection->getMesh())[idomain]=createEmptyMEDCouplingUMesh(); // or 0 if you want tests;
+    ParaMEDMEM::DataArrayInt* empty=ParaMEDMEM::DataArrayInt::New();
+    empty->alloc(0,1);
+    (_collection->getCellFamilyIds())[idomain]=empty;
+    cout<<"\nNO Level0Mesh (Cells)\n";
+  }
+  try 
+  { 
+    if (nonEmpty.size()>1 && nonEmpty[1]==-1)
+    {
+      (_collection->getFaceMesh())[idomain]=mfm->getLevelM1Mesh(false);
+      //reading families groups
+      ParaMEDMEM::DataArrayInt* faceIds(mfm->getFamilyFieldAtLevel(-1)->deepCpy());
+      (_collection->getFaceFamilyIds())[idomain]=faceIds;
+    }
+    else
+    {
+      throw "no faces";
+    }
+  }
+  catch(...)
+  {
+    //ParaMEDMEM::MEDCouplingUMesh *umesh=ParaMEDMEM::MEDCouplingUMesh::New(); //empty one
+    //umesh->setMeshDimension(3);
+    //umesh->allocateCells(0);
+    //int nb=umesh->getNumberOfCells(); //no use if no allocateCells(0)! because thrown exception
+    //cout<<"\nempty mesh"<<nb<<endl;
+    
+    (_collection->getFaceMesh())[idomain]=createEmptyMEDCouplingUMesh(); // or 0 if you want test;
+    ParaMEDMEM::DataArrayInt* empty=ParaMEDMEM::DataArrayInt::New();
+    (_collection->getFaceFamilyIds())[idomain]=empty;
+    if (MyGlobals::_verbose>10) cout<<"proc "<<MyGlobals::_rank<<" : NO LevelM1Mesh (Faces)\n";
+  }
+  
+  //reading groups
+  _collection->getFamilyInfo()=mfm->getFamilyInfo();
+  _collection->getGroupInfo()=mfm->getGroupInfo();
+
+  mfm->decrRef();
+  
+  vector<string> localInformation;
+  string str;
+  localInformation.push_back(str+"ioldDomain="+intToStr(idomain));
+  localInformation.push_back(str+"meshName="+meshname);
+  MyGlobals::_generalInformations.push_back(serializeFromVectorOfString(localInformation));
+  vector<string> localFields=browseAllFieldsOnMesh(file, meshname, idomain); //cvwat07
+  if (localFields.size()>0) 
+    MyGlobals::_fieldDescriptions.push_back(serializeFromVectorOfString(localFields));
+  //cout<< "End Reading "<<meshname<<" in "<<file<<endl;
+}
 
-  //reading families
-  ParaMEDMEM::DataArrayInt* cellIds(mfm->getFamilyFieldAtLevel(0)->deepCpy());
-  ParaMEDMEM::DataArrayInt* faceIds(mfm->getFamilyFieldAtLevel(-1)->deepCpy());
 
-  (_collection->getCellFamilyIds())[idomain]=cellIds;
-  (_collection->getFaceFamilyIds())[idomain]=faceIds; 
+void MESHCollectionDriver::readSubdomain(int idomain)
+{
+  string meshname=MyGlobals::_meshNames[idomain];
+  string file=MyGlobals::_fileNames[idomain];
 
+  //cout << "Reading "<<meshname<<" in "<<file<<endl; //cvw
+
+  ParaMEDMEM::MEDFileUMesh* mfm=ParaMEDMEM::MEDFileUMesh::New(file.c_str(),meshname.c_str());
+  vector<int> nonEmpty=mfm->getNonEmptyLevels();
+  
+  try 
+  { 
+    (_collection->getMesh())[idomain]=mfm->getLevel0Mesh(false); 
+    //reading families groups
+    ParaMEDMEM::DataArrayInt* cellIds(mfm->getFamilyFieldAtLevel(0)->deepCpy());
+    (_collection->getCellFamilyIds())[idomain]=cellIds;
+  }
+  catch(...)
+  { 
+    (_collection->getMesh())[idomain]=createEmptyMEDCouplingUMesh(); // or 0 if you want tests;
+    ParaMEDMEM::DataArrayInt* empty=ParaMEDMEM::DataArrayInt::New();
+    empty->alloc(0,1);
+    (_collection->getCellFamilyIds())[idomain]=empty;
+    cout<<"\nNO Level0Mesh (Cells)\n";
+  }
+  try 
+  { 
+    if (nonEmpty.size()>1 && nonEmpty[1]==-1)
+    {
+      (_collection->getFaceMesh())[idomain]=mfm->getLevelM1Mesh(false);
+      //reading families groups
+      ParaMEDMEM::DataArrayInt* faceIds(mfm->getFamilyFieldAtLevel(-1)->deepCpy());
+      (_collection->getFaceFamilyIds())[idomain]=faceIds;
+    }
+    else
+    {
+      throw "no faces";
+    }
+  }
+  catch(...)
+  {
+    (_collection->getFaceMesh())[idomain]=createEmptyMEDCouplingUMesh(); // or 0 if you want test;
+    ParaMEDMEM::DataArrayInt* empty=ParaMEDMEM::DataArrayInt::New();
+    (_collection->getFaceFamilyIds())[idomain]=empty;
+    if (MyGlobals::_verbose>10) cout<<"proc "<<MyGlobals::_rank<<" : NO LevelM1Mesh (Faces)\n";
+  }
+  
   //reading groups
   _collection->getFamilyInfo()=mfm->getFamilyInfo();
   _collection->getGroupInfo()=mfm->getGroupInfo();
 
-  cout <<"End of Read"<<endl;
-
   mfm->decrRef();
+  
+  vector<string> localInformation;
+  string str;
+  localInformation.push_back(str+"ioldDomain="+intToStr(idomain));
+  localInformation.push_back(str+"meshName="+meshname);
+  MyGlobals::_generalInformations.push_back(serializeFromVectorOfString(localInformation));
+  vector<string> localFields=browseAllFieldsOnMesh(file, meshname, idomain); //cvwat07
+  if (localFields.size()>0) 
+    MyGlobals::_fieldDescriptions.push_back(serializeFromVectorOfString(localFields));
+  //cout<< "End Reading "<<meshname<<" in "<<file<<endl;
 }
 
 
@@ -173,19 +282,276 @@ void MESHCollectionDriver::writeMedFile(int idomain, const string& distfilename)
 {
   vector<const ParaMEDMEM::MEDCouplingUMesh*> meshes;
   ParaMEDMEM::MEDCouplingUMesh* cellMesh=_collection->getMesh(idomain);
-  ParaMEDMEM::MEDCouplingUMesh*faceMesh =_collection->getFaceMesh(idomain);
+  ParaMEDMEM::MEDCouplingUMesh* faceMesh=_collection->getFaceMesh(idomain);
+  ParaMEDMEM::MEDCouplingUMesh* faceMeshFilter=0;
   
+  string finalMeshName=extractFromDescription(MyGlobals::_generalInformations[0], "finalMeshName=");
+  string cleFilter=cle1ToStr("filterFaceOnCell",idomain);
+  DataArrayInt* filter=0;
+  if (_collection->getMapDataArrayInt().find(cleFilter)!=_collection->getMapDataArrayInt().end())
+  {
+    filter=_collection->getMapDataArrayInt().find(cleFilter)->second;
+    int* index=filter->getPointer();
+    faceMeshFilter=(MEDCouplingUMesh *) faceMesh->buildPartOfMySelf(index,index+filter->getNbOfElems(),true);
+    faceMesh=faceMeshFilter;
+  }
+  cellMesh->setName(finalMeshName.c_str());
   meshes.push_back(cellMesh);
-  // faceMesh->zipCoords();
+  
+  //cellMesh->zipCoords();
+  //faceMesh->zipCoords();
+  
   faceMesh->checkCoherency();
-  faceMesh->tryToShareSameCoordsPermute(*cellMesh,1e-10);
-  meshes.push_back(faceMesh);
-  MEDLoader::WriteUMeshes(distfilename.c_str(), meshes,true);       
-  ParaMEDMEM::MEDFileUMesh* mfm=ParaMEDMEM::MEDFileUMesh::New(distfilename.c_str(),_collection->getMesh(idomain)->getName());
-  mfm->setFamilyFieldArr(-1,(_collection->getFaceFamilyIds())[idomain]);
+  if (faceMesh->getNumberOfCells()>0)
+  {
+    faceMesh->tryToShareSameCoordsPermute(*cellMesh, 1e-10);
+    meshes.push_back(faceMesh);
+  }
+  
+  /*do not work
+  ParaMEDMEM::MEDFileUMesh* mfm2=ParaMEDMEM::MEDFileUMesh::New();
+  MEDFileUMesh* mfm2 = static_cast<MEDFileUMesh*>(cellMesh->getMeshes()->getMeshAtPos(0));
+  MEDFileUMesh* mfm2 = ParaMEDMEM::MEDFileUMesh::New(cellMesh);
+  string fname="FUM_"+distfilename;
+  mfm2->setMeshAtLevel(0, cellMesh );
+  mfm2->setMeshAtLevel(-1, faceMesh );
+  mfm2->write(fname.c_str(),0);
+  mfm2->decrRef();
+  */
+  
+  ParaMEDMEM::MEDCouplingUMesh* boundaryMesh=0;
+  //ParaMEDMEM::MEDCouplingUMesh* boundaryMesh1=0;
+  //ParaMEDMEM::MEDCouplingUMesh* finalboundaryMesh=0;
+  if (MyGlobals::_creates_boundary_faces>0)
+  {
+    //try to write Boundary meshes
+    bool keepCoords=false; //TODO or true
+    boundaryMesh=(MEDCouplingUMesh *) cellMesh->buildBoundaryMesh(keepCoords);
+    boundaryMesh->setName("boundaryMesh");
+    //cout<<"boundaryMesh "<<boundaryMesh->getNumberOfCells()<<endl;
+    //do not work if faceMesh present yet //The mesh dimension of meshes must be different each other!
+    //boundaryMesh->checkCoherency();
+    //boundaryMesh->tryToShareSameCoordsPermute(*cellMesh, 1e-10);
+    //meshes.push_back(boundaryMesh);
+    //string boundary="boundary_"+distfilename;
+    
+    /*try to find joint do no work
+    int rang=MyGlobals::_rank;
+    if (rang==1) (_collection->getParaDomainSelector())->sendMesh(*(boundaryMesh),0);
+    if (rang==0) 
+    {
+      (_collection->getParaDomainSelector())->recvMesh(boundaryMesh1,1);
+      //vector<const ParaMEDMEM::MEDCouplingUMesh*> meshes;
+      //vector<DataArrayInt* > corr;
+      //meshes.push_back(boundaryMesh);
+      //meshes.push_back(boundaryMesh1);
+      //need share the same coords
+      //boundaryMesh1->tryToShareSameCoordsPermute(*boundaryMesh, 1e-10);
+      //finalboundaryMesh=MEDCouplingUMesh::FuseUMeshesOnSameCoords(meshes,2, corr);
+      //boundaryMesh=finalboundaryMesh;
+      
+      boundaryMesh->zipCoords();
+      boundaryMesh1->zipCoords();
+      finalboundaryMesh=MEDCouplingUMesh::MergeUMeshes(boundaryMesh,boundaryMesh1);
+      DataArrayInt* commonNodes=0;
+      commonNodes=finalboundaryMesh->zipCoordsTraducer();
+      boundaryMesh=finalboundaryMesh;
+      cout<<"zipcoords"<<commonNodes->repr()<<endl;
+    }
+    */
+  }
+  
+  MEDLoader::WriteUMeshes(distfilename.c_str(), meshes, true);
+  if (faceMeshFilter!=0) faceMeshFilter->decrRef();
+  
+  
+  if (boundaryMesh!=0)
+  {
+    //doing that testMesh becomes second mesh sorted by alphabetical order of name
+    MEDLoader::WriteUMesh(distfilename.c_str(), boundaryMesh, false);
+    boundaryMesh->decrRef();
+  }
+
+  //cout<<"familyInfo :\n"<<reprMapOfStringInt(_collection->getFamilyInfo())<<endl;
+  //cout<<"groupInfo :\n"<<reprMapOfStringVectorOfString(_collection->getGroupInfo())<<endl;
+  
+  ParaMEDMEM::MEDFileUMesh* mfm=ParaMEDMEM::MEDFileUMesh::New(distfilename.c_str(), _collection->getMesh(idomain)->getName());
+       
+  /*example of adding new family
+  (_collection->getFamilyInfo())["FaceNotOnCell"]=-500;
+  vector<string> FaceNotOnCell;
+  FaceNotOnCell.push_back("FaceNotOnCell");
+  (_collection->getGroupInfo())["FaceNotOnCell"]=FaceNotOnCell;
+  */
+  
   mfm->setFamilyInfo(_collection->getFamilyInfo());
   mfm->setGroupInfo(_collection->getGroupInfo());
+  
+  //cvwat08 
+  //without filter mfm->setFamilyFieldArr(-1,(_collection->getFaceFamilyIds())[idomain]);
+  
+  string cle=cle1ToStr("faceFamily_toArray",idomain);
+  if (_collection->getMapDataArrayInt().find(cle)!=_collection->getMapDataArrayInt().end())
+  {
+    DataArrayInt* fam=_collection->getMapDataArrayInt().find(cle)->second;
+    DataArrayInt* famFilter=0;
+    if (filter!=0)
+    {
+      int* index=filter->getPointer();
+      int nbTuples=filter->getNbOfElems();
+      //not the good one...buildPartOfMySelf do not exist for DataArray 
+      //Filter=fam->renumberAndReduce(index, filter->getNbOfElems());
+      famFilter=DataArrayInt::New();
+      famFilter->alloc(nbTuples,1);
+      int* pfamFilter=famFilter->getPointer();
+      int* pfam=fam->getPointer();
+      for (int i=0; i<nbTuples; i++) pfamFilter[i]=pfam[index[i]];
+      fam=famFilter;
+      mfm->setFamilyFieldArr(-1,fam);
+      famFilter->decrRef();
+    }
+    //cout<<"proc "<<MyGlobals::_rank<<"cvw111 "<<nbTuples<<endl;
+    //mfm->setFamilyFieldArr(-1,fam);
+   // if (famFilter!=0) famFilter->decrRef();
+  }
+  
+  /*example visualisation of filter
+  if (_collection->getMapDataArrayInt().find(cle)!=_collection->getMapDataArrayInt().end())
+  {
+    DataArrayInt* fam=_collection->getMapDataArrayInt().find(cle)->second;
+    string cle2=cle1ToStr("filterNotFaceOnCell",idomain);
+    if (_collection->getMapDataArrayInt().find(cle2)!=_collection->getMapDataArrayInt().end())
+    {
+      DataArrayInt* filter=_collection->getMapDataArrayInt().find(cle2)->second;
+      int* index=filter->getPointer();
+      int* pfam=fam->getPointer();
+      for (int i=0; i<filter->getNbOfElems(); i++) pfam[index[i]]=-500;
+    }
+    mfm->setFamilyFieldArr(-1,fam);
+    //mfm->setFamilyFieldArr(-1,_collection->getMapDataArrayInt().find(cle)->second);
+  }
+  */
+  
+  cle=cle1ToStr("cellFamily_toArray",idomain);
+  if (_collection->getMapDataArrayInt().find(cle)!=_collection->getMapDataArrayInt().end())
+    mfm->setFamilyFieldArr(0,_collection->getMapDataArrayInt().find(cle)->second);
+  
   mfm->write(distfilename.c_str(),0);
+  cle="/inewFieldDouble="+intToStr(idomain)+"/";
+    
+  map<string,ParaMEDMEM::DataArrayDouble*>::iterator it;
+  int nbfFieldFound=0;
+  for (it=_collection->getMapDataArrayDouble().begin() ; it!=_collection->getMapDataArrayDouble().end(); it++)
+  {
+    string desc=(*it).first;
+    size_t found=desc.find(cle);
+    if (found==string::npos) continue;
+    if (MyGlobals::_verbose>20) cout<<"proc "<<MyGlobals::_rank<<" : write field "<<desc<<endl;
+    string meshName, fieldName;
+    int typeField, DT, IT, entity;
+    fieldShortDescriptionToData(desc, fieldName, typeField, entity, DT, IT);
+    double time=strToDouble(extractFromDescription(desc, "time="));
+    int typeData=strToInt(extractFromDescription(desc, "typeData="));
+    //int nbPtGauss=strToInt(extractFromDescription(desc, "nbPtGauss="));
+    string entityName=extractFromDescription(desc, "entityName=");
+    MEDCouplingFieldDouble* field=0;
+    if (typeData!=6)
+    {
+      cout<<"WARNING : writeMedFile : typeData "<<typeData<<" not implemented for fields\n";
+      continue;
+    }
+    if (entityName=="MED_CELL")
+    {
+      //there is a field of idomain to write
+      field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
+    }
+    if (entityName=="MED_NODE_ELEMENT")
+    {
+      //there is a field of idomain to write
+      field=MEDCouplingFieldDouble::New(ON_GAUSS_NE,ONE_TIME);
+    }
+    if (!field)
+    {
+      cout<<"WARNING : writeMedFile : entityName "<<entityName<<" not implemented for fields\n";
+      continue;
+    }
+    nbfFieldFound++;
+    field->setName(fieldName.c_str());
+    field->setMesh(mfm->getLevel0Mesh(false));
+    DataArrayDouble* da=(*it).second;
+    
+    //get information for components etc..
+    vector<string> r1;
+    r1=selectTagsInVectorOfString(MyGlobals::_generalInformations,"fieldName="+fieldName);
+    r1=selectTagsInVectorOfString(r1,"typeField="+intToStr(typeField));
+    r1=selectTagsInVectorOfString(r1,"DT="+intToStr(DT));
+    r1=selectTagsInVectorOfString(r1,"IT="+intToStr(IT));
+    //not saved in file? field->setDescription(extractFromDescription(r1[0], "fieldDescription=").c_str());
+    int nbc=strToInt(extractFromDescription(r1[0], "nbComponents="));
+    //double time=strToDouble(extractFromDescription(r1[0], "time="));
+    if (nbc==da->getNumberOfComponents())
+    {
+      for (int i=0; i<nbc; i++) 
+        da->setInfoOnComponent(i,extractFromDescription(r1[0], "componentInfo"+intToStr(i)+"=").c_str());
+    }
+    else
+    {
+      cerr<<"Problem On field "<<fieldName<<" : number of components unexpected "<<da->getNumberOfComponents()<<endl;
+    }
+    
+    field->setArray(da);
+    field->setTime(time,DT,IT);
+    field->checkCoherency();
+    try
+    {
+      MEDLoader::WriteField(distfilename.c_str(),field,false);
+      //if entityName=="MED_NODE_ELEMENT"
+      //AN INTERP_KERNEL::EXCEPTION HAS BEEN THROWN : Not implemented other profile fitting from already written mesh for fields than on NODES and on CELLS.**********
+      //modification MEDLoader.cxx done
+    }
+    catch(INTERP_KERNEL::Exception& e)
+    {
+      //cout trying rewrite all data, only one field defined
+      string tmp,newName=distfilename;
+      tmp+="_"+fieldName+"_"+intToStr(nbfFieldFound)+".med";
+      newName.replace(newName.find(".med"),4,tmp);
+      cout<<"WARNING : writeMedFile : new file name with only one field :"<<newName<<endl;
+      MEDLoader::WriteField(newName.c_str(),field,true);
+    }
+    //cout<<"proc "<<MyGlobals::_rank<<" : write field "<<cle<<" done"<<endl;
+  }
+
   mfm->decrRef();
-  //  writeSubdomain(idomain, nbdomains, distfilename.c_str(), domainSelector);
+
 }
+
+/*
+void writeFieldNodeCellTryingToFitExistingMesh(const char *fileName, const ParaMEDMEM::MEDCouplingFieldDouble *f)
+{
+  med_int numdt,numo;
+  med_float dt;
+  int nbComp=f->getNumberOfComponents();
+  med_idt fid=appendFieldSimpleAtt(fileName,f,numdt,numo,dt);
+  std::list<MEDLoader::MEDFieldDoublePerCellType> split;
+  prepareCellFieldDoubleForWriting(f,thisMeshCellIdsPerType,split);
+  const double *pt=f->getArray()->getConstPointer();
+  int number=0;
+  for(std::list<MEDLoader::MEDFieldDoublePerCellType>::const_iterator iter=split.begin();iter!=split.end();iter++)
+    {
+      INTERP_KERNEL::AutoPtr<char> nommaa=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
+      MEDLoaderBase::safeStrCpy(f->getMesh()->getName(),MED_NAME_SIZE,nommaa,MEDLoader::_TOO_LONG_STR);
+      INTERP_KERNEL::AutoPtr<char> profileName=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
+      std::ostringstream oss; oss << "Pfl" << f->getName() << "_" << number++;
+      MEDLoaderBase::safeStrCpy(oss.str().c_str(),MED_NAME_SIZE,profileName,MEDLoader::_TOO_LONG_STR);
+      const std::vector<int>& ids=(*iter).getCellIdPerType();
+      int *profile=new int [ids.size()];
+      std::transform(ids.begin(),ids.end(),profile,std::bind2nd(std::plus<int>(),1));
+      MEDprofileWr(fid,profileName,ids.size(),profile);
+      delete [] profile;
+      MEDfieldValueWithProfileWr(fid,f->getName(),numdt,numo,dt,MED_NODE_CELL,typmai3[(int)(*iter).getType()],MED_COMPACT_PFLMODE,profileName,
+                                 MED_NO_LOCALIZATION,MED_FULL_INTERLACE,MED_ALL_CONSTITUENT,(*iter).getNbOfTuple(),(const unsigned char*)pt);
+      pt+=(*iter).getNbOfTuple()*nbComp;
+    }
+  MEDfileClose(fid);
+}*/
+
index 01502b62b7ea00712f1f45c24f1ef33fa6a8071b..53ec045db8f0009469b4bc025ebbe9e385c7d279 100644 (file)
@@ -20,6 +20,8 @@
 #define MEDPARTITIONER_MESHCOLLECTIONDRIVER_HXX_
 
 #include "MEDPARTITIONER.hxx"
+
+#include <vector>
 #include <string>
 
 namespace MEDPARTITIONER
@@ -38,45 +40,21 @@ namespace MEDPARTITIONER
     int readSeq(const char*,const char*);
 
     virtual void write(const char*, ParaDomainSelector* sel=0)=0;
-//     virtual void readFields (vector <MEDMEM::FIELD<int> *>& filenames, char* fieldname,
-//                              int itnumber, int ordernumber) =0;
-//     virtual void readFields (vector <MEDMEM::FIELD<double> *>& filenames, char* fieldname,
-//                              int itnumber, int ordernumber) =0;
-//     virtual void writeFields(vector <MEDMEM::FIELD<int> *>& filenames, char* fieldname)=0;
-//     virtual void writeFields(vector <MEDMEM::FIELD<double> *>& filenames, char* fieldname)=0;
-
-//     void readFileStruct(vector <string>&  field_names,vector<int>& iternumber,vector <int>&  ordernumber,vector <int> & types);
-
-//     int getFieldType(const std::string& fieldname);
-//     //  void exportFamily(vector<int*>,MED_EN::medEntityMesh, const string& name);
-
-//     void readLoc2GlobCellConnect(int idomain, const set<int>& loc_domains, ParaDomainSelector* ds,
-//                                  vector<int> & loc2glob_corr);
-
-//    int readMeshDimension() const;
 
   protected:
 
-    void readSubdomain(vector<int*>& cellglobal,
-                       vector<int*>& faceglobal,
-                       vector<int*>& nodeglobal, int idomain);
+    void readSubdomain(std::vector<int*>& cellglobal,
+                       std::vector<int*>& faceglobal,
+                       std::vector<int*>& nodeglobal, int idomain);
+    void readSubdomain(int idomain);
     void writeMedFile(int idomain, const std::string& distfilename);
 
-//     void writeElementJoint(medEntityMesh entity ,
-//                            int icz, 
-//                            int idomain, 
-//                            int idistant, 
-//                            char* mesh_name, 
-//                            char* joint_name,  
-//                            med_2_3::med_idt fid );
-//     void jointSort(int* elems, int nbelems, bool is_first);
-
-
 
     MESHCollection* _collection;
 
-    std::vector <std::string> _filename;
-    std::vector <std::string> _meshname;
+    //to Globals
+    //std::vector <std::string> _filename;
+    //std::vector <std::string> _meshname;
 
   };
 
index 222bc87eb6e160b37b70010907d8415caf3efdf1..515b1f8ec299652c295df720de8a2990271f808c 100644 (file)
@@ -30,8 +30,6 @@
 #include <libxml/xpathInternals.h>
 
 #include <sys/time.h>
-//Debug macros
-#include "MEDMEM_Exception.hxx"
 
 #include "MEDCouplingUMesh.hxx"
 #include "MEDLoader.hxx"
 #include "MEDPARTITIONER_MESHCollection.hxx"
 #include "MEDPARTITIONER_MESHCollectionMedAsciiDriver.hxx"
 #include "MEDPARTITIONER_ParaDomainSelector.hxx"
+#include "MEDPARTITIONER_utils.hxx"
 
 using namespace MEDPARTITIONER;
+using namespace std;
 
 //template inclusion
 //#include "MEDPARTITIONER_MESHCollectionMedAsciiDriver.H"
@@ -62,21 +62,17 @@ MESHCollectionMedAsciiDriver::MESHCollectionMedAsciiDriver(MESHCollection* colle
 
 int MESHCollectionMedAsciiDriver::read(const char* filename, ParaDomainSelector* domainSelector)
 {
-
-  //ditributed meshes
+  //distributed meshes
   vector<int*> cellglobal;
   vector<int*> nodeglobal;
   vector<int*> faceglobal;
-
   int nbdomain;
 
   // reading ascii master file
-  try{
+  try
+  {
     ifstream asciiinput(filename);
-
-    if (!asciiinput)     
-      throw INTERP_KERNEL::Exception("MEDPARTITIONER read - Master File does not exist");
-
+    if (!asciiinput) throw INTERP_KERNEL::Exception(LOCALIZED("Master ASCII File does not exist"));
     char charbuffer[512];
     asciiinput.getline(charbuffer,512);
 
@@ -87,20 +83,18 @@ int MESHCollectionMedAsciiDriver::read(const char* filename, ParaDomainSelector*
 
     //reading number of domains
     nbdomain=atoi(charbuffer);
-    cout << "nb domain "<<nbdomain<<endl;
+    //cout << "nb domain "<<nbdomain<<endl;
     //    asciiinput>>nbdomain;
-    _filename.resize(nbdomain);
-    _meshname.resize(nbdomain);
+    MyGlobals::_fileNames.resize(nbdomain);
+    MyGlobals::_meshNames.resize(nbdomain);
     (_collection->getMesh()).resize(nbdomain);
     cellglobal.resize(nbdomain);
     nodeglobal.resize(nbdomain);
     faceglobal.resize(nbdomain);
 
-    if (nbdomain == 0)
-      throw INTERP_KERNEL::Exception("Empty ASCII master file");
+    if (nbdomain == 0) throw INTERP_KERNEL::Exception(LOCALIZED("Empty ASCII master file"));
     for (int i=0; i<nbdomain;i++)
     {
-
       //reading information about the domain
       string mesh;
       int idomain;
@@ -108,18 +102,16 @@ int MESHCollectionMedAsciiDriver::read(const char* filename, ParaDomainSelector*
       cellglobal[i]=0;
       faceglobal[i]=0;
       nodeglobal[i]=0;
+      
+      asciiinput >> mesh >> idomain >> MyGlobals::_meshNames[i] >> host >> MyGlobals::_fileNames[i];
 
-      asciiinput >> mesh >> idomain >> _meshname[i] >> host >> _filename[i];
-
-      //Setting the name of the global mesh (which is the same
-      //for all the subdomains)
+      //Setting the name of the global mesh (which should be is the same for all the subdomains)
       if (i==0)
         _collection->setName(mesh);
 
       if (idomain!=i+1)
       {
-        cerr<<"Error : domain must be written from 1 to N in asciifile descriptor"<<endl;
-        return 1;
+        throw INTERP_KERNEL::Exception(LOCALIZED("domain must be written from 1 to N in ASCII file descriptor"));
       }
       if ( !domainSelector || domainSelector->isMyDomain(i))
         readSubdomain(cellglobal,faceglobal,nodeglobal, i);
@@ -128,8 +120,7 @@ int MESHCollectionMedAsciiDriver::read(const char* filename, ParaDomainSelector*
   }//of try
   catch(...)
   {
-    cerr << "I/O error reading parallel MED file"<<endl;
-    throw;
+    throw INTERP_KERNEL::Exception(LOCALIZED("I/O error reading parallel MED file"));
   }
 
   //creation of topology from mesh and connect zones
@@ -143,41 +134,33 @@ int MESHCollectionMedAsciiDriver::read(const char* filename, ParaDomainSelector*
     if (nodeglobal[i]!=0) delete[] nodeglobal[i];
     if (faceglobal[i]!=0) delete[] faceglobal[i];
   }
-
   return 0;
 }
 
 
-/*! writes the collection of meshes in a 
- * MED v2.3 file
+/*! writes the collection of meshes in a MED v2.3 file
  * with the connect zones being written as joints
  * \param filename name of the ascii file containing the meshes description
  */
 void MESHCollectionMedAsciiDriver::write(const char* filename, ParaDomainSelector* domainSelector)
 {
-
-
-  int nbdomains= _collection->getMesh().size();
-  _filename.resize(nbdomains);
+  int nbdomains=_collection->getMesh().size();
+  vector<string> filenames;
+  filenames.resize(nbdomains);
 
   //loop on the domains
-  for (int idomain=0; idomain<nbdomains;idomain++)
+  for (int idomain=0; idomain<nbdomains; idomain++)
   {
     string distfilename;
-
     ostringstream suffix;
-    suffix << filename<< idomain+1 <<".med";
-
+    suffix<<filename<<idomain+1<<".med";
     distfilename=suffix.str();
-
-    _filename[idomain]=distfilename;
+    filenames[idomain]=distfilename;
 
     if ( !domainSelector || domainSelector->isMyDomain( idomain ) )
     {
       if ( !_collection->getMesh()[idomain]->getNumberOfCells()==0 ) continue;//empty domain
-
       MEDLoader::WriteUMesh(distfilename.c_str(),(_collection->getMesh())[idomain],true);
-
       //      writeSubdomain(idomain, nbdomains, distfilename.c_str(), domainSelector);
     }
   }
@@ -186,15 +169,14 @@ void MESHCollectionMedAsciiDriver::write(const char* filename, ParaDomainSelecto
   if ( !domainSelector || domainSelector->rank() == 0 )
   {
     ofstream file(filename);
+    file << "#MED Fichier V 2.3"<<" "<<endl;
+    file << "#"<<" "<<endl;
+    file << _collection->getMesh().size()<<" "<<endl;
 
-    file <<"#MED Fichier V 2.3"<<" "<<endl;
-    file <<"#"<<" "<<endl;
-    file<<_collection->getMesh().size()<<" "<<endl;
-
-    for (int idomain=0; idomain<nbdomains;idomain++)
+    for (int idomain=0; idomain<nbdomains; idomain++)
       file << _collection->getName() <<" "<< idomain+1 << " "
            << (_collection->getMesh())[idomain]->getName() << " localhost "
-           << _filename[idomain] << " "<<endl;
+           << filenames[idomain] << " "<<endl;
   }
 
 }
index b9cfbf17e0fc4be1dab307e25ed20f90265c9452..49c2ac35de55020cb303763b636c4ca7ce811efe 100644 (file)
@@ -31,8 +31,6 @@
 
 #include <sys/time.h>
 
-#include "MEDMEM_Utilities.hxx"
-#include "MEDMEM_Exception.hxx"
 //MEDSPLITTER includes
 #include "MEDCouplingUMesh.hxx"
 #include "MEDLoader.hxx"
 #include "MEDPARTITIONER_MESHCollection.hxx"
 #include "MEDPARTITIONER_MESHCollectionMedXMLDriver.hxx"
 #include "MEDPARTITIONER_ParaDomainSelector.hxx"
+#include "MEDPARTITIONER_utils.hxx"
 
 using namespace MEDPARTITIONER;
+using namespace std;
 
 //template inclusion
 //#include "MEDPARTITIONER_MESHCollectionMedXMLDriver.H"
@@ -76,13 +76,11 @@ MESHCollectionMedXMLDriver::MESHCollectionMedXMLDriver(MESHCollection* collectio
 int MESHCollectionMedXMLDriver::read(const char* filename, ParaDomainSelector* domainSelector)
 {
 
-  const char* LOC = "MEDPARTITIONER::MESHCollectionDriver::read()";
-  BEGIN_OF_MED(LOC);
-
-  //ditributed meshes
+  //distributed meshes //cvwat02
+  /*cvw 
   vector<int*> cellglobal;
   vector<int*> nodeglobal;
-  vector<int*> faceglobal;
+  vector<int*> faceglobal;*/
 
   int nbdomain;
 
@@ -90,13 +88,11 @@ int MESHCollectionMedXMLDriver::read(const char* filename, ParaDomainSelector* d
 
   // reading ascii master file
   try{
-    MESSAGE_MED("Start reading");
-
     // Setting up the XML tree corresponding to filename
     xmlDocPtr master_doc=xmlParseFile(filename);
 
-    if (!master_doc)    
-      throw MEDMEM::MEDEXCEPTION("MEDPARTITIONER XML read - Master File does not exist o r is not compliant with XML scheme");
+    if (!master_doc)
+      throw INTERP_KERNEL::Exception(LOCALIZED("XML Master File does not exist or is not compliant with XML scheme"));
 
     ////////////////////
     //number of domains
@@ -104,7 +100,7 @@ int MESHCollectionMedXMLDriver::read(const char* filename, ParaDomainSelector* d
     xmlXPathContextPtr xpathCtx = xmlXPathNewContext(master_doc);
     xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression(BAD_CAST "//splitting/subdomain", xpathCtx);
     if (xpathObj==0 || xpathObj->nodesetval->nodeNr ==0)
-      throw MEDMEM::MEDEXCEPTION("MEDPARTITIONER read - XML Master File does not contain /MED/splitting/subdomain node");
+      throw INTERP_KERNEL::Exception(LOCALIZED("XML Master File does not contain /MED/splitting/subdomain node"));
 
     /* as subdomain has only one property which is "number"
      * it suffices to take the content of its first child */
@@ -114,40 +110,43 @@ int MESHCollectionMedXMLDriver::read(const char* filename, ParaDomainSelector* d
     //////////////////
     //mesh name
     //////////////////
+    xmlXPathFreeObject(xpathObj);
     xpathObj = xmlXPathEvalExpression(BAD_CAST "//content/mesh", xpathCtx);
     if (xpathObj==0 || xpathObj->nodesetval->nodeNr ==0)
-      throw MEDMEM::MEDEXCEPTION("MEDPARTITIONER read - XML Master File does not contain /MED/content/mesh node");
+      throw INTERP_KERNEL::Exception(LOCALIZED("XML Master File does not contain /MED/content/mesh node"));
     _collection->setName( (const char*)xpathObj->nodesetval->nodeTab[0]->properties->children->content);
 
-    cout << "nb domain " << nbdomain << endl;
-    _filename.resize(nbdomain);
-    _meshname.resize(nbdomain);
+    //cout << "nb domain " << nbdomain << endl;
+    MyGlobals::_fileNames.resize(nbdomain);
+    MyGlobals::_meshNames.resize(nbdomain);
     (_collection->getMesh()).resize(nbdomain);
     (_collection->getFaceMesh()).resize(nbdomain);
     (_collection->getCellFamilyIds()).resize(nbdomain);
     (_collection->getFaceFamilyIds()).resize(nbdomain);
 
+    /*cvw
     cellglobal.resize(nbdomain);
     nodeglobal.resize(nbdomain);
     faceglobal.resize(nbdomain);
-
+    */
 
     // retrieving the node which contains the file names
     const char filechar[]="//files/subfile";
+    xmlXPathFreeObject(xpathObj);
     xpathObj = xmlXPathEvalExpression(BAD_CAST filechar, xpathCtx);
     if (xpathObj==0 || xpathObj->nodesetval->nodeNr ==0)
-      throw MEDMEM::MEDEXCEPTION("MEDPARTITIONER read - XML Master File does not contain /MED/files/subfile nodes");
+      throw INTERP_KERNEL::Exception(LOCALIZED("XML Master File does not contain /MED/files/subfile nodes"));
     int nbfiles = xpathObj->nodesetval ->nodeNr;
     
     for (int i=0; i<nbfiles;i++)
     {
       //reading information about the domain
-
       string host;
-
+      /*cvw
       cellglobal[i]=0;
       faceglobal[i]=0;
       nodeglobal[i]=0;
+      */
 
       ////////////////////////////
       //reading file names 
@@ -158,8 +157,8 @@ int MESHCollectionMedXMLDriver::read(const char* filename, ParaDomainSelector* d
       xmlXPathObjectPtr xpathObjfilename =
         xmlXPathEvalExpression(BAD_CAST name_search_string.str().c_str(),xpathCtx);
       if (xpathObjfilename->nodesetval ==0)
-        throw MEDMEM::MEDEXCEPTION("MED XML reader : Error retrieving file name ");
-      _filename[i]=(const char*)xpathObjfilename->nodesetval->nodeTab[0]->children->content;
+        throw INTERP_KERNEL::Exception(LOCALIZED("Error retrieving a file name from subfile of XML Master File"));
+      MyGlobals::_fileNames[i]=(const char*)xpathObjfilename->nodesetval->nodeTab[0]->children->content;
 
       ////////////////////////////////
       //reading the local mesh names
@@ -169,13 +168,13 @@ int MESHCollectionMedXMLDriver::read(const char* filename, ParaDomainSelector* d
 
       xmlXPathObjectPtr xpathMeshObj = xmlXPathEvalExpression(BAD_CAST mesh_search_string.str().c_str(),xpathCtx);
       if (xpathMeshObj->nodesetval ==0)
-        throw MEDMEM::MEDEXCEPTION("MED XML reader : Error retrieving mesh name ");
-      _meshname[i]=(const char*)xpathMeshObj->nodesetval->nodeTab[0]->children->content;
+        throw INTERP_KERNEL::Exception(LOCALIZED("Error retrieving mesh name from chunk of XML Master File"));
+      MyGlobals::_meshNames[i]=(const char*)xpathMeshObj->nodesetval->nodeTab[0]->children->content;
 
       if ( !domainSelector || domainSelector->isMyDomain(i))
-        readSubdomain(cellglobal, faceglobal, nodeglobal, i);
+        readSubdomain(i);  //cvwat03
+        //cvw readSubdomain(cellglobal, faceglobal, nodeglobal, i);  //cvwat03
       xmlXPathFreeObject(xpathObjfilename);
-
       xmlXPathFreeObject(xpathMeshObj);
     }//loop on domains
 
@@ -184,26 +183,34 @@ int MESHCollectionMedXMLDriver::read(const char* filename, ParaDomainSelector* d
     xmlXPathFreeContext(xpathCtx); 
     xmlFreeDoc(master_doc); 
 
-    MESSAGE_MED("end of read");
   }//of try
   catch(...)
   {
-    throw MEDMEM::MEDEXCEPTION("I/O error reading parallel MED file");
+    throw INTERP_KERNEL::Exception(LOCALIZED("I/O error reading parallel MED file"));
   }
 
+
+  ParallelTopology* aPT = new ParallelTopology(_collection->getMesh());
   //creation of topology from mesh and connect zones
+  if ( _collection->isParallelMode() )
+  {
+    //to know nb of cells on each proc to compute global cell ids from locally global
+    domainSelector->gatherNbOf(_collection->getMesh());
+  }
+  /*cvw
   ParallelTopology* aPT = new ParallelTopology
     ((_collection->getMesh()), (_collection->getCZ()), cellglobal, nodeglobal, faceglobal);
+  */
   _collection->setTopology(aPT);
   _collection->setDomainNames(_collection->getName());
+  /*cvw
   for (int i=0; i<nbdomain; i++)
   {
     if (cellglobal[i]!=0) delete[] cellglobal[i];
     if (nodeglobal[i]!=0) delete[] nodeglobal[i];
     if (faceglobal[i]!=0) delete[] faceglobal[i];
-  }
-
-  END_OF_MED(LOC);
+  }*/
+  
   return 0;
 }
 
@@ -215,10 +222,6 @@ int MESHCollectionMedXMLDriver::read(const char* filename, ParaDomainSelector* d
  */
 void MESHCollectionMedXMLDriver::write(const char* filename, ParaDomainSelector* domainSelector)
 {
-
-  const char* LOC = "MEDPARTITIONER::MESHCollectionDriver::writeXML()";
-  BEGIN_OF_MED(LOC);
-
   xmlDocPtr master_doc = 0;
   xmlNodePtr root_node = 0, node, node2;
   //  xmlDTDPtr dtd = 0;
@@ -276,46 +279,57 @@ void MESHCollectionMedXMLDriver::write(const char* filename, ParaDomainSelector*
   xmlNewProp(mesh_node, BAD_CAST "name", BAD_CAST _collection->getName().c_str());
 
   int nbdomains= _collection->getMesh().size();
-  _filename.resize(nbdomains);
+  //vector<string> filenames;
+  //filenames.resize(nbdomains);
 
   //loop on the domains
+  string finalMeshName=extractFromDescription(MyGlobals::_generalInformations[0], "finalMeshName=");
   for (int idomain=nbdomains-1; idomain>=0;idomain--)
   {
     string distfilename;
-
     ostringstream suffix;
-    suffix << filename<< idomain+1 <<".med";
-
+    suffix<<filename<<idomain+1<<".med";
     distfilename=suffix.str();
+    //filenames[idomain]=distfilename;
 
-    _filename[idomain]=distfilename;
-
-    MESSAGE_MED("File name "<<distfilename);
     if ( !domainSelector || domainSelector->isMyDomain( idomain ) )
-      {
-        if ( (_collection->getMesh())[idomain]->getNumberOfCells()==0 ) continue;//empty domain
-        writeMedFile(idomain,distfilename);
+    {
+      if ( (_collection->getMesh())[idomain]->getNumberOfCells()==0 ) continue; //empty domain
+      if (MyGlobals::_verbose>1)
+        cout<<"proc "<<domainSelector->rank()<<" : writeMedFile "<<distfilename
+            << " "<<(_collection->getMesh())[idomain]->getNumberOfCells()<<" cells"
+            << " "<<(_collection->getFaceMesh())[idomain]->getNumberOfCells()<<" faces"
+            << " "<<(_collection->getMesh())[idomain]->getNumberOfNodes()<<" nodes"<<endl;
+      writeMedFile(idomain,distfilename);
+    }
               
-        //updating the ascii description file
-        node = xmlNewChild(file_node, 0, BAD_CAST "subfile",0);
-        sprintf (buff,"%d",idomain+1);
-        xmlNewProp(node, BAD_CAST "id", BAD_CAST buff);
-        xmlNewChild(node,0,BAD_CAST "name",BAD_CAST distfilename.c_str());
-        xmlNewChild(node,0,BAD_CAST "machine",BAD_CAST "localhost");
-        
-        node = xmlNewChild(mesh_node,0, BAD_CAST "chunk",0);
-        xmlNewProp(node, BAD_CAST "subdomain", BAD_CAST buff);
-        xmlNewChild(node,0,BAD_CAST "name", BAD_CAST (_collection->getMesh())[idomain]->getName());
-      }
+    if (domainSelector->rank()==0)
+    {
+      //updating the ascii description file
+      node = xmlNewChild(file_node, 0, BAD_CAST "subfile",0);
+      sprintf (buff,"%d",idomain+1);
+      xmlNewProp(node, BAD_CAST "id", BAD_CAST buff);
+      xmlNewChild(node,0,BAD_CAST "name",BAD_CAST distfilename.c_str());
+      xmlNewChild(node,0,BAD_CAST "machine",BAD_CAST "localhost");
+      
+      node = xmlNewChild(mesh_node,0, BAD_CAST "chunk",0);
+      xmlNewProp(node, BAD_CAST "subdomain", BAD_CAST buff);
+      xmlNewChild(node,0,BAD_CAST "name", BAD_CAST finalMeshName.c_str());
+      //xmlNewChild(node,0,BAD_CAST "name", BAD_CAST (_collection->getMesh())[idomain]->getName());
+    }
+  }
+  
+  //create the ascii description file
+  if (domainSelector->rank()==0)
+  {
+    string myfile(filename);
+    myfile.append(".xml");
+    _master_filename=myfile;
+    if ( !domainSelector || domainSelector->rank() == 0 )
+      xmlSaveFormatFileEnc(myfile.c_str(), master_doc, "UTF-8", 1);
+    //xmlFreeDoc(master_doc);
+    //xmlCleanupParser();
   }
-  string myfile(filename);
-  myfile.append(".xml");
-  _master_filename=myfile;
-  if ( !domainSelector || domainSelector->rank() == 0 )
-    xmlSaveFormatFileEnc(myfile.c_str(), master_doc, "UTF-8", 1);
   xmlFreeDoc(master_doc);
   xmlCleanupParser();
-
-  END_OF_MED(LOC);
-
 }
index f0c7d100eca7828775ac9e13a6109effede3e081..84731f495e0610ebb5e387a6a251e89c2f60c534 100644 (file)
@@ -25,7 +25,11 @@ extern "C" {
 }
 #include "MEDPARTITIONER_METISGraph.hxx"
 #include "MEDPARTITIONER_ParaDomainSelector.hxx"
-#include "MEDMEM_Exception.hxx"
+#include "MEDPARTITIONER_utils.hxx"
+#include "InterpKernelException.hxx"
+
+#include <iostream>
+
 using namespace MEDPARTITIONER;
 
 METISGraph::METISGraph():Graph()
@@ -41,61 +45,149 @@ METISGraph::~METISGraph()
 {
 }
 
-void METISGraph::partGraph(int                 ndomain,
-                           const std::string&       options_string,
+void METISGraph::partGraph(int ndomain, //cvwat10
+                           const std::string& options_string,
                            ParaDomainSelector* parallelizer)
 {
+  using std::vector;
+  vector<int> ran,vx,va; //for randomize
+  
+  if (MyGlobals::_verbose>10) cout<<"proc "<<MyGlobals::_rank<<" : METISGraph::partGraph"<<endl;
+  
   // number of graph vertices
-  int n = _graph->getNumberOf();
-
+  int n=_graph->getNumberOf();
   //graph
   int * xadj=const_cast<int*>(_graph->getIndex());
-  int * adjncy = const_cast<int*>(_graph->getValue());
+  int * adjncy=const_cast<int*>(_graph->getValue());
   //constraints
   int * vwgt=_cellweight;
   int * adjwgt=_edgeweight;
   int wgtflag=(_edgeweight!=0)?1:0+(_cellweight!=0)?2:0;
-
   //base 0 or 1
   int base=0;
-
   //ndomain
-  int nparts = ndomain;
-
+  int nparts=ndomain;
   //options
-  int options[5]={0,0,0,0,0};
-
+  /*
+  (0=default_option,option,random_seed) see defs.h
+  #define PMV3_OPTION_DBGLVL   1
+  #define PMV3_OPTION_SEED     2
+  #define PMV3_OPTION_IPART    3
+  #define PMV3_OPTION_PSR              3
+  seems no changes int options[4]={1,0,33,0}; //test for a random seed of 33
+  */
+  int options[4]={0,0,0,0};
   // output parameters
   int edgecut;
-  int* partition = new int[n];
+  int* partition=new int[n];
 
-  cout << "ParMETIS : n="<<n<<endl;
+  //if (MyGlobals::_verbose>10) cout<<"proc "<<MyGlobals::_rank<<" : METISGraph::partGraph n="<<n<<endl;
   if (nparts >1)
   {
     if ( parallelizer )
     {
 #ifdef ENABLE_PARMETIS
       // distribution of vertices of the graph among the processors
-      int * vtxdist = parallelizer ? parallelizer->getNbVertOfProcs() : 0;
-      MPI_Comm comm = MPI_COMM_WORLD;
-      cout<<"vtxdist[1]"<<" "<<vtxdist[2]<<endl;
-      ParMETIS_PartKway( vtxdist, xadj, adjncy, vwgt, adjwgt, &wgtflag,
-                         &base, &nparts, options, &edgecut, partition, &comm );
-       if (n<8 && nparts==3)
-         {
-           for (int i=0; i<n; i++)
-             partition[i]=i%3;
-         }
-        
-      
-      
+      if (MyGlobals::_verbose>100) 
+        cout<<"proc "<<MyGlobals::_rank
+            <<" : METISGraph::partGraph ParMETIS_PartKway"<<endl;
+      int * vtxdist=parallelizer->getProcVtxdist();
+      MPI_Comm comm=MPI_COMM_WORLD;
+      try
+      {
+        if (MyGlobals::_verbose>200) 
+        {
+          cout<<"proc "<<MyGlobals::_rank<<" : vtxdist :";
+          for (int i=0; i<MyGlobals::_world_size+1; ++i) cout<<vtxdist[i]<<" ";
+          cout<<endl;
+          
+          int lgxadj=vtxdist[MyGlobals::_rank+1]-vtxdist[MyGlobals::_rank];
+          //cout<<"lgxadj "<<lgxadj<<" "<<n<<endl;
+          
+          if (lgxadj>0)
+          {
+            cout<<"\nproc "<<MyGlobals::_rank<<" : lgxadj "<<lgxadj<<" lgadj "<<xadj[lgxadj+1]<<endl;
+            for (int i=0; i<10; ++i) cout<<xadj[i]<<" ";
+            cout<<"... "<<xadj[lgxadj]<<endl;
+            for (int i=0; i<15; ++i) cout<<adjncy[i]<<" ";
+            int ll=xadj[lgxadj]-1;
+            cout<<"... ["<<ll<<"] "<<adjncy[ll-1]<<" "<<adjncy[ll]<<endl;
+            /*for (int i=0; i<=ll; ++i) {
+              if (adjncy[i]<0) cout<<"***cvw00 error: adjncy[i]<0 "<<i<<endl;
+            }*/
+            int imaxx=0;
+            //for (int ilgxadj=0; ilgxadj<lgxadj; ilgxadj++)
+            for (int ilgxadj=0; ilgxadj<lgxadj; ilgxadj++)
+            {
+              int ilg=xadj[ilgxadj+1]-xadj[ilgxadj];
+              /*if (ilg<0) cout<<"***cvw01 error: ilg<0 in xadj "<<ilgxadj<<endl;
+              if (MyGlobals::_is0verbose>1000) 
+              {
+                cout<<"\n -cell "<<ilgxadj<<" "<<ilg<<" :";
+                for (int i=0; i<ilg; i++) cout<<" "<<adjncy[xadj[ilgxadj]+i];
+              }*/
+              if (ilg>imaxx) imaxx=ilg;
+            }
+            cout<<"\nproc "<<MyGlobals::_rank
+                <<" : on "<<lgxadj<<" cells, max neighbourg number (...for one cell) is "<<imaxx<<endl;
+          }
+          
+        }
+        if ((MyGlobals::_randomize!=0 || MyGlobals::_atomize!=0) && MyGlobals::_world_size==1)
+        {
+          //randomize initially was for test on ParMETIS error (sometimes)
+          //due to : seems no changes int options[4]={1,0,33,0}; //test for a random seed of 33
+          //it was keeped
+          ran=createRandomSize(n);
+          randomizeAdj(&xadj[0],&adjncy[0],ran,vx,va);
+          ParMETIS_PartKway( //cvwat11
+              vtxdist, &vx[0], &va[0], vwgt, 
+              adjwgt, &wgtflag, &base, &nparts, options, 
+              &edgecut, partition, &comm );
+        }
+        else
+        {
+          //MPI_Barrier(MPI_COMM_WORLD);
+          //cout<<"proc "<<MyGlobals::_rank<<" : barrier ParMETIS_PartKway done"<<endl;
+          ParMETIS_PartKway( //cvwat11
+              vtxdist, xadj, adjncy, vwgt, 
+              adjwgt, &wgtflag, &base, &nparts, options, 
+              &edgecut, partition, &comm );
+        }
+
+/*doc from parmetis.h
+       void __cdecl ParMETIS_PartKway(
+             idxtype *vtxdist, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, 
+                  idxtype *adjwgt, int *wgtflag, int *numflag, int *nparts, int *options, 
+             int *edgecut, idxtype *part, MPI_Comm *comm);
+
+       void __cdecl ParMETIS_V3_PartKway(
+             idxtype *vtxdist, idxtype *xadj, idxtype *adjncy, idxtype *vwgt, 
+                  idxtype *adjwgt, int *wgtflag, int *numflag, int *ncon, int *nparts, 
+                  float *tpwgts, float *ubvec, int *options, int *edgecut, idxtype *part, 
+                  MPI_Comm *comm);
+*/
+
+      }
+      catch(...)
+      {
+        //helas ParMETIS "Error! Key -2 not found!" not catched...
+        throw INTERP_KERNEL::Exception(LOCALIZED("Problem in ParMETIS_PartKway"));
+      }
+      if (n<8 && nparts==3)
+      {
+        for (int i=0; i<n; i++) partition[i]=i%3;
+      }
 #else
-      throw MEDMEM::MEDEXCEPTION("ParMETIS is not available. Check your products, please.");
+      throw INTERP_KERNEL::Exception(LOCALIZED("ParMETIS is not available. Check your products, please."));
 #endif
+    //throw INTERP_KERNEL::Exception(LOCALIZED("ParMETIS is not available. Check your products, please."));
     }
     else
     {
-    
+      if (MyGlobals::_verbose>10) 
+        cout<<"proc "<<MyGlobals::_rank
+            <<" : METISGraph::partGraph METIS_PartGraph Recursive or Kway"<<endl;
       if (options_string != "k")
         METIS_PartGraphRecursive(&n, xadj, adjncy, vwgt, adjwgt, &wgtflag,
                                  &base, &nparts, options, &edgecut, partition);
@@ -106,18 +198,29 @@ void METISGraph::partGraph(int                 ndomain,
   }
   else
   {
-    for (int i=0; i<n; i++)
-      partition[i]=0;
+    for (int i=0; i<n; i++) partition[i]=0;
   }
-  std::vector<int> index(n+1);
-  std::vector<int> value(n);
+  
+  vector<int> index(n+1);
+  vector<int> value(n);
   index[0]=0;
-  for (int i=0; i<n; i++)
+  if (ran.size()>0 && MyGlobals::_atomize==0) //there is randomize
   {
-    index[i+1]=index[i]+1;
-    value[i]=partition[i];
+    if (MyGlobals::_is0verbose>100) cout<<"randomize"<<endl;
+    for (int i=0; i<n; i++)
+    {
+      index[i+1]=index[i]+1;
+      value[ran[i]]=partition[i];
+    }
+  }
+  else
+  {
+    for (int i=0; i<n; i++)
+    {
+      index[i+1]=index[i]+1;
+      value[i]=partition[i];
+    }
   }
-
   delete[]partition;
 
   //creating a skylinearray with no copy of the index and partition array
index 0a96964c5377aee542f2ff0e9c94ec3e0ddf5db8..387e695246a724c965beb387ef7f1d91e127c138 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "MEDPARTITIONER_Graph.hxx"
 #include <string>
+
 namespace MEDPARTITIONER {
   class MEDSKYLINEARRAY;
   class MEDPARTITIONER_EXPORT METISGraph:public Graph
index 9c1a29202296376780b41fc1588c4db319e27733..199d545e2fcb7a5d7062b84ab5520511a0e84ca9 100644 (file)
 // Author    : Edward AGAPOV (eap)
 
 #include "MEDCouplingUMesh.hxx"
-
 #include "MEDPARTITIONER_ParaDomainSelector.hxx"
-
 #include "MEDPARTITIONER_UserGraph.hxx"
+#include "MEDPARTITIONER_utils.hxx"
 
+#include <iostream>
 #include <numeric>
 
 #ifdef HAVE_MPI2
@@ -36,9 +36,9 @@
 #include <sys/sysinfo.h>
 #endif
 
-using namespace MEDPARTITIONER;
-using namespace MED_EN;
+//using namespace MED_EN;
 using namespace std;
+using namespace MEDPARTITIONER;
 
 //================================================================================
 /*!
@@ -77,8 +77,7 @@ ParaDomainSelector::~ParaDomainSelector()
 bool ParaDomainSelector::isOnDifferentHosts() const
 {
   evaluateMemory();
-  if ( _world_size < 2 )
-    return false;
+  if ( _world_size < 2 ) return false;
 
 #ifdef HAVE_MPI2
   char name_here[ MPI_MAX_PROCESSOR_NAME+1 ], name_there[ MPI_MAX_PROCESSOR_NAME+1 ];
@@ -93,7 +92,18 @@ bool ParaDomainSelector::isOnDifferentHosts() const
   MPI_Sendrecv((void*)&name_here[0],  MPI_MAX_PROCESSOR_NAME, MPI_CHAR, next_proc, tag,
                (void*)&name_there[0], MPI_MAX_PROCESSOR_NAME, MPI_CHAR, prev_proc, tag,
                MPI_COMM_WORLD, &status);
-  return string(name_here) != string(name_there);
+               
+  //cout<<"proc "<<rank()<<" : names "<<name_here<<" "<<name_there<<endl;
+  //bug: (isOnDifferentHosts here and there) is not (isOnDifferentHosts somewhere)
+  //return string(name_here) != string(name_there);
+  
+  int sum_same=-1;
+  int same=1;
+  if (string(name_here) != string(name_there)) same=0;
+  MPI_Allreduce( &same, &sum_same, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD );
+  //cout<<"proc "<<rank()<<" : sum_same "<<sum_same<<endl;
+  
+  return (sum_same != nbProcs());
 #endif
 }
 
@@ -127,7 +137,7 @@ int ParaDomainSelector::getProcessorID(int domainIndex) const
 
 //================================================================================
 /*!
- * \brief Gather info on nb of entities on each processor and return total nb.
+ * \brief Gather info on nb of cell entities on each processor and return total nb.
  *
  * Is called
  * 1) for MED_CELL to know global id shift for domains at graph construction;
@@ -135,117 +145,147 @@ int ParaDomainSelector::getProcessorID(int domainIndex) const
  */
 //================================================================================
 
-int ParaDomainSelector::gatherNbOf(
-                                   const vector<ParaMEDMEM::MEDCouplingUMesh*>& domain_meshes)
+void ParaDomainSelector::gatherNbOf(const vector<ParaMEDMEM::MEDCouplingUMesh*>& domain_meshes)
 {
   evaluateMemory();
-
   // get nb of elems of each domain mesh
-  int nb_domains = domain_meshes.size();
-  vector<int> nb_elems( nb_domains, 0 );
-  for ( int i = 0; i < nb_domains; ++i )
+  int nb_domains=domain_meshes.size();
+  //cout<<"proc "<<MyGlobals::_rank<<" : gatherNbOf "<<nb_domains<<endl;
+  vector<int> nb_elems(nb_domains*2, 0); //NumberOfCells & NumberOfNodes
+  for (int i=0; i<nb_domains; ++i)
     if ( domain_meshes[i] )
-      nb_elems[i] = domain_meshes[i]->getNumberOfCells();
-
+    {
+      nb_elems[i*2] = domain_meshes[i]->getNumberOfCells();
+      nb_elems[i*2+1] = domain_meshes[i]->getNumberOfNodes();
+    }
   // receive nb of elems from other procs
-  vector<int> all_nb_elems( nb_domains );
+  vector<int> all_nb_elems( nb_domains*2 );
 #ifdef HAVE_MPI2
-  MPI_Allreduce((void*)&nb_elems[0], (void*)&all_nb_elems[0], nb_domains,
+  MPI_Allreduce((void*)&nb_elems[0], (void*)&all_nb_elems[0], nb_domains*2,
                 MPI_INT, MPI_SUM, MPI_COMM_WORLD);
 #endif
-  int total_nb = std::accumulate( all_nb_elems.begin(), all_nb_elems.end(), 0 );
-
-  vector<int>& elem_shift_by_domain  = _cell_shift_by_domain;
-
-  // fill elem_shift_by_domain
-
-  vector< int > ordered_nbs, domain_order( nb_domains );
-  ordered_nbs.push_back(0);
-  for ( int iproc = 0; iproc < nbProcs(); ++iproc )
-    for ( int idomain = 0; idomain < nb_domains; ++idomain )
-      if ( getProcessorID( idomain ) == iproc )
+  int total_nb_cells=0, total_nb_nodes=0;
+  for (int i=0; i<nb_domains; ++i)
+  {
+    total_nb_cells+=all_nb_elems[i*2];
+    total_nb_nodes+=all_nb_elems[i*2+1];
+  }
+  
+  if (MyGlobals::_is0verbose>10)
+    cout<<"totalNbCells "<<total_nb_cells<<" totalNbNodes "<<total_nb_nodes<<endl;
+  
+  vector<int>& cell_shift_by_domain=_cell_shift_by_domain;
+  vector<int>& node_shift_by_domain=_node_shift_by_domain;
+  vector<int>& face_shift_by_domain=_face_shift_by_domain;
+  vector< int > ordered_nbs_cell, ordered_nbs_node, domain_order(nb_domains);
+  ordered_nbs_cell.push_back(0);
+  ordered_nbs_node.push_back(0);
+  for (int iproc=0; iproc<nbProcs(); ++iproc)
+    for (int idomain=0; idomain<nb_domains; ++idomain)
+      if (getProcessorID( idomain )==iproc)
       {
-        domain_order[ idomain ] = ordered_nbs.size() - 1;
-        ordered_nbs.push_back( ordered_nbs.back() + all_nb_elems[idomain] );
+        domain_order[idomain] = ordered_nbs_cell.size() - 1;
+        ordered_nbs_cell.push_back( ordered_nbs_cell.back() + all_nb_elems[idomain*2] );
+        ordered_nbs_node.push_back( ordered_nbs_node.back() + all_nb_elems[idomain*2+1] );
       }
-  elem_shift_by_domain.resize( nb_domains+1, 0 );
-  for ( int idomain = 0; idomain < nb_domains; ++idomain )
-    elem_shift_by_domain[ idomain ] = ordered_nbs[ domain_order[ idomain ]];
-  
-  elem_shift_by_domain.back() = ordered_nbs.back(); // to know total nb of elements
+  cell_shift_by_domain.resize( nb_domains+1, 0 );
+  node_shift_by_domain.resize( nb_domains+1, 0 );
+  face_shift_by_domain.resize( nb_domains+1, 0 );
+  for (int idomain=0; idomain<nb_domains; ++idomain)
+  {
+    cell_shift_by_domain[ idomain ] = ordered_nbs_cell[ domain_order[ idomain ]];
+    node_shift_by_domain[ idomain ] = ordered_nbs_node[ domain_order[ idomain ]];
+  }
+  cell_shift_by_domain.back() = ordered_nbs_cell.back(); // to know total nb of elements
+  node_shift_by_domain.back() = ordered_nbs_node.back(); // to know total nb of elements
   
-  // fill _nb_vert_of_procs
-  _nb_vert_of_procs.resize( _world_size+1, 0 );
-  for ( int i = 0; i < nb_domains; ++i )
-    {
-      int rank = getProcessorID( i );
-      _nb_vert_of_procs[ rank+1 ] += all_nb_elems[ i ];
-    }
+  if (MyGlobals::_is0verbose>300)
+  {
+    cout<<"proc "<<MyGlobals::_rank<<" : cellShiftByDomain ";
+    for (int i=0; i<=nb_domains; ++i) cout<<cell_shift_by_domain[i]<<"|";
+    cout<<endl;
+    cout<<"proc "<<MyGlobals::_rank<<" : nodeShiftBy_domain ";
+    for (int i=0; i<=nb_domains; ++i) cout<<node_shift_by_domain[i]<<"|";
+    cout<<endl;
+  }
+  // fill _nb_vert_of_procs (is Vtxdist)
+  _nb_vert_of_procs.resize(_world_size+1);
   _nb_vert_of_procs[0] = 0; // base = 0
-  for ( int i = 1; i < _nb_vert_of_procs.size(); ++i )
-    _nb_vert_of_procs[ i ] += _nb_vert_of_procs[ i-1 ]; // to CSR format
+  for (int i=0; i<nb_domains; ++i)
+  {
+    int rank = getProcessorID(i);
+    _nb_vert_of_procs[rank+1] += all_nb_elems[i*2];
+  }
+  for (int i=1; i<_nb_vert_of_procs.size(); ++i)
+    _nb_vert_of_procs[i] += _nb_vert_of_procs[i-1]; // to CSR format : cumulated
   
-  evaluateMemory();
+  if (MyGlobals::_is0verbose>200)
+  {
+    cout<<"proc "<<MyGlobals::_rank<<" : gatherNbOf : vtxdist is ";
+    for (int i = 0; i <= _world_size; ++i) cout<<_nb_vert_of_procs[i]<<" ";
+    cout<<endl;
+  }
   
-  return total_nb;
+  evaluateMemory();
+  return;
 }
 
 //================================================================================
 /*!
  * \brief Return distribution of the graph vertices among the processors
- *  \retval int* - array conatining nb of vertices on all processors
+ *  \retval int* - array containing nb of vertices (=cells) on all processors
  *
- * gatherNbOf( MED_CELL ) must be called before.
+ * gatherNbOf() must be called before.
  * The result array is to be used as the first arg of ParMETIS_V3_PartKway() and
  * is freed by ParaDomainSelector.
  */
 //================================================================================
 
-#define gatherNbOf_NOT_CALLED(meth) throw INTERP_KERNEL::Exception  \
-("ParaDomainSelector::" #meth "(): gatherNbOf( MED_CELL ) must be called before")
-
-int* ParaDomainSelector::getNbVertOfProcs() const
+int* ParaDomainSelector::getProcVtxdist() const
 {
   evaluateMemory();
-  if ( _nb_vert_of_procs.empty() )
-    gatherNbOf_NOT_CALLED(getNbVertOfProcs);
-
+  if (_nb_vert_of_procs.empty()) throw INTERP_KERNEL::Exception(LOCALIZED("_nb_vert_of_procs not set"));
   return (int*) & _nb_vert_of_procs[0];
 }
 //================================================================================
 /*!
  * \brief Return nb of cells in domains with lower index.
  *
- * gatherNbOf( MED_CELL ) must be called before.
+ * gatherNbOf() must be called before.
  * Result added to local id on given domain gives id in the whole distributed mesh
  */
 //================================================================================
 
-int ParaDomainSelector::getDomainShift(int domainIndex) const
+int ParaDomainSelector::getDomainCellShift(int domainIndex) const
 {
   evaluateMemory();
-  if ( _cell_shift_by_domain.empty() )
-    gatherNbOf_NOT_CALLED(getDomainShift);
+  if (_cell_shift_by_domain.empty()) throw INTERP_KERNEL::Exception(LOCALIZED("_cell_shift_by_domain not set"));
+  return _cell_shift_by_domain[domainIndex];
+}
 
-  return _cell_shift_by_domain[ domainIndex ];
+int ParaDomainSelector::getDomainNodeShift(int domainIndex) const
+{
+  evaluateMemory();
+  if (_node_shift_by_domain.empty()) throw INTERP_KERNEL::Exception(LOCALIZED("_node_shift_by_domain not set"));
+  return _node_shift_by_domain[domainIndex];
 }
 
 //================================================================================
 /*!
- * \brief Return nb of cells on processors with lower rank.
+ * \brief Return nb of nodes on processors with lower rank.
  *
- * gatherNbOf( MED_CELL ) must be called before.
+ * gatherNbOf() must be called before.
  * Result added to global id on this processor gives id in the whole distributed mesh
  */
 //================================================================================
 
-int ParaDomainSelector::getProcShift() const
+int ParaDomainSelector::getProcNodeShift() const
 {
   evaluateMemory();
-  if ( _nb_vert_of_procs.empty() )
-    gatherNbOf_NOT_CALLED(getProcShift);
-
-  return _nb_vert_of_procs[_rank]-1;
+  if (_nb_vert_of_procs.empty()) throw INTERP_KERNEL::Exception(LOCALIZED("_nb_vert_of_procs not set"));
+  //cout<<"_nb_vert_of_procs "<<_nb_vert_of_procs[0]<<" "<<_nb_vert_of_procs[1]<<endl;
+  return _nb_vert_of_procs[_rank];
 }
 
 //================================================================================
@@ -398,7 +438,6 @@ int ParaDomainSelector::getNbCellPairs( int dist_domain, int loc_domain ) const
 
 void ParaDomainSelector::gatherNbCellPairs()
 {
-  const char* LOC = "MEDPARTITIONER::ParaDomainSelector::gatherNbCellPairs(): ";
   if ( _nb_cell_pairs_by_joint.empty() )
     _nb_cell_pairs_by_joint.resize( _nb_result_domains*(_nb_result_domains+1), 0);
   evaluateMemory();
@@ -414,7 +453,7 @@ void ParaDomainSelector::gatherNbCellPairs()
   // namely that each joint is treated on one proc only
   for ( int j = 0; j < _nb_cell_pairs_by_joint.size(); ++j )
     if ( _nb_cell_pairs_by_joint[j] != send_buf[j] && send_buf[j]>0 )
-      throw INTERP_KERNEL::Exception("invalid nb of cell pairs");
+      throw INTERP_KERNEL::Exception(LOCALIZED("invalid nb of cell pairs"));
 }
 
 //================================================================================
@@ -433,8 +472,7 @@ int ParaDomainSelector::getFisrtGlobalIdOfSubentity( int loc_domain, int dist_do
   int id = total_nb_faces + 1;
 
   if ( _nb_cell_pairs_by_joint.empty() )
-    throw INTERP_KERNEL::Exception("MEDPARTITIONER::ParaDomainSelector::getFisrtGlobalIdOfSubentity(), "
-                        "gatherNbCellPairs() must be called before");
+    throw INTERP_KERNEL::Exception(LOCALIZED("gatherNbCellPairs() must be called before"));
   int joint_id = jointId( loc_domain, dist_domain );
   for ( int j = 0; j < joint_id; ++j )
     id += _nb_cell_pairs_by_joint[ j ];
@@ -475,7 +513,7 @@ int ParaDomainSelector::jointId( int local_domain, int distant_domain ) const
 {
   evaluateMemory();
   if (_nb_result_domains < 0)
-    throw INTERP_KERNEL::Exception("ParaDomainSelector::jointId(): setNbDomains() must be called before()");
+    throw INTERP_KERNEL::Exception(LOCALIZED("setNbDomains() must be called before"));
 
   if ( local_domain < distant_domain )
     swap( local_domain, distant_domain );
@@ -533,8 +571,7 @@ Sends content of \a mesh to processor \a target. To be used with \a recvMesh met
 
 void ParaDomainSelector::sendMesh(const ParaMEDMEM::MEDCouplingUMesh& mesh, int target) const
 {
-
-
+    if (MyGlobals::_verbose>600) cout<<"proc "<<_rank<<" : sendMesh '"<<mesh.getName()<<"' size "<<mesh.getNumberOfCells()<<" to "<<target<<endl;
     // First stage : sending sizes
     // ------------------------------
     vector<int> tinyInfoLocal;
@@ -543,54 +580,59 @@ void ParaDomainSelector::sendMesh(const ParaMEDMEM::MEDCouplingUMesh& mesh, int
     //Getting tiny info of local mesh to allow the distant proc to initialize and allocate
     //the transmitted mesh.
     mesh.getTinySerializationInformation(tinyInfoLocalD,tinyInfoLocal,tinyInfoLocalS);
+    //cout<<"sendMesh getTinySerializationInformation "<<mesh.getName()<<endl;
     tinyInfoLocal.push_back(mesh.getNumberOfCells());
  #ifdef        HAVE_MPI2
     int tinySize=tinyInfoLocal.size();
+    //cout<<"MPI_Send cvw11 "<<tinySize<<endl;
     MPI_Send(&tinySize, 1, MPI_INT, target, 1113, MPI_COMM_WORLD);
-    MPI_Send(&tinyInfoLocal[0], tinyInfoLocal.size(), MPI_INT, target, 1112,
-                            MPI_COMM_WORLD);
+    //cout<<"MPI_Send cvw22 "<<tinyInfoLocal.size()<<endl;
+    MPI_Send(&tinyInfoLocal[0], tinyInfoLocal.size(), MPI_INT, target, 1112, MPI_COMM_WORLD);
 #endif
-    ParaMEDMEM::DataArrayInt *v1Local=0;
-    ParaMEDMEM::DataArrayDouble *v2Local=0;
-    //serialization of local mesh to send data to distant proc.
-    mesh.serialize(v1Local,v2Local);
-    int nbLocalElems;
-    int* ptLocal=0;
-    if(v1Local)
+
+    if (mesh.getNumberOfCells()>0) //no sends if empty
+    {
+      ParaMEDMEM::DataArrayInt *v1Local=0;
+      ParaMEDMEM::DataArrayDouble *v2Local=0;
+      //serialization of local mesh to send data to distant proc.
+      mesh.serialize(v1Local,v2Local);
+      int nbLocalElems=0;
+      int* ptLocal=0;
+      if(v1Local) //cvw if empty getNbOfElems() is 1!
       {
-        nbLocalElems=v1Local->getNbOfElems();
+        nbLocalElems=v1Local->getNbOfElems(); //cvw if empty be 1!
         ptLocal=v1Local->getPointer();
       }
- #ifdef        HAVE_MPI2
-    MPI_Send(ptLocal, nbLocalElems, MPI_INT,
-                            target, 1111, MPI_COMM_WORLD);
-    #endif
-    double *ptLocal2=0;
-    if(v2Local)
+#ifdef        HAVE_MPI2
+      MPI_Send(ptLocal, nbLocalElems, MPI_INT, target, 1111, MPI_COMM_WORLD);
+#endif
+      int nbLocalElems2=0;
+      double *ptLocal2=0;
+      if(v2Local) //cvw if empty be 0!
       {
-        nbLocalElems=v2Local->getNbOfElems();
+        nbLocalElems2=v2Local->getNbOfElems();
         ptLocal2=v2Local->getPointer();
       }
 #ifdef HAVE_MPI2
-    MPI_Send(ptLocal2, nbLocalElems, MPI_DOUBLE,
-                            target, 1110, MPI_COMM_WORLD);
+      MPI_Send(ptLocal2, nbLocalElems2, MPI_DOUBLE, target, 1110, MPI_COMM_WORLD);
 #endif
-     if(v1Local)
-      v1Local->decrRef();
-    if(v2Local)
-      v2Local->decrRef();
-    
+      if(v1Local) v1Local->decrRef();
+      if(v2Local) v2Local->decrRef();
+    }
+    else
+    {
+      //cout<<"sendMesh empty Mesh cvw3344 "<<endl;
+    }
+    //cout<<"end sendMesh "<<mesh.getName()<<endl;
 }
 
 /*! Receives messages from proc \a source to fill mesh \a mesh.
 To be used with \a sendMesh method.
-
 \param mesh  pointer to mesh that is filled
 \param source processor id of the incoming messages
  */
 void ParaDomainSelector::recvMesh(ParaMEDMEM::MEDCouplingUMesh*& mesh, int source)const
 {
-
     // First stage : exchanging sizes
     // ------------------------------
     vector<int> tinyInfoDistant;
@@ -601,7 +643,7 @@ void ParaDomainSelector::recvMesh(ParaMEDMEM::MEDCouplingUMesh*& mesh, int sourc
 #ifdef HAVE_MPI2
     MPI_Status status; 
     int tinyVecSize;
-    MPI_Recv(&tinyVecSize, 1, MPI_INT,source,1113,MPI_COMM_WORLD, &status);
+    MPI_Recv(&tinyVecSize, 1, MPI_INT, source, 1113, MPI_COMM_WORLD, &status);
     tinyInfoDistant.resize(tinyVecSize);
 #endif
     std::fill(tinyInfoDistant.begin(),tinyInfoDistant.end(),0);
@@ -609,103 +651,50 @@ void ParaDomainSelector::recvMesh(ParaMEDMEM::MEDCouplingUMesh*& mesh, int sourc
 #ifdef HAVE_MPI2
     MPI_Recv(&tinyInfoDistant[0], tinyVecSize, MPI_INT,source,1112,MPI_COMM_WORLD, &status);
 #endif
-    ParaMEDMEM::DataArrayInt *v1Distant=ParaMEDMEM::DataArrayInt::New();
-    ParaMEDMEM::DataArrayDouble *v2Distant=ParaMEDMEM::DataArrayDouble::New();
-    //Building the right instance of copy of distant mesh.
-    ParaMEDMEM::MEDCouplingPointSet *distant_mesh_tmp=ParaMEDMEM::MEDCouplingPointSet::BuildInstanceFromMeshType((ParaMEDMEM::MEDCouplingMeshType)tinyInfoDistant[0]);
-    std::vector<std::string> unusedTinyDistantSts;
-    mesh=dynamic_cast<ParaMEDMEM::MEDCouplingUMesh*> (distant_mesh_tmp);
+    //there was tinyInfoLocal.push_back(mesh.getNumberOfCells());
+    int NumberOfCells=tinyInfoDistant[tinyVecSize-1];
+    //cout<<"recvMesh NumberOfCells "<<NumberOfCells<<endl;
+    if (NumberOfCells>0)
+    {
+      ParaMEDMEM::DataArrayInt *v1Distant=ParaMEDMEM::DataArrayInt::New();
+      ParaMEDMEM::DataArrayDouble *v2Distant=ParaMEDMEM::DataArrayDouble::New();
+      //Building the right instance of copy of distant mesh.
+      ParaMEDMEM::MEDCouplingPointSet *distant_mesh_tmp=
+        ParaMEDMEM::MEDCouplingPointSet::BuildInstanceFromMeshType(
+          (ParaMEDMEM::MEDCouplingMeshType) tinyInfoDistant[0]);
+      std::vector<std::string> unusedTinyDistantSts;
+      mesh=dynamic_cast<ParaMEDMEM::MEDCouplingUMesh*> (distant_mesh_tmp);
  
-    mesh->resizeForUnserialization(tinyInfoDistant,v1Distant,v2Distant,unusedTinyDistantSts);
-    int nbDistElem=0;
-    int *ptDist=0;
-    if(v1Distant)
+      mesh->resizeForUnserialization(tinyInfoDistant,v1Distant,v2Distant,unusedTinyDistantSts);
+      int nbDistElem=0;
+      int *ptDist=0;
+      if(v1Distant)
       {
         nbDistElem=v1Distant->getNbOfElems();
         ptDist=v1Distant->getPointer();
       }
 #ifdef HAVE_MPI2
-    MPI_Recv(ptDist, nbDistElem, MPI_INT,
-                            source,1111,
-                            MPI_COMM_WORLD, &status);
+      MPI_Recv(ptDist, nbDistElem, MPI_INT, source,1111, MPI_COMM_WORLD, &status);
 #endif
-    int nbLocalElems=0;
-    double *ptDist2=0;
-    nbDistElem=0;
-    if(v2Distant)
+      double *ptDist2=0;
+      nbDistElem=0;
+      if(v2Distant)
       {
         nbDistElem=v2Distant->getNbOfElems();
         ptDist2=v2Distant->getPointer();
       }
 #ifdef HAVE_MPI2
-    MPI_Recv(ptDist2, nbDistElem, MPI_DOUBLE,source, 1110, MPI_COMM_WORLD, &status);
-#endif
-    //
-    //finish unserialization
-    mesh->unserialization(tinyInfoDistantD,tinyInfoDistant,v1Distant,v2Distant,unusedTinyDistantSts);
-    
-    if(v1Distant)
-      v1Distant->decrRef();
-    if(v2Distant)
-      v2Distant->decrRef();
-  
-}
-/*!
-Sends content of \a vec to processor \a target. To be used with \a recvDoubleVec method.
-\param vec vector to be sent
-\param target processor id of the target
-*/
-void ParaDomainSelector::sendDoubleVec(const std::vector<double>& vec, int target)const
-{
-  int size=vec.size();
-#ifdef HAVE_MPI2
-  MPI_Send(&size,1,MPI_INT,target,1211, MPI_COMM_WORLD);
-  MPI_Send(const_cast<double*>(&vec[0]), size,MPI_DOUBLE, target, 1212, MPI_COMM_WORLD);
-#endif
-}
-/*! Receives messages from proc \a source to fill vector<int> vec.
-To be used with \a sendDoubleVec method.
-
-\param vec vector that is filled
-\param source processor id of the incoming messages
- */
-void ParaDomainSelector::recvDoubleVec(std::vector<double>& vec, int source)const
-{
-  int size;
-#ifdef HAVE_MPI2
-  MPI_Status status;  
-  MPI_Recv(&size,1,MPI_INT,source,1211, MPI_COMM_WORLD, &status);
-  vec.resize(size);
-  MPI_Recv(&vec[0],size,MPI_DOUBLE,source, 1212, MPI_COMM_WORLD,&status);
-#endif
-}
-/*!
-Sends content of \a vec to processor \a target. To be used with \a recvIntVec method.
-\param vec vector to be sent
-\param target processor id of the target
-*/
-void ParaDomainSelector::sendIntVec(const std::vector<int>& vec, int target)const
-{
-  int size=vec.size();
-#ifdef HAVE_MPI2
-  MPI_Send(&size,1,MPI_INT,target,1211, MPI_COMM_WORLD);
-  MPI_Send(const_cast<int*>(&vec[0]), size,MPI_INT, target, 1212, MPI_COMM_WORLD);
-#endif
-}
-/*! Receives messages from proc \a source to fill vector<int> vec.
-To be used with \a sendIntVec method.
-
-\param vec vector that is filled
-\param source processor id of the incoming messages
- */
-void ParaDomainSelector::recvIntVec(std::vector<int>& vec, int source)const
-{
-  int size;
-#ifdef HAVE_MPI2
-  MPI_Status status;  
-  MPI_Recv(&size,1,MPI_INT,source,1211, MPI_COMM_WORLD, &status);
-  vec.resize(size);
-  MPI_Recv(&vec[0],size,MPI_INT,source, 1212, MPI_COMM_WORLD,&status);
+      MPI_Recv(ptDist2, nbDistElem, MPI_DOUBLE,source, 1110, MPI_COMM_WORLD, &status);
 #endif
+      //finish unserialization
+      mesh->unserialization(tinyInfoDistantD,tinyInfoDistant,v1Distant,v2Distant,unusedTinyDistantSts);
+      if(v1Distant) v1Distant->decrRef();
+      if(v2Distant) v2Distant->decrRef();
+    }
+    else
+    {
+      mesh=createEmptyMEDCouplingUMesh();
+    }
+    if (MyGlobals::_verbose>600) cout<<"proc "<<_rank<<" : recvMesh '"<<mesh->getName()<<"' size "<<mesh->getNumberOfCells()<<" from "<<source<<endl;
 }
 
index 465e121cbadfb43d0919adfe26b3286926c6dd76..028b00464e59a09d22de9292a641620fe044116a 100644 (file)
@@ -26,8 +26,6 @@
 
 #include "MEDPARTITIONER.hxx"
 
-#include <MEDMEM_define.hxx>
-
 #include <memory>
 #include <vector>
 
@@ -47,62 +45,54 @@ namespace MEDPARTITIONER
  */
 class MEDPARTITIONER_EXPORT ParaDomainSelector
 {
+
 public:
 
   ParaDomainSelector(bool mesure_memory=false);
   ~ParaDomainSelector();
 
-  //!< return processor rank
+  // return processor rank
   int rank() const { return _rank; }
-
-  //!< return number of processors
+  // return number of processors
   int nbProcs() const { return _world_size; }
-
   // Return true if is running on different hosts
   bool isOnDifferentHosts() const;
-
   // Return true if the domain with domainIndex is to be loaded on this proc
   bool isMyDomain(int domainIndex) const;
-
   // Return processor id where the domain with domainIndex resides
   int getProcessorID(int domainIndex) const;
-
-
-  //!< Set nb of required domains. (Used to sort joints via jointId())
+  //Set nb of required domains. (Used to sort joints via jointId())
   void setNbDomains(int nb) { _nb_result_domains = nb; }
-
   // Return identifier for a joint
   int jointId( int local_domain, int distant_domain ) const;
+  
+  int getNbTotalCells() { return _cell_shift_by_domain.back(); }
+  int getNbTotalNodes() { return _node_shift_by_domain.back(); };
+  int getNbTotalFaces() { return _face_shift_by_domain.back(); };
 
   // Return domain order
-  //int getDomianOrder(int domainIndex, int nb_domains) const;
-
-
-  // Collect nb of entities on procs and return total nb
-  int gatherNbOf(
-                 //MED_EN::medEntityMesh entity, 
-const std::vector<ParaMEDMEM::MEDCouplingUMesh*>& domain_meshes);
+  //int getDomainOrder(int domainIndex, int nb_domains) const;
 
+  // Collect nb of entities on procs
+  void gatherNbOf(const std::vector<ParaMEDMEM::MEDCouplingUMesh*>& domain_meshes);
+  
   // Return distribution of the graph vertices among the processors
-  int* getNbVertOfProcs() const;
-
-  // Return nb of cells on processors with lower rank
-  int getProcShift() const;
+  int* getProcVtxdist() const;
 
+  // Return nb of nodes on processors with lower rank
+  int getProcNodeShift() const;
   // Return nb of cells in domains with lower index
-  int getDomainShift(int domainIndex) const;
-
+  int getDomainCellShift(int domainIndex) const;
+  // Return nb of nodes in domains with lower index
+  int getDomainNodeShift(int domainIndex) const;
 
   // Gather graphs from all processors into one
   std::auto_ptr<Graph> gatherGraph(const Graph* graph) const;
 
-
   // Set nb of cell/cell pairs in a joint between domains
   void setNbCellPairs( int nb_cell_pairs, int dist_domain, int loc_domain );
-
   // Gather size of each proc/proc joint
   void gatherNbCellPairs();
-
   // Return nb of cell/cell pairs in a joint between domains on different procs
   int getNbCellPairs( int dist_domain, int loc_domain ) const;
 
@@ -111,11 +101,9 @@ const std::vector<ParaMEDMEM::MEDCouplingUMesh*>& domain_meshes);
 
   // Return the first global id of sub-entity for the joint
   int getFisrtGlobalIdOfSubentity( int loc_domain, int dist_domain ) const;
-
   // Send-receive local ids of joint faces
   int* exchangeSubentityIds( int loc_domain, int dist_domain,
                              const std::vector<int>& loc_ids_here ) const;
-
   // Return time passed from construction in seconds
   double getPassedTime() const;
 
@@ -123,35 +111,25 @@ const std::vector<ParaMEDMEM::MEDCouplingUMesh*>& domain_meshes);
   int evaluateMemory() const;
 
   void sendMesh(const ParaMEDMEM::MEDCouplingUMesh& mesh, int target) const;
-    
   void recvMesh(ParaMEDMEM::MEDCouplingUMesh*& mesh, int source) const;
-    
-  void sendDoubleVec(const std::vector<double>& vec, int target) const;
-    
-  void recvDoubleVec(std::vector<double>& vec, int source) const;
-    
-  void sendIntVec(const std::vector<int>& vec, int target) const;
-  void recvIntVec(std::vector<int>& vec, int source) const;
-
+  
 private:
 
   int _rank, _world_size; // my rank and nb of processors
-
   int _nb_result_domains; // required nb of domains
 
   //int _total_nb_faces; // nb of faces in the whole mesh without proc/proc joint faces
 
   std::vector< int > _nb_cell_pairs_by_joint;
-
   std::vector< int > _nb_vert_of_procs; // graph vertices
   std::vector< int > _cell_shift_by_domain;
+  std::vector< int > _node_shift_by_domain;
   std::vector< int > _face_shift_by_domain;
 
   double _init_time;
   bool   _mesure_memory;
   int    _init_memory, _max_memory;
 };
-
 }
 
 #endif
index 010ef4fd30156c673aa38749d2c43ab3f7d69a97..42055958f5144296744214994f822d9bf4d6c0fa 100644 (file)
@@ -19,6 +19,7 @@
 #include <set>
 #include <map>
 #include <vector>
+#include <iostream>
 
 #include "InterpKernelHashMap.hxx"
 #include "MEDPARTITIONER_MESHCollection.hxx"
 #include "MEDPARTITIONER_ConnectZone.hxx"
 
 #include "MEDCouplingUMesh.hxx"
-#include "MEDMEM_Exception.hxx"
-#include "MEDMEM_Utilities.hxx"
+#include "MEDPARTITIONER_utils.hxx"
 
-#ifndef WNT
-using namespace __gnu_cxx;
-#else
-using namespace std;
+#ifdef HAVE_MPI2
+#include <mpi.h>
 #endif
 
 using namespace MEDPARTITIONER;
+using namespace std;
 
 //empty constructor
 ParallelTopology::ParallelTopology():_nb_domain(0),_mesh_dimension(0)
 {}
 
+//!constructing topology according to mesh collection without global numerotation (use setGlobalNumerotation later)
+ParallelTopology::ParallelTopology(const vector<ParaMEDMEM::MEDCouplingUMesh*>& meshes)
+{
+  _nb_domain=meshes.size();
+  _nb_cells.resize(_nb_domain);
+  _nb_nodes.resize(_nb_domain);
+  //  _nb_faces.resize(_nb_domain);
+  
+  if (MyGlobals::_is0verbose>100) cout<<"new ParallelTopology\n";
+  _loc_to_glob.resize(0);      //precaution, need gatherNbOf() setGlobalNumerotation()
+  _node_loc_to_glob.resize(0); //precaution, need gatherNbOf() setGlobalNumerotation()
+  //_face_loc_to_glob.resize(_nb_domain);
+  _mesh_dimension = -1;
+  bool parallel_mode = false;
+  for (int idomain=0; !parallel_mode && idomain<_nb_domain; idomain++)
+    parallel_mode = (!meshes[idomain]);
+
+  if (MyGlobals::_is0verbose>20 && !parallel_mode) cout<<"WARNING : ParallelTopology contructor without parallel_mode"<<endl;
+  for (int idomain=0; idomain<_nb_domain; idomain++)
+  {
+    if ( !meshes[idomain] ) continue;
+    if (_mesh_dimension==-1)
+    {
+      _mesh_dimension = meshes[idomain]->getMeshDimension();
+    }
+    else
+    {
+      if (_mesh_dimension!=meshes[idomain]->getMeshDimension())
+        throw INTERP_KERNEL::Exception(LOCALIZED("meshes dimensions incompatible"));
+    }
+    _nb_cells[idomain]=meshes[idomain]->getNumberOfCells();
+    _nb_nodes[idomain]=meshes[idomain]->getNumberOfNodes();
+    //note: in parallel mode _nb_cells and _nb_nodes are not complete now, needs gatherNbOf()
+  }
+}
+
+//!constructing _loc_to_glob etc by default, needs gatherNbOf() done
+void ParallelTopology::setGlobalNumerotationDefault(ParaDomainSelector* domainSelector)
+{
+  if (MyGlobals::_is0verbose>100) cout<<"setGlobalNumerotationDefault on "<<_nb_domain<<" domains\n";
+  if (_loc_to_glob.size()!=0) throw INTERP_KERNEL::Exception(LOCALIZED("a global numerotation is done yet"));
+  _loc_to_glob.resize(_nb_domain);
+  _node_loc_to_glob.resize(_nb_domain);
+  
+  //warning because _nb_cells[idomain] is 0 if not my domain(s)
+  //we set loc_to_glob etc.. only for my domain(s)
+  if (MyGlobals::_is0verbose>500) cout<<"(c)idomain|ilocalCell|iglobalCell"<<endl;
+  for (int idomain=0; idomain<_nb_domain; idomain++)
+  {
+    _loc_to_glob[idomain].resize(_nb_cells[idomain]);
+    int domainCellShift=domainSelector->getDomainCellShift(idomain);
+    for (int i=0; i<_nb_cells[idomain]; i++)
+    {
+      int global=domainCellShift+i ;
+      _glob_to_loc.insert(make_pair(global,make_pair(idomain,i)));
+      _loc_to_glob[idomain][i]=global;
+      if (MyGlobals::_verbose>500) cout<<"c"<<idomain<<"|"<<i<<"|"<<global<<" ";
+    }
+  }
+  if (MyGlobals::_verbose>500) MPI_Barrier(MPI_COMM_WORLD);
+  if (MyGlobals::_is0verbose>500) cout<<endl;
+  
+  if (MyGlobals::_is0verbose>500) cout<<"(n)idomain|ilocalNode|iglobalNode"<<endl;
+  for (int idomain=0; idomain<_nb_domain; idomain++)
+  {
+    _node_loc_to_glob[idomain].resize(_nb_nodes[idomain]);
+    int domainNodeShift=domainSelector->getDomainNodeShift(idomain);
+    for (int i=0; i<_nb_nodes[idomain]; i++)
+    {
+      int global=domainNodeShift+i ;
+      _node_glob_to_loc.insert(make_pair(global,make_pair(idomain,i)));
+      _node_loc_to_glob[idomain][i]=global;
+      if (MyGlobals::_verbose>500) cout<<"n"<<idomain<<"|"<<i<<"|"<<global<<" ";
+    }
+  }
+  if (MyGlobals::_verbose>500) MPI_Barrier(MPI_COMM_WORLD);
+  if (MyGlobals::_is0verbose>500) cout<<endl;
+  
+  _nb_total_cells=domainSelector->getNbTotalCells();
+  _nb_total_nodes=domainSelector->getNbTotalNodes();
+  _nb_total_faces=domainSelector->getNbTotalFaces();
+  if (MyGlobals::_is0verbose>200) cout<<"globalNumerotation default done meshDimension "<<_mesh_dimension<<" nbTotalCells "<<_nb_total_cells<<" nbTotalNodes "<<_nb_total_nodes<<endl;
+}
+
 //!constructing topology according to mesh collection
 ParallelTopology::ParallelTopology(const vector<ParaMEDMEM::MEDCouplingUMesh*>& meshes, 
                                    const vector<MEDPARTITIONER::CONNECTZONE*>& cz,
                                    vector<int*>& cellglobal,
                                    vector<int*>& nodeglobal,
-                                   vector<int*>& faceglobal):_nb_domain(meshes.size())/*,_mesh_dimension(meshes[0]->getMeshDimension())*/
+                                   vector<int*>& faceglobal)
 {
-
+  _nb_domain=meshes.size();
   int index_global=0;
   int index_node_global=0;
   int index_face_global=0;
@@ -58,24 +141,20 @@ ParallelTopology::ParallelTopology(const vector<ParaMEDMEM::MEDCouplingUMesh*>&
   _nb_cells.resize(_nb_domain);
   _nb_nodes.resize(_nb_domain);
   //  _nb_faces.resize(_nb_domain);
-
+  
   _loc_to_glob.resize(_nb_domain);
   _node_loc_to_glob.resize(_nb_domain);
   //  _face_loc_to_glob.resize(_nb_domain);
 
-  //MED_EN::medEntityMesh constituent_entity;
-
   bool parallel_mode = false;
   for (int idomain=0; !parallel_mode && idomain<_nb_domain; idomain++)
     parallel_mode = (!meshes[idomain]);
 
   for (int idomain=0; idomain<_nb_domain; idomain++)
   {
-    if ( !meshes[idomain] )
-      continue;
+    if ( !meshes[idomain] ) continue;
     _mesh_dimension = meshes[idomain]->getMeshDimension();
-    //constituent_entity = (_mesh_dimension == 3 ? MED_EN::MED_FACE : MED_EN::MED_EDGE );
-
+    
     //creating cell maps
     _nb_cells[idomain]=meshes[idomain]->getNumberOfCells();
     //    cout << "Nb cells (domain "<<idomain<<") = "<<_nb_cells[idomain];
@@ -83,21 +162,20 @@ ParallelTopology::ParallelTopology(const vector<ParaMEDMEM::MEDCouplingUMesh*>&
 
     if (cellglobal[idomain]==0 || parallel_mode)
     {
-      MESSAGE_MED("Creating global numbering"); 
+      //int cellDomainShift=_cell_shift_by_domain[idomain];
       //creating global numbering from scratch
       for (int i=0; i<_nb_cells[idomain]; i++)
       {
-       
-        _glob_to_loc.insert(make_pair(index_global,make_pair(idomain,i+1)));
-        _loc_to_glob[idomain][i]=index_global;
-        //        cout<<"glob:"<<index_global<<" --> ("<<idomain<<","<<i+1<<")"<<endl;
+        int global=i ;//cellDomainShift+i;
+        _glob_to_loc.insert(make_pair(global,make_pair(idomain,i)));
+        _loc_to_glob[idomain][i]=global;
+        //cvw cout<<idomain<<"|"<<i<<"|"<<global<<" ";
         index_global++;
       }
     }
     //using global numbering coming from a previous numbering
     else
     {
-      MESSAGE_MED("Using former global numbering");
       for (int i=0; i<_nb_cells[idomain]; i++)
       {
         int global=cellglobal[idomain][i];
@@ -122,9 +200,6 @@ ParallelTopology::ParallelTopology(const vector<ParaMEDMEM::MEDCouplingUMesh*>&
       }
       _nb_total_nodes=meshes[idomain]->getNumberOfNodes();   
       _nb_nodes[0]=_nb_total_nodes; 
-
-      MESSAGE_MED ("nb total cells "<< _nb_total_cells);
-      MESSAGE_MED("nb total nodes "<< _nb_total_nodes);  
       return;
     }
 
@@ -185,19 +260,68 @@ ParallelTopology::ParallelTopology(const vector<ParaMEDMEM::MEDCouplingUMesh*>&
   _nb_total_cells=index_global;
   _nb_total_nodes=index_node_global;   
   _nb_total_faces=index_face_global;
-  SCRUTE_MED(_nb_total_cells);
-  SCRUTE_MED(_nb_total_faces);
-  SCRUTE_MED(_nb_total_nodes);
-
 }
 
 
 //!constructing ParallelTopology from an old topology and a graph
-ParallelTopology::ParallelTopology(Graph* graph, int nb_domain, int mesh_dimension):
-  _nb_domain(nb_domain),
-  _nb_cells(graph->nbVertices()),
-  _mesh_dimension(mesh_dimension)
+ParallelTopology::ParallelTopology(Graph* graph, Topology* oldTopology, int nb_domain, int mesh_dimension)
 {
+
+  _nb_domain=nb_domain;
+  //cvw !!whatisit! _nb_cells=graph->nbVertices();
+  _mesh_dimension=mesh_dimension;
+  
+  if (MyGlobals::_verbose>200)
+    cout<<"proc "<<MyGlobals::_rank<<" : new topology oldNbDomain "<<
+                   oldTopology->nbDomain()<<" newNbDomain "<<_nb_domain<<endl;
+  _nb_cells.resize(_nb_domain,0);
+  _nb_nodes.resize(_nb_domain,0);
+  _nb_faces.resize(_nb_domain,0);
+
+  _loc_to_glob.resize(_nb_domain);
+  _node_loc_to_glob.resize(_nb_domain);
+  _face_loc_to_glob.resize(_nb_domain);
+  
+  const int* part=graph->getPart(); //all cells for this proc (may be more domains)
+  _nb_total_cells=graph->nbVertices(); //all cells for this proc (may be more domains)
+  if (MyGlobals::_verbose>300)
+    cout<<"proc "<<MyGlobals::_rank<<" : topology from partition, nbTotalCells "<<_nb_total_cells<<endl;
+  
+  int icellProc=0; //all cells of my domains are concatenated in part
+  for (int iold=0; iold<oldTopology->nbDomain(); iold++)
+  {
+    int ioldNbCell=oldTopology->getCellNumber(iold);
+    //cout<<"proc "<<MyGlobals::_rank<<" : cell number old domain "<<iold<<" : "<<ioldNbCell<<endl;
+    //if not my old domains getCellNumber is 0
+    std::vector<int> globalids(ioldNbCell);
+    oldTopology->getCellList(iold, &globalids[0]); //unique global numerotation
+    for (int icell=0; icell<ioldNbCell; icell++)
+    {
+      int idomain=part[icellProc];
+      _nb_cells[idomain]++;
+      icellProc++;
+      int iGlobalCell=globalids[icell];
+      _loc_to_glob[idomain].push_back(iGlobalCell);
+      _glob_to_loc.insert(make_pair(iGlobalCell, make_pair(idomain, _nb_cells[idomain])));
+    }
+  }
+
+  if (MyGlobals::_verbose>300)
+    for (int idomain=0; idomain<_nb_domain; idomain++)
+      cout<<"proc "<<MyGlobals::_rank<<" : nbCells in new domain "<<idomain<<" : "<<_nb_cells[idomain]<<endl; 
+}
+
+//!constructing ParallelTopology from an old topology and a graph
+/*
+ParallelTopology::ParallelTopology(Graph* graph, Topology* oldTopology, int nb_domain, int mesh_dimension)
+{
+
+  _nb_domain=nb_domain;
+  //cvw !!whatisit! _nb_cells=graph->nbVertices();
+  _mesh_dimension=mesh_dimension;
+  
+  cout<<"proc "<<MyGlobals::_rank<<" : new topology from partition old nbDomain "<<
+                 oldTopology->nbDomain()<<" new nbDomain "<<_nb_domain<<endl;
   _nb_cells.resize(_nb_domain);
   _nb_nodes.resize(_nb_domain);
   _nb_faces.resize(_nb_domain);
@@ -210,27 +334,27 @@ ParallelTopology::ParallelTopology(Graph* graph, int nb_domain, int mesh_dimensi
   _cell_loc_to_glob_fuse.resize(_nb_domain);
   _face_loc_to_glob_fuse.resize(_nb_domain);
 
-  for (int i=0; i<_nb_domain; i++)
-    _nb_cells[i]=0;  
+  for (int i=0; i<_nb_domain; i++) _nb_cells[i]=0;
+
+  const int* part=graph->getPart();
+  _nb_total_cells=graph->nbVertices();
 
-  const int* part = graph-> getPart();
-  _nb_total_cells= graph->nbVertices();
+  cout<<"proc "<<MyGlobals::_rank<<" : topology from partition, _nb_total_cells "<<_nb_total_cells<<endl;
   
   for (int icell=0; icell<_nb_total_cells; icell++)
   {
     int idomain = part[icell];
     _nb_cells[idomain]++;
-    //_loc_to_glob[make_pair(idomain,_nb_cells[idomain])]=icell+1;
+    //cvw problem _nb_cells[idomain] is not only on this proc...
+    //cout<<"proc "<<MyGlobals::_rank<<" : topology from partition, houston! there is a bug in _loc_to_glob and _glob_to_loc"<<endl;
     _loc_to_glob[idomain].push_back(icell);
-    _glob_to_loc.insert(make_pair(icell,make_pair(idomain,_nb_cells[idomain])));
-
+    _glob_to_loc.insert(make_pair(icell, make_pair(idomain, _nb_cells[idomain])));
+    cout<<"proc "<<MyGlobals::_rank<<" : glob_to_loc.insert : "<<icell<<" "<<idomain<<" "<<_nb_cells[idomain]<<endl;
   }
   for (int idomain=0; idomain<_nb_domain; idomain++)
-    MESSAGE_MED("Nombre de cellules dans le domaine "<< idomain <<" : "<<_nb_cells[idomain]); 
-
-  SCRUTE_MED(_nb_total_cells);
-
+    cout<<"proc "<<MyGlobals::_rank<<" : Nb cells in new domain "<<idomain<<" : "<<_nb_cells[idomain]<<endl; 
 }
+*/
 
 ParallelTopology::~ParallelTopology()
 {
@@ -245,7 +369,7 @@ ParallelTopology::~ParallelTopology()
 void ParallelTopology::convertGlobalNodeList(const int* node_list, int nbnode, int* local, int* ip)
 {
   if (_node_glob_to_loc.empty()) 
-    throw MEDMEM::MEDEXCEPTION("convertGlobalNodeList - Node mapping has not yet been built");
+    throw INTERP_KERNEL::Exception(LOCALIZED("Node mapping has not yet been built"));
   for (int i=0; i< nbnode; i++)
   {
     pair<int,int> local_node = _node_glob_to_loc.find(node_list[i])->second;
@@ -264,7 +388,7 @@ void ParallelTopology::convertGlobalNodeList(const int* node_list, int nbnode, i
 void ParallelTopology::convertGlobalNodeList(const int* node_list, int nbnode, int* local, int ip)
 {
   if (_node_glob_to_loc.empty()) 
-    throw MEDMEM::MEDEXCEPTION("convertGlobalNodeList - Node mapping has not yet been built");
+    throw INTERP_KERNEL::Exception(LOCALIZED("Node mapping has not yet been built"));
 
   for (int i=0; i< nbnode; i++)
   {
@@ -288,7 +412,7 @@ void ParallelTopology::convertGlobalNodeList(const int* node_list, int nbnode, i
 void ParallelTopology::convertGlobalNodeListWithTwins(const int* node_list, int nbnode, int*& local, int*& ip,int*& full_array, int& size)
 {
   if (_node_glob_to_loc.empty()) 
-    throw MEDMEM::MEDEXCEPTION("convertGlobalNodeList - Node mapping has not yet been built");
+    throw INTERP_KERNEL::Exception(LOCALIZED("Node mapping has not yet been built"));
 
   size=0;
   for (int i=0; i< nbnode; i++)
@@ -355,11 +479,21 @@ void ParallelTopology::convertGlobalFaceListWithTwins(const int* face_list, int
 //!to a distributed array with local cell numbers 
 void ParallelTopology::convertGlobalCellList(const int* cell_list, int nbcell, int* local, int* ip)
 {
-  for (int i=0; i< nbcell; i++)
+  for (int i=0; i<nbcell; i++)
   {
+    //cvw INTERP_KERNEL::HashMap<int, pair<int,int> >::const_iterator iter = _glob_to_loc.find(cell_list[i]);
     INTERP_KERNEL::HashMap<int, pair<int,int> >::const_iterator iter = _glob_to_loc.find(cell_list[i]);
-    ip[i]=(iter->second).first;
-    local[i]=(iter->second).second;
+    if (iter == _glob_to_loc.end())
+    {
+      cerr<<"proc "<<MyGlobals::_rank<<" : KO cell_list["<<i<<"] : "<<cell_list[i]<<endl;
+      throw INTERP_KERNEL::Exception(LOCALIZED("ParallelTopology::convertGlobalCellList : Cell not found"));
+    }
+    else
+    {
+      ip[i]=(iter->second).first;     //no domain
+      local[i]=(iter->second).second; //no local cell
+      //cout<<"proc "<<MyGlobals::_rank<<" : OK cell_list["<<i<<"] : "<<cell_list[i]<<" "<<ip[i]<<" "<<local[i]<<endl;
+    }
   }
 }
 
@@ -373,7 +507,7 @@ void ParallelTopology::convertGlobalFaceList(const int* face_list, int nbface, i
     INTERP_KERNEL::HashMap<int, pair<int,int> >::const_iterator iter = _face_glob_to_loc.find(face_list[i]);
     if (iter == _face_glob_to_loc.end())
     {
-      throw MED_EXCEPTION("convertGlobalFaceList - Face  not found");
+      throw INTERP_KERNEL::Exception(LOCALIZED("ParallelTopology::convertGlobalFaceList : Face not found"));
     }
     ip[i]=(iter->second).first;
     local[i]=(iter->second).second;
@@ -404,8 +538,6 @@ void ParallelTopology::convertGlobalFaceList(const int* face_list, int nbface, i
   }
 } 
 
-
-
 //replacing a table of global numbering with a table with local numberings
 // type_connectivity contains global connectivity for each type in input
 // type_connectivity contains local connectivity for each type in output
@@ -421,17 +553,15 @@ void ParallelTopology::convertToLocal2ndVersion(int* nodes, int nbnodes, int ido
     {
       if ((it->second).first==idomain)
         nodes[inode]=(it->second).second;
-    }        
+    }
   }
 }
 
-
 //================================================================================
 /*!
  * \brief Return max global face number
  */
 //================================================================================
-
 int ParallelTopology::getMaxGlobalFace() const
 {
   int max = 0;
index 3d6e7f41868025b75f0c3bab2eafb7c47c3b2b32..72dbcc5743202d979b9eb657958fa403dbf6ad27 100644 (file)
@@ -24,7 +24,9 @@
 #include "InterpKernelHashMap.hxx"
 
 #include "MEDPARTITIONER_Topology.hxx"
+#include "MEDPARTITIONER_ParaDomainSelector.hxx"
 
+/*
 namespace INTERP_KERNEL
 {
   template<> struct hash< std::pair<int,int> >
@@ -34,7 +36,7 @@ namespace INTERP_KERNEL
       return hash< int >()( x.first*1000000+x.second );
     }
   };
-}
+}*/
 
 namespace MEDPARTITIONER {
 
@@ -49,15 +51,19 @@ namespace MEDPARTITIONER {
 
     ParallelTopology();
 
+    ParallelTopology(const std::vector<ParaMEDMEM::MEDCouplingUMesh*>&);
     ParallelTopology(const std::vector<ParaMEDMEM::MEDCouplingUMesh*>&,
                      const std::vector<MEDPARTITIONER::CONNECTZONE*>&,
                      std::vector<int*>&,
                      std::vector<int*>&,
                      std::vector<int*>&);
 
-    ParallelTopology(Graph* graph, int nbdomain, int mesh_dimension);
+    ParallelTopology(Graph* graph, Topology* oldTopology, int nbdomain, int mesh_dimension);
 
     ~ParallelTopology();
+    
+    void setGlobalNumerotationDefault(ParaDomainSelector* domainSelector);
+
     //!converts a list of global cell numbers
     //!to a distributed array with local cell numbers
     void convertGlobalNodeList(const int*, int,int*,int*);
@@ -131,17 +137,17 @@ namespace MEDPARTITIONER {
     {
       return _nb_total_cells;
     }
+    
     int nbNodes() const
-    {return _nb_total_nodes;}
+    {
+      return _nb_total_nodes;
+    }
 
     inline  int nbCells( int idomain) const
     {
       return _nb_cells[idomain];
     }
 
-
-
-
     //!retrieving number of nodes
     inline  int getNodeNumber(int idomain) const
     {
@@ -163,7 +169,7 @@ namespace MEDPARTITIONER {
     //!retrieving list of nodes in global numbers
     inline  void getNodeList(int idomain, int* list) const
     {
-      for (int i=0; i<_nb_nodes[idomain];i++) 
+      for (int i=0; i<_nb_nodes[idomain]; i++) 
         list[i]=_node_loc_to_glob[idomain][i];
     }
 
@@ -172,6 +178,7 @@ namespace MEDPARTITIONER {
     {
       return _cell_loc_to_glob_fuse[idomain];
     }
+    
     const std::vector<int> & getFusedCellNumbers(int idomain) const
     {
       return _cell_loc_to_glob_fuse[idomain];
@@ -204,8 +211,6 @@ namespace MEDPARTITIONER {
     {
       for (int i=0; i<_nb_cells[idomain];i++)
         list[i]=_loc_to_glob[idomain][i];
-      
-
     }
 
     inline int getFaceNumber(int idomain) const
@@ -258,6 +263,7 @@ namespace MEDPARTITIONER {
       }
       return -1;
     }
+    
     //!adding a face to the topology
     inline void appendFace(int idomain, int ilocal, int iglobal)
     {
@@ -268,12 +274,9 @@ namespace MEDPARTITIONER {
     //return max global face number
     int getMaxGlobalFace() const;
 
-
   private:
-
     bool hasCellWithNodes( const MESHCollection&, int dom, const std::set<int>& nodes );
 
-
   private:
     //!mapping global -> local
     typedef INTERP_KERNEL::HashMultiMap<int,std::pair<int,int> > TGlob2DomainLoc;
@@ -291,30 +294,20 @@ namespace MEDPARTITIONER {
     std::vector<std::vector <int> > _cell_loc_to_glob_fuse; // glob nums after fusing
     std::vector<std::vector <int> > _face_loc_to_glob_fuse; // glob nums after fusing
 
-
     //!mapping global -> local
     typedef INTERP_KERNEL::HashMultiMap<int,std::pair<int,int> > TGlob2LocsMap;
     TGlob2LocsMap _face_glob_to_loc;
 
     //!mapping local -> global
     std::vector<std::vector <int> > _face_loc_to_glob;
-
     std::vector<int> _nb_cells;
-
     std::vector<int> _nb_nodes;
-
     std::vector<int> _nb_faces;
-
     int _nb_total_cells;
-
     int _nb_total_nodes;
-
     int _nb_total_faces;
-
     int _nb_domain;
-
     int _mesh_dimension;
-
   };
 
 
index 20cfd4c50795c2d55b40e630d3dd758c8acd7f90..3f0cf14fdad9260ca508c7590653fee6b42d0299 100644 (file)
@@ -21,7 +21,6 @@
 //
 
 #include "MEDPARTITIONER_SkyLineArray.hxx"
-#include "MEDMEM_Utilities.hxx"
 #include <vector>
 
 
@@ -29,7 +28,7 @@ using namespace MEDPARTITIONER;
 
 MEDSKYLINEARRAY::MEDSKYLINEARRAY()
 {
-  MESSAGE_MED("Constructeur MEDSKYLINEARRAY sans parametre");
+  //MESSAGE_MED("Constructeur MEDSKYLINEARRAY sans parametre");
 }
 
 MEDSKYLINEARRAY::MEDSKYLINEARRAY(const MEDSKYLINEARRAY &myArray)
@@ -40,7 +39,7 @@ MEDSKYLINEARRAY::MEDSKYLINEARRAY(const MEDSKYLINEARRAY &myArray)
 
 MEDSKYLINEARRAY::~MEDSKYLINEARRAY()
 {
-  MESSAGE_MED("Destructeur ~MEDSKYLINEARRAY");
+  //MESSAGE_MED("Destructeur ~MEDSKYLINEARRAY");
 
   //if (_index != NULL) delete [] _index;
   //if (_value != NULL) delete [] _value;
index 21d6fffbc4bcdbb4dca4664dbe963242d94eec44..d56fd94bbe1576906769ef3cc9d23de72d05b7d6 100644 (file)
@@ -41,23 +41,21 @@ public :
   // Constructeur par recopie
   MEDSKYLINEARRAY( const MEDSKYLINEARRAY &myArray );
 
-  // Avec ce constructeur la mémoire pour le tableau  de valeur et le
-  // tableau d'index est réservée. Il suffit d'effectuer les séquences
+  // Avec ce constructeur la mmoire pour le tableau  de valeur et le
+  // tableau d'index est r�serv�e. Il suffit d'effectuer les s�quences
   // d'appels suivantes pour initialiser le MEDSKYLINEARRAY
-  // 1) setIndex(index) puis <count> fois setI(i,&listValeurN°I) avec i dans 1..count
-  //    rem :   listValeurN°I est dupliquée
+  // 1) setIndex(index) puis <count> fois setI(i,&listValeurNI) avec i dans 1..count
+  //    rem :   listValeurN�I est dupliqu�e
   // 2) appeler <length> fois setIJ(i,j,valeur) avec i dans 1..count et avec j dans 1..count
   MEDSKYLINEARRAY( const std::vector<int>& index, const std::vector<int>& value );
 
-
   ~MEDSKYLINEARRAY();
   //void setMEDSKYLINEARRAY( const int count, const int length, int* index , int* value ) ;
 
-  inline int  getNumberOf()       const;
-  inline int  getLength()         const;
-  inline const int*  getIndex()   const;
-  inline const int*  getValue()   const;
+  inline int getNumberOf() const;
+  inline int getLength() const;
+  inline const int* getIndex() const;
+  inline const int* getValue() const;
 };
 
 // ---------------------------------------
index a38bdda020bd55a4e7a611e15af55afd2b1687a7..d0821e7af1c8ad8ac17738efd575ee5ebab7f4ba 100644 (file)
@@ -19,8 +19,6 @@
 #ifndef MEDPARTITIONER_TOPOLOGY_HXX_
 #define MEDPARTITIONER_TOPOLOGY_HXX_
 
-//#include "MEDMEM_define.hxx"
-
 //#include "boost/shared_ptr.hpp"
 
 #include <map>
diff --git a/src/MEDPartitioner/MEDPARTITIONER_utils.cxx b/src/MEDPartitioner/MEDPARTITIONER_utils.cxx
new file mode 100644 (file)
index 0000000..19843ca
--- /dev/null
@@ -0,0 +1,1627 @@
+//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D
+//
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU Lesser General Public
+//  License as published by the Free Software Foundation; either
+//  version 2.1 of the License.
+//
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "MEDLoader.hxx"
+#include "MEDLoaderBase.hxx"
+#include "MEDFileUtilities.hxx"
+#include "CellModel.hxx"
+#include "MEDCouplingUMesh.hxx"
+#include "MEDCouplingFieldDouble.hxx"
+#include "MEDPARTITIONER_utils.hxx"
+#include "InterpKernelException.hxx"
+#include "MEDCouplingAutoRefCountObjectPtr.hxx"
+#include "InterpKernelAutoPtr.hxx"
+
+#ifdef HAVE_MPI2
+#include <mpi.h>
+#endif
+
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+#include <string>
+
+using namespace std;
+using namespace MEDPARTITIONER;
+
+int MEDPARTITIONER::MyGlobals::_verbose=0;
+int MEDPARTITIONER::MyGlobals::_is0verbose=0;
+int MEDPARTITIONER::MyGlobals::_rank=-1;
+int MEDPARTITIONER::MyGlobals::_world_size=-1;
+int MEDPARTITIONER::MyGlobals::_randomize=0;
+int MEDPARTITIONER::MyGlobals::_atomize=0;
+int MEDPARTITIONER::MyGlobals::_creates_boundary_faces=0;
+vector<string> MEDPARTITIONER::MyGlobals::_fileNames;
+vector<string> MEDPARTITIONER::MyGlobals::_meshNames;
+vector<string> MEDPARTITIONER::MyGlobals::_fieldDescriptions;
+vector<string> MEDPARTITIONER::MyGlobals::_generalInformations;
+
+string MEDPARTITIONER::trim(string& s, const string& drop)
+{
+  string r=s.erase(s.find_last_not_of(drop)+1);
+  return r.erase(0,r.find_first_not_of(drop));
+}
+
+string MEDPARTITIONER::intToStr(int i)
+{
+  ostringstream oss;
+  oss<<i;
+  return oss.str();
+}
+
+int MEDPARTITIONER::strToInt(string s)
+{
+  int res;
+  istringstream iss(s);
+  iss>>res;
+  return res;
+}
+
+string MEDPARTITIONER::doubleToStr(double i)
+{
+  ostringstream oss;
+  oss<<i;
+  return oss.str();
+}
+
+double MEDPARTITIONER::strToDouble(string s)
+{
+  double res;
+  istringstream iss(s);
+  iss>>res;
+  return res;
+}
+
+bool MEDPARTITIONER::testArg(const char *arg, const char *argExpected, string& argValue)
+{
+  argValue="";
+  int i;
+  for (i=0; i<strlen(arg); i++)
+  {
+    if (arg[i]=='=') break;
+    if (arg[i]!=argExpected[i]) return false;
+  }
+  for (int j=i+1; j<strlen(arg); j++) argValue+=arg[j];
+  //cout<<"found at "<<i<<" "<<argValue<<endl;
+  return true;
+}
+
+vector<int> MEDPARTITIONER::createRandomSize(int size)
+{
+  vector<int> res(size);
+  for (int i=0; i<size; i++) res[i]=i;
+  //cvw TODO srand( (unsigned)time( NULL ) );
+  srand( MyGlobals::_randomize );
+  for (int i=0; i<size; i++)
+  {
+    int ii=rand()%size;
+    int tmp=res[ii];
+    res[ii]=res[i];
+    res[i]=tmp;
+  }
+  //cout<<"createRandomSize "<<size<<endl;
+  if (size<50) { for (int i=0; i<size; i++) cout<<res[i]<<" "; cout<<endl; }
+  return res;
+}
+
+void MEDPARTITIONER::randomizeAdj(int* xadj, int* adjncy, vector<int>& ran, vector<int>& vx, vector<int>& va)
+//randomize a xadj and adjncy, renumbering vertices belong rand.
+//work only on one processor!!!!
+{
+  if (MyGlobals::_world_size>1)
+  {
+    cerr<<"randomizeAdj only on one proc!"<<endl;
+    return;
+  }
+  int size=ran.size();
+  vector<int> invran(size);
+  for (int i=0; i<size; i++) invran[ran[i]]=i;
+  vx.resize(size+1);
+  int lga=xadj[size];
+  va.resize(lga);
+  int jj=0;
+  vx[0]=0;
+  for (int i=0; i<size; i++)
+  {
+    int ir=ran[i];
+    int ii=xadj[ir];
+    int lgj=xadj[ir+1]-ii;
+    for (int j=0; j<lgj; j++)
+    {
+      //va[jj]=adjncy[ii]; //for first debug only
+      va[jj]=invran[adjncy[ii]];
+      jj=jj+1;
+      ii=ii+1;
+    }
+    vx[i+1]=jj;
+  }
+}
+
+void MEDPARTITIONER::testRandomize()
+{
+  //int xadj[6]={0,2,5,9,12,13}; //for first debug only
+  //int adjncy[13]={1,4,0,2,4,1,3,4,2,4,4,3,4};
+  int xadj[6]={0,2,5,9,12,13};
+  int adjncy[13]={0,0,1,1,1,2,2,2,2,3,3,3,4};
+  cout<<"testRandomize"<<endl;
+  for (int i=0; i<6; i++) cout<<xadj[i]<<" "; cout<<endl;
+  for (int i=0; i<13; i++) cout<<adjncy[i]<<" "; cout<<endl;
+  int size=5;
+  vector<int> r=createRandomSize(size);
+  vector<int> vx,va;
+  randomizeAdj(&xadj[0],&adjncy[0],r,vx,va);
+  for (int i=0; i<vx.size(); i++) cout<<vx[i]<<" "; cout<<endl;
+  for (int i=0; i<va.size(); i++) cout<<va[i]<<" "; cout<<endl;
+}
+
+string MEDPARTITIONER::reprVectorOfString(const vector<string>& vec)
+{
+  if (vec.size()==0) return string(" NONE\n");
+  ostringstream oss;
+  for (vector<string>::const_iterator i=vec.begin(); i!=vec.end(); ++i) 
+    oss<<" -> '"<<*i<<"'"<<endl;
+  return oss.str();
+}
+
+string MEDPARTITIONER::reprVectorOfString(const vector<string>& vec, string sep)
+{
+  if (vec.size()==0) return string(" NONE\n");
+  ostringstream oss;
+  for (vector<string>::const_iterator i=vec.begin(); i!=vec.end(); ++i) 
+    oss<<sep<<*i;
+  return oss.str();
+}
+
+string MEDPARTITIONER::reprMapOfStringInt(const map<string,int>& mymap)
+{
+  if (mymap.size()==0) return string(" NONE\n");
+  ostringstream oss;
+  for (map<string,int>::const_iterator i=mymap.begin(); i!=mymap.end(); ++i) 
+    oss<<" -> ["<<(*i).first<<"]="<<(*i).second<<endl;
+  return oss.str();
+}
+
+string MEDPARTITIONER::reprMapOfStringVectorOfString(const map< string,vector<string> >& mymap)
+{
+  if (mymap.size()==0) return string(" NONE\n");
+  ostringstream oss;
+  for (map< string,vector<string> >::const_iterator i=mymap.begin(); i!=mymap.end(); ++i) 
+    oss<<" -> ["<<(*i).first<<"]="<<endl<<reprVectorOfString((*i).second)<<endl;
+  return oss.str();
+}
+
+string MEDPARTITIONER::reprFieldDescriptions(const vector<string>& vec, string sep)
+{
+  if (vec.size()==0) return string(" NONE\n");
+  ostringstream oss;
+  for (vector<string>::const_iterator i=vec.begin(); i!=vec.end(); ++i)
+  {
+    oss<<" ->"; 
+    oss<<reprVectorOfString(deserializeToVectorOfString(*i), sep)<<endl;
+    /*vector<string> vec2=deserializeToVectorOfString(*i);
+    for (vector<string>::const_iterator j=vec2.begin(); j!=vec2.end(); ++j)
+      oss<<reprVectorOfString(deserializeToVectorOfString(*j), sep)<<endl;*/
+  }
+  return oss.str();
+}
+
+string MEDPARTITIONER::serializeFromString(const string& s)
+//a string "hello" gives a string "    5/hello/"
+//serialized_FromVectorOfString_string+serializeFromString("toto") is
+//equivalent to vector<string>.push_back("toto") on serialized_FromVectorOfString_string
+{
+  ostringstream oss;
+  oss<<setw(5)<<s.size()<<"/"<<s<<"/";
+  return oss.str();
+}
+
+string MEDPARTITIONER::serializeFromVectorOfString(const vector<string>& vec)
+//a vector of string gives a string
+{
+  ostringstream oss;
+  for (vector<string>::const_iterator i=vec.begin(); i!=vec.end(); ++i)
+    oss<<setw(5)<<(*i).size()<<"/"<<*i<<"/";
+  //string res(oss.str());
+  return oss.str();
+}
+
+vector<string> MEDPARTITIONER::deserializeToVectorOfString(const string& str)
+//a string gives a vector of string
+{
+  //vector<string> res=new vector<string>;
+  vector<string> res;
+  size_t pos=0;
+  size_t posmax=str.size();
+  if (posmax==0) return res;  //empty vector
+  size_t length;
+  while (pos < posmax-6)  //setw(5)+" "
+  {
+    istringstream iss(str.substr(pos,5));
+    iss>>length;
+    //cout<<"length "<<length<<endl;
+    if ((str[pos+5]!='/') || (str[pos+6+length]!='/'))
+    {
+      cerr<<"Error on string '"<<str<<"'"<<endl;;
+      throw INTERP_KERNEL::Exception(LOCALIZED("Error on string"));
+    }
+    res.push_back(str.substr(pos+6,length));
+    pos=pos+6+length+1;
+  }
+  return res;
+}
+
+string MEDPARTITIONER::eraseTagSerialized(string fromStr, string tag)
+{
+  vector<string> vec=deserializeToVectorOfString(fromStr);
+  vector<string> res;
+  for (int i=0; i<vec.size(); i++)
+  {
+    if (vec[i].find(tag)==string::npos) res.push_back(vec[i]);
+  }
+  return MEDPARTITIONER::serializeFromVectorOfString(res);
+}
+
+vector<string> MEDPARTITIONER::vectorizeFromMapOfStringInt(const map<string,int>& mymap)
+//elements first and second of map give one elements in result vector of string
+//converting formatted the int second as firsts characters ending at first slash
+{
+  vector<string> res;
+  for (map<string,int>::const_iterator i=mymap.begin(); i!=mymap.end(); ++i)
+  {
+    ostringstream oss;
+    oss<<(*i).second<<"/"<<(*i).first;
+    res.push_back(oss.str());
+  }
+  return res;
+}
+
+map<string,int> MEDPARTITIONER::devectorizeToMapOfStringInt(const vector<string>& vec)
+//if existing identicals (first,second) in vector no problem, else Exception
+{
+  map<string,int> res;
+  for (vector<string>::const_iterator i=vec.begin(); i!=vec.end(); ++i)
+  {
+    size_t pos=0;
+    size_t posmax=(*i).size();
+    size_t found=(*i).find('/'); //first slash
+    if ((found==string::npos) || (found<1))
+      throw INTERP_KERNEL::Exception(LOCALIZED("Error aIntNumber/anyString is expected"));
+    int second;
+    istringstream iss((*i).substr(pos,found));
+    iss>>second;
+    string first=(*i).substr(pos+found+1,posmax-found);
+    map<string,int>::iterator it=res.find(first);
+    if (it!=res.end())
+      if ((*it).second!=second)
+        throw INTERP_KERNEL::Exception(LOCALIZED("Error not the same map value"));
+    res[first]=second;
+  }
+  return res;
+}
+
+vector<string> MEDPARTITIONER::vectorizeFromMapOfStringVectorOfString(const map< string,vector<string> >& mymap)
+//elements first and second of map give one elements in result vector of string
+//adding key map and length of second vector as first string in each serialized vector
+//one serialized vector per key map
+{
+  vector<string> res;
+  for (map< string,vector<string> >::const_iterator i=mymap.begin(); i!=mymap.end(); ++i)
+  {
+    vector<string> vs=(*i).second;  //a vector of string;
+    ostringstream oss;
+    oss<<"Keymap/"<<(*i).first<<"/"<<(*i).second.size();
+    vs.insert(vs.begin(), oss.str());
+    res.push_back(serializeFromVectorOfString(vs));
+  }
+  return res;
+}
+
+map< string,vector<string> > MEDPARTITIONER::devectorizeToMapOfStringVectorOfString(const vector<string>& vec)
+//if existing identicals keymap in vector no problem
+//duplicates in second vector
+{
+  map< string,vector<string> > res;
+  for (vector<string>::const_iterator i=vec.begin(); i!=vec.end(); ++i)
+  {
+    vector<string> vs=deserializeToVectorOfString(*i);
+    
+    string enTete=vs[0];
+    size_t posmax=enTete.size();
+    size_t foundKey=enTete.find("Keymap/");
+    size_t foundSizeVector=enTete.find_last_of('/');
+    if ((foundKey==string::npos) || (foundKey!=0) || ((foundKey+7)>=foundSizeVector))
+      throw INTERP_KERNEL::Exception(LOCALIZED("Error Keymap/anyString/aIntNumber is expected"));
+    int sizeVector;
+    istringstream iss(enTete.substr(foundSizeVector+1,posmax-foundSizeVector));
+    iss>>sizeVector;
+    string keymap=enTete.substr(foundKey+7,foundSizeVector-foundKey-7);
+    //cout<<keymap<<" : sizeVector="<<enTete.substr(foundSizeVector+1,posmax-foundSizeVector)<<endl;
+    for (int i=1; i<=sizeVector; i++)
+      res[keymap].push_back(vs[i]); //add unconditionnaly,so merge duplicates in second vector
+  }
+  return res;
+}
+
+vector<string> MEDPARTITIONER::selectTagsInVectorOfString(const vector<string>& vec, string tag)
+{
+  vector<string> res;
+  if (vec.size()==0) return res;
+  //shit for unique and unique_copy for the duplicate CONSECUTIVE elements
+  //I do not want to sort
+  for (vector<string>::const_iterator i=vec.begin(); i!=vec.end(); ++i)
+  {
+    if ((*i).find(tag)!=string::npos) res.push_back(*i);
+  }
+  return res;
+}
+
+vector<string> MEDPARTITIONER::deleteDuplicatesInVectorOfString(const vector<string>& vec)
+{
+  vector<string> res;
+  if (vec.size()==0) return res;
+  //shit for unique and unique_copy for the duplicate CONSECUTIVE elements
+  //I do not want to sort
+  for (vector<string>::const_iterator i=vec.begin(); i!=vec.end(); ++i)
+  {
+    bool found=false;
+    for (vector<string>::const_iterator j=res.begin(); j!=res.end(); ++j)
+    {
+      if ((*i).compare(*j)==0)
+      {
+        found=true;
+        break;
+      }
+    }
+    if (!found) res.push_back(*i);
+  }
+  return res;
+}
+
+map< string,vector<string> > MEDPARTITIONER::deleteDuplicatesInMapOfStringVectorOfString(const map< string,vector<string> >& mymap)
+{
+  map< string,vector<string> > res;
+  for (map< string,vector<string> >::const_iterator i=mymap.begin(); i!=mymap.end(); ++i)
+    res[(*i).first]=deleteDuplicatesInVectorOfString((*i).second);
+  return res;
+}
+
+void MEDPARTITIONER::sendVectorOfString(const vector<string>& vec, const int target)
+//non conseille, interblocages, utiliser sendAndReceive
+{
+  throw INTERP_KERNEL::Exception(LOCALIZED("use sendAndReceiveVectorOfString please."));
+  string str=serializeFromVectorOfString(vec);
+  int tag=111000;
+  int size=str.length();
+  MPI_Send( &size, 1, MPI_INT, target, tag, MPI_COMM_WORLD );
+  MPI_Send( (void*)str.data(), str.length(), MPI_CHAR, target, tag+100, MPI_COMM_WORLD );
+  cout<<"proc "<<MyGlobals::_rank<<" : send to "<<target<<" '"<<str<<"'"<<endl;
+}
+
+vector<string> MEDPARTITIONER::recvVectorOfString(const int source)
+//non conseille, interblocages, utiliser sendAndReceive
+{
+  throw INTERP_KERNEL::Exception(LOCALIZED("use sendAndReceiveVectorOfString please."));
+  int recSize=0;
+  int tag=111000;
+  MPI_Status status;
+  MPI_Recv(&recSize, 1, MPI_INT, source, tag, MPI_COMM_WORLD, &status);
+  string recData(recSize,'x');
+  MPI_Recv((void*)recData.data(), recSize, MPI_CHAR, 1, tag+100, MPI_COMM_WORLD, &status);
+  //cout<<"proc "<<MyGlobals::_rank<<" : receive from "<<source<<" '"<<recData<<"'"<<endl;
+  return deserializeToVectorOfString(recData);
+}
+
+vector<string> MEDPARTITIONER::sendAndReceiveVectorOfString(const vector<string>& vec, const int source, const int target)
+//not optimized but suffisant
+//return empty vector if i am not target
+{
+  int rank=MyGlobals::_rank;
+  
+  /*for test
+  ostringstream oss;
+  oss<<"sendAndReceive from "<<setw(3)<<source<<" to "<<setw(3)<<target<<"-";
+  string str(oss.str());*/
+
+  MPI_Status status;
+  int tag = 111001;
+  if (rank == source)
+  {
+    string str=serializeFromVectorOfString(vec);
+    int size=str.length();
+    MPI_Send( &size, 1, MPI_INT, target, tag, MPI_COMM_WORLD );
+    //cout<<"proc "<<source<<" : send "<<size<<endl;
+    MPI_Send( (void*)str.data(), str.length(), MPI_CHAR, target, tag+100, MPI_COMM_WORLD );
+    //cout<<"proc "<<source<<" : send    '"<<str<<"'"<<endl;
+  }
+  
+  int recSize=0;
+  if (rank == target)
+  {
+    MPI_Recv(&recSize, 1, MPI_INT, source, tag, MPI_COMM_WORLD, &status);
+    //cout<<"proc "<<target<<" : receive "<<recSize<<endl;
+    string recData(recSize,'x');
+    MPI_Recv((void*)recData.data(), recSize, MPI_CHAR, source, tag+100, MPI_COMM_WORLD, &status);
+    //cout<<"proc "<<target<<" : receive '"<<recData<<"'"<<endl;
+    return deserializeToVectorOfString(recData); //not empty one for target proc
+  }
+  vector<string> res;
+  return res; //empty one for other proc
+}
+
+vector<string> MEDPARTITIONER::allgathervVectorOfString(const vector<std::string>& vec)
+//strings NO need all same size!!!!
+{
+  int world_size=MyGlobals::_world_size;
+  string str=serializeFromVectorOfString(vec);
+  
+  /*for test
+  int rank=MyGlobals::_rank;
+  ostringstream oss;
+  oss<<"allgatherv from "<<setw(3)<<rank<<" to all"<<"-";
+  string str(oss.str());*/
+  
+  vector<int> indexes(world_size);
+  int size=str.length();
+  MPI_Allgather(&size, 1, MPI_INT, 
+                &indexes[0], 1, MPI_INT, MPI_COMM_WORLD);
+  
+  /*{
+    ostringstream oss;
+    for (int i=0; i<world_size; i++) oss<<" "<<indexes[i];
+    cout<<"proc "<<rank<<" : receive '"<<oss.str()<<"'"<<endl;
+  }*/
+  
+  //calcul of displacement
+  vector< int > disp(1,0);
+  for (int i=0; i<world_size; i++) disp.push_back( disp.back() + indexes[i] );
+  
+  string recData(disp.back(),'x');
+  MPI_Allgatherv((void*)str.data(), str.length(), MPI_CHAR,
+                 (void*)recData.data(), &indexes[0], &disp[0], MPI_CHAR,
+                 MPI_COMM_WORLD);
+  
+  //really extraordinary verbose for debug
+  vector<string> deserial=deserializeToVectorOfString(recData);
+  if (MyGlobals::_verbose>1000) 
+  {
+    cout<<"proc "<<MyGlobals::_rank<<" : receive '"<<recData<<"'"<<endl;
+    cout<<"deserialize is : a vector of size "<<deserial.size()<<endl;
+    cout<<reprVectorOfString(deserial)<<endl;
+  }
+  return deserial;
+}
+
+//void MEDPARTITIONER::sendrecvVectorOfString(const vector<string>& vec, const int source, const int target)
+//TODO
+
+string MEDPARTITIONER::cle1ToStr(string s, int inew)
+{
+  ostringstream oss;
+  oss<<s<<" "<<inew;
+  return oss.str();
+}
+
+void MEDPARTITIONER::cle1ToData(string cle, string& s, int& inew)
+{
+  size_t posmax=cle.size();
+  size_t found=cle.find(' ');
+  if ((found==string::npos) || (found<1))
+      throw INTERP_KERNEL::Exception(LOCALIZED("Error 'aStringWithoutWhitespace aInt' is expected"));
+  s=cle.substr(0,found);
+  istringstream iss(cle.substr(found,posmax-found));
+  iss>>inew;
+}
+
+string MEDPARTITIONER::cle2ToStr(string s, int inew, int iold)
+{
+  ostringstream oss;
+  oss<<s<<" "<<inew<<" "<<iold;
+  return oss.str();
+}
+
+void MEDPARTITIONER::cle2ToData(string cle, string& s, int& inew, int& iold)
+{
+  size_t posmax=cle.size();
+  size_t found=cle.find(' ');
+  if ((found==string::npos) || (found<1))
+      throw INTERP_KERNEL::Exception(LOCALIZED("Error 'aStringWithoutWhitespace aInt aInt' is expected"));
+  s=cle.substr(0,found);
+  istringstream iss(cle.substr(found,posmax-found));
+  iss>>inew>>iold;
+}
+
+string MEDPARTITIONER::extractFromDescription(string description,string tag)
+{
+  size_t found=description.find(tag);
+  if ((found==string::npos) || (found<1))
+  {
+    cerr<<"ERROR : not found '"<<tag<<"' in '"<<description<<"'\n";
+    throw INTERP_KERNEL::Exception(LOCALIZED("Error"));
+  }
+  size_t beg=found;
+  size_t end=beg;
+  if (description[found-1]!='/')
+  {
+    //find without '/'... and pray looking for first whitespace
+    //something like 'idomain=0 fileName=tmp.med meshName=...'
+    end=description.size();
+    beg+=tag.length();
+    string res=description.substr(beg,end-beg);
+    found=res.find(' ');
+    if (found==string::npos) found=res.length();
+    res=res.substr(0,found);
+    //cout<<"find without '/' !"<<tag<<"!"<<res<<"!"<<endl;
+    return res;
+  }
+  size_t lg=strToInt(description.substr(found-6,found));
+  beg+=tag.length();
+  //cout<<"find with '/' !"<<tag<<"!"<<description.substr(beg,lg-tag.length())<<"!"<<lg<<endl;
+  return description.substr(beg,lg-tag.length());
+}
+
+void MEDPARTITIONER::fieldDescriptionToData(string description, 
+    int& idomain, string& fileName, string& meshName, string& fieldName, int& typeField, int& DT, int& IT)
+{
+  idomain=strToInt(extractFromDescription(description,"idomain="));
+  fileName=extractFromDescription(description,"fileName=");
+  meshName=extractFromDescription(description,"meshName=");
+  fieldName=extractFromDescription(description,"fieldName=");
+  typeField=strToInt(extractFromDescription(description,"typeField="));
+  DT=strToInt(extractFromDescription(description,"DT="));
+  IT=strToInt(extractFromDescription(description,"IT="));
+  cout<<"idomain="<<idomain<<" fileName="<<fileName<<" meshName="<<meshName<<" fieldName="<<fieldName<<endl;
+}
+
+void MEDPARTITIONER::fieldShortDescriptionToData(string description, 
+    string& fieldName, int& typeField, int& entity, int& DT, int& IT)
+{
+  //*meshName=extractFromDescription(description,"meshName=");
+  fieldName=extractFromDescription(description,"fieldName=");
+  typeField=strToInt(extractFromDescription(description,"typeField="));
+  entity=strToInt(extractFromDescription(description,"entity="));
+  DT=strToInt(extractFromDescription(description,"DT="));
+  IT=strToInt(extractFromDescription(description,"IT="));
+  //cout<<" meshName="<<*meshName<<" fieldName="<<*fieldName<<endl;
+}
+
+ParaMEDMEM::DataArrayInt* MEDPARTITIONER::createDataArrayIntFromVector(vector<int>& v)
+{
+  ParaMEDMEM::DataArrayInt* p=DataArrayInt::New();
+  p->alloc(v.size(),1);
+  std::copy(v.begin(),v.end(),p->getPointer());
+  return p;
+}
+
+ParaMEDMEM::DataArrayInt* MEDPARTITIONER::createDataArrayIntFromVector(vector<int>& v, int nbComponents)
+{
+  ParaMEDMEM::DataArrayInt* p=DataArrayInt::New();
+  if (v.size()%nbComponents!=0)
+    throw INTERP_KERNEL::Exception(LOCALIZED("Problem size modulo nbComponents != 0"));
+  p->alloc(v.size()/nbComponents,nbComponents);
+  std::copy(v.begin(),v.end(),p->getPointer());
+  return p;
+}
+
+ParaMEDMEM::DataArrayDouble* MEDPARTITIONER::createDataArrayDoubleFromVector(vector<double>& v)
+{
+  ParaMEDMEM::DataArrayDouble* p=DataArrayDouble::New();
+  p->alloc(v.size(),1);
+  std::copy(v.begin(),v.end(),p->getPointer());
+  return p;
+}
+
+vector<string> MEDPARTITIONER::browseFieldDouble(const MEDCouplingFieldDouble* fd)
+//quick almost human readable information on a field double
+/* example done by fd->simpleRepr() :
+FieldDouble with name : "VectorFieldOnCells"
+Description of field is : ""
+FieldDouble space discretization is : P0
+FieldDouble time discretization is : One time label. Time is defined by iteration=0 order=1 and time=2.
+Time unit is : ""
+FieldDouble nature of field is : NoNature
+FieldDouble default array has 3 components and 30000 tuples.
+FieldDouble default array has following info on components : "vx" "vy" "vz"
+Mesh support information :
+__________________________
+Unstructured mesh with name : "testMesh"
+Description of mesh : ""
+Time attached to the mesh [unit] : 0 []
+Iteration : -1 Order : -1
+Mesh dimension : 3
+Space dimension : 3
+Info attached on space dimension : "" "" ""
+Number of nodes : 33201
+Number of cells : 30000
+Cell types present : NORM_HEXA8
+*/
+{
+  vector<string> res;
+  //res.push_back("fieldName="); res.back()+=fd->getName();
+  //not saved in file? res.push_back("fieldDescription="); res.back()+=fd->getDescription();
+  //ret << "FieldDouble space discretization is : " << _type->getStringRepr() << "\n";
+  //ret << "FieldDouble time discretization is : " << _time_discr->getStringRepr() << "\n";
+  //ret << "FieldDouble nature of field is : " << MEDCouplingNatureOfField::getRepr(_nature) << "\n";
+  if (fd->getArray())
+  {
+    int nb=fd->getArray()->getNumberOfComponents();
+    res.push_back("nbComponents="); res.back()+=intToStr(nb);
+    //ret << "FieldDouble default array has " << nbOfCompo << " components and " << getArray()->getNumberOfTuples() << " tuples.\n";
+    //ret << "FieldDouble default array has following info on components : ";
+    for (int i=0; i<nb; i++)
+    {
+      //ret << "\"" << getArray()->getInfoOnComponent(i) << "\" ";
+      res.push_back("componentInfo");
+      res.back()+=intToStr(i)+"="+fd->getArray()->getInfoOnComponent(i);
+    }
+  }
+  else
+  {
+    res.push_back("nbComponents=0");  //unknown
+  }
+  return res;
+}
+
+vector<string> MEDPARTITIONER::browseAllFields(const string& myfile)
+//quick almost human readable information on all fields in a .med file
+{
+  vector<string> res;
+  vector<string> meshNames=MEDLoader::GetMeshNames(myfile.c_str());
+  
+  for (int i=0; i<meshNames.size(); i++)
+  {
+    vector<string> fieldNames=
+      MEDLoader::GetAllFieldNamesOnMesh(myfile.c_str(),meshNames[i].c_str());
+    for (int j = 0; j < fieldNames.size(); j++)
+    {
+      vector< ParaMEDMEM::TypeOfField > typeFields=
+        MEDLoader::GetTypesOfField(myfile.c_str(), meshNames[i].c_str(), fieldNames[j].c_str());
+      for (int k = 0; k < typeFields.size(); k++)
+      {
+        vector< pair< int, int > > its=
+          MEDLoader::GetFieldIterations(typeFields[k], myfile.c_str(), meshNames[i].c_str(), fieldNames[j].c_str());
+        if (MyGlobals::_is0verbose>100) cout<<"fieldName "<<fieldNames[j].c_str()<<" typeField "<<typeFields[k]<<" its.size() "<<its.size()<<endl;
+        for (int m = 0; m < its.size(); m++)
+        {
+          vector<string> resi;
+          resi.push_back("fileName="); resi.back()+=myfile;
+          resi.push_back("meshName="); resi.back()+=meshNames[i];
+          resi.push_back("fieldName="); resi.back()+=fieldNames[j];
+          resi.push_back("typeField="); resi.back()+=intToStr((int)typeFields[k]);
+          resi.push_back("DT="); resi.back()+=intToStr((int)its[m].first);
+          resi.push_back("IT="); resi.back()+=intToStr((int)its[m].second);
+          res.push_back(serializeFromVectorOfString(resi));
+        }
+      }
+    }
+  }
+  return res;
+}
+
+/*
+vector<string> MEDPARTITIONER::browseAllFieldsOnMesh(const string& myfile, const string& mymesh, int idomain)
+//quick almost human readable information on all fields on a mesh in a .med file using MEDFILEBROWSER
+{
+  vector<string> res;
+  vector<string> meshNames;
+  meshNames.push_back(mymesh);
+  MEDMEM::MEDFILEBROWSER myMed(myfile);
+  for (int i=0; i<meshNames.size(); i++)
+  {
+    
+  }
+  return res;
+}*/
+
+vector<string> MEDPARTITIONER::GetInfosOfField(const char *fileName, const char *meshName, int idomain)
+{
+const int lggeom=10;
+const med_geometry_type GEOMTYPE[lggeom]={ //MED_N_CELL_FIXED_GEO] = { 
+  //MED_POINT1,
+  //MED_SEG2,
+  //MED_SEG3,
+  //MED_SEG4,
+  //MED_TRIA3,
+  //MED_QUAD4,
+  //MED_TRIA6,
+  //MED_TRIA7,
+  //MED_QUAD8,
+  //MED_QUAD9,
+  MED_TETRA4,
+  MED_PYRA5,
+  MED_PENTA6,
+  MED_HEXA8,
+  MED_OCTA12,
+  MED_TETRA10,
+  MED_PYRA13,
+  MED_PENTA15,
+  MED_HEXA20,
+  MED_HEXA27,
+  //MED_POLYGON,
+  //MED_POLYHEDRON 
+};
+
+const char * const GEOMTYPENAME[lggeom]={
+  //"MED_POINT1",
+  //"MED_SEG2",
+  //"MED_SEG3",
+  //"MED_SEG4",
+  //"MED_TRIA3",
+  //"MED_QUAD4",
+  //"MED_TRIA6",
+  //"MED_TRIA7",
+  //"MED_QUAD8",
+  //"MED_QUAD9",
+  "MED_TETRA4",
+  "MED_PYRA5",
+  "MED_PENTA6",
+  "MED_HEXA8",
+  "MED_OCTA12",
+  "MED_TETRA10",
+  "MED_PYRA13",
+  "MED_PENTA15",
+  "MED_HEXA20",
+  "MED_HEXA27",
+  //"MED_POLYGONE",
+  //"MED_POLYEDRE",
+};
+
+
+const int lgentity=3;
+const med_entity_type ENTITYTYPE[lgentity]={ //MED_N_ENTITY_TYPES+2]={
+  //MED_UNDEF_ENTITY_TYPE,
+  MED_CELL,
+  //MED_DESCENDING_FACE,
+  //MED_DESCENDING_EDGE,
+  MED_NODE,
+  MED_NODE_ELEMENT,
+  //MED_STRUCT_ELEMENT,
+  //MED_UNDEF_ENTITY_TYPE
+};
+
+const char * const ENTITYTYPENAME[lgentity]={ //MED_N_ENTITY_TYPES+2]={
+  //"MED_UNDEF_ENTITY_TYPE",
+  "MED_CELL",
+  //"MED_FACE",
+  //"MED_ARETE",
+  "MED_NODE",
+  "MED_NODE_ELEMENT",
+  //"MED_STRUCT_ELEMENT",
+  //"MED_UNDEF_ENTITY_TYPE"
+};
+  
+  vector<string> res;
+  med_idt fid=MEDfileOpen(fileName,MED_ACC_RDONLY);
+  med_int nbFields=MEDnField(fid);
+  if (MyGlobals::_verbose>20) cout<<"on filename "<<fileName<<" nbOfField "<<nbFields<<endl;
+  //
+  med_field_type typcha;
+  med_int numdt=0,numo=0;
+  med_float dt=0.0;
+  char *maa_ass=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
+  char *nomcha=MEDLoaderBase::buildEmptyString(MED_NAME_SIZE);
+  med_bool localmesh;
+  //
+  for(int i=1; i<=nbFields; i++)
+  {
+    med_int ncomp=MEDfieldnComponent(fid,i);
+    INTERP_KERNEL::AutoPtr<char> comp=new char[ncomp*MED_SNAME_SIZE+1];
+    INTERP_KERNEL::AutoPtr<char> unit=new char[ncomp*MED_SNAME_SIZE+1];
+    INTERP_KERNEL::AutoPtr<char> dt_unit=new char[MED_LNAME_SIZE+1];
+    med_int nbPdt;
+    MEDfieldInfo(fid,i,nomcha,maa_ass,&localmesh,&typcha,comp,unit,dt_unit,&nbPdt);
+    std::string curFieldName=MEDLoaderBase::buildStringFromFortran(nomcha,MED_NAME_SIZE+1);
+    std::string curMeshName=MEDLoaderBase::buildStringFromFortran(maa_ass,MED_NAME_SIZE+1);
+    for (int k=1; k<=nbPdt; k++)
+    {
+      MEDfieldComputingStepInfo(fid,nomcha,k,&numdt,&numo,&dt);
+      if (MyGlobals::_verbose>20) 
+        cout<<"on filename "<<fileName<<" field "<<i<<" fieldName "<<curFieldName<<" meshName "<<curMeshName<<
+                  " typ "<<typcha<<" nbComponent "<<ncomp<<" nbPdt "<<nbPdt<<" noPdt "<<k<<
+                  " ndt "<<numdt<<" nor "<<numo<<" dt "<<dt<<endl;
+      for (int ie=0; ie<lgentity; ie++)
+      {
+        for (int j=0; j<lggeom; j++)
+        {
+          int profilesize=0,nbi=0;
+          med_entity_type enttype=ENTITYTYPE[ie];
+          //enttype=MED_NODE;enttype=MED_CELL;enttype=MED_NODE_ELEMENT;
+          char pflname[MED_NAME_SIZE+1]="";
+          char locname[MED_NAME_SIZE+1]="";
+          med_int nbofprofile=MEDfieldnProfile(fid,nomcha,numdt,numo,enttype,GEOMTYPE[j],pflname,locname);
+
+/*
+med_proto.h firefox file:///export/home/.../med-3.0.3/doc/html.dox/index.html
+MEDfieldnValueWithProfileByName(const med_idt fid, const char * const fieldname,const med_int numdt,const med_int numit,
+  const med_entity_type entitype, const med_geometry_type geotype, const char * const profilename,
+  const med_storage_mode storagemode,med_int * const profilesize,
+  char * const localizationname, med_int * const nbofintegrationpoint);
+
+MEDfieldnValueWithProfile(const med_idt fid, const char * const fieldname,const med_int numdt,const med_int numit,
+  const med_entity_type entitype, const med_geometry_type geotype,
+  const int profileit,
+  const med_storage_mode storagemode,char * const profilename ,med_int * const profilesize,
+  char * const localizationname, med_int * const nbofintegrationpoint);
+*/
+          int profileit=1;
+          if (enttype==MED_NODE)
+          {
+            med_geometry_type mygeomtype=MED_UNDEF_ENTITY_TYPE;
+            med_int nbOfVal=MEDfieldnValueWithProfile(fid,nomcha,numdt,numo,enttype,mygeomtype,profileit,
+                                                      MED_COMPACT_PFLMODE,pflname,&profilesize,locname,&nbi);
+            if (nbOfVal>0)
+            {
+              if (MyGlobals::_verbose>20)
+                cout<<"on filename "<<fileName<<" entity "<<enttype<<" nbOfVal with "<<
+                      nbofprofile<<" profile(s) for geomType (AUCUN) nbOfVal "<<
+                      nbOfVal<<" profilName '"<<pflname<<"' profileSize "<<profilesize<<" nbPtGauss "<<nbi<<endl;
+              vector<string> resi;
+              resi.push_back("idomain="); resi.back()+=intToStr(idomain);
+              resi.push_back("fileName="); resi.back()+=fileName;
+              resi.push_back("meshName="); resi.back()+=curMeshName;
+              resi.push_back("fieldName="); resi.back()+=curFieldName;
+              resi.push_back("typeField="); resi.back()+=intToStr((int)ON_NODES);
+              resi.push_back("typeData="); resi.back()+=intToStr((int)typcha);  //6 for double?
+              resi.push_back("nbComponent="); resi.back()+=intToStr((int)ncomp);
+              resi.push_back("DT="); resi.back()+=intToStr((int)numdt);
+              resi.push_back("IT="); resi.back()+=intToStr((int)numo);
+              resi.push_back("time="); resi.back()+=doubleToStr(dt);
+              resi.push_back("entity="); resi.back()+=intToStr((int)enttype);
+              resi.push_back("entityName="); resi.back()+=ENTITYTYPENAME[ie];
+              resi.push_back("nbOfVal="); resi.back()+=intToStr((int)nbOfVal);
+              resi.push_back("profilName="); resi.back()+=pflname;
+              resi.push_back("profileSize="); resi.back()+=intToStr((int)profilesize);
+              resi.push_back("nbPtGauss="); resi.back()+=intToStr((int)nbi);
+              res.push_back(serializeFromVectorOfString(resi));
+            }
+            break; //on nodes no need to scute all geomtype
+          }
+          else
+          {
+            med_geometry_type mygeomtype=GEOMTYPE[j];
+            med_int nbOfVal=MEDfieldnValueWithProfile(fid,nomcha,numdt,numo,enttype,mygeomtype,profileit,
+                                                      MED_COMPACT_PFLMODE,pflname,&profilesize,locname,&nbi);
+            if (nbOfVal>0)
+            {
+              if (MyGlobals::_verbose>20)
+                cout<<"on filename "<<fileName<<" entity "<<enttype<<" nbOfVal with "<<
+                      nbofprofile<<" profile(s) for geomType "<<
+                      GEOMTYPE[j]<<" "<<GEOMTYPENAME[j]<<" nbOfVal "<<
+                      nbOfVal<<" profilName '"<<pflname<<"' profileSize "<<profilesize<<" nbPtGauss "<<nbi<<endl;
+              int typeField=-1; //unknown
+              if (enttype==MED_CELL) typeField=ON_CELLS;
+              if (enttype==MED_NODE_ELEMENT) typeField=ON_GAUSS_NE;
+              //if (enttype==??) typeField=ON_GAUSS_PT;
+              vector<string> resi;
+              resi.push_back("idomain="); resi.back()+=intToStr(idomain);
+              resi.push_back("fileName="); resi.back()+=fileName;
+              resi.push_back("meshName="); resi.back()+=curMeshName;
+              resi.push_back("fieldName="); resi.back()+=curFieldName;
+              resi.push_back("typeField="); resi.back()+=intToStr((int)typeField);
+              resi.push_back("typeData="); resi.back()+=intToStr((int)typcha);  //6 for double?
+              resi.push_back("nbComponent="); resi.back()+=intToStr((int)ncomp);
+              resi.push_back("DT="); resi.back()+=intToStr((int)numdt);
+              resi.push_back("IT="); resi.back()+=intToStr((int)numo);
+              resi.push_back("time="); resi.back()+=doubleToStr(dt);
+              resi.push_back("entity="); resi.back()+=intToStr((int)enttype);
+              resi.push_back("entityName="); resi.back()+=ENTITYTYPENAME[ie];
+              resi.push_back("geomType="); resi.back()+=intToStr((int)GEOMTYPE[j]);
+              resi.push_back("geomTypeName="); resi.back()+=GEOMTYPENAME[j];
+              resi.push_back("nbOfVal="); resi.back()+=intToStr((int)nbOfVal);
+              resi.push_back("profilName="); resi.back()+=pflname;
+              resi.push_back("profileSize="); resi.back()+=intToStr((int)profilesize);
+              resi.push_back("nbPtGauss="); resi.back()+=intToStr((int)nbi);
+              if (typeField==-1)
+              {
+                cout<<"WARNING : unknown typeField for entity type "<<enttype<<endl<<
+                      serializeFromVectorOfString(resi)<<endl;
+                continue;  //do not register push_back
+              }
+              res.push_back(serializeFromVectorOfString(resi));
+            }
+          }
+        }
+      }
+    }
+  }
+  delete [] maa_ass;
+  delete [] nomcha;
+  MEDfileClose(fid);
+  if (MyGlobals::_verbose>10) cout<<"detected fields:\n"<<reprVectorOfString(res)<<endl;
+  return res;
+}
+
+vector<string> MEDPARTITIONER::browseAllFieldsOnMesh(const string& myfile, const string& mymesh, int idomain)
+//quick almost human readable information on all fields on a mesh in a .med file
+{
+  vector<string> res=GetInfosOfField(myfile.c_str(),mymesh.c_str(),idomain);
+  return res;
+  
+  /*obsolete do no work on GetTypesOfField ON_GAUSS_NE
+  vector<string> res;
+  vector<string> meshNames;
+  meshNames.push_back(mymesh);
+  
+  for (int i=0; i<meshNames.size(); i++)
+  {
+    vector<string> fieldNames=
+      MEDLoader::GetAllFieldNamesOnMesh(myfile.c_str(),meshNames[i].c_str());
+    for (int j=0; j<fieldNames.size(); j++)
+    {
+      vector< ParaMEDMEM::TypeOfField > typeFields=
+        MEDLoader::GetTypesOfField(myfile.c_str(), meshNames[i].c_str(), fieldNames[j].c_str());
+      //if (MyGlobals::_is0verbose>100) cout<<"fieldName "<<fieldNames[j].c_str()<<"typeField.size "<<typeFields.size()<<endl;
+      if (typeFields.size()==0) {
+        cerr<<"problem : fieldNames "<<fieldNames[j]<<" without GetTypesOfField ! Type of field specified not managed"<<endl;
+        //typeFields.push_back(ON_GAUSS_NE);
+      }
+      for (int k=0; k<typeFields.size(); k++)
+      {
+        vector< pair< int, int > > its;
+        its=MEDLoader::GetFieldIterations(typeFields[k], myfile.c_str(), meshNames[i].c_str(), fieldNames[j].c_str());
+        //if (typeFields[k]==ON_GAUSS_NE) its.push_back(make_pair(5,6));
+        if (MyGlobals::_is0verbose>100) cout<<"fieldName "<<fieldNames[j].c_str()<<" typeField "<<typeFields[k]<<" its.size() "<<its.size()<<endl;
+        for (int m = 0; m < its.size(); m++)
+        {
+          vector<string> resi;
+          resi.push_back("idomain="); resi.back()+=intToStr(idomain);
+          resi.push_back("fileName="); resi.back()+=myfile;
+          resi.push_back("meshName="); resi.back()+=meshNames[i];
+          resi.push_back("fieldName="); resi.back()+=fieldNames[j];
+          resi.push_back("typeField="); resi.back()+=intToStr((int)typeFields[k]);
+          resi.push_back("DT="); resi.back()+=intToStr((int)its[m].first);
+          resi.push_back("IT="); resi.back()+=intToStr((int)its[m].second);
+          //cout<<"browseAllFieldsOnMesh add "<<resi.size()<<endl;
+          res.push_back(serializeFromVectorOfString(resi));
+        }
+      }
+    }
+  }
+  return res;
+  */
+}
+
+/*!
+Sends content of \a vec to processor \a target. To be used with \a recvDoubleVec method.
+\param vec vector to be sent
+\param target processor id of the target
+*/
+void MEDPARTITIONER::sendDoubleVec(const std::vector<double>& vec, int target)
+{
+  int tag = 111002;
+  int size=vec.size();
+  if (MyGlobals::_verbose>1000) 
+    cout<<"proc "<<MyGlobals::_rank<<" : --> sendDoubleVec "<<size<<endl;
+#ifdef HAVE_MPI2
+  MPI_Send(&size, 1, MPI_INT, target, tag, MPI_COMM_WORLD);
+  MPI_Send(const_cast<double*>(&vec[0]), size, MPI_DOUBLE, target, tag+100, MPI_COMM_WORLD);
+#endif
+}
+
+/*! Receives messages from proc \a source to fill vector<int> vec.
+To be used with \a sendDoubleVec method.
+
+\param vec vector that is filled
+\param source processor id of the incoming messages
+ */
+std::vector<double>* MEDPARTITIONER::recvDoubleVec(int source)
+{
+  int tag = 111002;
+  int size;
+#ifdef HAVE_MPI2
+  MPI_Status status;  
+  MPI_Recv(&size, 1, MPI_INT, source, tag, MPI_COMM_WORLD, &status);
+  if (MyGlobals::_verbose>1000) 
+    cout<<"proc "<<MyGlobals::_rank<<" : <-- recvDoubleVec "<<size<<endl;;
+  std::vector<double>* vec=new std::vector<double>;
+  vec->resize(size);
+  MPI_Recv(&vec[0], size, MPI_DOUBLE, source, tag+100, MPI_COMM_WORLD, &status);
+#endif
+  return vec;
+}
+
+void MEDPARTITIONER::recvDoubleVec(std::vector<double>& vec, int source)
+{
+  int tag = 111002;
+  int size;
+#ifdef HAVE_MPI2
+  MPI_Status status;  
+  MPI_Recv(&size, 1, MPI_INT, source, tag, MPI_COMM_WORLD, &status);
+  if (MyGlobals::_verbose>1000)
+    cout<<"proc "<<MyGlobals::_rank<<" : <-- recvDoubleVec "<<size<<endl;;
+  vec.resize(size);
+  MPI_Recv(&vec[0], size, MPI_DOUBLE, source, tag+100, MPI_COMM_WORLD, &status);
+#endif
+}
+/*!
+Sends content of \a vec to processor \a target. To be used with \a recvIntVec method.
+\param vec vector to be sent
+\param target processor id of the target
+*/
+void MEDPARTITIONER::sendIntVec(const std::vector<int>& vec, int target)
+{
+  int tag = 111003;
+  int size=vec.size();
+  if (MyGlobals::_verbose>1000)
+    cout<<"proc "<<MyGlobals::_rank<<" : --> sendIntVec "<<size<<endl; //cvw 
+#ifdef HAVE_MPI2
+  MPI_Send(&size, 1, MPI_INT, target, tag, MPI_COMM_WORLD);
+  MPI_Send(const_cast<int*>(&vec[0]), size,MPI_INT, target, tag+100, MPI_COMM_WORLD);
+#endif
+}
+
+/*! Receives messages from proc \a source to fill vector<int> vec.
+To be used with \a sendIntVec method.
+\param vec vector that is filled
+\param source processor id of the incoming messages
+ */
+std::vector<int>* MEDPARTITIONER::recvIntVec(int source)
+{
+  int tag = 111003;
+  int size;
+#ifdef HAVE_MPI2
+  MPI_Status status;  
+  MPI_Recv(&size, 1, MPI_INT, source, tag, MPI_COMM_WORLD, &status);
+  if (MyGlobals::_verbose>1000) 
+    cout<<"proc "<<MyGlobals::_rank<<" : <-- recvIntVec "<<size<<endl; //cvw 
+  std::vector<int>* vec=new std::vector<int>;
+  vec->resize(size);
+  MPI_Recv(&vec[0], size, MPI_INT, source, tag+100, MPI_COMM_WORLD, &status);
+#endif
+  return vec;
+}
+
+void MEDPARTITIONER::recvIntVec(std::vector<int>& vec, int source)
+{
+  int tag = 111003;
+  int size;
+#ifdef HAVE_MPI2
+  MPI_Status status;  
+  MPI_Recv(&size, 1, MPI_INT, source, tag, MPI_COMM_WORLD, &status);
+  if (MyGlobals::_verbose>1000)
+    cout<<"proc "<<MyGlobals::_rank<<" : <-- recvIntVec "<<size<<endl; //cvw 
+  vec.resize(size);
+  MPI_Recv(&vec[0], size, MPI_INT, source, tag+100, MPI_COMM_WORLD,&status);
+#endif
+}
+
+/*!
+Sends content of \a dataArrayInt to processor \a target. 
+To be used with \a recvDataArrayInt method.
+\param da dataArray to be sent
+\param target processor id of the target
+*/
+void MEDPARTITIONER::sendDataArrayInt(ParaMEDMEM::DataArrayInt* da, int target)
+{
+  if (da==0) throw INTERP_KERNEL::Exception(LOCALIZED("Problem send DataArrayInt* NULL"));
+  int tag = 111004;
+  int size[3];
+  size[0]=da->getNbOfElems();
+  size[1]=da->getNumberOfTuples();
+  size[2]=da->getNumberOfComponents();
+  if (MyGlobals::_verbose>1000) 
+    cout<<"proc "<<MyGlobals::_rank<<" : --> sendDataArrayInt "<<size[0]<<endl; //cvw 
+#ifdef HAVE_MPI2
+  MPI_Send(&size, 3, MPI_INT, target, tag, MPI_COMM_WORLD);
+  const int * p=da->getPointer();
+  MPI_Send(const_cast<int*>(&p[0]), size[0] ,MPI_INT, target, tag+100, MPI_COMM_WORLD);
+#endif
+}
+
+/*! Receives messages from proc \a source to fill dataArrayInt da.
+To be used with \a sendIntVec method.
+\param da dataArrayInt that is filled
+\param source processor id of the incoming messages
+ */
+ParaMEDMEM::DataArrayInt* MEDPARTITIONER::recvDataArrayInt(int source)
+//std::vector<int>& vec, int source)const
+{
+  int tag = 111004;
+  int size[3];
+#ifdef HAVE_MPI2
+  MPI_Status status;
+  MPI_Recv(size, 3, MPI_INT, source, tag, MPI_COMM_WORLD, &status);
+  if (MyGlobals::_verbose>1000)
+    cout<<"proc "<<MyGlobals::_rank<<" : <-- recvDataArrayInt "<<size[0]<<endl; //cvw 
+  if (size[0]!=(size[1]*size[2]))
+    throw INTERP_KERNEL::Exception(LOCALIZED("Problem in recvDataArrayInt incoherent sizes"));
+  ParaMEDMEM::DataArrayInt* da=ParaMEDMEM::DataArrayInt::New();
+  da->alloc(size[1],size[2]);
+  int * p=da->getPointer();
+  MPI_Recv(const_cast<int*>(&p[0]), size[0], MPI_INT, source, tag+100, MPI_COMM_WORLD, &status);
+#endif
+  return da;
+}
+
+/*!
+Sends content of \a dataArrayInt to processor \a target. 
+To be used with \a recvDataArrayDouble method.
+\param da dataArray to be sent
+\param target processor id of the target
+*/
+void MEDPARTITIONER::sendDataArrayDouble(ParaMEDMEM::DataArrayDouble* da, int target)
+{
+  if (da==0) throw INTERP_KERNEL::Exception(LOCALIZED("Problem send DataArrayDouble* NULL"));
+  int tag = 111005;
+  int size[3];
+  size[0]=da->getNbOfElems();
+  size[1]=da->getNumberOfTuples();
+  size[2]=da->getNumberOfComponents();
+  if (MyGlobals::_verbose>1000) 
+    cout<<"proc "<<MyGlobals::_rank<<" : --> sendDataArrayDouble "<<size[0]<<endl; //cvw 
+#ifdef HAVE_MPI2
+  MPI_Send(&size, 3, MPI_INT, target, tag, MPI_COMM_WORLD);
+  double * p=da->getPointer();
+  MPI_Send(const_cast<double*>(&p[0]), size[0] ,MPI_DOUBLE, target, tag+100, MPI_COMM_WORLD);
+#endif
+}
+
+/*! Receives messages from proc \a source to fill dataArrayDouble da.
+To be used with \a sendDoubleVec method.
+\param da dataArrayDouble that is filled
+\param source processor id of the incoming messages
+ */
+ParaMEDMEM::DataArrayDouble* MEDPARTITIONER::recvDataArrayDouble(int source)
+//std::vector<int>& vec, int source)const
+{
+  int tag = 111005;
+  int size[3];
+#ifdef HAVE_MPI2
+  MPI_Status status;
+  MPI_Recv(size, 3, MPI_INT, source, tag, MPI_COMM_WORLD, &status);
+  if (MyGlobals::_verbose>1000)
+    cout<<"proc "<<MyGlobals::_rank<<" : <-- recvDataArrayDouble "<<size[0]<<endl; //cvw 
+  if (size[0]!=(size[1]*size[2]))
+    throw INTERP_KERNEL::Exception(LOCALIZED("Problem in recvDataArrayDouble incoherent sizes"));
+  ParaMEDMEM::DataArrayDouble* da=ParaMEDMEM::DataArrayDouble::New();
+  da->alloc(size[1],size[2]);
+  double * p=da->getPointer();
+  MPI_Recv(const_cast<double*>(&p[0]), size[0], MPI_DOUBLE, source, tag+100, MPI_COMM_WORLD, &status);
+#endif
+  return da;
+}
+
+ParaMEDMEM::MEDCouplingUMesh* MEDPARTITIONER::createEmptyMEDCouplingUMesh()
+ //create empty MEDCouplingUMesh* dim 3
+{
+  ParaMEDMEM::MEDCouplingUMesh* umesh=ParaMEDMEM::MEDCouplingUMesh::New();
+  umesh->setMeshDimension(3);
+  umesh->allocateCells(0);
+  umesh->finishInsertingCells();
+  ParaMEDMEM::DataArrayDouble *myCoords=ParaMEDMEM::DataArrayDouble::New();
+  myCoords->alloc(0,3);
+  umesh->setCoords(myCoords);
+  umesh->setName("EMPTY");
+  myCoords->decrRef();
+  umesh->checkCoherency();
+  return umesh;
+}
+
+void MEDPARTITIONER::testVectorOfStringMPI()
+{
+  int rank=MyGlobals::_rank;
+  int world_size=MyGlobals::_world_size;
+  vector<string> myVector;
+  ostringstream oss;
+  oss<<"hello from "<<setw(5)<<rank<<" "<<string(rank+1,'n')<<
+       " next is an empty one";
+  myVector.push_back(oss.str());
+  myVector.push_back("");
+  myVector.push_back("next is an singleton");
+  myVector.push_back("1");
+  
+  if (rank==0)
+  {
+    /*
+    string s0=serializeFromVectorOfString(myVector);
+    cout<<"s0 is : a string '"<<s0<<"'"<<endl;
+    vector<string> v0=deserializeToVectorOfString(s0);
+    cout<<"v0 is : a vector of size "<<v0.size()<<endl;
+    cout<<reprVectorOfString(v0)<<endl;
+    */
+    string s0=serializeFromVectorOfString(myVector);
+    vector<string> res=deserializeToVectorOfString(s0);
+    if (res.size()!=myVector.size()) 
+      throw INTERP_KERNEL::Exception(LOCALIZED("Problem in (de)serialise VectorOfString incoherent sizes"));
+    for (int i=0; i<myVector.size(); i++)
+      if (res[i]!=myVector[i])
+        throw INTERP_KERNEL::Exception(LOCALIZED("Problem in (de)serialise VectorOfString incoherent elements"));
+  }
+
+  for (int i=0; i<world_size; i++)
+  {
+    for (int j=0; j<world_size; j++)
+    {
+      vector<string> res=sendAndReceiveVectorOfString(myVector, i, j);
+      if ((rank==j) && MyGlobals::_verbose>20)
+        cout<<"proc "<<rank<<" : receive \n"<<reprVectorOfString(res)<<endl;
+      if (rank==j)
+      {
+        if (res.size()!=myVector.size()) 
+          throw INTERP_KERNEL::Exception(LOCALIZED("Problem in sendAndReceiveVectorOfString incoherent sizes"));
+        for (int i=1; i<myVector.size(); i++) //first is different
+          if (res[i]!=myVector[i])
+            throw INTERP_KERNEL::Exception(LOCALIZED("Problem in sendAndReceiveVectorOfString incoherent elements"));
+      }
+      else 
+      {
+        if (res.size()!=0) 
+        throw INTERP_KERNEL::Exception(LOCALIZED("Problem in sendAndReceiveVectorOfString size have to be 0"));
+      }
+    }
+  }
+  vector<string> res=allgathervVectorOfString(myVector);
+  //sometimes for test
+  res=allgathervVectorOfString(myVector);
+  res=allgathervVectorOfString(myVector);
+  if (rank==0 && MyGlobals::_verbose>20)
+    cout<<"proc "<<rank<<" : receive \n"<<reprVectorOfString(res)<<endl;
+  if (res.size()!=myVector.size()*world_size) 
+    throw INTERP_KERNEL::Exception(LOCALIZED("Problem in allgathervVectorOfString incoherent sizes"));
+  int jj=-1;
+  for (int j=0; j<world_size; j++)
+  {
+    for (int i=0; i<myVector.size(); i++)
+    {
+      jj=jj+1;
+      if (i==0) continue; //first is different
+      if (res[jj]!=myVector[i])
+        throw INTERP_KERNEL::Exception(LOCALIZED("Problem in allgathervVectorOfString incoherent elements"));
+    }
+  }
+  if (MyGlobals::_verbose) cout<<"proc "<<rank<<" : OK testVectorOfStringMPI END"<< endl;
+}
+
+void MEDPARTITIONER::testMapOfStringIntMPI()
+{
+  int rank=MyGlobals::_rank;
+  //int world_size=MyGlobals::_world_size;
+  map<string,int> myMap;
+  myMap["one"]=1;
+  myMap["two"]=22;  //a bug
+  myMap["three"]=3;
+  myMap["two"]=2; //last speaking override
+  
+  if (rank==0)
+  {
+    vector<string> v2=vectorizeFromMapOfStringInt(myMap);
+    /*
+    cout<<"v2 is : a vector of size "<<v2.size()<<endl;
+    cout<<reprVectorOfString(v2)<<endl;
+    */
+    map<string,int> m3=devectorizeToMapOfStringInt(v2);
+    if (reprMapOfStringInt(m3)!=reprMapOfStringInt(myMap))
+      throw INTERP_KERNEL::Exception(LOCALIZED("Problem in (de)vectorize MapOfStringInt"));
+  }
+    
+  vector<string> v2=allgathervVectorOfString(vectorizeFromMapOfStringInt(myMap));
+  if (rank==0 && MyGlobals::_verbose>20)
+  {
+    cout<<"v2 is : a vector of size "<<v2.size()<<endl;
+    cout<<reprVectorOfString(v2)<<endl;
+    map<string,int> m2=devectorizeToMapOfStringInt(v2);
+    cout<<"m2 is : a map of size "<<m2.size()<<endl;
+    cout<<reprMapOfStringInt(m2)<<endl;
+  }
+  if (MyGlobals::_verbose) cout<<"proc "<<rank<<" : OK testMapOfStringIntMPI END"<< endl;
+}
+
+void MEDPARTITIONER::testMapOfStringVectorOfStringMPI()
+{
+  int rank=MyGlobals::_rank;
+  //int world_size=MyGlobals::_world_size;
+  vector<string> myVector;
+  ostringstream oss;
+  oss<<"hello from "<<setw(5)<<MyGlobals::_rank<<" "<<string(rank+1,'n')<<
+       " next is an empty one";
+  myVector.push_back(oss.str());
+  myVector.push_back("");
+  myVector.push_back("next is an singleton");
+  myVector.push_back("1");
+  
+  if (rank==0)
+  {
+    map< string,vector<string> > m2;
+    m2["first key"]=myVector;
+    m2["second key"]=myVector;
+    vector<string> v2=vectorizeFromMapOfStringVectorOfString(m2);
+    map< string,vector<string> > m3=devectorizeToMapOfStringVectorOfString(v2);
+    if (rank==0 && MyGlobals::_verbose>20)
+      cout<<"m2 is : a MapOfStringVectorOfString of size "<<m2.size()<<endl;
+      cout<<reprMapOfStringVectorOfString(m2)<<endl;
+      cout<<"v2 is : a vector of size "<<v2.size()<<endl;
+      cout<<reprVectorOfString(v2)<<endl;
+      cout<<"m3 is : a map of size "<<m3.size()<<endl;
+      cout<<reprMapOfStringVectorOfString(m3)<<endl;
+    if (reprMapOfStringVectorOfString(m3)!=reprMapOfStringVectorOfString(m2))
+      throw INTERP_KERNEL::Exception(LOCALIZED("Problem in (de)vectorize MapOfStringVectorOfString"));
+  }
+    
+  map< string,vector<string> > m4;
+  m4["1rst key"]=myVector;
+  m4["2snd key"]=myVector;
+  vector<string> v4=allgathervVectorOfString(vectorizeFromMapOfStringVectorOfString(m4));
+  if (rank==0 && MyGlobals::_verbose>20)
+  {
+    map< string,vector<string> > m5=devectorizeToMapOfStringVectorOfString(v4);
+    map< string,vector<string> > m6=deleteDuplicatesInMapOfStringVectorOfString(m5);
+    cout<<"m5 is : a map of size "<<m5.size()<<endl;
+    cout<<reprMapOfStringVectorOfString(m5)<<endl;
+    cout<<"m6 is : a map from m5 with deleteDuplicates of size "<<m6.size()<<endl;
+    cout<<reprMapOfStringVectorOfString(m6)<<endl;
+  }
+  if (MyGlobals::_verbose) cout<<"proc "<<rank<<" : OK testMapOfStringVectorOfStringMPI END"<< endl;
+}
+
+void MEDPARTITIONER::testDataArrayMPI()
+{
+  int rank=MyGlobals::_rank;
+  //int
+  {
+    ParaMEDMEM::DataArrayInt* send=ParaMEDMEM::DataArrayInt::New();
+    ParaMEDMEM::DataArrayInt* recv=0;
+    int nbOfTuples=5;
+    int numberOfComponents=3;
+    send->alloc(nbOfTuples,numberOfComponents);
+    vector<int> vals;
+    for (int j=0; j<nbOfTuples; j++)
+      for (int i=0; i<numberOfComponents; i++) vals.push_back((j+1)*10+i+1);
+    std::copy(vals.begin(),vals.end(),send->getPointer());
+    if (rank==0) sendDataArrayInt(send, 1);
+    if (rank==1) recv=recvDataArrayInt(0);
+    if (rank==1 && MyGlobals::_verbose>20)
+    {
+      cout<<send->repr()<<endl;
+      cout<<recv->repr()<<endl;
+    }
+    if (rank==1)
+    {
+      if (send->repr()!=recv->repr())
+        throw INTERP_KERNEL::Exception(LOCALIZED("Problem in send&recv DataArrayInt"));
+    }
+    send->decrRef();
+    if (rank==1) recv->decrRef();
+  }
+  //double
+  {
+    ParaMEDMEM::DataArrayDouble* send=ParaMEDMEM::DataArrayDouble::New();
+    ParaMEDMEM::DataArrayDouble* recv=0;
+    int nbOfTuples=5;
+    int numberOfComponents=3;
+    send->alloc(nbOfTuples,numberOfComponents);
+    vector<double> vals;
+    for (int j=0; j<nbOfTuples; j++)
+      for (int i=0; i<numberOfComponents; i++) vals.push_back(double(j+1)+double(i+1)/10);
+    std::copy(vals.begin(),vals.end(),send->getPointer());
+    if (rank==0) sendDataArrayDouble(send, 1);
+    if (rank==1) recv=recvDataArrayDouble(0);
+    if (rank==1 && MyGlobals::_verbose>20)
+    {
+      cout<<send->repr()<<endl;
+      cout<<recv->repr()<<endl;
+    }
+    if (rank==1)
+    {
+      if (send->repr()!=recv->repr())
+        throw INTERP_KERNEL::Exception(LOCALIZED("Problem in send&recv DataArrayDouble"));
+    }
+    send->decrRef();
+    if (rank==1) recv->decrRef();
+  }
+  
+  if (MyGlobals::_verbose) cout<<"proc "<<rank<<" : OK testDataArrayMPI END"<< endl;
+ }
+
+void MEDPARTITIONER::testPersistantMpi0To1(int taille, int nb)
+{
+  double temps_debut=MPI_Wtime();
+  int rang=MyGlobals::_rank;
+  vector<int> x, y;
+  int tag=111111;
+  MPI_Request requete0, requete1;
+  MPI_Status statut;
+  int ok=0;
+  string res;
+  if (rang==0)
+  {
+    x.resize(taille);
+    MPI_Ssend_init(&x[0], taille, MPI_INT, 1, tag, MPI_COMM_WORLD , &requete0);
+    for(int k=0; k<nb; k++)
+    {
+      for (int i=0; i<taille; ++i) x[i]=k;
+      //Envoi d’un gros message --> cela peut prendre du temps
+      MPI_Start(&requete0);
+      //Traitement sequentiel independant de "x"
+      //...
+      MPI_Wait(&requete0, &statut);
+      //Traitement sequentiel impliquant une modification de "x" en memoire
+      //x=...
+    }
+    MPI_Request_free(&requete0);
+  }
+  else if (rang == 1)
+  {
+    y.resize(taille);
+    MPI_Recv_init(&y[0], taille,  MPI_INT, 0, tag, MPI_COMM_WORLD , &requete1);
+    for(int k=0; k<nb; k++)
+    {
+      //Pre-traitement sequentiel
+      //...
+      for (int i=0; i<taille; ++i) y[i]=-1;
+      //Reception du gros message --> cela peut prendre du temps
+      MPI_Start(&requete1);
+      //Traitement sequentiel independant de "y"
+      //...
+      MPI_Wait(&requete1, &statut);
+      //Traitement sequentiel dependant de "y"
+      //...=f(y)
+      int nb=0;
+      for (int i=0; i<taille; ++i)
+        if (y[i]==k) nb++;
+      if (nb==taille) ok++;
+      if (MyGlobals::_verbose>9)
+      {
+        res="0K"; if (nb!=taille) res="KO";
+        cout<<res<<k<<" ";
+      }
+    }
+    res="0K"; if (ok!=nb) res="MAUVAIS";
+    if (MyGlobals::_verbose>1) 
+      cout<<"resultat "<<res<<" time(sec) "<<MPI_Wtime()-temps_debut<<endl;
+    MPI_Request_free(&requete1);
+  }
+  //temps_fin=(MPI_WTIME()-temps_debut);
+}
+
+void MEDPARTITIONER::testPersistantMpiRing(int taille, int nb)
+{
+  double temps_debut=MPI_Wtime();
+  int befo, next, rang, wsize, tagbefo, tagnext;
+  rang=MyGlobals::_rank;
+  wsize=MyGlobals::_world_size;
+  befo=rang-1; if (befo<0) befo=wsize-1;
+  next=rang+1; if (next>=wsize) next=0;
+  vector<int> x, y;
+  tagbefo=111111+befo;
+  tagnext=111111+rang;
+  MPI_Request requete0, requete1;
+  MPI_Status statut1, statut2;
+  int ok=0;
+  string res;
+  //cout<<"ini|"<<rang<<'|'<<befo<<'|'<<next<<' ';
+  {
+    x.resize(taille);
+    y.resize(taille);
+    MPI_Ssend_init(&x[0], taille, MPI_INT, next, tagnext, MPI_COMM_WORLD , &requete0);
+    MPI_Recv_init(&y[0], taille,  MPI_INT, befo, tagbefo, MPI_COMM_WORLD , &requete1);
+    //cout<<"isr|"<<rang<<'|'<<requete0<<'|'<<requete1<<' ';
+    for(int k=0; k<nb; k++)
+    {
+      for (int i=0; i<taille; ++i) x[i]=k+rang;
+      //Envoi d’un gros message --> cela peut prendre du temps
+      MPI_Start(&requete0);
+      //Reception du gros message --> cela peut prendre du temps
+      for (int i=0; i<taille; ++i) y[i]=-1;
+      MPI_Start(&requete1);
+      //Traitement sequentiel independant de "x"
+      //...
+      //Traitement sequentiel independant de "y"
+      //...
+      //cout<<"dsr|"<<rang<<' ';
+      MPI_Wait(&requete1, &statut1);
+      //Traitement sequentiel dependant de "y"
+      //...=f(y)
+      int nb=0;
+      for (int i=0; i<taille; ++i)
+        if (y[i]==k+befo) nb++;
+      if (nb==taille) ok++;
+      if (MyGlobals::_verbose>9)
+      {
+        res="0K"+intToStr(rang); if (nb!=taille) res="KO"+intToStr(rang);
+        cout<<res<<k<<" ";
+      }
+      MPI_Wait(&requete0, &statut2);
+      //Traitement sequentiel impliquant une modification de "x" en memoire
+      //x=...
+    }
+    res="0K"; if (ok!=nb) res="MAUVAIS";
+    temps_debut=MPI_Wtime()-temps_debut;
+    MPI_Request_free(&requete1);
+    MPI_Request_free(&requete0);
+  }
+  //temps_fin=(MPI_WTIME()-temps_debut);
+  if (MyGlobals::_verbose>1) 
+    cout<<"resultat proc "<<rang<<" "<<res<<" time(sec) "<<temps_debut<<endl;
+}
+void MEDPARTITIONER::testPersistantMpiRingOnCommSplit(int taille, int nb)
+{
+  double temps_debut=MPI_Wtime();
+  int rang=MyGlobals::_rank;
+  MPI_Comm newcomm;
+  int couleur=1;
+  int rangMax=4;
+  if (rang>=rangMax) couleur=MPI_UNDEFINED;
+  cout<<"coul|"<<rang<<'|'<<couleur<<' ';
+  //MPI_Comm_dup (MPI_COMM_WORLD, &newcomm) ;
+  MPI_Comm_split(MPI_COMM_WORLD, couleur, rang, &newcomm);
+  
+  int befo, next, wsize, tagbefo, tagnext;
+  wsize=rangMax;
+  if (wsize>MyGlobals::_world_size) wsize=MyGlobals::_world_size;
+  befo=rang-1; if (befo<0) befo=wsize-1;
+  next=rang+1; if (next>=wsize) next=0;
+  vector<int> x, y;
+  tagbefo=111111+befo;
+  tagnext=111111+rang;
+  MPI_Request requete0, requete1;
+  MPI_Status statut1, statut2;
+  int ok=0;
+  string res;
+  
+  //cout<<"ini|"<<rang<<'|'<<befo<<'|'<<next<<' ';
+  if (couleur==1)
+  {
+    x.resize(taille);
+    y.resize(taille);
+    MPI_Ssend_init(&x[0], taille, MPI_INT, next, tagnext, newcomm , &requete0);
+    MPI_Recv_init(&y[0], taille,  MPI_INT, befo, tagbefo, newcomm , &requete1);
+    //cout<<"isr|"<<rang<<'|'<<requete0<<'|'<<requete1<<' ';
+    for(int k=0; k<nb; k++)
+    {
+      for (int i=0; i<taille; ++i) x[i]=k+rang;
+      //Envoi d’un gros message --> cela peut prendre du temps
+      MPI_Start(&requete0);
+      //Reception du gros message --> cela peut prendre du temps
+      for (int i=0; i<taille; ++i) y[i]=-1;
+      MPI_Start(&requete1);
+      //Traitement sequentiel independant de "x"
+      //...
+      //Traitement sequentiel independant de "y"
+      //...
+      //cout<<"dsr|"<<rang<<' ';
+      MPI_Wait(&requete1, &statut1);
+      //Traitement sequentiel dependant de "y"
+      //...=f(y)
+      int nb=0;
+      for (int i=0; i<taille; ++i)
+        if (y[i]==k+befo) nb++;
+      if (nb==taille) ok++;
+      if (MyGlobals::_verbose>9)
+      {
+        res="0K"+intToStr(rang); if (nb!=taille) res="KO"+intToStr(rang);
+        cout<<res<<k<<" ";
+      }
+      MPI_Wait(&requete0, &statut2);
+      //Traitement sequentiel impliquant une modification de "x" en memoire
+      //x=...
+    }
+    res="0K"; if (ok!=nb) res="MAUVAIS";
+    temps_debut=MPI_Wtime()-temps_debut;
+    MPI_Request_free(&requete1);
+    MPI_Request_free(&requete0);
+  }
+  //MPI_Barrier(MPI_COMM_WORLD);
+  cout<<"barrier|"<<rang<<"|"<<newcomm<<" ";
+  if (couleur==1) MPI_Comm_free(&newcomm);
+  //temps_fin=(MPI_WTIME()-temps_debut);
+  if (MyGlobals::_verbose>1) 
+    cout<<"resultat proc "<<rang<<" "<<res<<" time(sec) "<<temps_debut<<endl;
+}
+
+
index 1bb7d30691870bf6a335c5c68150a2c7e9b24415..4c6fbea02ca1f660e4ec6bff27d6d615f54c7566 100644 (file)
 //
 #ifndef MEDPARTITIONER_UTILS_HXX_
 #define MEDPARTITIONER_UTILS_HXX_
+#include "MEDCouplingUMesh.hxx"
 
 #include <string>
+#include <vector>
+#include <map>
 
-namespace MEDPARTITIONER {
-  std::string trim(std::string& s,const std::string& drop = " ")
-  {
-    std::string r=s.erase(s.find_last_not_of(drop)+1);
-    return r.erase(0,r.find_first_not_of(drop));
-  }
+#ifdef LOCALIZED
+#undef LOCALIZED
+#endif
+
+#if defined(_DEBUG_) || defined(_DEBUG)
+//# define LOCALIZED(message) #message , __FILE__ , __FUNCTION__ , __LINE__
+# define LOCALIZED(message) #message , __FUNCTION__ , __LINE__
+#else
+# define LOCALIZED(message) #message
+#endif
+
+namespace MEDPARTITIONER
+{
+  using namespace std;
+  using namespace ParaMEDMEM;
+  
+  string trim(string& s,const string& drop);
+  string intToStr(int i);
+  string doubleToStr(double i);
+  int strToInt(string s);
+  double strToDouble(string s);
+  bool testArg(const char *arg, const char *argExpected, string& argValue);
+  vector<int> createRandomSize(int size);
+  void randomizeAdj(int* xadj, int* adjncy, vector<int>& ran, vector<int>& vx, vector<int>& va);
+  void testRandomize();
+  
+  string reprVectorOfString(const vector<string>& vec);
+  string reprVectorOfString(const vector<string>& vec, string sep);
+  string reprMapOfStringInt(const map<string,int>& mymap);
+  string reprMapOfStringVectorOfString(const map< string,vector<string> >& mymap);
+  string reprFieldDescriptions(const vector<string>& vec, string sep);
+  
+  string serializeFromString(const string& s);
+  string serializeFromVectorOfString(const vector<string>& vec);
+  vector<string> deserializeToVectorOfString(const string& str);
+  string eraseTagSerialized(string fromStr, string tag);
+  
+  vector<string> vectorizeFromMapOfStringInt(const map<string,int>& mymap);
+  map<string,int> devectorizeToMapOfStringInt(const vector<string>& vec);
+  
+  vector<string> vectorizeFromMapOfStringVectorOfString(const map< string,vector<string> >& mymap);
+  map< string,vector<string> > devectorizeToMapOfStringVectorOfString(const vector<string>& vec);
+  
+  vector<string> selectTagsInVectorOfString(const vector<string>& vec, string tag);
+  vector<string> deleteDuplicatesInVectorOfString(const vector<string>& vec);
+  map< string,vector<string> > deleteDuplicatesInMapOfStringVectorOfString(const map< string,vector<string> >& mymap);
+  
+  string cle1ToStr(string s, int inew);
+  void cle1ToData(string cle, string& s, int& inew);
+  
+  string cle2ToStr(string s, int inew, int iold);
+  void cle2ToData(string cle, string& s, int& inew, int& iold);
+  
+  string extractFromDescription(string description, string tag);
+  void fieldDescriptionToData(string description,
+    int& idomain, string& fileName, string& meshName, string& fieldName,
+    int& typeField, int& DT, int& IT);
+  void fieldShortDescriptionToData(string description,
+    string& fieldName, int& typeField, int& entity, int& DT, int& IT);
+  
+  ParaMEDMEM::DataArrayInt* createDataArrayIntFromVector(vector<int>& v);
+  ParaMEDMEM::DataArrayInt* createDataArrayIntFromVector(vector<int>& v, int nbComponents);
+  ParaMEDMEM::DataArrayDouble* createDataArrayDoubleFromVector(vector<double>& v);
 
+  void sendVectorOfString(const vector<string>& vec, const int target);
+  vector<string> recvVectorOfString(const int source);
+  //TODO void sendrecvVectorOfString(const vector<string>& vec, const int source, const int target);
+  vector<string> sendAndReceiveVectorOfString(const vector<string>& vec, const int source, const int target);
+  vector<string> allgathervVectorOfString(const vector<std::string>& vec);
+  
+  vector<string> browseFieldDouble(const MEDCouplingFieldDouble* fd);
+  vector<string> browseAllFields(const string& myfile);
+  vector<string> browseAllFieldsOnMesh(const string& myfile, const string& mymesh, int idomain);
+  vector<string> GetInfosOfField(const char *fileName, const char *meshName, int idomain );
+
+  void sendDoubleVec(const std::vector<double>& vec, int target);
+  std::vector<double>* recvDoubleVec(int source);
+  void recvDoubleVec(std::vector<double>& vec, int source);
+    
+  void sendIntVec(const std::vector<int>& vec, int target);
+  std::vector<int>* recvIntVec(int source);
+  void recvIntVec(std::vector<int>& vec, int source);
+  
+  void sendDataArrayInt(ParaMEDMEM::DataArrayInt* da, int target);
+  ParaMEDMEM::DataArrayInt* recvDataArrayInt(int source);
+  void sendDataArrayDouble(ParaMEDMEM::DataArrayDouble* da, int target);
+  ParaMEDMEM::DataArrayDouble* recvDataArrayDouble(int source);
+  
+  ParaMEDMEM::MEDCouplingUMesh* createEmptyMEDCouplingUMesh();
+  
+  void testVectorOfStringMPI();
+  void testMapOfStringIntMPI();
+  void testMapOfStringVectorOfStringMPI();
+  void testDataArrayMPI();
+  void testPersistantMpi0To1(int taille, int nb);
+  void testPersistantMpiRing(int taille, int nb);
+  void testPersistantMpiRingOnCommSplit(int taille, int nb);
+
+  class MyGlobals
+  {
+    public : static int _verbose;  //0 to 1000 over 200 is debug
+    public : static int _rank;
+    public : static int _world_size;
+    public : static int _randomize;
+    public : static int _atomize;
+    public : static int _creates_boundary_faces;
+    public : static int _is0verbose; //cout if rank 0 and verbose
+    public : static vector<string> _fileNames;    //on [iold]
+    public : static vector<string> _meshNames;    //on [iold]
+    public : static vector<string> _fieldDescriptions;
+    //used for descriptions of components of fields for example...
+    public : static vector<string> _generalInformations;
+    
+  };
+  
+  /*int MyGlobals::_verbose=0;
+  int MyGlobals::_is0verbose=0;
+  int MyGlobals::_rank=-1;
+  int MyGlobals::_world_size=-1;*/
 }
 #endif /*MEDPARTITIONER_UTILS_HXX_*/
index 56326d10e97c6dab42da9d2296c4269b1bfa600b..c731db9848768b27139f85b98e8a5424fcfffeed 100644 (file)
 #
 #  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 #
-#  MED MEDMEM : MED files in memory
+#  MED : MED files in memory
 #
 include $(top_srcdir)/adm_local/unix/make_common_starter.am
 
 # this directory must be recompiled before Test folder
 
 if CPPUNIT_IS_OK
- SUBDIRS=. 
+ SUBDIRS=. Test
 endif
 
 lib_LTLIBRARIES= libmedpartitioner.la
@@ -53,6 +53,7 @@ if MED_ENABLE_SCOTCH
 endif
 
 dist_libmedpartitioner_la_SOURCES= \
+MEDPARTITIONER_utils.cxx \
 MEDPARTITIONER_MESHCollection.cxx \
 MEDPARTITIONER_MESHCollectionDriver.cxx \
 MEDPARTITIONER_MESHCollectionMedXMLDriver.cxx \
@@ -74,7 +75,6 @@ endif
 
 libmedpartitioner_la_CPPFLAGS= $(MPI_INCLUDES) $(MED2_INCLUDES) $(HDF5_INCLUDES) @CXXTMPDPTHFLAGS@ \
        $(BOOST_CPPFLAGS) $(LIBXML_INCLUDES) \
-       -I$(srcdir)/../MEDMEM -I$(srcdir)/../MEDWrapper/V2_1/Core \
        -I$(srcdir)/../INTERP_KERNEL/Bases -I$(srcdir)/../MEDCoupling \
   -I$(srcdir)/../MEDLoader -I$(srcdir)/../INTERP_KERNEL
 
@@ -99,8 +99,10 @@ if MED_ENABLE_KERNEL
   libmedpartitioner_la_LDFLAGS+= ${KERNEL_LDFLAGS} -lSALOMELocalTrace 
 endif
 
+#libmedpartitioner_la_LDFLAGS+= $(MED2_LIBS) $(HDF5_LIBS) $(STDLIB) $(LIBXML_LIBS) $(MPI_LIBS) \
+#      ../MEDMEM/libmedmem.la  ../INTERP_KERNEL/libinterpkernel.la ../MEDCoupling/libmedcoupling.la ../MEDLoader/libmedloader.la 
 libmedpartitioner_la_LDFLAGS+= $(MED2_LIBS) $(HDF5_LIBS) $(STDLIB) $(LIBXML_LIBS) $(MPI_LIBS) \
-       ../MEDMEM/libmedmem.la  ../INTERP_KERNEL/libinterpkernel.la ../MEDCoupling/libmedcoupling.la ../MEDLoader/libmedloader.la 
+       ../INTERP_KERNEL/libinterpkernel.la ../MEDCoupling/libmedcoupling.la ../MEDLoader/libmedloader.la 
 
 # Executables targets
 bin_PROGRAMS= medpartitioner
index fa6c5de9c17c191cea6e94cb451c5faaad0c47aa..572af0cc0f05aa5fa89991ac9e0aa5b096000d67 100644 (file)
@@ -40,8 +40,6 @@ namespace po=boost::program_options;
 
 using namespace std;
 
-
-
 int main(int argc, char** argv)
 {
 #ifndef ENABLE_METIS
@@ -67,10 +65,8 @@ int main(int argc, char** argv)
   int ndomains;
 
 #ifdef BOOST_PROGRAM_OPTIONS_LIB
-
   // Use boost::program_options for command-line options parsing
-
-  po::options_description desc("Available options");
+  po::options_description desc("Available options of medpartitioner V1.0");
   desc.add_options()
     ("help","produces this help message")
     ("mesh-only","prevents the splitter from creating the fields contained in the original file(s)")
@@ -114,7 +110,7 @@ int main(int argc, char** argv)
 
   if (!vm.count("distributed") && !vm.count("meshname") )
   {
-    cout << "MEDPARTITIONER : for a serial MED file, mesh name must be selected with --meshname=..."<<endl;
+    cout << "for a serial MED file, mesh name must be selected with --meshname=..."<<endl;
     return 1;
   }
 
@@ -146,7 +142,7 @@ int main(int argc, char** argv)
 
   // Primitive parsing of command-line options
 
-  string desc ("Available options:\n"
+  string desc ("Available options of medpartitioner V1.0:\n"
                "\t--help                 : produces this help message\n"
                "\t--mesh-only            : do not create the fields contained in the original file(s)\n"
                "\t--distributed          : specifies that the input file is distributed\n"
@@ -260,13 +256,13 @@ int main(int argc, char** argv)
 
   // Loading the mesh collection
   MEDPARTITIONER::MESHCollection* collection;
-  cout << "MEDPARTITIONER - reading input files "<<endl;
+  cout << "MEDPARTITIONER : reading input files "<<endl;
   if (is_sequential)
     collection = new MEDPARTITIONER::MESHCollection(input,meshname);
   else
     collection = new MEDPARTITIONER::MESHCollection(input);
 
-  cout << "MEDPARTITIONER - computing partition "<<endl;
+  cout << "MEDPARTITIONER : computing partition "<<endl;
 
   // Creating the graph and partitioning it   
 #ifdef ENABLE_METIS
@@ -284,7 +280,7 @@ int main(int argc, char** argv)
   else
     new_topo = collection->createPartition(ndomains,MEDPARTITIONER::Graph::SCOTCH);
 
-  cout << "MEDPARTITIONER - creating new meshes"<<endl;
+  cout << "MEDPARTITIONER : creating new meshes"<<endl;
 
   // Creating a new mesh collection from the partitioning
   MEDPARTITIONER::MESHCollection new_collection(*collection, new_topo, split_families, empty_groups);
@@ -299,7 +295,7 @@ int main(int argc, char** argv)
 
   //  new_collection.setSubdomainBoundaryCreates(creates_boundary_faces);
 
-  cout << "MEDPARTITIONER - writing output files "<<endl;
+  cout << "MEDPARTITIONER : writing output files "<<endl;
   new_collection.write(output);
 
   // Casting the fields on the new collection
index 04ac90040459a7851df8802c3374ef115b9fdfeb..d597cbe6cc8034633550f8f0621586df0856138e 100644 (file)
 //  Module : MED
 //
 
+
+/*
+examples of launch
+rm ttmp* tttmp*
+export verb=11
+mpirun -np 2 medpartitioner_para --input-file=blade.med --output-file=ttmp1_ --ndomains=2 --dump-cpu-memory --verbose=$verb
+mpirun -np 5 medpartitioner_para --input-file=blade.med --output-file=ttmp1_ --ndomains=2 --dump-cpu-memory --verbose=$verb
+mpirun -np 4 medpartitioner_para --input-file=ttmp1_.xml --output-file=tttmp1_ --ndomains=4 --verbose=$verb
+
+mpirun -np 2 medpartitioner_para --ndomains=2 --input-file=tmp_testMesh_20x30x50.med --output-file=ttmp2_ --verbose=$verb
+mpirun -np 2 medpartitioner_para --ndomains=2 --input-file=ttmp2_.xml --output-file=ttmp3_ --verbose=$verb
+
+mpirun -np 2 medpartitioner_para --ndomains=2 --input-file=tmp_testMeshWithFaces_20x30x50.med --output-file=ttmp2_ --verbose=$verb
+mpirun -np 2 medpartitioner_para --ndomains=2 --input-file=ttmp2_.xml --output-file=ttmp3_ --verbose=$verb
+
+mpirun -np 2 medpartitioner_para --ndomains=2 --input-file=tmp_testMesh_20x30x50_WithVecFieldOnCells.med --output-file=ttmp2_ --verbose=$verb
+mpirun -np 2 medpartitioner_para --ndomains=2 --input-file=tmp_testMesh_20x30x50_WithVecFieldOnNodes.med --output-file=ttmp2_ --verbose=$verb
+mpirun -np 2 medpartitioner_para --ndomains=2 --input-file=ttmp2_.xml --output-file=ttmp3_ --verbose=$verb
+
+mpirun -np 4 medpartitioner_para --ndomains=4 --input-file=tmp_testMeshHuge_20x30x50_6.xml --output-file=ttmp3_ --verbose=1
+*/
+
+
 #include "MEDPARTITIONER_MESHCollection.hxx"
-#include "MEDPARTITIONER_Topology.hxx"
+//#include "MEDPARTITIONER_Topology.hxx"
+#include "MEDPARTITIONER_ParallelTopology.hxx"
 #include "MEDPARTITIONER_ParaDomainSelector.hxx"
+#include "MEDLoader.hxx"
+#include "MEDPARTITIONER_utils.hxx"
 
-#include "MEDMEM_STRING.hxx"
-#include <cstdlib>
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+#include <string>
 
 #ifdef HAVE_MPI2
 #include <mpi.h>
 #endif
 
-#include <fstream>
-
 #ifdef BOOST_PROGRAM_OPTIONS_LIB
 #include <boost/program_options.hpp>
 namespace po=boost::program_options;
 #endif
 
 using namespace std;
-
-
+using namespace MEDPARTITIONER;
 
 int main(int argc, char** argv)
 {
@@ -56,272 +82,281 @@ int main(int argc, char** argv)
 
   // Defining options
   // by parsing the command line
-  //bool mesh_only = false;
-  //bool is_sequential = true;
-  bool xml_output_master=true;
-  bool creates_boundary_faces=false;  
+  //bool xml_output_master=true;
   bool split_family=false;
   bool empty_groups=false;
   bool mesure_memory=false;
+  bool filter_face=true;
 
   string input;
   string output;
   string meshname;
   string library;
   int ndomains;
-
-#ifdef BOOST_PROGRAM_OPTIONS_LIB
-
-  // Use boost::program_options for command-line options parsing
-
-  po::options_description desc("Available options");
-  desc.add_options()
-    ("help","produces this help message")
-    //("mesh-only","prevents the splitter from creating the fields contained in the original file(s)")
-    //("distributed","specifies that the input file is distributed")
-    ("input-file",po::value<string>(),"name of the input MED file")
-    ("output-file",po::value<string>(),"name of the resulting file")
-    //("meshname",po::value<string>(),"name of the input mesh")
+  int help=0;
+  int test=0;
+  MPI_Init(&argc,&argv);
+  MPI_Comm_size(MPI_COMM_WORLD, &MyGlobals::_world_size);
+  MPI_Comm_rank(MPI_COMM_WORLD, &MyGlobals::_rank);
+  //cout<<"proc "<<MyGlobals::_rank<<" of "<<MyGlobals::_world_size<<endl; //cvw for debug
+  //testVectorOfStringMPI(); //cvw
+  //testRandomize();
+  
+  // Primitive parsing of command-line options
+  string desc ("Available options of medpartitioner_para V1.0:\n"
+               "\t--help                   : produces this help message\n"
+               "\t--verbose                : echoes arguments\n"
+               "\t--input-file=<string>    : name of the input .med file or .xml master file\n"
+               "\t--output-file=<string>   : name of the resulting file (without exension)\n"
+               "\t--ndomains=<number>      : number of subdomains in the output file, default is 1\n"
 #ifdef ENABLE_PARMETIS
 #ifdef ENABLE_PTSCOTCH
-    ("split-method",po::value<string>(&library)->default_value("metis"),"name of the splitting library (metis,scotch)")
+               "\t--split-method=<string>  : name of the splitting library (metis/scotch), default is metis\n"
 #endif
 #endif
-    ("ndomains",po::value<int>(&ndomains)->default_value(1),"number of subdomains in the output file")
-    ("plain-master","creates a plain masterfile instead of an XML file")
-    ("creates-boundary-faces","creates the necessary faces so that faces joints are created in the output files")
-    ("family-splitting","preserves the family names instead of focusing on the groups")
-    ("empty-groups","creates empty groups in zones that do not contain a group from the original domain")
-    ("dump-cpu-memory","dumps passed CPU time and maximal increase of used memory");
-
-  po::variables_map vm;
-  po::store(po::parse_command_line(argc,argv,desc),vm);
-  po::notify(vm);
+               "\t--creates-boundary-faces : creates boundary faces mesh in the output files\n"
+               //"\t--family-splitting       : preserves the family names instead of focusing on the groups\n"
+               "\t--dump-cpu-memory        : dumps passed CPU time and maximal increase of used memory\n"
+               //"\t--randomize=<number>     : random seed for other partitionning (only on one proc)\n"
+               //"\t--atomize              : do the opposite of a good partitionner (only on one proc)\n"
+               );
 
-  if (vm.count("help"))
+  if (argc<=1) help=1;
+  string value;
+  for (int i = 1; i < argc; i++)
   {
-    cout<<desc<<"\n";
-    return 1;
+    if (strlen(argv[i]) < 3) 
+    {
+      if (MyGlobals::_rank==0) cerr << "bad argument : "<< argv[i] << endl;
+      MPI_Finalize(); return 1;
+    }
+    
+    if (testArg(argv[i],"--verbose",value)) 
+    {
+      MyGlobals::_verbose=1;
+      if (value!="") MyGlobals::_verbose = atoi(value.c_str());
+    }
+    else if (testArg(argv[i],"--help",value)) help=1;
+    else if (testArg(argv[i],"--test",value)) test=1;
+    else if (testArg(argv[i],"--input-file",value)) input=value;
+    else if (testArg(argv[i],"--output-file",value)) output=value;
+    else if (testArg(argv[i],"--split-method",value)) library=value;
+    //else if (testArg(argv[i],"--family-splitting",value)) split_family=true;
+    else if (testArg(argv[i],"--ndomains",value)) ndomains=atoi(value.c_str());
+    else if (testArg(argv[i],"--randomize",value)) MyGlobals::_randomize=atoi(value.c_str());
+    else if (testArg(argv[i],"--atomize",value)) MyGlobals::_atomize=atoi(value.c_str());
+    else if (testArg(argv[i],"--creates-boundary-faces",value)) MyGlobals::_creates_boundary_faces=1;
+    //else if (testArg(argv[i],"--empty-groups",value)) empty_groups=true;
+    else if (testArg(argv[i],"--dump-cpu-memory",value)) mesure_memory=true;
+    else 
+    {
+      if (MyGlobals::_rank==0) cerr << "unknown argument : "<< argv[i] << endl;
+      MPI_Finalize(); return 1;
+    }
   }
 
-  if (!vm.count("ndomains"))
-  {
-    cout << "ndomains must be specified !"<<endl;
-    return 1;
-  }
 
-  ndomains = vm["ndomains"].as<int>();
-  if (!vm.count("input-file") || !vm.count("output-file"))
+  if (MyGlobals::_randomize!=0 && MyGlobals::_world_size!=1)
   {
-    cout << "input-file and output-file names must be specified"<<endl;
-    return 1;
+    if (MyGlobals::_rank==0) cerr << "randomize only available on 1 proc (mpirun -np 1)" << endl;
+    MyGlobals::_randomize=0;
   }
-
-//   if (!vm.count("distributed") && !vm.count("meshname") )
-//   {
-//     cout << "MEDPARTITIONER : for a serial MED file, mesh name must be selected with --meshname=..."<<endl;
-//     return 1;
-//   }
-
-  input = vm["input-file"].as<string>();
-  output = vm["output-file"].as<string>();
-
-//   if (vm.count("mesh-only"))
-//     mesh_only=true;
-
-//   if (vm.count("distributed"))
-//     is_sequential=false;
-
-//   if (is_sequential)
-//     meshname = vm["meshname"].as<string>();
-
-  if (vm.count("plain-master"))
-    xml_output_master=false;
-
-  if (vm.count("creates-boundary-faces"))
-    creates_boundary_faces=true;
-
-  if (vm.count("split-families"))
-    split_family=true;
-
-  if (vm.count("empty-groups"))
-    empty_groups=true;
-
-  if (vm.count("dump-cpu-memory"))
-    mesure_memory=true;
-
-#else // BOOST_PROGRAM_OPTIONS_LIB
-
-  // Primitive parsing of command-line options
-
-  string desc ("Available options:\n"
-               "\t--help                  : produces this help message\n"
-               //"\t--mesh-only            : do not create the fields contained in the original file(s)\n"
-               //"\t--distributed          : specifies that the input file is distributed\n"
-               "\t--input-file=<string>   : name of the input MED file\n"
-               "\t--output-file=<string>  : name of the resulting file\n"
-               //"\t--meshname=<string>    : name of the input mesh (not used with --distributed option)\n"
-               "\t--ndomains=<number>     : number of subdomains in the output file, default is 1\n"
+  
 #ifdef ENABLE_PARMETIS
-#ifdef ENABLE_PTSCOTCH
-               "\t--split-method=<string> : name of the splitting library (metis/scotch), default is metis\n"
+#ifndef ENABLE_PTSCOTCH
+  library = "metis";
 #endif
+#else
+  library = "scotch";
 #endif
-               "\t--plain-master          : creates a plain masterfile instead of an XML file\n"
-               "\t--creates-boundary-faces: creates the necessary faces so that faces joints are created in the output files\n"
-               "\t--family-splitting      : preserves the family names instead of focusing on the groups\n"
-               "\t--dump-cpu-memory       : dumps passed CPU time and maximal increase of used memory\n"
-               );
-
-  if (argc < 4) {
-    cout << desc.c_str() << endl;
+  if (help==1)
+  {
+    if (MyGlobals::_rank==0) cout<<desc<<"\n";
+    MPI_Finalize(); return 0;
+  }
+  
+  MyGlobals::_is0verbose=0;
+  if (MyGlobals::_rank==0) MyGlobals::_is0verbose=MyGlobals::_verbose;
+  //MyGlobals::_is0verbose=((MyGlobals::_rank==0) && MyGlobals::_verbose);
+  if (test==1) //only for debugger
+  {
+    if (MyGlobals::_is0verbose>0) cout<<"tests on "<<MyGlobals::_atomize<<" "<<ndomains<<endl;
+    //testPersistantMpi0To1(MyGlobals::_atomize, ndomains);
+    //testPersistantMpiRing(MyGlobals::_atomize, ndomains);
+    testPersistantMpiRingOnCommSplit(MyGlobals::_atomize, ndomains);
+    //MPI_Barrier(MPI_COMM_WORLD);
+    MPI_Finalize();
+    return 0;
+    testVectorOfStringMPI();
+    testMapOfStringIntMPI();
+    testMapOfStringVectorOfStringMPI();
+    testDataArrayMPI();
+    MPI_Finalize();
     return 1;
   }
-
-  for (int i = 1; i < argc; i++) {
-    if (strlen(argv[i]) < 3) {
-      cout << desc.c_str() << endl;
-      return 1;
+  
+  if (MyGlobals::_is0verbose)
+  {
+    cout << "medpartitioner_para V1.0 :" << endl;
+    cout << "  input-file = " << input << endl;
+    cout << "  output-file = " << output << endl;
+    cout << "  split-method = " << library << endl;
+    //cout << "  family-splitting = " << split_family << endl;
+    cout << "  ndomains = " << ndomains << endl;
+    //cout << "  xml_output_master = " << xml_output_master << endl;
+    cout << "  creates_boundary_faces = " << MyGlobals::_creates_boundary_faces << endl;
+    //cout << "  empty_groups = " << empty_groups<< endl;
+    cout << "  dump-cpu-memory = " << mesure_memory<< endl;
+    cout << "  verbose = " << MyGlobals::_verbose << endl;
+    //cout << "  randomize = " << MyGlobals::_randomize << endl;
+    cout << "  verbose = " << MyGlobals::_verbose << endl;
+  }
+  //testing whether it is possible to write a file at the specified location
+  if (MyGlobals::_rank==0)
+  {
+    string outputtest = output + ".testioms.";
+    ofstream testfile (outputtest.c_str());
+    if (testfile.fail())
+    { 
+      cerr << "output-file directory does not exist or is in read-only access" << endl;
+      MPI_Finalize(); return 1;
     }
+    //deletes test file
+    remove(outputtest.c_str());
+  }
+  
+  // Beginning of the computation
 
-/*    if (strncmp(argv[i],"--m",3) == 0) {
-      if (strcmp(argv[i],"--mesh-only") == 0) {
-        mesh_only = true;
-        cout << "\tmesh-only = " << mesh_only << endl; // tmp
-      }
-      else if (strlen(argv[i]) > 11) { // "--meshname="
-        meshname = (argv[i] + 11);
-        cout << "\tmeshname = " << meshname << endl; // tmp
-      }
-    }
-    else if (strncmp(argv[i],"--d",3) == 0) {
-      is_sequential = false;
-      cout << "\tis_sequential = " << is_sequential << endl; // tmp
-    }
-    else */if (strncmp(argv[i],"--i",3) == 0) {
-      if (strlen(argv[i]) > 13) { // "--input-file="
-        input = (argv[i] + 13);
-        cout << "\tinput-file = " << input << endl; // tmp
-      }
-    }
-    else if (strncmp(argv[i],"--o",3) == 0) {
-      if (strlen(argv[i]) > 14) { // "--output-file="
-        output = (argv[i] + 14);
-        cout << "\toutput-file = " << output << endl; // tmp
-      }
+  // Loading the mesh collection
+  if (MyGlobals::_is0verbose) cout << "Reading input files "<<endl;
+  
+  try
+  {
+    MEDPARTITIONER::ParaDomainSelector parallelizer(mesure_memory);
+    MEDPARTITIONER::MESHCollection collection(input,parallelizer); //cvwat01
+    MEDPARTITIONER::ParallelTopology* aPT = (MEDPARTITIONER::ParallelTopology*) collection.getTopology();
+    aPT->setGlobalNumerotationDefault(collection.getParaDomainSelector());
+    //int nbfiles=MyGlobals::_fileMedNames->size(); //nb domains
+    //to have unique valid fields names/pointers/descriptions for partitionning
+    collection.prepareFieldDescriptions();
+    //int nbfields=collection.getFieldDescriptions().size(); //on all domains
+    //cout<<reprVectorOfString(collection.getFieldDescriptions());
+    
+    if (MyGlobals::_is0verbose)
+    {
+      cout<<"fileNames :"<<endl
+          <<reprVectorOfString(MyGlobals::_fileNames);
+      cout<<"fieldDescriptions :"<<endl
+          <<reprFieldDescriptions(collection.getFieldDescriptions()," "); //cvwat07
+      cout<<"familyInfo :\n"
+          <<reprMapOfStringInt(collection.getFamilyInfo())<<endl;
+      cout<<"groupInfo :\n"
+          <<reprMapOfStringVectorOfString(collection.getGroupInfo())<<endl;
     }
-    else if (strncmp(argv[i],"--s",3) == 0) {
-      if (strlen(argv[i]) > 15) { // "--split-method="
-        library = (argv[i] + 15);
-        cout << "\tsplit-method = " << library << endl; // tmp
+    
+    // Creating the graph and partitioning it   
+    if (MyGlobals::_is0verbose) cout << "Computing partition "<<endl; //cvw
+  
+    auto_ptr< MEDPARTITIONER::Topology > new_topo;
+    if (library == "metis") //cvwat06
+      new_topo.reset( collection.createPartition(ndomains,MEDPARTITIONER::Graph::METIS));
+    else
+      new_topo.reset( collection.createPartition(ndomains,MEDPARTITIONER::Graph::SCOTCH));
+    parallelizer.evaluateMemory();
+  
+    // Creating a new mesh collection from the partitioning
+    if (MyGlobals::_is0verbose)  cout << "Creating new meshes"<<endl; //cvwat04
+    MEDPARTITIONER::MESHCollection new_collection(collection,new_topo.get(),split_family,empty_groups);
+    //cout<<"proc "<<MyGlobals::_rank<<" : new_collection done"<<endl;
+    parallelizer.evaluateMemory();
+  
+    //if (!xml_output_master) new_collection.setDriverType(MEDPARTITIONER::MedAscii);
+    if (filter_face) new_collection.filterFaceOnCell();
+    
+    //to get infos on all procs
+    
+    //see meshName
+    vector<string> finalInformations;
+    vector<string> r1,r2;
+    r1=allgathervVectorOfString(MyGlobals::_generalInformations);
+    //if (MyGlobals::_is0verbose>1000) cout << "generalInformations : \n"<<reprVectorOfString(r1);
+    r2=selectTagsInVectorOfString(r1,"ioldDomain=");
+    r2=selectTagsInVectorOfString(r2,"meshName=");
+    if (r2.size()==(collection.getMesh()).size())
+    {
+      for (int i=0; i<r2.size(); i++) r2[i]=eraseTagSerialized(r2[i],"ioldDomain=");
+      r2=deleteDuplicatesInVectorOfString(r2);
+      if (r2.size()==1)
+      {
+        string finalMesh="finalMeshName="+extractFromDescription(r2[0], "meshName=");
+        finalInformations.push_back(serializeFromString(finalMesh));
       }
     }
-    else if (strncmp(argv[i],"--f",3) == 0) { //"--family-splitting"
-      split_family=true;
-      cout << "\tfamily-splitting true" << endl; // tmp
+    if (finalInformations.size()==0)
+    {
+      if (MyGlobals::_rank==0)
+        cerr<<"Problem on final meshName : set at 'Merge'"<<endl;
+      finalInformations.push_back("finalMeshName=Merge");
     }
-    else if (strncmp(argv[i],"--n",3) == 0) {
-      if (strlen(argv[i]) > 11) { // "--ndomains="
-        ndomains = atoi(argv[i] + 11);
-        cout << "\tndomains = " << ndomains << endl; // tmp
+    
+    //see field info nbComponents & componentInfo (if fields present)
+    r2=selectTagsInVectorOfString(r1,"fieldName=");
+    r2=selectTagsInVectorOfString(r2,"nbComponents=");
+    //may be yes? or not?
+    for (int i=0; i<r2.size(); i++) r2[i]=eraseTagSerialized(r2[i],"ioldFieldDouble=");
+    r2=deleteDuplicatesInVectorOfString(r2);
+    for (int i=0; i<r2.size(); i++) finalInformations.push_back(r2[i]);
+    
+    MyGlobals::_generalInformations=finalInformations;
+    if (MyGlobals::_is0verbose) 
+      cout << "generalInformations : \n"<<reprVectorOfString(finalInformations);
+    
+    //new_collection.setSubdomainBoundaryCreates(creates_boundary_faces);
+    if (MyGlobals::_is0verbose) cout << "Writing "<<ndomains<<" output files "<<output<<"xx.med"<<" and "<<output<<".xml"<<endl;
+    new_collection.write(output);
+  
+    if ( mesure_memory )
+      if ( parallelizer.isOnDifferentHosts() || MyGlobals::_rank==0 )
+      {
+        cout << "Elapsed time = " << parallelizer.getPassedTime()
+             << ", max memory usage = " << parallelizer.evaluateMemory() << " KB"
+             << endl;
       }
-    }
-    else if (strncmp(argv[i],"--p",3) == 0) { // "--plain-master"
-      xml_output_master = false;
-      cout << "\txml_output_master = " << xml_output_master << endl; // tmp
-    }
-    else if (strncmp(argv[i],"--c",3) == 0) { // "--creates-boundary-faces"
-      creates_boundary_faces = true;
-      cout << "\tcreates_boundary_faces = " << creates_boundary_faces << endl; // tmp
-    }
-    else if (strncmp(argv[i],"--e",3) == 0) { // "--empty-groups"
-      empty_groups = true;
-      cout << "\tempty_groups = true" << endl; // tmp
-    }
-    else if (strncmp(argv[i],"--d",3) == 0) { // "--dump-cpu-memory"
-      mesure_memory = true;
-      cout << "\tdump-cpu-memory = true" << endl; // tmp
-    }
-    else {
-      cout << desc.c_str() << endl;
-      return 1;
-    }
+  //   Casting the fields on the new collection
+  //   if (!mesh_only)
+  //     new_collection.castAllFields(*collection);
+    MPI_Barrier(MPI_COMM_WORLD);
+    if (MyGlobals::_is0verbose>0) cout<<"OK END"<< endl;
+    MPI_Finalize();
+    return 0;
   }
-
-//   if (is_sequential && meshname.empty()) {
-//     cout << "Mesh name must be given for sequential(not distributed) input file." << endl;
-//     cout << desc << endl;
-//     return 1;
-//   }
-
-#endif // BOOST_PROGRAM_OPTIONS_LIB
-
-
-  //testing whether it is possible to write a file at the specified location
-  string outputtest = output + ".testioms.";
-  ofstream testfile (outputtest.c_str());
-  if (testfile.fail())
-  { 
-    cout << "MEDPARTITIONER : output-file directory does not exist or is in read-only access" << endl;
+  catch(const char *mess)
+  {
+    cerr<<"proc "<<MyGlobals::_rank<<" : "<<mess<<endl;
+    fflush(stderr);
+    MPI_Finalize();
+    return 1;
+  }
+  catch(INTERP_KERNEL::Exception& e)
+  {
+    cerr<<"proc "<<MyGlobals::_rank<<" : INTERP_KERNEL_Exception : "<<e.what()<<endl;
+    fflush(stderr);
+    MPI_Finalize();
+    return 1;
+  }
+  catch(std::exception& e)
+  {
+    cerr<<"proc "<<MyGlobals::_rank<<" : std_Exception : "<<e.what()<<endl;
+    fflush(stderr);
+    MPI_Finalize();
+    return 1;
+  }
+  catch(...)
+  {
+    cerr<<"proc "<<MyGlobals::_rank<<" : an unknown type exception error was occured"<<endl;
+    fflush(stderr);
+    MPI_Finalize();
     return 1;
   }
-  //deletes test file
-  remove(outputtest.c_str());
-
-  // Beginning of the computation
-
-  MPI_Init(&argc,&argv);
-  
-
-  // Loading the mesh collection
-  cout << "MEDPARTITIONER - reading input files "<<endl;
-  MEDPARTITIONER::ParaDomainSelector parallelizer(mesure_memory);
-  MEDPARTITIONER::MESHCollection collection(input,parallelizer);
-
-  // Creating the graph and partitioning it   
-  cout << "MEDPARTITIONER - computing partition "<<endl;
-#ifdef ENABLE_PARMETIS
-#ifndef ENABLE_PTSCOTCH
-  library = "metis";
-#endif
-#else
-  library = "scotch";
-#endif
-  cout << "\tsplit-method = " << library << endl; // tmp
-
-  auto_ptr< MEDPARTITIONER::Topology > new_topo;
-  if (library == "metis")
-    new_topo.reset( collection.createPartition(ndomains,MEDPARTITIONER::Graph::METIS));
-  else
-    new_topo.reset( collection.createPartition(ndomains,MEDPARTITIONER::Graph::SCOTCH));
-  parallelizer.evaluateMemory();
-
-  // Creating a new mesh collection from the partitioning
-  cout << "MEDPARTITIONER - creating new meshes"<<endl;
-  MEDPARTITIONER::MESHCollection new_collection(collection,new_topo.get(),split_family,empty_groups);
-  parallelizer.evaluateMemory();
-
-  if (!xml_output_master)
-    new_collection.setDriverType(MEDPARTITIONER::MedAscii);
-
-  //  new_collection.setSubdomainBoundaryCreates(creates_boundary_faces);
-
-  cout << "MEDPARTITIONER - writing output files "<<endl;
-  new_collection.write(output);
-
-  if ( mesure_memory )
-    if ( parallelizer.isOnDifferentHosts() || parallelizer.rank()==0 )
-    {
-      MEDMEM::STRING text("proc ");
-      text << parallelizer.rank() << ": elapsed time = " << parallelizer.getPassedTime()
-           << ", max memory usage = " << parallelizer.evaluateMemory() << " KB";
-      cout << text << endl;
-    }
-  // Casting the fields on the new collection
-//   if (!mesh_only)
-//     new_collection.castAllFields(*collection);
-
-  MPI_Finalize();
-
-  return 0;
 }