]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
*** empty log message ***
authorageay <ageay>
Fri, 16 Jul 2010 16:43:24 +0000 (16:43 +0000)
committerageay <ageay>
Fri, 16 Jul 2010 16:43:24 +0000 (16:43 +0000)
src/MEDCoupling/MEDCouplingUMesh.cxx
src/MEDCoupling/MEDCouplingUMesh.hxx
src/MEDCoupling/Test/MEDCouplingBasicsTest.hxx
src/MEDCoupling/Test/MEDCouplingBasicsTest1.cxx
src/MEDLoader/MEDLoader.cxx

index 760ef3282c81f37c1531c96a02129e5c1b753964..aa6504ff0926818e8c550f4a5fcf7d9d0f8f0ce6 100644 (file)
@@ -465,8 +465,8 @@ bool MEDCouplingUMesh::areCellsEquals2(int cell1, int cell2) const
 {
   const int *conn=getNodalConnectivity()->getConstPointer();
   const int *connI=getNodalConnectivityIndex()->getConstPointer();
-  std::set<int> s1(conn+connI[cell1],conn+connI[cell1+1]); s1.erase(-1);
-  std::set<int> s2(conn+connI[cell2],conn+connI[cell2+1]); s1.erase(-1);
+  std::set<int> s1(conn+connI[cell1],conn+connI[cell1+1]);
+  std::set<int> s2(conn+connI[cell2],conn+connI[cell2+1]);
   return s1==s2;
 }
 
@@ -544,10 +544,12 @@ void MEDCouplingUMesh::findCommonCellsBase(int compType, std::vector<int>& res,
                     bb[2*j+1]=std::max(bb[2*j+1],coords[SPACEDIM*(*pt)+j]);
                   }
               }
+          std::vector<int> candidates1;
+          myTree.getIntersectingElems(bb,candidates1);
           std::vector<int> candidates;
-          myTree.getIntersectingElems(bb,candidates);
-          std::vector<int>::iterator it=std::find(candidates.begin(),candidates.end(),k);
-          candidates.erase(candidates.begin(),it);
+          for(std::vector<int>::const_iterator iter=candidates1.begin();iter!=candidates1.end();iter++)
+            if(!isFetched[*iter])
+              candidates.push_back(*iter);
           if(areCellsEqualsInPool(candidates,compType,res))
             {
               int pos=resI.back();
@@ -555,6 +557,7 @@ void MEDCouplingUMesh::findCommonCellsBase(int compType, std::vector<int>& res,
               for(std::vector<int>::const_iterator it=res.begin()+pos;it!=res.end();it++)
                 isFetched[*it]=true;
             }
+          isFetched[k]=true;
         }
     }
 }
@@ -1603,6 +1606,7 @@ namespace ParaMEDMEMImpl
  */
 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
 {
+  checkFullyDefined();
   const int *conn=_nodal_connec->getConstPointer();
   const int *connI=_nodal_connec_index->getConstPointer();
   int nbOfCells=getNumberOfCells();
@@ -1618,6 +1622,42 @@ bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
   return true;
 }
 
+/*!
+ * This method reorganize the cells of 'this' so that the cells with same geometric types are put together.
+ * If checkConsecutiveCellTypes() returns true, this method do not change anything of this.
+ * The number of cells remains unchanged after the call of this method.
+ * @return the array giving the correspondance old to new.
+ */
+DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
+{
+  checkFullyDefined();
+  computeTypes();
+  const int *conn=_nodal_connec->getConstPointer();
+  const int *connI=_nodal_connec_index->getConstPointer();
+  int nbOfCells=getNumberOfCells();
+  std::vector<INTERP_KERNEL::NormalizedCellType> types;
+  for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
+    if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
+      {
+        INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
+        types.push_back(curType);
+        for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
+      }
+  DataArrayInt *ret=DataArrayInt::New();
+  ret->alloc(nbOfCells,1);
+  int *retPtr=ret->getPointer();
+  std::fill(retPtr,retPtr+nbOfCells,-1);
+  int newCellId=0;
+  for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
+    {
+      for(const int *i=connI;i!=connI+nbOfCells;i++)
+        if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
+          retPtr[std::distance(connI,i)]=newCellId++;
+    }
+  renumberCells(retPtr,retPtr+nbOfCells,false);
+  return ret;
+}
+
 /*!
  * This methods split this into as mush as untructured meshes that consecutive set of same type cells.
  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
@@ -1625,6 +1665,7 @@ bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
  */
 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
 {
+  checkFullyDefined();
   const int *conn=_nodal_connec->getConstPointer();
   const int *connI=_nodal_connec_index->getConstPointer();
   int nbOfCells=getNumberOfCells();
@@ -1733,7 +1774,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::mergeUMeshes(const MEDCouplingUMesh *mesh1,
 
 /*!
  * Idem mergeUMeshes except that 'meshes' are expected to lyie on the same coords and 'meshes' have the same meshdim.
- * 'meshes' must be a non empty vector. 'meshes' have to be with the same mesh dimension.
+ * 'meshes' must be a non empty vector.
  */
 MEDCouplingUMesh *MEDCouplingUMesh::mergeUMeshesOnSameCoords(const std::vector<MEDCouplingUMesh *>& meshes)
 {
@@ -1784,7 +1825,7 @@ MEDCouplingUMesh *MEDCouplingUMesh::mergeUMeshesOnSameCoords(const std::vector<M
 }
 
 /*!
- * This method fuses meshes 'meshes' and returned the fused mesh and the correspondances arrays for each mesh in 'meshes' in returned mesh.
+ * This method fuses meshes 'meshes' and returns the fused mesh and the correspondances arrays for each mesh in 'meshes' in returned mesh.
  * If a same cell is detected in several meshes in 'meshes', this cell will appear only once in returned mesh (see ParaMEDMEM::MEDCouplingUMesh::zipConnectivityTraducer for more details)
  *
  * @param meshes input non empty vector containing meshes having same coordiantes array and same mesh dimension.
index e109fc69877f1146465bf22297ef9273db239516..f6bb25da4dd45b563b8bbb0aa97d64edece8b6d2 100644 (file)
@@ -91,6 +91,7 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT void getBoundingBoxForBBTree(std::vector<double>& bbox) const;
     //utilities for MED File RW
     MEDCOUPLING_EXPORT bool checkConsecutiveCellTypes() const;
+    MEDCOUPLING_EXPORT DataArrayInt *rearrange2ConsecutiveCellTypes();
     MEDCOUPLING_EXPORT std::vector<MEDCouplingUMesh *> splitByType() const;
     //
     MEDCOUPLING_EXPORT MEDCouplingMesh *mergeMyselfWith(const MEDCouplingMesh *other) const;
index 82fcd1f58845acc39f7aef012bad8a9ef05dd7ff..629ebf6805aa532760962529cf6942288be1ba3b 100644 (file)
@@ -69,8 +69,10 @@ namespace ParaMEDMEM
     CPPUNIT_TEST( testOperationsOnFields4 );
     CPPUNIT_TEST( testMergeNodesOnField );
     CPPUNIT_TEST( testCheckConsecutiveCellTypes );
+    CPPUNIT_TEST( testRearrange2ConsecutiveCellTypes );
     CPPUNIT_TEST( testSplitByType );
     CPPUNIT_TEST( testFuseUMeshesOnSameCoords );
+    CPPUNIT_TEST( testFuseUMeshesOnSameCoords2 );
     CPPUNIT_TEST( testBuildOrthogonalField );
     CPPUNIT_TEST( testGetCellsContainingPoint );
     CPPUNIT_TEST( testGetValueOn1 );
@@ -137,7 +139,6 @@ namespace ParaMEDMEM
     CPPUNIT_TEST( test2DCurveInterpP0P1_1 );
     CPPUNIT_TEST( test2DCurveInterpP1P0_1 );
     CPPUNIT_TEST( test2DCurveInterpP1P1_1 );
-
     CPPUNIT_TEST_SUITE_END();
   public:
     void testArray();
@@ -177,8 +178,10 @@ namespace ParaMEDMEM
     void testOperationsOnFields4();
     void testMergeNodesOnField();
     void testCheckConsecutiveCellTypes();
+    void testRearrange2ConsecutiveCellTypes();
     void testSplitByType();
     void testFuseUMeshesOnSameCoords();
+    void testFuseUMeshesOnSameCoords2();
     void testBuildOrthogonalField();
     void testGetCellsContainingPoint();
     void testGetValueOn1();
index 18ce4fbdb9c9da362bd5d9da305e0a6bce27f400..b707c2416980617c70f70f49b001e1f309d064f3 100644 (file)
@@ -1761,6 +1761,37 @@ void MEDCouplingBasicsTest::testCheckConsecutiveCellTypes()
   sourceMesh->decrRef();
 }
 
+void MEDCouplingBasicsTest::testRearrange2ConsecutiveCellTypes()
+{
+  MEDCouplingUMesh *m1_1=build2DSourceMesh_1();
+  MEDCouplingUMesh *m2_1=build2DTargetMesh_1();
+  DataArrayInt *arr1=m1_1->rearrange2ConsecutiveCellTypes();
+  MEDCouplingUMesh *m1_2=build2DSourceMesh_1();
+  CPPUNIT_ASSERT(m1_2->isEqual(m1_1,1e-12));
+  const int expected1[2]={0,1};
+  CPPUNIT_ASSERT_EQUAL(2,arr1->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,arr1->getNumberOfComponents());
+  CPPUNIT_ASSERT(std::equal(expected1,expected1+2,arr1->getConstPointer()));
+  arr1->decrRef();
+  const int expected2[5]={0,3,4,1,2};
+  arr1=m2_1->rearrange2ConsecutiveCellTypes();
+  CPPUNIT_ASSERT_EQUAL(5,arr1->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,arr1->getNumberOfComponents());
+  CPPUNIT_ASSERT(std::equal(expected2,expected2+5,arr1->getConstPointer()));
+  MEDCouplingUMesh *m2_2=build2DTargetMesh_1();
+  CPPUNIT_ASSERT_EQUAL(5,arr1->getNumberOfTuples());
+  CPPUNIT_ASSERT_EQUAL(1,arr1->getNumberOfComponents());
+  CPPUNIT_ASSERT(std::equal(expected2,expected2+5,arr1->getConstPointer()));
+  CPPUNIT_ASSERT(!m2_2->isEqual(m2_1,1e-12));
+  m2_2->renumberCells(expected2,expected2+5,false);
+  CPPUNIT_ASSERT(m2_2->isEqual(m2_1,1e-12));
+  arr1->decrRef();
+  m1_1->decrRef();
+  m1_2->decrRef();
+  m2_1->decrRef();
+  m2_2->decrRef();
+}
+
 void MEDCouplingBasicsTest::testSplitByType()
 {
   MEDCouplingUMesh *m1=build3DSurfTargetMesh_1();
@@ -1836,6 +1867,46 @@ void MEDCouplingBasicsTest::testFuseUMeshesOnSameCoords()
   m5->decrRef();
 }
 
+void MEDCouplingBasicsTest::testFuseUMeshesOnSameCoords2()
+{
+  MEDCouplingUMesh *m2;
+  MEDCouplingUMesh *m1=build3DExtrudedUMesh_1(m2);
+  m2->decrRef();
+  const int part1[5]={2,3,6,4,10};
+  MEDCouplingUMesh *m3=(MEDCouplingUMesh *)m1->buildPartOfMySelf(part1,part1+5,true);
+  const int part2[4]={5,6,4,7};
+  MEDCouplingUMesh *m4=(MEDCouplingUMesh *)m1->buildPartOfMySelf(part2,part2+4,true);
+  std::vector<MEDCouplingUMesh *> meshes;
+  meshes.push_back(m1);
+  meshes.push_back(m3);
+  meshes.push_back(m3);
+  meshes.push_back(m4);
+  std::vector<DataArrayInt *> corr;
+  MEDCouplingUMesh *m5=MEDCouplingUMesh::fuseUMeshesOnSameCoords(meshes,0,corr);
+  CPPUNIT_ASSERT_EQUAL(18,m5->getNumberOfCells());
+  std::vector<DataArrayInt *>::iterator it=corr.begin();
+  const int exp1[4]={18,5,5,4};
+  const int exp2[4][18]={
+    {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17},
+    {2,3,6,4,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
+    {2,3,6,4,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
+    {5,6,4,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}
+  };
+  int i=0;
+  for(;it!=corr.end();it++,i++)
+    {
+      int sz=(*it)->getNumberOfTuples();
+      CPPUNIT_ASSERT_EQUAL(exp1[i],sz);
+      CPPUNIT_ASSERT(std::equal(exp2[i],exp2[i]+sz,(*it)->getConstPointer()));
+    }
+  for(it=corr.begin();it!=corr.end();it++)
+    (*it)->decrRef();
+  m5->decrRef();
+  m4->decrRef();
+  m3->decrRef();
+  m1->decrRef();
+}
+
 void MEDCouplingBasicsTest::testBuildOrthogonalField()
 {
   MEDCouplingUMesh *targetMesh=build3DSurfTargetMesh_1();
index abf37e8147a43d6714c755b108d085c7ba9766da..06eb6eff7edb422e50b308221d0e4685808a505b 100644 (file)
@@ -141,8 +141,9 @@ namespace MEDLoaderNS
   med_int getIdFromMeshName(med_idt fid, const char *meshName, std::string& trueMeshName) throw(INTERP_KERNEL::Exception);
   void dispatchElems(int nbOfElemCell, int nbOfElemFace, int& nbOfElem, med_entite_maillage& whichEntity);
   void readUMeshDataInMedFile(med_idt fid, med_int meshId, double *&coords, int& nCoords, int& spaceDim, std::list<MEDLoader::MEDConnOfOneElemType>& conn);
-  int buildMEDSubConnectivityOfOneType(const DataArrayInt *conn, const DataArrayInt *connIndex, INTERP_KERNEL::NormalizedCellType type, std::vector<int>& conn4MEDFile,
-                                       std::vector<int>& connIndex4MEDFile, std::vector<int>& connIndexRk24MEDFile);
+  int buildMEDSubConnectivityOfOneType(const DataArrayInt *conn, const DataArrayInt *connIndex, const DataArrayInt *families, INTERP_KERNEL::NormalizedCellType type,
+                                       std::vector<int>& conn4MEDFile, std::vector<int>& connIndex4MEDFile, std::vector<int>& connIndexRk24MEDFile,
+                                       std::vector<int>& fam4MEDFile);
   MEDCouplingUMesh *readUMeshFromFileLev1(const char *fileName, const char *meshName, int meshDimRelToMax, const std::vector<int>& ids,
                                           const std::vector<INTERP_KERNEL::NormalizedCellType>& typesToKeep, unsigned& meshDimExtract) throw(INTERP_KERNEL::Exception);
   void tradMEDFileCoreFrmt2MEDCouplingUMesh(const std::list<MEDLoader::MEDConnOfOneElemType>& medConnFrmt,
@@ -150,15 +151,18 @@ namespace MEDLoaderNS
                                             DataArrayInt* &connIndex,
                                             const std::vector<int>& familiesToKeep);
   ParaMEDMEM::DataArrayDouble *buildArrayFromRawData(const std::list<MEDLoader::MEDFieldDoublePerCellType>& fieldPerType);
-  int buildMEDSubConnectivityOfOneTypesPolyg(const DataArrayInt *conn, const DataArrayInt *connIndex, std::vector<int>& conn4MEDFile, std::vector<int>& connIndex4MEDFile);
-  int buildMEDSubConnectivityOfOneTypesPolyh(const DataArrayInt *conn, const DataArrayInt *connIndex, std::vector<int>& conn4MEDFile,
-                                             std::vector<int>& connIndex4MEDFile, std::vector<int>& connIndexRk24MEDFile);
-  int buildMEDSubConnectivityOfOneTypeStaticTypes(const DataArrayInt *conn, const DataArrayInt *connIndex, INTERP_KERNEL::NormalizedCellType type, std::vector<int>& conn4MEDFile);
+  int buildMEDSubConnectivityOfOneTypesPolyg(const DataArrayInt *conn, const DataArrayInt *connIndex, const DataArrayInt *families,
+                                             std::vector<int>& conn4MEDFile, std::vector<int>& connIndex4MEDFile, std::vector<int>& fam4MEDFile);
+  int buildMEDSubConnectivityOfOneTypesPolyh(const DataArrayInt *conn, const DataArrayInt *connIndex, const DataArrayInt *families, std::vector<int>& conn4MEDFile,
+                                             std::vector<int>& connIndex4MEDFile, std::vector<int>& connIndexRk24MEDFile,
+                                             std::vector<int>& fam4MEDFile);
+  int buildMEDSubConnectivityOfOneTypeStaticTypes(const DataArrayInt *conn, const DataArrayInt *connIndex, const DataArrayInt *families,
+                                                  INTERP_KERNEL::NormalizedCellType type, std::vector<int>& conn4MEDFile, std::vector<int>& fam4MEDFile);
   ParaMEDMEM::MEDCouplingFieldDouble *readFieldDoubleLev1(const char *fileName, const char *meshName, int meshDimRelToMax, const char *fieldName, int iteration, int order,
                                                           ParaMEDMEM::TypeOfField typeOfOutField);
   void appendFieldDirectly(const char *fileName, ParaMEDMEM::MEDCouplingFieldDouble *f);
   void prepareCellFieldDoubleForWriting(const ParaMEDMEM::MEDCouplingFieldDouble *f, std::list<MEDLoader::MEDFieldDoublePerCellType>& split);
-  void writeUMeshDirectly(const char *fileName, ParaMEDMEM::MEDCouplingUMesh *mesh, bool forceFromScratch);
+  void writeUMeshDirectly(const char *fileName, ParaMEDMEM::MEDCouplingUMesh *mesh, const DataArrayInt *families, bool forceFromScratch);
   void writeUMeshesDirectly(const char *fileName, const char *meshName, const std::vector<ParaMEDMEM::MEDCouplingUMesh *>& meshes, bool forceFromScratch);
   void writeFieldAndMeshDirectly(const char *fileName, ParaMEDMEM::MEDCouplingFieldDouble *f, bool forceFromScratch);
 }
@@ -963,24 +967,32 @@ namespace MEDLoaderNS
  * This method builds a sub set of connectivity for a given type 'type'.
  * @param conn input containing connectivity with MEDCoupling format.
  * @param connIndex input containing connectivity index in MEDCoupling format.
+ * @param families input that may be equal to 0. This specifies an array specifying cell family foreach cell.
  * @param type input specifying which cell types will be extracted in conn4MEDFile. 
  * @param conn4MEDFile output containing the connectivity directly understandable by MEDFile; conn4MEDFile has to be empty before this method called.
  * @param connIndex4MEDFile output containing index connectivity understandable by MEDFile; only used by polygons and polyhedrons (it is face nodal connec).
  * @param connIndexRk24MEDFile output containing index of rank 2 understandable by MEDFile; only used by polyhedrons.
+ * @param fam4MEDFile output containing family number of cells whose type is 'type'. This output is updated only if 'families' is different than 0.
  * @return nb of elements extracted.
  */
-int MEDLoaderNS::buildMEDSubConnectivityOfOneTypeStaticTypes(const DataArrayInt *conn, const DataArrayInt *connIndex, INTERP_KERNEL::NormalizedCellType type, std::vector<int>& conn4MEDFile)
+int MEDLoaderNS::buildMEDSubConnectivityOfOneTypeStaticTypes(const DataArrayInt *conn, const DataArrayInt *connIndex, const DataArrayInt *families, INTERP_KERNEL::NormalizedCellType type, std::vector<int>& conn4MEDFile,
+                                                             std::vector<int>& fam4MEDFile)
 {
   int ret=0;
   int nbOfElem=connIndex->getNbOfElems()-1;
   const int *connPtr=conn->getConstPointer();
   const int *connIdxPtr=connIndex->getConstPointer();
+  const int *famPtr=0;
+  if(families)
+    famPtr=families->getConstPointer();
   for(int i=0;i<nbOfElem;i++)
     {
       int delta=connIdxPtr[1]-connIdxPtr[0];
       if(*connPtr==type)
         {
           conn4MEDFile.insert(conn4MEDFile.end(),connPtr+1,connPtr+delta);
+          if(families)
+            fam4MEDFile.push_back(famPtr[i]);
           ret++;
         }
       connIdxPtr++;
@@ -990,13 +1002,17 @@ int MEDLoaderNS::buildMEDSubConnectivityOfOneTypeStaticTypes(const DataArrayInt
   return ret;
 }
 
-int MEDLoaderNS::buildMEDSubConnectivityOfOneTypesPolyg(const DataArrayInt *conn, const DataArrayInt *connIndex, std::vector<int>& conn4MEDFile, std::vector<int>& connIndex4MEDFile)
+int MEDLoaderNS::buildMEDSubConnectivityOfOneTypesPolyg(const DataArrayInt *conn, const DataArrayInt *connIndex, const DataArrayInt *families, std::vector<int>& conn4MEDFile, std::vector<int>& connIndex4MEDFile,
+                                                        std::vector<int>& fam4MEDFile)
 {
   int ret=0;
   int nbOfElem=connIndex->getNbOfElems()-1;
   const int *connPtr=conn->getConstPointer();
   const int *connIdxPtr=connIndex->getConstPointer();
   connIndex4MEDFile.push_back(1);
+  const int *famPtr=0;
+  if(families)
+    famPtr=families->getConstPointer();
   for(int i=0;i<nbOfElem;i++)
     {
       int delta=connIdxPtr[1]-connIdxPtr[0];
@@ -1004,6 +1020,8 @@ int MEDLoaderNS::buildMEDSubConnectivityOfOneTypesPolyg(const DataArrayInt *conn
         {
           conn4MEDFile.insert(conn4MEDFile.end(),connPtr+1,connPtr+delta);
           connIndex4MEDFile.push_back(connIndex4MEDFile.back()+delta-1);
+          if(families)
+            fam4MEDFile.push_back(famPtr[i]);
           ret++;
         }
       connIdxPtr++;
@@ -1013,7 +1031,9 @@ int MEDLoaderNS::buildMEDSubConnectivityOfOneTypesPolyg(const DataArrayInt *conn
   return ret;
 }
   
-int MEDLoaderNS::buildMEDSubConnectivityOfOneTypesPolyh(const DataArrayInt *conn, const DataArrayInt *connIndex, std::vector<int>& conn4MEDFile, std::vector<int>& connIndex4MEDFile, std::vector<int>& connIndexRk24MEDFile)
+int MEDLoaderNS::buildMEDSubConnectivityOfOneTypesPolyh(const DataArrayInt *conn, const DataArrayInt *connIndex, const DataArrayInt *families,
+                                                        std::vector<int>& conn4MEDFile, std::vector<int>& connIndex4MEDFile, std::vector<int>& connIndexRk24MEDFile,
+                                                        std::vector<int>& fam4MEDFile)
 {
   int ret=0;
   int nbOfElem=connIndex->getNbOfElems()-1;
@@ -1021,6 +1041,9 @@ int MEDLoaderNS::buildMEDSubConnectivityOfOneTypesPolyh(const DataArrayInt *conn
   const int *connIdxPtr=connIndex->getConstPointer();
   connIndexRk24MEDFile.push_back(1);
   connIndex4MEDFile.push_back(1);
+  const int *famPtr=0;
+  if(families)
+    famPtr=families->getConstPointer();
   for(int i=0;i<nbOfElem;i++)
     {
       int delta=connIdxPtr[1]-connIdxPtr[0];
@@ -1039,6 +1062,8 @@ int MEDLoaderNS::buildMEDSubConnectivityOfOneTypesPolyh(const DataArrayInt *conn
                 work=end+1;
             }
           connIndexRk24MEDFile.push_back(connIndexRk24MEDFile.back()+nbOfFacesOfPolyh);
+          if(families)
+            fam4MEDFile.push_back(famPtr[i]);
           ret++;
         }
       connIdxPtr++;
@@ -1052,25 +1077,28 @@ int MEDLoaderNS::buildMEDSubConnectivityOfOneTypesPolyh(const DataArrayInt *conn
  * This method builds a sub set of connectivity for a given type 'type'.
  * @param conn input containing connectivity with MEDCoupling format.
  * @param connIndex input containing connectivity index in MEDCoupling format.
+ * @param families input containing, if any, the family number of each cells
  * @param type input specifying which cell types will be extracted in conn4MEDFile. 
  * @param conn4MEDFile output containing the connectivity directly understandable by MEDFile; conn4MEDFile has to be empty before this method called.
  * @param connIndex4MEDFile output containing index connectivity understandable by MEDFile; only used by polygons and polyhedrons (it is face nodal connec).
  * @param connIndexRk24MEDFile output containing index of rank 2 understandable by MEDFile; only used by polyhedrons.
+ * @param fam4MEDFile output containing families id of cells whose type is 'type'.
  * @return nb of elements extracted.
  */
-int MEDLoaderNS::buildMEDSubConnectivityOfOneType(const DataArrayInt *conn, const DataArrayInt *connIndex, INTERP_KERNEL::NormalizedCellType type, std::vector<int>& conn4MEDFile,
-                                                  std::vector<int>& connIndex4MEDFile, std::vector<int>& connIndexRk24MEDFile)
+int MEDLoaderNS::buildMEDSubConnectivityOfOneType(const DataArrayInt *conn, const DataArrayInt *connIndex, const DataArrayInt *families,
+                                                  INTERP_KERNEL::NormalizedCellType type, std::vector<int>& conn4MEDFile,
+                                                  std::vector<int>& connIndex4MEDFile, std::vector<int>& connIndexRk24MEDFile, std::vector<int>& fam4MEDFile)
 {
     
   const INTERP_KERNEL::CellModel& cellMod=INTERP_KERNEL::CellModel::getCellModel(type);
   if(!cellMod.isDynamic())
-    return buildMEDSubConnectivityOfOneTypeStaticTypes(conn,connIndex,type,conn4MEDFile);
+    return buildMEDSubConnectivityOfOneTypeStaticTypes(conn,connIndex,families,type,conn4MEDFile,fam4MEDFile);
   else
     {
       if(type==INTERP_KERNEL::NORM_POLYGON)
-        return buildMEDSubConnectivityOfOneTypesPolyg(conn,connIndex,conn4MEDFile,connIndex4MEDFile);
+        return buildMEDSubConnectivityOfOneTypesPolyg(conn,connIndex,families,conn4MEDFile,connIndex4MEDFile,fam4MEDFile);
       else
-        return buildMEDSubConnectivityOfOneTypesPolyh(conn,connIndex,conn4MEDFile,connIndex4MEDFile,connIndexRk24MEDFile);
+        return buildMEDSubConnectivityOfOneTypesPolyh(conn,connIndex,families,conn4MEDFile,connIndex4MEDFile,connIndexRk24MEDFile,fam4MEDFile);
     }
 }
   
@@ -1200,7 +1228,7 @@ ParaMEDMEM::MEDCouplingFieldDouble *MEDLoader::ReadFieldDoubleNode(const char *f
   return MEDLoaderNS::readFieldDoubleLev1(fileName,meshName,meshDimRelToMax,fieldName,iteration,order,ON_NODES);
 }
 
-void MEDLoaderNS::writeUMeshDirectly(const char *fileName, ParaMEDMEM::MEDCouplingUMesh *mesh, bool forceFromScratch)
+void MEDLoaderNS::writeUMeshDirectly(const char *fileName, ParaMEDMEM::MEDCouplingUMesh *mesh, const DataArrayInt *families, bool forceFromScratch)
 {
   med_idt fid=MEDouvrir((char *)fileName,forceFromScratch?MED_CREATION:MED_LECTURE_ECRITURE);
   std::string meshName(mesh->getName());
@@ -1209,9 +1237,11 @@ void MEDLoaderNS::writeUMeshDirectly(const char *fileName, ParaMEDMEM::MEDCoupli
       MEDfermer(fid);
       throw INTERP_KERNEL::Exception("MEDCouplingMesh must have a not null name !");
     }
-  char maa[MED_TAILLE_NOM+1];
+  char *maa=MEDLoaderBase::buildEmptyString(MED_TAILLE_NOM);
+  char *desc=MEDLoaderBase::buildEmptyString(MED_TAILLE_DESC);
   strcpy(maa,meshName.c_str());
-  MEDmaaCr(fid,maa,mesh->getSpaceDimension(),MED_NON_STRUCTURE,maa);
+  strcpy(desc,meshName.c_str());
+  MEDmaaCr(fid,maa,mesh->getSpaceDimension(),MED_NON_STRUCTURE,desc);
   MEDdimEspaceCr(fid,maa,mesh->getSpaceDimension());
   std::set<INTERP_KERNEL::NormalizedCellType> allTypes(mesh->getAllTypes());
   DataArrayInt *conn=mesh->getNodalConnectivity();
@@ -1229,7 +1259,8 @@ void MEDLoaderNS::writeUMeshDirectly(const char *fileName, ParaMEDMEM::MEDCoupli
           std::vector<int> medConn;
           std::vector<int> medConnIndex;
           std::vector<int> medConnIndex2;
-          int nbOfElt=MEDLoaderNS::buildMEDSubConnectivityOfOneType(conn,connIndex,curType,medConn,medConnIndex,medConnIndex2);
+          std::vector<int> fam;
+          int nbOfElt=MEDLoaderNS::buildMEDSubConnectivityOfOneType(conn,connIndex,families,curType,medConn,medConnIndex,medConnIndex2,fam);
           if(curMedType!=MED_POLYGONE && curMedType!=MED_POLYEDRE)
             MEDconnEcr(fid,maa,mesh->getMeshDimension(),&medConn[0],MED_FULL_INTERLACE,nbOfElt,MED_MAILLE,curMedType,MED_NOD);
           else
@@ -1242,6 +1273,8 @@ void MEDLoaderNS::writeUMeshDirectly(const char *fileName, ParaMEDMEM::MEDCoupli
                                      &medConn[0],MED_NOD);
                 }
             }
+          if(families)
+            MEDfamEcr(fid,maa,&fam[0],nbOfElt,MED_MAILLE,curMedType);
         }
     }
   MEDfamCr(fid,maa,familyName,0,0,0,0,0,0,0);
@@ -1255,20 +1288,66 @@ void MEDLoaderNS::writeUMeshDirectly(const char *fileName, ParaMEDMEM::MEDCoupli
     *work='X'+i;
   std::fill(unit,unit+2*MED_TAILLE_PNOM+1,'\0');
   MEDcoordEcr(fid,maa,mesh->getSpaceDimension(),arr->getPointer(),MED_FULL_INTERLACE,mesh->getNumberOfNodes(),MED_CART,comp,unit);
+  delete [] maa;
+  delete [] desc;
   MEDfermer(fid);
 }
 
 /*!
  * In this method meshes are assumed to shared the same coords.
+ * This method makes the assumption that 'meshes' is not empty, no check on that is done (responsability of the caller)
  */
 void MEDLoaderNS::writeUMeshesDirectly(const char *fileName, const char *meshName, const std::vector<ParaMEDMEM::MEDCouplingUMesh *>& meshes, bool forceFromScratch)
 {
-  med_idt fid=MEDouvrir((char *)fileName,forceFromScratch?MED_CREATION:MED_LECTURE_ECRITURE);
-  char maa[MED_TAILLE_NOM+1];
+  std::string meshNameCpp(meshName);
+  char *maa=MEDLoaderBase::buildEmptyString(MED_TAILLE_NOM);
   strcpy(maa,meshName);
-  //MEDmaaCr(fid,maa,mesh->getSpaceDimension(),MED_NON_STRUCTURE,maa);
-  //MEDdimEspaceCr(fid,maa,mesh->getSpaceDimension());
-  MEDfermer(fid);
+  if(meshName=="")
+    throw INTERP_KERNEL::Exception("writeUMeshesDirectly : Invalid meshName : Must be different from \"\" !");
+  //MEDnumEcr(fid,maa,num,nele,_type_ent,typ_geo);
+  std::vector< DataArrayInt * > corr;
+  MEDCouplingUMesh *m=ParaMEDMEM::MEDCouplingUMesh::fuseUMeshesOnSameCoords(meshes,0,corr);
+  m->setName(meshName);
+  std::vector< std::vector<int> > fidsOfGroups;
+  DataArrayInt *arr2=DataArrayInt::makePartition(corr,m->getNumberOfCells(),fidsOfGroups);
+  for(std::vector< DataArrayInt * >::iterator it=corr.begin();it!=corr.end();it++)
+    (*it)->decrRef();
+  writeUMeshDirectly(fileName,m,arr2,forceFromScratch);
+  // families creation
+  std::set<int> familyIds;
+  for(std::vector< std::vector<int> >::const_iterator it1=fidsOfGroups.begin();it1!=fidsOfGroups.end();it1++)
+    for(std::vector<int>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
+      familyIds.insert(*it2);
+  std::vector< std::vector<int> > gidsOfFamilies(familyIds.size());
+  int fid=0;
+  for(std::set<int>::const_iterator it=familyIds.begin();it!=familyIds.end();it++,fid++)
+    {
+      int gid=0;
+      for(std::vector< std::vector<int> >::const_iterator it1=fidsOfGroups.begin();it1!=fidsOfGroups.end();it1++,gid++)
+        for(std::vector<int>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
+          if(*it2==*it)
+            gidsOfFamilies[fid].push_back(gid);
+    }
+  fid=0;
+  med_idt fid2=MEDouvrir((char *)fileName,MED_LECTURE_ECRITURE);
+  for(std::set<int>::const_iterator it=familyIds.begin();it!=familyIds.end();it++,fid++)
+    {
+      int ngro=gidsOfFamilies[fid].size();
+      char *groName=MEDLoaderBase::buildEmptyString(MED_TAILLE_LNOM*ngro);
+      for(int i=0;i<ngro;i++)
+        strcpy(groName+i*MED_TAILLE_LNOM,meshes[gidsOfFamilies[fid][i]]->getName());
+      std::ostringstream oss; oss << "Family_" << *it;
+      char *famName=MEDLoaderBase::buildEmptyString(MED_TAILLE_NOM);
+      strcpy(famName,oss.str().c_str());
+      MEDfamCr(fid2,maa,famName,*it,0,0,0,0,groName,ngro);
+      delete [] famName;
+      delete [] groName;
+    }
+  MEDfermer(fid2);
+  // end families creation
+  delete [] maa;
+  arr2->decrRef();
+  m->decrRef();
 }
 
 void MEDLoaderNS::appendFieldDirectly(const char *fileName, ParaMEDMEM::MEDCouplingFieldDouble *f)
@@ -1360,7 +1439,7 @@ void MEDLoaderNS::writeFieldAndMeshDirectly(const char *fileName, ParaMEDMEM::ME
   if(fieldName.empty())
     throw INTERP_KERNEL::Exception("Trying to write a field with no name ! MED file format needs a not empty field name !");
   MEDCouplingUMesh *mesh=dynamic_cast<MEDCouplingUMesh *>((MEDCouplingMesh *)f->getMesh());
-  writeUMeshDirectly(fileName,mesh,forceFromScratch);
+  writeUMeshDirectly(fileName,mesh,0,forceFromScratch);
   appendFieldDirectly(fileName,f);
 }
 
@@ -1377,19 +1456,19 @@ void MEDLoader::WriteUMesh(const char *fileName, ParaMEDMEM::MEDCouplingUMesh *m
     }
   if(writeFromScratch)
     {
-      MEDLoaderNS::writeUMeshDirectly(fileName,mesh,true);
+      MEDLoaderNS::writeUMeshDirectly(fileName,mesh,0,true);
       return ;
     }
   if(status==MEDLoaderBase::NOT_EXIST)
     {
-      MEDLoaderNS::writeUMeshDirectly(fileName,mesh,true);
+      MEDLoaderNS::writeUMeshDirectly(fileName,mesh,0,true);
       return;
     }
   else
     {
       std::vector<std::string> meshNames=GetMeshNames(fileName);
       if(std::find(meshNames.begin(),meshNames.end(),meshName)==meshNames.end())
-        MEDLoaderNS::writeUMeshDirectly(fileName,mesh,false);
+        MEDLoaderNS::writeUMeshDirectly(fileName,mesh,0,false);
       else
         {
           std::ostringstream oss; oss << "File \'" << fileName << "\' already exists and has already a mesh called \"";