Salome HOME
Make the medwriter engine usable from the outside
authorAnthony Geay <anthony.geay@edf.fr>
Tue, 5 Dec 2017 10:49:53 +0000 (11:49 +0100)
committerAnthony Geay <anthony.geay@edf.fr>
Tue, 5 Dec 2017 10:49:53 +0000 (11:49 +0100)
src/Plugins/MEDWriter/CMakeLists.txt
src/Plugins/MEDWriter/IO/CMakeLists.txt
src/Plugins/MEDWriter/IO/VTKToMEDMem.cxx [new file with mode: 0644]
src/Plugins/MEDWriter/IO/VTKToMEDMem.hxx [new file with mode: 0644]
src/Plugins/MEDWriter/IO/vtkMEDWriter.cxx

index add77d45539cbff188524deb759a83ad1ab4169b..2c132b00b14ab6f747b33750ec8d81f7ce9c686e 100644 (file)
@@ -41,6 +41,9 @@ OPTION(BUILD_SHARED_LIBS "Build with shared libraries." ${VTK_BUILD_SHARED_LIBS}
 SET(VTK_INSTALL_RUNTIME_DIR lib/salome)
 SET(VTK_INSTALL_LIBRARY_DIR lib/salome)
 SET(VTK_INSTALL_ARCHIVE_DIR lib/salome)
+SET(MEDWRITER_INSTALL_CMAKE_LOCAL adm_local/cmake_files CACHE PATH "Install path: local SALOME CMake files")
+SET(MEDWRITER_INSTALL_HEADERS include/salome CACHE PATH "Install path: local include files")
+
 
 SET(MEDCOUPLING_ROOT_DIR $ENV{MEDCOUPLING_ROOT_DIR} CACHE PATH "MEDCOUPLING_ROOT_DIR")
 LIST(APPEND CMAKE_MODULE_PATH "${MEDCOUPLING_ROOT_DIR}/cmake_files")
@@ -52,3 +55,5 @@ FIND_PACKAGE(SalomeMEDFile REQUIRED)
 PV_PROCESS_MODULES()
 
 ADD_SUBDIRECTORY(ParaViewPlugin)
+
+INSTALL(EXPORT ${PROJECT_NAME}TargetGroup DESTINATION "${MEDWRITER_INSTALL_CMAKE_LOCAL}" FILE ${PROJECT_NAME}Targets.cmake)
index 90c3b710adb10aa9785e9c2088f28f14706410d3..16dbc23b895b867a733edc26a7ac2dc41ea0b0c4 100644 (file)
@@ -23,6 +23,14 @@ INCLUDE_DIRECTORIES(
   ${MEDFILE_INCLUDE_DIRS}
   ${HDF5_INCLUDE_DIRS})
 
+ADD_LIBRARY(VTKToMEDMem SHARED VTKToMEDMem.cxx)
+TARGET_LINK_LIBRARIES(VTKToMEDMem vtkPVVTKExtensionsRendering vtkFiltersGeneral vtkFiltersCore ${PARAVIEW_LIBRARIES} ${MEDCoupling_medloader} ${MEDFILE_C_LIBRARIES})
 VTK_MODULE_LIBRARY(vtkMEDWriter vtkMEDWriter.cxx)
-TARGET_LINK_LIBRARIES(vtkMEDWriter vtkPVVTKExtensionsRendering vtkFiltersGeneral vtkFiltersCore ${PARAVIEW_LIBRARIES} ${MEDCoupling_medloader} ${MEDFILE_C_LIBRARIES})
-INSTALL(TARGETS vtkMEDWriter RUNTIME DESTINATION ${VTK_INSTALL_RUNTIME_DIR} LIBRARY DESTINATION ${VTK_INSTALL_LIBRARY_DIR} ARCHIVE DESTINATION ${VTK_INSTALL_ARCHIVE_DIR})
+TARGET_LINK_LIBRARIES(vtkMEDWriter VTKToMEDMem)
+INSTALL(TARGETS vtkMEDWriter RUNTIME DESTINATION ${VTK_INSTALL_RUNTIME_DIR} LIBRARY DESTINATION ${VTK_INSTALL_LIBRARY_DIR} ARCHIVE DESTINATION ${VTK_INSTALL_ARCHIVE_DIR} )
+INSTALL(TARGETS VTKToMEDMem  EXPORT ${PROJECT_NAME}TargetGroup RUNTIME DESTINATION ${VTK_INSTALL_RUNTIME_DIR} LIBRARY DESTINATION ${VTK_INSTALL_LIBRARY_DIR} ARCHIVE DESTINATION ${VTK_INSTALL_ARCHIVE_DIR} )
+
+INSTALL(FILES VTKToMEDMem.hxx DESTINATION ${MEDWRITER_INSTALL_HEADERS})
+
+SET(_${PROJECT_NAME}_exposed_targets VTKToMEDMem)
+EXPORT(TARGETS ${_${PROJECT_NAME}_exposed_targets} FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake)
diff --git a/src/Plugins/MEDWriter/IO/VTKToMEDMem.cxx b/src/Plugins/MEDWriter/IO/VTKToMEDMem.cxx
new file mode 100644 (file)
index 0000000..c3d20a9
--- /dev/null
@@ -0,0 +1,948 @@
+// Copyright (C) 2017  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, or (at your option) any later version.
+//
+// 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
+//
+// Author : Anthony Geay (EDF R&D)
+
+#include "VTKToMEDMem.hxx"
+
+#include "vtkAdjacentVertexIterator.h"
+#include "vtkIntArray.h"
+#include "vtkLongArray.h"
+#include "vtkCellData.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+#include "vtkCellArray.h"
+
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkInformationDataObjectMetaDataKey.h"
+#include "vtkUnstructuredGrid.h"
+#include "vtkMultiBlockDataSet.h"
+#include "vtkRectilinearGrid.h"
+#include "vtkInformationStringKey.h"
+#include "vtkAlgorithmOutput.h"
+#include "vtkObjectFactory.h"
+#include "vtkMutableDirectedGraph.h"
+#include "vtkMultiBlockDataSet.h"
+#include "vtkPolyData.h"
+#include "vtkDataSet.h"
+#include "vtkInformationVector.h"
+#include "vtkInformation.h"
+#include "vtkDataArraySelection.h"
+#include "vtkTimeStamp.h"
+#include "vtkInEdgeIterator.h"
+#include "vtkInformationDataObjectKey.h"
+#include "vtkExecutive.h"
+#include "vtkVariantArray.h"
+#include "vtkStringArray.h"
+#include "vtkDoubleArray.h"
+#include "vtkCharArray.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkDataSetAttributes.h"
+#include "vtkDemandDrivenPipeline.h"
+#include "vtkDataObjectTreeIterator.h"
+#include "vtkWarpScalar.h"
+
+#include <map>
+#include <deque>
+#include <sstream>
+#include <cstring>
+
+using VTKToMEDMem::Grp;
+using VTKToMEDMem::Fam;
+
+using MEDCoupling::MEDFileData;
+using MEDCoupling::MEDFileMesh;
+using MEDCoupling::MEDFileCMesh;
+using MEDCoupling::MEDFileUMesh;
+using MEDCoupling::MEDFileFields;
+using MEDCoupling::MEDFileMeshes;
+
+using MEDCoupling::MEDFileIntField1TS;
+using MEDCoupling::MEDFileField1TS;
+using MEDCoupling::MEDFileIntFieldMultiTS;
+using MEDCoupling::MEDFileFieldMultiTS;
+using MEDCoupling::MEDFileAnyTypeFieldMultiTS;
+using MEDCoupling::DataArray;
+using MEDCoupling::DataArrayInt;
+using MEDCoupling::DataArrayFloat;
+using MEDCoupling::DataArrayDouble;
+using MEDCoupling::MEDCouplingMesh;
+using MEDCoupling::MEDCouplingUMesh;
+using MEDCoupling::MEDCouplingCMesh;
+using MEDCoupling::MEDCouplingFieldDouble;
+using MEDCoupling::MEDCouplingFieldFloat;
+using MEDCoupling::MEDCouplingFieldInt;
+using MEDCoupling::MCAuto;
+using MEDCoupling::Traits;
+using MEDCoupling::MLFieldTraits;
+
+///////////////////
+
+Fam::Fam(const std::string& name)
+{
+  static const char ZE_SEP[]="@@][@@";
+  std::size_t pos(name.find(ZE_SEP));
+  std::string name0(name.substr(0,pos)),name1(name.substr(pos+strlen(ZE_SEP)));
+  std::istringstream iss(name1);
+  iss >> _id;
+  _name=name0;
+}
+
+///////////////////
+
+template<class T>
+class MEDFileVTKTraits
+{
+public:
+  typedef void VtkType;
+  typedef void MCType;
+};
+
+template<>
+class MEDFileVTKTraits<int>
+{
+public:
+  typedef vtkIntArray VtkType;
+  typedef MEDCoupling::DataArrayInt MCType;
+};
+
+template<>
+class MEDFileVTKTraits<float>
+{
+public:
+  typedef vtkFloatArray VtkType;
+  typedef MEDCoupling::DataArrayFloat MCType;
+};
+
+template<>
+class MEDFileVTKTraits<double>
+{
+public:
+  typedef vtkDoubleArray VtkType;
+  typedef MEDCoupling::DataArrayDouble MCType;
+};
+
+std::map<int,int> ComputeMapOfType()
+{
+  std::map<int,int> ret;
+  int nbOfTypesInMC(sizeof(MEDCouplingUMesh::MEDCOUPLING2VTKTYPETRADUCER)/sizeof(int));
+  for(int i=0;i<nbOfTypesInMC;i++)
+    {
+      int vtkId(MEDCouplingUMesh::MEDCOUPLING2VTKTYPETRADUCER[i]);
+      if(vtkId!=-1)
+        ret[vtkId]=i;
+    }
+  return ret;
+}
+
+std::string GetMeshNameWithContext(const std::vector<int>& context)
+{
+  static const char DFT_MESH_NAME[]="Mesh";
+  if(context.empty())
+    return DFT_MESH_NAME;
+  std::ostringstream oss; oss << DFT_MESH_NAME;
+  for(std::vector<int>::const_iterator it=context.begin();it!=context.end();it++)
+    oss << "_" << *it;
+  return oss.str();
+}
+
+DataArrayInt *ConvertVTKArrayToMCArrayInt(vtkDataArray *data)
+{
+  if(!data)
+    throw MZCException("ConvertVTKArrayToMCArrayInt : internal error !");
+  int nbTuples(data->GetNumberOfTuples()),nbComp(data->GetNumberOfComponents());
+  std::size_t nbElts(nbTuples*nbComp);
+  MCAuto<DataArrayInt> ret(DataArrayInt::New());
+  ret->alloc(nbTuples,nbComp);
+  for(int i=0;i<nbComp;i++)
+    {
+      const char *comp(data->GetComponentName(i));
+      if(comp)
+        ret->setInfoOnComponent(i,comp);
+    }
+  int *ptOut(ret->getPointer());
+  vtkIntArray *d0(vtkIntArray::SafeDownCast(data));
+  if(d0)
+    {
+      const int *pt(d0->GetPointer(0));
+      std::copy(pt,pt+nbElts,ptOut);
+      return ret.retn();
+    }
+  vtkLongArray *d1(vtkLongArray::SafeDownCast(data));
+  if(d1)
+    {
+      const long *pt(d1->GetPointer(0));
+      std::copy(pt,pt+nbElts,ptOut);
+      return ret.retn();
+    }
+  vtkUnsignedCharArray *d2(vtkUnsignedCharArray::SafeDownCast(data));
+  if(d2)
+    {
+      const unsigned char *pt(d2->GetPointer(0));
+      std::copy(pt,pt+nbElts,ptOut);
+      return ret.retn();
+    }
+  std::ostringstream oss;
+  oss << "ConvertVTKArrayToMCArrayInt : unrecognized array \"" << typeid(*data).name() << "\" type !";
+  throw MZCException(oss.str());
+}
+
+template<class T>
+typename Traits<T>::ArrayType *ConvertVTKArrayToMCArrayDouble(vtkDataArray *data)
+{
+  if(!data)
+    throw MZCException("ConvertVTKArrayToMCArrayDouble : internal error !");
+  int nbTuples(data->GetNumberOfTuples()),nbComp(data->GetNumberOfComponents());
+  std::size_t nbElts(nbTuples*nbComp);
+  MCAuto< typename Traits<T>::ArrayType > ret(Traits<T>::ArrayType::New());
+  ret->alloc(nbTuples,nbComp);
+  for(int i=0;i<nbComp;i++)
+    {
+      const char *comp(data->GetComponentName(i));
+      if(comp)
+        ret->setInfoOnComponent(i,comp);
+      else
+        {
+          if(nbComp>1 && nbComp<=3)
+            {
+              char tmp[2];
+              tmp[0]='X'+i; tmp[1]='\0';
+              ret->setInfoOnComponent(i,tmp);
+            }
+        }
+    }
+  T *ptOut(ret->getPointer());
+  typename MEDFileVTKTraits<T>::VtkType *d0(MEDFileVTKTraits<T>::VtkType::SafeDownCast(data));
+  if(d0)
+    {
+      const T *pt(d0->GetPointer(0));
+      for(std::size_t i=0;i<nbElts;i++)
+        ptOut[i]=(T)pt[i];
+      return ret.retn();
+    }
+  std::ostringstream oss;
+  oss << "ConvertVTKArrayToMCArrayDouble : unrecognized array \"" << data->GetClassName() << "\" type !";
+  throw MZCException(oss.str());
+}
+
+DataArrayDouble *ConvertVTKArrayToMCArrayDoubleForced(vtkDataArray *data)
+{
+  if(!data)
+    throw MZCException("ConvertVTKArrayToMCArrayDoubleForced : internal error 0 !");
+  vtkFloatArray *d0(vtkFloatArray::SafeDownCast(data));
+  if(d0)
+    {
+      MCAuto<DataArrayFloat> ret(ConvertVTKArrayToMCArrayDouble<float>(data));
+      MCAuto<DataArrayDouble> ret2(ret->convertToDblArr());
+      return ret2.retn();
+    }
+  vtkDoubleArray *d1(vtkDoubleArray::SafeDownCast(data));
+  if(d1)
+    return ConvertVTKArrayToMCArrayDouble<double>(data);
+  throw MZCException("ConvertVTKArrayToMCArrayDoubleForced : unrecognized type of data for double !");
+}
+
+DataArray *ConvertVTKArrayToMCArray(vtkDataArray *data)
+{
+  if(!data)
+    throw MZCException("ConvertVTKArrayToMCArray : internal error !");
+  vtkFloatArray *d0(vtkFloatArray::SafeDownCast(data));
+  if(d0)
+    return ConvertVTKArrayToMCArrayDouble<float>(data);
+  vtkDoubleArray *d1(vtkDoubleArray::SafeDownCast(data));
+  if(d1)
+    return ConvertVTKArrayToMCArrayDouble<double>(data);
+  vtkIntArray *d2(vtkIntArray::SafeDownCast(data));
+  vtkLongArray *d3(vtkLongArray::SafeDownCast(data));
+  vtkUnsignedCharArray *d4(vtkUnsignedCharArray::SafeDownCast(data));
+  if(d2 || d3 || d4)
+    return ConvertVTKArrayToMCArrayInt(data);
+  std::ostringstream oss;
+  oss << "ConvertVTKArrayToMCArray : unrecognized array \"" << typeid(*data).name() << "\" type !";
+  throw MZCException(oss.str());
+}
+
+MEDCouplingUMesh *BuildMeshFromCellArray(vtkCellArray *ca, DataArrayDouble *coords, int meshDim, INTERP_KERNEL::NormalizedCellType type)
+{
+  MCAuto<MEDCouplingUMesh> subMesh(MEDCouplingUMesh::New("",meshDim));
+  subMesh->setCoords(coords); subMesh->allocateCells();
+  int nbCells(ca->GetNumberOfCells());
+  if(nbCells==0)
+    return 0;
+  vtkIdType nbEntries(ca->GetNumberOfConnectivityEntries());
+  const vtkIdType *conn(ca->GetPointer());
+  for(int i=0;i<nbCells;i++)
+    {
+      int sz(*conn++);
+      std::vector<int> conn2(sz);
+      for(int jj=0;jj<sz;jj++)
+        conn2[jj]=conn[jj];
+      subMesh->insertNextCell(type,sz,&conn2[0]);
+      conn+=sz;
+    }
+  return subMesh.retn();
+}
+
+MEDCouplingUMesh *BuildMeshFromCellArrayTriangleStrip(vtkCellArray *ca, DataArrayDouble *coords, MCAuto<DataArrayInt>& ids)
+{
+  MCAuto<MEDCouplingUMesh> subMesh(MEDCouplingUMesh::New("",2));
+  subMesh->setCoords(coords); subMesh->allocateCells();
+  int nbCells(ca->GetNumberOfCells());
+  if(nbCells==0)
+    return 0;
+  vtkIdType nbEntries(ca->GetNumberOfConnectivityEntries());
+  const vtkIdType *conn(ca->GetPointer());
+  ids=DataArrayInt::New() ; ids->alloc(0,1);
+  for(int i=0;i<nbCells;i++)
+    {
+      int sz(*conn++);
+      int nbTri(sz-2);
+      if(nbTri>0)
+        {
+          for(int j=0;j<nbTri;j++,conn++)
+            {
+              int conn2[3]; conn2[0]=conn[0] ; conn2[1]=conn[1] ; conn2[2]=conn[2];
+              subMesh->insertNextCell(INTERP_KERNEL::NORM_TRI3,3,conn2);
+              ids->pushBackSilent(i);
+            }
+        }
+      else
+        {
+          std::ostringstream oss; oss << "BuildMeshFromCellArrayTriangleStrip : on cell #" << i << " the triangle stip looks bab !";
+          throw MZCException(oss.str());
+        }
+      conn+=sz;
+    }
+  return subMesh.retn();
+}
+
+class MicroField
+{
+public:
+  MicroField(const MCAuto<MEDCouplingUMesh>& m, const std::vector<MCAuto<DataArray> >& cellFs):_m(m),_cellFs(cellFs) { }
+  MicroField(const std::vector< MicroField >& vs);
+  void setNodeFields(const std::vector<MCAuto<DataArray> >& nf) { _nodeFs=nf; }
+  MCAuto<MEDCouplingUMesh> getMesh() const { return _m; }
+  std::vector<MCAuto<DataArray> > getCellFields() const { return _cellFs; }
+private:
+  MCAuto<MEDCouplingUMesh> _m;
+  std::vector<MCAuto<DataArray> > _cellFs;
+  std::vector<MCAuto<DataArray> > _nodeFs;
+};
+
+MicroField::MicroField(const std::vector< MicroField >& vs)
+{
+  std::size_t sz(vs.size());
+  std::vector<const MEDCouplingUMesh *> vs2(sz);
+  std::vector< std::vector< MCAuto<DataArray> > > arrs2(sz);
+  int nbElts(-1);
+  for(std::size_t ii=0;ii<sz;ii++)
+    {
+      vs2[ii]=vs[ii].getMesh();
+      arrs2[ii]=vs[ii].getCellFields();
+      if(nbElts<0)
+        nbElts=arrs2[ii].size();
+      else
+        if(arrs2[ii].size()!=nbElts)
+          throw MZCException("MicroField cstor : internal error !");
+    }
+  _cellFs.resize(nbElts);
+  for(int ii=0;ii<nbElts;ii++)
+    {
+      std::vector<const DataArray *> arrsTmp(sz);
+      for(std::size_t jj=0;jj<sz;jj++)
+        {
+          arrsTmp[jj]=arrs2[jj][ii];
+        }
+      _cellFs[ii]=DataArray::Aggregate(arrsTmp);
+    }
+  _m=MEDCouplingUMesh::MergeUMeshesOnSameCoords(vs2);
+}
+
+template<class T>
+void AppendToFields(MEDCoupling::TypeOfField tf, MEDCouplingMesh *mesh, const DataArrayInt *n2oPtr, typename MEDFileVTKTraits<T>::MCType *dadPtr, MEDFileFields *fs, double timeStep, int tsId)
+{
+  std::string fieldName(dadPtr->getName());
+  MCAuto< typename Traits<T>::FieldType > f(Traits<T>::FieldType::New(tf));
+  f->setTime(timeStep,tsId,0);
+  {
+    std::string fieldNameForChuckNorris(MEDCoupling::MEDFileAnyTypeField1TSWithoutSDA::FieldNameToMEDFileConvention(fieldName));
+    f->setName(fieldNameForChuckNorris);
+  }
+  if(!n2oPtr)
+    f->setArray(dadPtr);
+  else
+    {
+      MCAuto< typename Traits<T>::ArrayType > dad2(dadPtr->selectByTupleId(n2oPtr->begin(),n2oPtr->end()));
+      f->setArray(dad2);
+    }
+  f->setMesh(mesh);
+  MCAuto< typename MLFieldTraits<T>::FMTSType > fmts(MLFieldTraits<T>::FMTSType::New());
+  MCAuto< typename MLFieldTraits<T>::F1TSType > f1ts(MLFieldTraits<T>::F1TSType::New());
+  f1ts->setFieldNoProfileSBT(f);
+  fmts->pushBackTimeStep(f1ts);
+  fs->pushField(fmts);
+}
+
+void AppendMCFieldFrom(MEDCoupling::TypeOfField tf, MEDCouplingMesh *mesh, MEDFileData *mfd, MCAuto<DataArray> da, const DataArrayInt *n2oPtr, double timeStep, int tsId)
+{
+  static const char FAMFIELD_FOR_CELLS[]="FamilyIdCell";
+  static const char FAMFIELD_FOR_NODES[]="FamilyIdNode";
+  if(!da || !mesh || !mfd)
+    throw MZCException("AppendMCFieldFrom : internal error !");
+  MEDFileFields *fs(mfd->getFields());
+  MEDFileMeshes *ms(mfd->getMeshes());
+  if(!fs || !ms)
+    throw MZCException("AppendMCFieldFrom : internal error 2 !");
+  MCAuto<DataArrayDouble> dad(MEDCoupling::DynamicCast<DataArray,DataArrayDouble>(da));
+  if(dad.isNotNull())
+    {
+      AppendToFields<double>(tf,mesh,n2oPtr,dad,fs,timeStep,tsId);
+      return ;
+    }
+  MCAuto<DataArrayFloat> daf(MEDCoupling::DynamicCast<DataArray,DataArrayFloat>(da));
+  if(daf.isNotNull())
+    {
+      AppendToFields<float>(tf,mesh,n2oPtr,daf,fs,timeStep,tsId);
+      return ;
+    }
+  MCAuto<DataArrayInt> dai(MEDCoupling::DynamicCast<DataArray,DataArrayInt>(da));
+  if(dai.isNotNull())
+    {
+      std::string fieldName(dai->getName());
+      if((fieldName!=FAMFIELD_FOR_CELLS || tf!=MEDCoupling::ON_CELLS) && (fieldName!=FAMFIELD_FOR_NODES || tf!=MEDCoupling::ON_NODES))
+        {
+          AppendToFields<int>(tf,mesh,n2oPtr,dai,fs,timeStep,tsId);
+          return ;
+        }
+      else if(fieldName==FAMFIELD_FOR_CELLS && tf==MEDCoupling::ON_CELLS)
+        {
+          MEDFileMesh *mm(ms->getMeshWithName(mesh->getName()));
+          if(!mm)
+            throw MZCException("AppendMCFieldFrom : internal error 3 !");
+          if(!n2oPtr)
+            mm->setFamilyFieldArr(mesh->getMeshDimension()-mm->getMeshDimension(),dai);
+          else
+            {
+              MCAuto<DataArrayInt> dai2(dai->selectByTupleId(n2oPtr->begin(),n2oPtr->end()));
+              mm->setFamilyFieldArr(mesh->getMeshDimension()-mm->getMeshDimension(),dai2);
+            }
+        }
+      else if(fieldName==FAMFIELD_FOR_NODES || tf==MEDCoupling::ON_NODES)
+        {
+          MEDFileMesh *mm(ms->getMeshWithName(mesh->getName()));
+          if(!mm)
+            throw MZCException("AppendMCFieldFrom : internal error 4 !");
+          if(!n2oPtr)
+            mm->setFamilyFieldArr(1,dai);
+          else
+            {
+              MCAuto<DataArrayInt> dai2(dai->selectByTupleId(n2oPtr->begin(),n2oPtr->end()));
+              mm->setFamilyFieldArr(1,dai2);
+            }
+        }
+    }
+}
+
+void PutAtLevelDealOrder(MEDFileData *mfd, int meshDimRel, const MicroField& mf, double timeStep, int tsId)
+{
+  if(!mfd)
+    throw MZCException("PutAtLevelDealOrder : internal error !");
+  MEDFileMesh *mm(mfd->getMeshes()->getMeshAtPos(0));
+  MEDFileUMesh *mmu(dynamic_cast<MEDFileUMesh *>(mm));
+  if(!mmu)
+    throw MZCException("PutAtLevelDealOrder : internal error 2 !");
+  MCAuto<MEDCouplingUMesh> mesh(mf.getMesh());
+  mesh->setName(mfd->getMeshes()->getMeshAtPos(0)->getName());
+  MCAuto<DataArrayInt> o2n(mesh->sortCellsInMEDFileFrmt());
+  const DataArrayInt *o2nPtr(o2n);
+  MCAuto<DataArrayInt> n2o;
+  mmu->setMeshAtLevel(meshDimRel,mesh);
+  const DataArrayInt *n2oPtr(0);
+  if(o2n)
+    {
+      n2o=o2n->invertArrayO2N2N2O(mesh->getNumberOfCells());
+      n2oPtr=n2o;
+      if(n2oPtr && n2oPtr->isIota(mesh->getNumberOfCells()))
+        n2oPtr=0;
+      if(n2oPtr)
+        mm->setRenumFieldArr(meshDimRel,n2o);
+    }
+  //
+  std::vector<MCAuto<DataArray> > cells(mf.getCellFields());
+  for(std::vector<MCAuto<DataArray> >::const_iterator it=cells.begin();it!=cells.end();it++)
+    {
+      MCAuto<DataArray> da(*it);
+      AppendMCFieldFrom(MEDCoupling::ON_CELLS,mesh,mfd,da,n2oPtr,timeStep,tsId);
+    }
+}
+
+void AssignSingleGTMeshes(MEDFileData *mfd, const std::vector< MicroField >& ms, double timeStep, int tsId)
+{
+  if(!mfd)
+    throw MZCException("AssignSingleGTMeshes : internal error !");
+  MEDFileMesh *mm0(mfd->getMeshes()->getMeshAtPos(0));
+  MEDFileUMesh *mm(dynamic_cast<MEDFileUMesh *>(mm0));
+  if(!mm)
+    throw MZCException("AssignSingleGTMeshes : internal error 2 !");
+  int meshDim(-std::numeric_limits<int>::max());
+  std::map<int, std::vector< MicroField > > ms2;
+  for(std::vector< MicroField >::const_iterator it=ms.begin();it!=ms.end();it++)
+    {
+      const MEDCouplingUMesh *elt((*it).getMesh());
+      if(elt)
+        {
+          int myMeshDim(elt->getMeshDimension());
+          meshDim=std::max(meshDim,myMeshDim);
+          ms2[myMeshDim].push_back(*it);
+        }
+    }
+  if(ms2.empty())
+    return ;
+  for(std::map<int, std::vector< MicroField > >::const_iterator it=ms2.begin();it!=ms2.end();it++)
+    {
+      const std::vector< MicroField >& vs((*it).second);
+      if(vs.size()==1)
+        {
+          PutAtLevelDealOrder(mfd,(*it).first-meshDim,vs[0],timeStep,tsId);
+        }
+      else
+        {
+          MicroField merge(vs);
+          PutAtLevelDealOrder(mfd,(*it).first-meshDim,merge,timeStep,tsId);
+        }
+    }
+}
+
+DataArrayDouble *BuildCoordsFrom(vtkPointSet *ds)
+{
+  if(!ds)
+    throw MZCException("BuildCoordsFrom : internal error !");
+  vtkPoints *pts(ds->GetPoints());
+  if(!pts)
+    throw MZCException("BuildCoordsFrom : internal error 2 !");
+  vtkDataArray *data(pts->GetData());
+  if(!data)
+    throw MZCException("BuildCoordsFrom : internal error 3 !");
+  return ConvertVTKArrayToMCArrayDoubleForced(data);
+}
+
+void AddNodeFields(MEDFileData *mfd, vtkDataSetAttributes *dsa, double timeStep, int tsId)
+{
+  if(!mfd || !dsa)
+    throw MZCException("AddNodeFields : internal error !");
+  MEDFileMesh *mm(mfd->getMeshes()->getMeshAtPos(0));
+  MEDFileUMesh *mmu(dynamic_cast<MEDFileUMesh *>(mm));
+  if(!mmu)
+    throw MZCException("AddNodeFields : internal error 2 !");
+  MCAuto<MEDCouplingUMesh> mesh;
+  if(!mmu->getNonEmptyLevels().empty())
+    mesh=mmu->getMeshAtLevel(0);
+  else
+    {
+      mesh=MEDCouplingUMesh::Build0DMeshFromCoords(mmu->getCoords());
+      mesh->setName(mmu->getName());
+    }
+  int nba(dsa->GetNumberOfArrays());
+  for(int i=0;i<nba;i++)
+    {
+      vtkDataArray *arr(dsa->GetArray(i));
+      const char *name(arr->GetName());
+      if(!arr)
+        continue;
+      MCAuto<DataArray> da(ConvertVTKArrayToMCArray(arr));
+      da->setName(name);
+      AppendMCFieldFrom(MEDCoupling::ON_NODES,mesh,mfd,da,NULL,timeStep,tsId);
+    }
+}
+
+std::vector<MCAuto<DataArray> > AddPartFields(const DataArrayInt *part, vtkDataSetAttributes *dsa)
+{
+  std::vector< MCAuto<DataArray> > ret;
+  if(!dsa)
+    return ret;
+  int nba(dsa->GetNumberOfArrays());
+  for(int i=0;i<nba;i++)
+    {
+      vtkDataArray *arr(dsa->GetArray(i));
+      if(!arr)
+        continue;
+      const char *name(arr->GetName());
+      int nbCompo(arr->GetNumberOfComponents());
+      vtkIdType nbTuples(arr->GetNumberOfTuples());
+      MCAuto<DataArray> mcarr(ConvertVTKArrayToMCArray(arr));
+      if(part)
+        mcarr=mcarr->selectByTupleId(part->begin(),part->end());
+      mcarr->setName(name);
+      ret.push_back(mcarr);
+    }
+  return ret;
+}
+
+std::vector<MCAuto<DataArray> > AddPartFields2(int bg, int end, vtkDataSetAttributes *dsa)
+{
+  std::vector< MCAuto<DataArray> > ret;
+  if(!dsa)
+    return ret;
+  int nba(dsa->GetNumberOfArrays());
+  for(int i=0;i<nba;i++)
+    {
+      vtkDataArray *arr(dsa->GetArray(i));
+      if(!arr)
+        continue;
+      const char *name(arr->GetName());
+      int nbCompo(arr->GetNumberOfComponents());
+      vtkIdType nbTuples(arr->GetNumberOfTuples());
+      MCAuto<DataArray> mcarr(ConvertVTKArrayToMCArray(arr));
+      mcarr=mcarr->selectByTupleIdSafeSlice(bg,end,1);
+      mcarr->setName(name);
+      ret.push_back(mcarr);
+    }
+  return ret;
+}
+
+void ConvertFromRectilinearGrid(MEDFileData *ret, vtkRectilinearGrid *ds, const std::vector<int>& context, double timeStep, int tsId)
+{
+  if(!ds || !ret)
+    throw MZCException("ConvertFromRectilinearGrid : internal error !");
+  //
+  MCAuto<MEDFileMeshes> meshes(MEDFileMeshes::New());
+  ret->setMeshes(meshes);
+  MCAuto<MEDFileFields> fields(MEDFileFields::New());
+  ret->setFields(fields);
+  //
+  MCAuto<MEDFileCMesh> cmesh(MEDFileCMesh::New());
+  meshes->pushMesh(cmesh);
+  MCAuto<MEDCouplingCMesh> cmeshmc(MEDCouplingCMesh::New());
+  vtkDataArray *cx(ds->GetXCoordinates()),*cy(ds->GetYCoordinates()),*cz(ds->GetZCoordinates());
+  if(cx)
+    {
+      MCAuto<DataArrayDouble> arr(ConvertVTKArrayToMCArrayDoubleForced(cx));
+      cmeshmc->setCoordsAt(0,arr);
+    }
+  if(cy)
+    {
+      MCAuto<DataArrayDouble> arr(ConvertVTKArrayToMCArrayDoubleForced(cy));
+      cmeshmc->setCoordsAt(1,arr);
+    }
+  if(cz)
+    {
+      MCAuto<DataArrayDouble> arr(ConvertVTKArrayToMCArrayDoubleForced(cz));
+      cmeshmc->setCoordsAt(2,arr);
+    }
+  std::string meshName(GetMeshNameWithContext(context));
+  cmeshmc->setName(meshName);
+  cmesh->setMesh(cmeshmc);
+  std::vector<MCAuto<DataArray> > cellFs(AddPartFields(0,ds->GetCellData()));
+  for(std::vector<MCAuto<DataArray> >::const_iterator it=cellFs.begin();it!=cellFs.end();it++)
+    {
+      MCAuto<DataArray> da(*it);
+      AppendMCFieldFrom(MEDCoupling::ON_CELLS,cmeshmc,ret,da,NULL,timeStep,tsId);
+    }
+  std::vector<MCAuto<DataArray> > nodeFs(AddPartFields(0,ds->GetPointData()));
+  for(std::vector<MCAuto<DataArray> >::const_iterator it=nodeFs.begin();it!=nodeFs.end();it++)
+    {
+      MCAuto<DataArray> da(*it);
+      AppendMCFieldFrom(MEDCoupling::ON_NODES,cmeshmc,ret,da,NULL,timeStep,tsId);
+    }
+}
+
+void ConvertFromPolyData(MEDFileData *ret, vtkPolyData *ds, const std::vector<int>& context, double timeStep, int tsId)
+{
+  if(!ds || !ret)
+    throw MZCException("ConvertFromPolyData : internal error !");
+  //
+  MCAuto<MEDFileMeshes> meshes(MEDFileMeshes::New());
+  ret->setMeshes(meshes);
+  MCAuto<MEDFileFields> fields(MEDFileFields::New());
+  ret->setFields(fields);
+  //
+  MCAuto<MEDFileUMesh> umesh(MEDFileUMesh::New());
+  meshes->pushMesh(umesh);
+  MCAuto<DataArrayDouble> coords(BuildCoordsFrom(ds));
+  umesh->setCoords(coords);
+  umesh->setName(GetMeshNameWithContext(context));
+  //
+  int offset(0);
+  std::vector< MicroField > ms;
+  vtkCellArray *cd(ds->GetVerts());
+  if(cd)
+    {
+      MCAuto<MEDCouplingUMesh> subMesh(BuildMeshFromCellArray(cd,coords,0,INTERP_KERNEL::NORM_POINT1));
+      if((const MEDCouplingUMesh *)subMesh)
+        {
+          std::vector<MCAuto<DataArray> > cellFs(AddPartFields2(offset,offset+subMesh->getNumberOfCells(),ds->GetCellData()));
+          offset+=subMesh->getNumberOfCells();
+          ms.push_back(MicroField(subMesh,cellFs));
+        }
+    }
+  vtkCellArray *cc(ds->GetLines());
+  if(cc)
+    {
+      MCAuto<MEDCouplingUMesh> subMesh(BuildMeshFromCellArray(cc,coords,1,INTERP_KERNEL::NORM_SEG2));
+      if((const MEDCouplingUMesh *)subMesh)
+        {
+          std::vector<MCAuto<DataArray> > cellFs(AddPartFields2(offset,offset+subMesh->getNumberOfCells(),ds->GetCellData()));
+          offset+=subMesh->getNumberOfCells();
+          ms.push_back(MicroField(subMesh,cellFs));
+        }
+    }
+  vtkCellArray *cb(ds->GetPolys());
+  if(cb)
+    {
+      MCAuto<MEDCouplingUMesh> subMesh(BuildMeshFromCellArray(cb,coords,2,INTERP_KERNEL::NORM_POLYGON));
+      if((const MEDCouplingUMesh *)subMesh)
+        {
+          std::vector<MCAuto<DataArray> > cellFs(AddPartFields2(offset,offset+subMesh->getNumberOfCells(),ds->GetCellData()));
+          offset+=subMesh->getNumberOfCells();
+          ms.push_back(MicroField(subMesh,cellFs));
+        }
+    }
+  vtkCellArray *ca(ds->GetStrips());
+  if(ca)
+    {
+      MCAuto<DataArrayInt> ids;
+      MCAuto<MEDCouplingUMesh> subMesh(BuildMeshFromCellArrayTriangleStrip(ca,coords,ids));
+      if((const MEDCouplingUMesh *)subMesh)
+        {
+          std::vector<MCAuto<DataArray> > cellFs(AddPartFields(ids,ds->GetCellData()));
+          offset+=subMesh->getNumberOfCells();
+          ms.push_back(MicroField(subMesh,cellFs));
+        }
+    }
+  AssignSingleGTMeshes(ret,ms,timeStep,tsId);
+  AddNodeFields(ret,ds->GetPointData(),timeStep,tsId);
+}
+
+void ConvertFromUnstructuredGrid(MEDFileData *ret, vtkUnstructuredGrid *ds, const std::vector<int>& context, double timeStep, int tsId)
+{
+  if(!ds || !ret)
+    throw MZCException("ConvertFromUnstructuredGrid : internal error !");
+  //
+  MCAuto<MEDFileMeshes> meshes(MEDFileMeshes::New());
+  ret->setMeshes(meshes);
+  MCAuto<MEDFileFields> fields(MEDFileFields::New());
+  ret->setFields(fields);
+  //
+  MCAuto<MEDFileUMesh> umesh(MEDFileUMesh::New());
+  meshes->pushMesh(umesh);
+  MCAuto<DataArrayDouble> coords(BuildCoordsFrom(ds));
+  umesh->setCoords(coords);
+  umesh->setName(GetMeshNameWithContext(context));
+  vtkIdType nbCells(ds->GetNumberOfCells());
+  vtkCellArray *ca(ds->GetCells());
+  if(!ca)
+    return ;
+  vtkIdType nbEnt(ca->GetNumberOfConnectivityEntries());
+  vtkIdType *caPtr(ca->GetPointer());
+  vtkUnsignedCharArray *ct(ds->GetCellTypesArray());
+  if(!ct)
+    throw MZCException("ConvertFromUnstructuredGrid : internal error");
+  vtkIdTypeArray *cla(ds->GetCellLocationsArray());
+  const vtkIdType *claPtr(cla->GetPointer(0));
+  if(!cla)
+    throw MZCException("ConvertFromUnstructuredGrid : internal error 2");
+  const unsigned char *ctPtr(ct->GetPointer(0));
+  std::map<int,int> m(ComputeMapOfType());
+  MCAuto<DataArrayInt> lev(DataArrayInt::New()) ;  lev->alloc(nbCells,1);
+  int *levPtr(lev->getPointer());
+  for(vtkIdType i=0;i<nbCells;i++)
+    {
+      std::map<int,int>::iterator it(m.find(ctPtr[i]));
+      if(it!=m.end())
+        {
+          const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)(*it).second));
+          levPtr[i]=cm.getDimension();
+        }
+      else
+        {
+          std::ostringstream oss; oss << "ConvertFromUnstructuredGrid : at pos #" << i << " unrecognized VTK cell with type =" << ctPtr[i];
+          throw MZCException(oss.str());
+        }
+    }
+  int dummy(0);
+  MCAuto<DataArrayInt> levs(lev->getDifferentValues());
+  std::vector< MicroField > ms;
+  vtkIdTypeArray *faces(ds->GetFaces()),*faceLoc(ds->GetFaceLocations());
+  for(const int *curLev=levs->begin();curLev!=levs->end();curLev++)
+    {
+      MCAuto<MEDCouplingUMesh> m0(MEDCouplingUMesh::New("",*curLev));
+      m0->setCoords(coords); m0->allocateCells();
+      MCAuto<DataArrayInt> cellIdsCurLev(lev->findIdsEqual(*curLev));
+      for(const int *cellId=cellIdsCurLev->begin();cellId!=cellIdsCurLev->end();cellId++)
+        {
+          std::map<int,int>::iterator it(m.find(ctPtr[*cellId]));
+          vtkIdType offset(claPtr[*cellId]);
+          vtkIdType sz(caPtr[offset]);
+          INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)(*it).second);
+          if(ct!=INTERP_KERNEL::NORM_POLYHED)
+            {
+              std::vector<int> conn2(sz);
+              for(int kk=0;kk<sz;kk++)
+                conn2[kk]=caPtr[offset+1+kk];
+              m0->insertNextCell(ct,sz,&conn2[0]);
+            }
+          else
+            {
+              if(!faces || !faceLoc)
+                throw MZCException("ConvertFromUnstructuredGrid : faces are expected when there are polyhedra !");
+              const vtkIdType *facPtr(faces->GetPointer(0)),*facLocPtr(faceLoc->GetPointer(0));
+              std::vector<int> conn;
+              int off0(facLocPtr[*cellId]);
+              int nbOfFaces(facPtr[off0++]);
+              for(int k=0;k<nbOfFaces;k++)
+                {
+                  int nbOfNodesInFace(facPtr[off0++]);
+                  std::copy(facPtr+off0,facPtr+off0+nbOfNodesInFace,std::back_inserter(conn));
+                  off0+=nbOfNodesInFace;
+                  if(k<nbOfFaces-1)
+                    conn.push_back(-1);
+                }
+              m0->insertNextCell(ct,conn.size(),&conn[0]);
+            }
+        }
+      std::vector<MCAuto<DataArray> > cellFs(AddPartFields(cellIdsCurLev,ds->GetCellData()));
+      ms.push_back(MicroField(m0,cellFs));
+    }
+  AssignSingleGTMeshes(ret,ms,timeStep,tsId);
+  AddNodeFields(ret,ds->GetPointData(),timeStep,tsId);
+}
+
+///////////////////
+
+void WriteMEDFileFromVTKDataSet(MEDFileData *mfd, vtkDataSet *ds, const std::vector<int>& context, double timeStep, int tsId)
+{
+  if(!ds || !mfd)
+    throw MZCException("Internal error in WriteMEDFileFromVTKDataSet.");
+  vtkPolyData *ds2(vtkPolyData::SafeDownCast(ds));
+  vtkUnstructuredGrid *ds3(vtkUnstructuredGrid::SafeDownCast(ds));
+  vtkRectilinearGrid *ds4(vtkRectilinearGrid::SafeDownCast(ds));
+  if(ds2)
+    {
+      ConvertFromPolyData(mfd,ds2,context,timeStep,tsId);
+    }
+  else if(ds3)
+    {
+      ConvertFromUnstructuredGrid(mfd,ds3,context,timeStep,tsId);
+    }
+  else if(ds4)
+    {
+      ConvertFromRectilinearGrid(mfd,ds4,context,timeStep,tsId);
+    }
+  else
+    throw MZCException("Unrecognized vtkDataSet ! Sorry ! Try to convert it to UnstructuredGrid to be able to write it !");
+}
+
+void WriteMEDFileFromVTKMultiBlock(MEDFileData *mfd, vtkMultiBlockDataSet *ds, const std::vector<int>& context, double timeStep, int tsId)
+{
+  if(!ds || !mfd)
+    throw MZCException("Internal error in WriteMEDFileFromVTKMultiBlock.");
+  int nbBlocks(ds->GetNumberOfBlocks());
+  if(nbBlocks==1 && context.empty())
+    {
+      vtkDataObject *uniqueElt(ds->GetBlock(0));
+      if(!uniqueElt)
+        throw MZCException("Unique elt in multiblock is NULL !");
+      vtkDataSet *uniqueEltc(vtkDataSet::SafeDownCast(uniqueElt));
+      if(uniqueEltc)
+        {
+          WriteMEDFileFromVTKDataSet(mfd,uniqueEltc,context,timeStep,tsId);
+          return ;
+        }
+    }
+  for(int i=0;i<nbBlocks;i++)
+    {
+      vtkDataObject *elt(ds->GetBlock(i));
+      std::vector<int> context2;
+      context2.push_back(i);
+      if(!elt)
+        {
+          std::ostringstream oss; oss << "In context ";
+          std::copy(context.begin(),context.end(),std::ostream_iterator<int>(oss," "));
+          oss << " at pos #" << i << " elt is NULL !";
+          throw MZCException(oss.str());
+        }
+      vtkDataSet *elt1(vtkDataSet::SafeDownCast(elt));
+      if(elt1)
+        {
+          WriteMEDFileFromVTKDataSet(mfd,elt1,context,timeStep,tsId);
+          continue;
+        }
+      vtkMultiBlockDataSet *elt2(vtkMultiBlockDataSet::SafeDownCast(elt));
+      if(elt2)
+        {
+          WriteMEDFileFromVTKMultiBlock(mfd,elt2,context,timeStep,tsId);
+          continue;
+        }
+      std::ostringstream oss; oss << "In context ";
+      std::copy(context.begin(),context.end(),std::ostream_iterator<int>(oss," "));
+      oss << " at pos #" << i << " elt not recognized data type !";
+      throw MZCException(oss.str());
+    }
+}
+
+void WriteMEDFileFromVTKGDS(MEDFileData *mfd, vtkDataObject *input, double timeStep, int tsId)
+{
+  if(!input || !mfd)
+    throw MZCException("WriteMEDFileFromVTKGDS : internal error !");
+  std::vector<int> context;
+  vtkDataSet *input1(vtkDataSet::SafeDownCast(input));
+  if(input1)
+    {
+      WriteMEDFileFromVTKDataSet(mfd,input1,context,timeStep,tsId);
+      return ;
+    }
+  vtkMultiBlockDataSet *input2(vtkMultiBlockDataSet::SafeDownCast(input));
+  if(input2)
+    {
+      WriteMEDFileFromVTKMultiBlock(mfd,input2,context,timeStep,tsId);
+      return ;
+    }
+  throw MZCException("WriteMEDFileFromVTKGDS : not recognized data type !");
+}
+
+void PutFamGrpInfoIfAny(MEDFileData *mfd, const std::string& meshName, const std::vector<Grp>& groups, const std::vector<Fam>& fams)
+{
+  if(!mfd)
+    return ;
+  if(meshName.empty())
+    return ;
+  MEDFileMeshes *meshes(mfd->getMeshes());
+  if(!meshes)
+    return ;
+  if(meshes->getNumberOfMeshes()!=1)
+    return ;
+  MEDFileMesh *mm(meshes->getMeshAtPos(0));
+  if(!mm)
+    return ;
+  mm->setName(meshName);
+  for(std::vector<Fam>::const_iterator it=fams.begin();it!=fams.end();it++)
+    mm->setFamilyId((*it).getName(),(*it).getID());
+  for(std::vector<Grp>::const_iterator it=groups.begin();it!=groups.end();it++)
+    mm->setFamiliesOnGroup((*it).getName(),(*it).getFamilies());
+  MEDFileFields *fields(mfd->getFields());
+  if(!fields)
+    return ;
+  for(int i=0;i<fields->getNumberOfFields();i++)
+    {
+      MEDFileAnyTypeFieldMultiTS *fmts(fields->getFieldAtPos(i));
+      if(!fmts)
+        continue;
+      fmts->setMeshName(meshName);
+    }
+}
diff --git a/src/Plugins/MEDWriter/IO/VTKToMEDMem.hxx b/src/Plugins/MEDWriter/IO/VTKToMEDMem.hxx
new file mode 100644 (file)
index 0000000..5a0def7
--- /dev/null
@@ -0,0 +1,86 @@
+// Copyright (C) 2017  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, or (at your option) any later version.
+//
+// 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
+//
+// Author : Anthony Geay (EDF R&D)
+
+#ifndef __VTKTOMEDMEM_HXX__
+#define __VTKTOMEDMEM_HXX__
+
+#include "MEDFileMesh.hxx"
+#include "MEDFileField.hxx"
+#include "MEDFileData.hxx"
+#include "MEDCouplingMemArray.hxx"
+#include "MEDCouplingFieldInt.hxx"
+#include "MEDCouplingFieldFloat.hxx"
+#include "MEDCouplingFieldDouble.hxx"
+#include "MEDCouplingRefCountObject.hxx"
+#include "MEDLoaderTraits.hxx"
+
+#include <exception>
+#include <string>
+
+///////////////////
+
+class vtkDataSet;
+
+class MZCException : public std::exception
+{
+public:
+  MZCException(const std::string& s):_reason(s) { }
+  virtual const char *what() const throw() { return _reason.c_str(); }
+  virtual ~MZCException() throw() { }
+private:
+  std::string _reason;
+};
+
+namespace VTKToMEDMem
+{
+  class Grp
+  {
+  public:
+    Grp(const std::string& name):_name(name) { }
+    void setFamilies(const std::vector<std::string>& fams) { _fams=fams; }
+    std::string getName() const { return _name; }
+    std::vector<std::string> getFamilies() const { return _fams; }
+  private:
+    std::string _name;
+    std::vector<std::string> _fams;
+  };
+
+  class Fam
+  {
+  public:
+    Fam(const std::string& name);
+    std::string getName() const { return _name; }
+    int getID() const { return _id; }
+  private:
+    std::string _name;
+    int _id;
+  };
+}
+
+class vtkDataObject;
+
+void WriteMEDFileFromVTKDataSet(MEDCoupling::MEDFileData *mfd, vtkDataSet *ds, const std::vector<int>& context, double timeStep, int tsId);
+
+void WriteMEDFileFromVTKGDS(MEDCoupling::MEDFileData *mfd, vtkDataObject *input, double timeStep, int tsId);
+  
+void PutFamGrpInfoIfAny(MEDCoupling::MEDFileData *mfd, const std::string& meshName, const std::vector<VTKToMEDMem::Grp>& groups, const std::vector<VTKToMEDMem::Fam>& fams);
+
+#endif
+
index 9367b11476b0233b0588dd92fd664936b7e92e15..65537b3e262a7ffa2ec74392815b16cc8a617cdd 100644 (file)
@@ -19,6 +19,7 @@
 // Author : Anthony Geay (EDF R&D)
 
 #include "vtkMEDWriter.h"
+#include "VTKToMEDMem.hxx"
 
 #include "vtkAdjacentVertexIterator.h"
 #include "vtkIntArray.h"
 #include <deque>
 #include <sstream>
 
-using MEDCoupling::MEDFileData;
-using MEDCoupling::MEDFileMesh;
-using MEDCoupling::MEDFileCMesh;
-using MEDCoupling::MEDFileUMesh;
-using MEDCoupling::MEDFileFields;
-using MEDCoupling::MEDFileMeshes;
-
-using MEDCoupling::MEDFileIntField1TS;
-using MEDCoupling::MEDFileField1TS;
-using MEDCoupling::MEDFileIntFieldMultiTS;
-using MEDCoupling::MEDFileFieldMultiTS;
-using MEDCoupling::MEDFileAnyTypeFieldMultiTS;
-using MEDCoupling::DataArray;
-using MEDCoupling::DataArrayInt;
-using MEDCoupling::DataArrayFloat;
-using MEDCoupling::DataArrayDouble;
-using MEDCoupling::MEDCouplingMesh;
-using MEDCoupling::MEDCouplingUMesh;
-using MEDCoupling::MEDCouplingCMesh;
-using MEDCoupling::MEDCouplingFieldDouble;
-using MEDCoupling::MEDCouplingFieldFloat;
-using MEDCoupling::MEDCouplingFieldInt;
-using MEDCoupling::MCAuto;
-using MEDCoupling::Traits;
-using MEDCoupling::MLFieldTraits;
-
 vtkStandardNewMacro(vtkMEDWriter);
 
-///////////////////
-
-class MZCException : public std::exception
-{
-public:
-  MZCException(const std::string& s):_reason(s) { }
-  virtual const char *what() const throw() { return _reason.c_str(); }
-  virtual ~MZCException() throw() { }
-private:
-  std::string _reason;
-};
-
-template<class T>
-class MEDFileVTKTraits
-{
-public:
-  typedef void VtkType;
-  typedef void MCType;
-};
-
-template<>
-class MEDFileVTKTraits<int>
-{
-public:
-  typedef vtkIntArray VtkType;
-  typedef MEDCoupling::DataArrayInt MCType;
-};
-
-template<>
-class MEDFileVTKTraits<float>
-{
-public:
-  typedef vtkFloatArray VtkType;
-  typedef MEDCoupling::DataArrayFloat MCType;
-};
-
-template<>
-class MEDFileVTKTraits<double>
-{
-public:
-  typedef vtkDoubleArray VtkType;
-  typedef MEDCoupling::DataArrayDouble MCType;
-};
-
-///////////////////
-
-std::map<int,int> ComputeMapOfType()
-{
-  std::map<int,int> ret;
-  int nbOfTypesInMC(sizeof(MEDCouplingUMesh::MEDCOUPLING2VTKTYPETRADUCER)/sizeof(int));
-  for(int i=0;i<nbOfTypesInMC;i++)
-    {
-      int vtkId(MEDCouplingUMesh::MEDCOUPLING2VTKTYPETRADUCER[i]);
-      if(vtkId!=-1)
-        ret[vtkId]=i;
-    }
-  return ret;
-}
-
-std::string GetMeshNameWithContext(const std::vector<int>& context)
-{
-  static const char DFT_MESH_NAME[]="Mesh";
-  if(context.empty())
-    return DFT_MESH_NAME;
-  std::ostringstream oss; oss << DFT_MESH_NAME;
-  for(std::vector<int>::const_iterator it=context.begin();it!=context.end();it++)
-    oss << "_" << *it;
-  return oss.str();
-}
-
-DataArrayInt *ConvertVTKArrayToMCArrayInt(vtkDataArray *data)
-{
-  if(!data)
-    throw MZCException("ConvertVTKArrayToMCArrayInt : internal error !");
-  int nbTuples(data->GetNumberOfTuples()),nbComp(data->GetNumberOfComponents());
-  std::size_t nbElts(nbTuples*nbComp);
-  MCAuto<DataArrayInt> ret(DataArrayInt::New());
-  ret->alloc(nbTuples,nbComp);
-  for(int i=0;i<nbComp;i++)
-    {
-      const char *comp(data->GetComponentName(i));
-      if(comp)
-        ret->setInfoOnComponent(i,comp);
-    }
-  int *ptOut(ret->getPointer());
-  vtkIntArray *d0(vtkIntArray::SafeDownCast(data));
-  if(d0)
-    {
-      const int *pt(d0->GetPointer(0));
-      std::copy(pt,pt+nbElts,ptOut);
-      return ret.retn();
-    }
-  vtkLongArray *d1(vtkLongArray::SafeDownCast(data));
-  if(d1)
-    {
-      const long *pt(d1->GetPointer(0));
-      std::copy(pt,pt+nbElts,ptOut);
-      return ret.retn();
-    }
-  vtkUnsignedCharArray *d2(vtkUnsignedCharArray::SafeDownCast(data));
-  if(d2)
-    {
-      const unsigned char *pt(d2->GetPointer(0));
-      std::copy(pt,pt+nbElts,ptOut);
-      return ret.retn();
-    }
-  std::ostringstream oss;
-  oss << "ConvertVTKArrayToMCArrayInt : unrecognized array \"" << typeid(*data).name() << "\" type !";
-  throw MZCException(oss.str());
-}
-
-template<class T>
-typename Traits<T>::ArrayType *ConvertVTKArrayToMCArrayDouble(vtkDataArray *data)
-{
-  if(!data)
-    throw MZCException("ConvertVTKArrayToMCArrayDouble : internal error !");
-  int nbTuples(data->GetNumberOfTuples()),nbComp(data->GetNumberOfComponents());
-  std::size_t nbElts(nbTuples*nbComp);
-  MCAuto< typename Traits<T>::ArrayType > ret(Traits<T>::ArrayType::New());
-  ret->alloc(nbTuples,nbComp);
-  for(int i=0;i<nbComp;i++)
-    {
-      const char *comp(data->GetComponentName(i));
-      if(comp)
-        ret->setInfoOnComponent(i,comp);
-      else
-        {
-          if(nbComp>1 && nbComp<=3)
-            {
-              char tmp[2];
-              tmp[0]='X'+i; tmp[1]='\0';
-              ret->setInfoOnComponent(i,tmp);
-            }
-        }
-    }
-  T *ptOut(ret->getPointer());
-  typename MEDFileVTKTraits<T>::VtkType *d0(MEDFileVTKTraits<T>::VtkType::SafeDownCast(data));
-  if(d0)
-    {
-      const T *pt(d0->GetPointer(0));
-      for(std::size_t i=0;i<nbElts;i++)
-        ptOut[i]=(T)pt[i];
-      return ret.retn();
-    }
-  std::ostringstream oss;
-  oss << "ConvertVTKArrayToMCArrayDouble : unrecognized array \"" << data->GetClassName() << "\" type !";
-  throw MZCException(oss.str());
-}
-
-DataArrayDouble *ConvertVTKArrayToMCArrayDoubleForced(vtkDataArray *data)
-{
-  if(!data)
-    throw MZCException("ConvertVTKArrayToMCArrayDoubleForced : internal error 0 !");
-  vtkFloatArray *d0(vtkFloatArray::SafeDownCast(data));
-  if(d0)
-    {
-      MCAuto<DataArrayFloat> ret(ConvertVTKArrayToMCArrayDouble<float>(data));
-      MCAuto<DataArrayDouble> ret2(ret->convertToDblArr());
-      return ret2.retn();
-    }
-  vtkDoubleArray *d1(vtkDoubleArray::SafeDownCast(data));
-  if(d1)
-    return ConvertVTKArrayToMCArrayDouble<double>(data);
-  throw MZCException("ConvertVTKArrayToMCArrayDoubleForced : unrecognized type of data for double !");
-}
-
-DataArray *ConvertVTKArrayToMCArray(vtkDataArray *data)
-{
-  if(!data)
-    throw MZCException("ConvertVTKArrayToMCArray : internal error !");
-  vtkFloatArray *d0(vtkFloatArray::SafeDownCast(data));
-  if(d0)
-    return ConvertVTKArrayToMCArrayDouble<float>(data);
-  vtkDoubleArray *d1(vtkDoubleArray::SafeDownCast(data));
-  if(d1)
-    return ConvertVTKArrayToMCArrayDouble<double>(data);
-  vtkIntArray *d2(vtkIntArray::SafeDownCast(data));
-  vtkLongArray *d3(vtkLongArray::SafeDownCast(data));
-  vtkUnsignedCharArray *d4(vtkUnsignedCharArray::SafeDownCast(data));
-  if(d2 || d3 || d4)
-    return ConvertVTKArrayToMCArrayInt(data);
-  std::ostringstream oss;
-  oss << "ConvertVTKArrayToMCArray : unrecognized array \"" << typeid(*data).name() << "\" type !";
-  throw MZCException(oss.str());
-}
-
-MEDCouplingUMesh *BuildMeshFromCellArray(vtkCellArray *ca, DataArrayDouble *coords, int meshDim, INTERP_KERNEL::NormalizedCellType type)
-{
-  MCAuto<MEDCouplingUMesh> subMesh(MEDCouplingUMesh::New("",meshDim));
-  subMesh->setCoords(coords); subMesh->allocateCells();
-  int nbCells(ca->GetNumberOfCells());
-  if(nbCells==0)
-    return 0;
-  vtkIdType nbEntries(ca->GetNumberOfConnectivityEntries());
-  const vtkIdType *conn(ca->GetPointer());
-  for(int i=0;i<nbCells;i++)
-    {
-      int sz(*conn++);
-      std::vector<int> conn2(sz);
-      for(int jj=0;jj<sz;jj++)
-        conn2[jj]=conn[jj];
-      subMesh->insertNextCell(type,sz,&conn2[0]);
-      conn+=sz;
-    }
-  return subMesh.retn();
-}
-
-MEDCouplingUMesh *BuildMeshFromCellArrayTriangleStrip(vtkCellArray *ca, DataArrayDouble *coords, MCAuto<DataArrayInt>& ids)
-{
-  MCAuto<MEDCouplingUMesh> subMesh(MEDCouplingUMesh::New("",2));
-  subMesh->setCoords(coords); subMesh->allocateCells();
-  int nbCells(ca->GetNumberOfCells());
-  if(nbCells==0)
-    return 0;
-  vtkIdType nbEntries(ca->GetNumberOfConnectivityEntries());
-  const vtkIdType *conn(ca->GetPointer());
-  ids=DataArrayInt::New() ; ids->alloc(0,1);
-  for(int i=0;i<nbCells;i++)
-    {
-      int sz(*conn++);
-      int nbTri(sz-2);
-      if(nbTri>0)
-        {
-          for(int j=0;j<nbTri;j++,conn++)
-            {
-              int conn2[3]; conn2[0]=conn[0] ; conn2[1]=conn[1] ; conn2[2]=conn[2];
-              subMesh->insertNextCell(INTERP_KERNEL::NORM_TRI3,3,conn2);
-              ids->pushBackSilent(i);
-            }
-        }
-      else
-        {
-          std::ostringstream oss; oss << "BuildMeshFromCellArrayTriangleStrip : on cell #" << i << " the triangle stip looks bab !";
-          throw MZCException(oss.str());
-        }
-      conn+=sz;
-    }
-  return subMesh.retn();
-}
-
-class MicroField
-{
-public:
-  MicroField(const MCAuto<MEDCouplingUMesh>& m, const std::vector<MCAuto<DataArray> >& cellFs):_m(m),_cellFs(cellFs) { }
-  MicroField(const std::vector< MicroField >& vs);
-  void setNodeFields(const std::vector<MCAuto<DataArray> >& nf) { _nodeFs=nf; }
-  MCAuto<MEDCouplingUMesh> getMesh() const { return _m; }
-  std::vector<MCAuto<DataArray> > getCellFields() const { return _cellFs; }
-private:
-  MCAuto<MEDCouplingUMesh> _m;
-  std::vector<MCAuto<DataArray> > _cellFs;
-  std::vector<MCAuto<DataArray> > _nodeFs;
-};
-
-MicroField::MicroField(const std::vector< MicroField >& vs)
-{
-  std::size_t sz(vs.size());
-  std::vector<const MEDCouplingUMesh *> vs2(sz);
-  std::vector< std::vector< MCAuto<DataArray> > > arrs2(sz);
-  int nbElts(-1);
-  for(std::size_t ii=0;ii<sz;ii++)
-    {
-      vs2[ii]=vs[ii].getMesh();
-      arrs2[ii]=vs[ii].getCellFields();
-      if(nbElts<0)
-        nbElts=arrs2[ii].size();
-      else
-        if(arrs2[ii].size()!=nbElts)
-          throw MZCException("MicroField cstor : internal error !");
-    }
-  _cellFs.resize(nbElts);
-  for(int ii=0;ii<nbElts;ii++)
-    {
-      std::vector<const DataArray *> arrsTmp(sz);
-      for(std::size_t jj=0;jj<sz;jj++)
-        {
-          arrsTmp[jj]=arrs2[jj][ii];
-        }
-      _cellFs[ii]=DataArray::Aggregate(arrsTmp);
-    }
-  _m=MEDCouplingUMesh::MergeUMeshesOnSameCoords(vs2);
-}
-
-template<class T>
-void AppendToFields(MEDCoupling::TypeOfField tf, MEDCouplingMesh *mesh, const DataArrayInt *n2oPtr, typename MEDFileVTKTraits<T>::MCType *dadPtr, MEDFileFields *fs, double timeStep, int tsId)
-{
-  std::string fieldName(dadPtr->getName());
-  MCAuto< typename Traits<T>::FieldType > f(Traits<T>::FieldType::New(tf));
-  f->setTime(timeStep,tsId,0);
-  {
-    std::string fieldNameForChuckNorris(MEDCoupling::MEDFileAnyTypeField1TSWithoutSDA::FieldNameToMEDFileConvention(fieldName));
-    f->setName(fieldNameForChuckNorris);
-  }
-  if(!n2oPtr)
-    f->setArray(dadPtr);
-  else
-    {
-      MCAuto< typename Traits<T>::ArrayType > dad2(dadPtr->selectByTupleId(n2oPtr->begin(),n2oPtr->end()));
-      f->setArray(dad2);
-    }
-  f->setMesh(mesh);
-  MCAuto< typename MLFieldTraits<T>::FMTSType > fmts(MLFieldTraits<T>::FMTSType::New());
-  MCAuto< typename MLFieldTraits<T>::F1TSType > f1ts(MLFieldTraits<T>::F1TSType::New());
-  f1ts->setFieldNoProfileSBT(f);
-  fmts->pushBackTimeStep(f1ts);
-  fs->pushField(fmts);
-}
-
-void AppendMCFieldFrom(MEDCoupling::TypeOfField tf, MEDCouplingMesh *mesh, MEDFileData *mfd, MCAuto<DataArray> da, const DataArrayInt *n2oPtr, double timeStep, int tsId)
-{
-  static const char FAMFIELD_FOR_CELLS[]="FamilyIdCell";
-  static const char FAMFIELD_FOR_NODES[]="FamilyIdNode";
-  if(!da || !mesh || !mfd)
-    throw MZCException("AppendMCFieldFrom : internal error !");
-  MEDFileFields *fs(mfd->getFields());
-  MEDFileMeshes *ms(mfd->getMeshes());
-  if(!fs || !ms)
-    throw MZCException("AppendMCFieldFrom : internal error 2 !");
-  MCAuto<DataArrayDouble> dad(MEDCoupling::DynamicCast<DataArray,DataArrayDouble>(da));
-  if(dad.isNotNull())
-    {
-      AppendToFields<double>(tf,mesh,n2oPtr,dad,fs,timeStep,tsId);
-      return ;
-    }
-  MCAuto<DataArrayFloat> daf(MEDCoupling::DynamicCast<DataArray,DataArrayFloat>(da));
-  if(daf.isNotNull())
-    {
-      AppendToFields<float>(tf,mesh,n2oPtr,daf,fs,timeStep,tsId);
-      return ;
-    }
-  MCAuto<DataArrayInt> dai(MEDCoupling::DynamicCast<DataArray,DataArrayInt>(da));
-  if(dai.isNotNull())
-    {
-      std::string fieldName(dai->getName());
-      if((fieldName!=FAMFIELD_FOR_CELLS || tf!=MEDCoupling::ON_CELLS) && (fieldName!=FAMFIELD_FOR_NODES || tf!=MEDCoupling::ON_NODES))
-        {
-          AppendToFields<int>(tf,mesh,n2oPtr,dai,fs,timeStep,tsId);
-          return ;
-        }
-      else if(fieldName==FAMFIELD_FOR_CELLS && tf==MEDCoupling::ON_CELLS)
-        {
-          MEDFileMesh *mm(ms->getMeshWithName(mesh->getName()));
-          if(!mm)
-            throw MZCException("AppendMCFieldFrom : internal error 3 !");
-          if(!n2oPtr)
-            mm->setFamilyFieldArr(mesh->getMeshDimension()-mm->getMeshDimension(),dai);
-          else
-            {
-              MCAuto<DataArrayInt> dai2(dai->selectByTupleId(n2oPtr->begin(),n2oPtr->end()));
-              mm->setFamilyFieldArr(mesh->getMeshDimension()-mm->getMeshDimension(),dai2);
-            }
-        }
-      else if(fieldName==FAMFIELD_FOR_NODES || tf==MEDCoupling::ON_NODES)
-        {
-          MEDFileMesh *mm(ms->getMeshWithName(mesh->getName()));
-          if(!mm)
-            throw MZCException("AppendMCFieldFrom : internal error 4 !");
-          if(!n2oPtr)
-            mm->setFamilyFieldArr(1,dai);
-          else
-            {
-              MCAuto<DataArrayInt> dai2(dai->selectByTupleId(n2oPtr->begin(),n2oPtr->end()));
-              mm->setFamilyFieldArr(1,dai2);
-            }
-        }
-    }
-}
-
-void PutAtLevelDealOrder(MEDFileData *mfd, int meshDimRel, const MicroField& mf, double timeStep, int tsId)
-{
-  if(!mfd)
-    throw MZCException("PutAtLevelDealOrder : internal error !");
-  MEDFileMesh *mm(mfd->getMeshes()->getMeshAtPos(0));
-  MEDFileUMesh *mmu(dynamic_cast<MEDFileUMesh *>(mm));
-  if(!mmu)
-    throw MZCException("PutAtLevelDealOrder : internal error 2 !");
-  MCAuto<MEDCouplingUMesh> mesh(mf.getMesh());
-  mesh->setName(mfd->getMeshes()->getMeshAtPos(0)->getName());
-  MCAuto<DataArrayInt> o2n(mesh->sortCellsInMEDFileFrmt());
-  const DataArrayInt *o2nPtr(o2n);
-  MCAuto<DataArrayInt> n2o;
-  mmu->setMeshAtLevel(meshDimRel,mesh);
-  const DataArrayInt *n2oPtr(0);
-  if(o2n)
-    {
-      n2o=o2n->invertArrayO2N2N2O(mesh->getNumberOfCells());
-      n2oPtr=n2o;
-      if(n2oPtr && n2oPtr->isIota(mesh->getNumberOfCells()))
-        n2oPtr=0;
-      if(n2oPtr)
-        mm->setRenumFieldArr(meshDimRel,n2o);
-    }
-  //
-  std::vector<MCAuto<DataArray> > cells(mf.getCellFields());
-  for(std::vector<MCAuto<DataArray> >::const_iterator it=cells.begin();it!=cells.end();it++)
-    {
-      MCAuto<DataArray> da(*it);
-      AppendMCFieldFrom(MEDCoupling::ON_CELLS,mesh,mfd,da,n2oPtr,timeStep,tsId);
-    }
-}
-
-void AssignSingleGTMeshes(MEDFileData *mfd, const std::vector< MicroField >& ms, double timeStep, int tsId)
-{
-  if(!mfd)
-    throw MZCException("AssignSingleGTMeshes : internal error !");
-  MEDFileMesh *mm0(mfd->getMeshes()->getMeshAtPos(0));
-  MEDFileUMesh *mm(dynamic_cast<MEDFileUMesh *>(mm0));
-  if(!mm)
-    throw MZCException("AssignSingleGTMeshes : internal error 2 !");
-  int meshDim(-std::numeric_limits<int>::max());
-  std::map<int, std::vector< MicroField > > ms2;
-  for(std::vector< MicroField >::const_iterator it=ms.begin();it!=ms.end();it++)
-    {
-      const MEDCouplingUMesh *elt((*it).getMesh());
-      if(elt)
-        {
-          int myMeshDim(elt->getMeshDimension());
-          meshDim=std::max(meshDim,myMeshDim);
-          ms2[myMeshDim].push_back(*it);
-        }
-    }
-  if(ms2.empty())
-    return ;
-  for(std::map<int, std::vector< MicroField > >::const_iterator it=ms2.begin();it!=ms2.end();it++)
-    {
-      const std::vector< MicroField >& vs((*it).second);
-      if(vs.size()==1)
-        {
-          PutAtLevelDealOrder(mfd,(*it).first-meshDim,vs[0],timeStep,tsId);
-        }
-      else
-        {
-          MicroField merge(vs);
-          PutAtLevelDealOrder(mfd,(*it).first-meshDim,merge,timeStep,tsId);
-        }
-    }
-}
-
-DataArrayDouble *BuildCoordsFrom(vtkPointSet *ds)
-{
-  if(!ds)
-    throw MZCException("BuildCoordsFrom : internal error !");
-  vtkPoints *pts(ds->GetPoints());
-  if(!pts)
-    throw MZCException("BuildCoordsFrom : internal error 2 !");
-  vtkDataArray *data(pts->GetData());
-  if(!data)
-    throw MZCException("BuildCoordsFrom : internal error 3 !");
-  return ConvertVTKArrayToMCArrayDoubleForced(data);
-}
-
-void AddNodeFields(MEDFileData *mfd, vtkDataSetAttributes *dsa, double timeStep, int tsId)
-{
-  if(!mfd || !dsa)
-    throw MZCException("AddNodeFields : internal error !");
-  MEDFileMesh *mm(mfd->getMeshes()->getMeshAtPos(0));
-  MEDFileUMesh *mmu(dynamic_cast<MEDFileUMesh *>(mm));
-  if(!mmu)
-    throw MZCException("AddNodeFields : internal error 2 !");
-  MCAuto<MEDCouplingUMesh> mesh;
-  if(!mmu->getNonEmptyLevels().empty())
-    mesh=mmu->getMeshAtLevel(0);
-  else
-    {
-      mesh=MEDCouplingUMesh::Build0DMeshFromCoords(mmu->getCoords());
-      mesh->setName(mmu->getName());
-    }
-  int nba(dsa->GetNumberOfArrays());
-  for(int i=0;i<nba;i++)
-    {
-      vtkDataArray *arr(dsa->GetArray(i));
-      const char *name(arr->GetName());
-      if(!arr)
-        continue;
-      MCAuto<DataArray> da(ConvertVTKArrayToMCArray(arr));
-      da->setName(name);
-      AppendMCFieldFrom(MEDCoupling::ON_NODES,mesh,mfd,da,NULL,timeStep,tsId);
-    }
-}
-
-std::vector<MCAuto<DataArray> > AddPartFields(const DataArrayInt *part, vtkDataSetAttributes *dsa)
-{
-  std::vector< MCAuto<DataArray> > ret;
-  if(!dsa)
-    return ret;
-  int nba(dsa->GetNumberOfArrays());
-  for(int i=0;i<nba;i++)
-    {
-      vtkDataArray *arr(dsa->GetArray(i));
-      if(!arr)
-        continue;
-      const char *name(arr->GetName());
-      int nbCompo(arr->GetNumberOfComponents());
-      vtkIdType nbTuples(arr->GetNumberOfTuples());
-      MCAuto<DataArray> mcarr(ConvertVTKArrayToMCArray(arr));
-      if(part)
-        mcarr=mcarr->selectByTupleId(part->begin(),part->end());
-      mcarr->setName(name);
-      ret.push_back(mcarr);
-    }
-  return ret;
-}
-
-std::vector<MCAuto<DataArray> > AddPartFields2(int bg, int end, vtkDataSetAttributes *dsa)
-{
-  std::vector< MCAuto<DataArray> > ret;
-  if(!dsa)
-    return ret;
-  int nba(dsa->GetNumberOfArrays());
-  for(int i=0;i<nba;i++)
-    {
-      vtkDataArray *arr(dsa->GetArray(i));
-      if(!arr)
-        continue;
-      const char *name(arr->GetName());
-      int nbCompo(arr->GetNumberOfComponents());
-      vtkIdType nbTuples(arr->GetNumberOfTuples());
-      MCAuto<DataArray> mcarr(ConvertVTKArrayToMCArray(arr));
-      mcarr=mcarr->selectByTupleIdSafeSlice(bg,end,1);
-      mcarr->setName(name);
-      ret.push_back(mcarr);
-    }
-  return ret;
-}
-
-void ConvertFromRectilinearGrid(MEDFileData *ret, vtkRectilinearGrid *ds, const std::vector<int>& context, double timeStep, int tsId)
-{
-  if(!ds || !ret)
-    throw MZCException("ConvertFromRectilinearGrid : internal error !");
-  //
-  MCAuto<MEDFileMeshes> meshes(MEDFileMeshes::New());
-  ret->setMeshes(meshes);
-  MCAuto<MEDFileFields> fields(MEDFileFields::New());
-  ret->setFields(fields);
-  //
-  MCAuto<MEDFileCMesh> cmesh(MEDFileCMesh::New());
-  meshes->pushMesh(cmesh);
-  MCAuto<MEDCouplingCMesh> cmeshmc(MEDCouplingCMesh::New());
-  vtkDataArray *cx(ds->GetXCoordinates()),*cy(ds->GetYCoordinates()),*cz(ds->GetZCoordinates());
-  if(cx)
-    {
-      MCAuto<DataArrayDouble> arr(ConvertVTKArrayToMCArrayDoubleForced(cx));
-      cmeshmc->setCoordsAt(0,arr);
-    }
-  if(cy)
-    {
-      MCAuto<DataArrayDouble> arr(ConvertVTKArrayToMCArrayDoubleForced(cy));
-      cmeshmc->setCoordsAt(1,arr);
-    }
-  if(cz)
-    {
-      MCAuto<DataArrayDouble> arr(ConvertVTKArrayToMCArrayDoubleForced(cz));
-      cmeshmc->setCoordsAt(2,arr);
-    }
-  std::string meshName(GetMeshNameWithContext(context));
-  cmeshmc->setName(meshName);
-  cmesh->setMesh(cmeshmc);
-  std::vector<MCAuto<DataArray> > cellFs(AddPartFields(0,ds->GetCellData()));
-  for(std::vector<MCAuto<DataArray> >::const_iterator it=cellFs.begin();it!=cellFs.end();it++)
-    {
-      MCAuto<DataArray> da(*it);
-      AppendMCFieldFrom(MEDCoupling::ON_CELLS,cmeshmc,ret,da,NULL,timeStep,tsId);
-    }
-  std::vector<MCAuto<DataArray> > nodeFs(AddPartFields(0,ds->GetPointData()));
-  for(std::vector<MCAuto<DataArray> >::const_iterator it=nodeFs.begin();it!=nodeFs.end();it++)
-    {
-      MCAuto<DataArray> da(*it);
-      AppendMCFieldFrom(MEDCoupling::ON_NODES,cmeshmc,ret,da,NULL,timeStep,tsId);
-    }
-}
-
-void ConvertFromPolyData(MEDFileData *ret, vtkPolyData *ds, const std::vector<int>& context, double timeStep, int tsId)
-{
-  if(!ds || !ret)
-    throw MZCException("ConvertFromPolyData : internal error !");
-  //
-  MCAuto<MEDFileMeshes> meshes(MEDFileMeshes::New());
-  ret->setMeshes(meshes);
-  MCAuto<MEDFileFields> fields(MEDFileFields::New());
-  ret->setFields(fields);
-  //
-  MCAuto<MEDFileUMesh> umesh(MEDFileUMesh::New());
-  meshes->pushMesh(umesh);
-  MCAuto<DataArrayDouble> coords(BuildCoordsFrom(ds));
-  umesh->setCoords(coords);
-  umesh->setName(GetMeshNameWithContext(context));
-  //
-  int offset(0);
-  std::vector< MicroField > ms;
-  vtkCellArray *cd(ds->GetVerts());
-  if(cd)
-    {
-      MCAuto<MEDCouplingUMesh> subMesh(BuildMeshFromCellArray(cd,coords,0,INTERP_KERNEL::NORM_POINT1));
-      if((const MEDCouplingUMesh *)subMesh)
-        {
-          std::vector<MCAuto<DataArray> > cellFs(AddPartFields2(offset,offset+subMesh->getNumberOfCells(),ds->GetCellData()));
-          offset+=subMesh->getNumberOfCells();
-          ms.push_back(MicroField(subMesh,cellFs));
-        }
-    }
-  vtkCellArray *cc(ds->GetLines());
-  if(cc)
-    {
-      MCAuto<MEDCouplingUMesh> subMesh(BuildMeshFromCellArray(cc,coords,1,INTERP_KERNEL::NORM_SEG2));
-      if((const MEDCouplingUMesh *)subMesh)
-        {
-          std::vector<MCAuto<DataArray> > cellFs(AddPartFields2(offset,offset+subMesh->getNumberOfCells(),ds->GetCellData()));
-          offset+=subMesh->getNumberOfCells();
-          ms.push_back(MicroField(subMesh,cellFs));
-        }
-    }
-  vtkCellArray *cb(ds->GetPolys());
-  if(cb)
-    {
-      MCAuto<MEDCouplingUMesh> subMesh(BuildMeshFromCellArray(cb,coords,2,INTERP_KERNEL::NORM_POLYGON));
-      if((const MEDCouplingUMesh *)subMesh)
-        {
-          std::vector<MCAuto<DataArray> > cellFs(AddPartFields2(offset,offset+subMesh->getNumberOfCells(),ds->GetCellData()));
-          offset+=subMesh->getNumberOfCells();
-          ms.push_back(MicroField(subMesh,cellFs));
-        }
-    }
-  vtkCellArray *ca(ds->GetStrips());
-  if(ca)
-    {
-      MCAuto<DataArrayInt> ids;
-      MCAuto<MEDCouplingUMesh> subMesh(BuildMeshFromCellArrayTriangleStrip(ca,coords,ids));
-      if((const MEDCouplingUMesh *)subMesh)
-        {
-          std::vector<MCAuto<DataArray> > cellFs(AddPartFields(ids,ds->GetCellData()));
-          offset+=subMesh->getNumberOfCells();
-          ms.push_back(MicroField(subMesh,cellFs));
-        }
-    }
-  AssignSingleGTMeshes(ret,ms,timeStep,tsId);
-  AddNodeFields(ret,ds->GetPointData(),timeStep,tsId);
-}
-
-void ConvertFromUnstructuredGrid(MEDFileData *ret, vtkUnstructuredGrid *ds, const std::vector<int>& context, double timeStep, int tsId)
-{
-  if(!ds || !ret)
-    throw MZCException("ConvertFromUnstructuredGrid : internal error !");
-  //
-  MCAuto<MEDFileMeshes> meshes(MEDFileMeshes::New());
-  ret->setMeshes(meshes);
-  MCAuto<MEDFileFields> fields(MEDFileFields::New());
-  ret->setFields(fields);
-  //
-  MCAuto<MEDFileUMesh> umesh(MEDFileUMesh::New());
-  meshes->pushMesh(umesh);
-  MCAuto<DataArrayDouble> coords(BuildCoordsFrom(ds));
-  umesh->setCoords(coords);
-  umesh->setName(GetMeshNameWithContext(context));
-  vtkIdType nbCells(ds->GetNumberOfCells());
-  vtkCellArray *ca(ds->GetCells());
-  if(!ca)
-    return ;
-  vtkIdType nbEnt(ca->GetNumberOfConnectivityEntries());
-  vtkIdType *caPtr(ca->GetPointer());
-  vtkUnsignedCharArray *ct(ds->GetCellTypesArray());
-  if(!ct)
-    throw MZCException("ConvertFromUnstructuredGrid : internal error");
-  vtkIdTypeArray *cla(ds->GetCellLocationsArray());
-  const vtkIdType *claPtr(cla->GetPointer(0));
-  if(!cla)
-    throw MZCException("ConvertFromUnstructuredGrid : internal error 2");
-  const unsigned char *ctPtr(ct->GetPointer(0));
-  std::map<int,int> m(ComputeMapOfType());
-  MCAuto<DataArrayInt> lev(DataArrayInt::New()) ;  lev->alloc(nbCells,1);
-  int *levPtr(lev->getPointer());
-  for(vtkIdType i=0;i<nbCells;i++)
-    {
-      std::map<int,int>::iterator it(m.find(ctPtr[i]));
-      if(it!=m.end())
-        {
-          const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)(*it).second));
-          levPtr[i]=cm.getDimension();
-        }
-      else
-        {
-          std::ostringstream oss; oss << "ConvertFromUnstructuredGrid : at pos #" << i << " unrecognized VTK cell with type =" << ctPtr[i];
-          throw MZCException(oss.str());
-        }
-    }
-  int dummy(0);
-  MCAuto<DataArrayInt> levs(lev->getDifferentValues());
-  std::vector< MicroField > ms;
-  vtkIdTypeArray *faces(ds->GetFaces()),*faceLoc(ds->GetFaceLocations());
-  for(const int *curLev=levs->begin();curLev!=levs->end();curLev++)
-    {
-      MCAuto<MEDCouplingUMesh> m0(MEDCouplingUMesh::New("",*curLev));
-      m0->setCoords(coords); m0->allocateCells();
-      MCAuto<DataArrayInt> cellIdsCurLev(lev->findIdsEqual(*curLev));
-      for(const int *cellId=cellIdsCurLev->begin();cellId!=cellIdsCurLev->end();cellId++)
-        {
-          std::map<int,int>::iterator it(m.find(ctPtr[*cellId]));
-          vtkIdType offset(claPtr[*cellId]);
-          vtkIdType sz(caPtr[offset]);
-          INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)(*it).second);
-          if(ct!=INTERP_KERNEL::NORM_POLYHED)
-            {
-              std::vector<int> conn2(sz);
-              for(int kk=0;kk<sz;kk++)
-                conn2[kk]=caPtr[offset+1+kk];
-              m0->insertNextCell(ct,sz,&conn2[0]);
-            }
-          else
-            {
-              if(!faces || !faceLoc)
-                throw MZCException("ConvertFromUnstructuredGrid : faces are expected when there are polyhedra !");
-              const vtkIdType *facPtr(faces->GetPointer(0)),*facLocPtr(faceLoc->GetPointer(0));
-              std::vector<int> conn;
-              int off0(facLocPtr[*cellId]);
-              int nbOfFaces(facPtr[off0++]);
-              for(int k=0;k<nbOfFaces;k++)
-                {
-                  int nbOfNodesInFace(facPtr[off0++]);
-                  std::copy(facPtr+off0,facPtr+off0+nbOfNodesInFace,std::back_inserter(conn));
-                  off0+=nbOfNodesInFace;
-                  if(k<nbOfFaces-1)
-                    conn.push_back(-1);
-                }
-              m0->insertNextCell(ct,conn.size(),&conn[0]);
-            }
-        }
-      std::vector<MCAuto<DataArray> > cellFs(AddPartFields(cellIdsCurLev,ds->GetCellData()));
-      ms.push_back(MicroField(m0,cellFs));
-    }
-  AssignSingleGTMeshes(ret,ms,timeStep,tsId);
-  AddNodeFields(ret,ds->GetPointData(),timeStep,tsId);
-}
-
-///////////////////
-
-vtkMEDWriter::vtkMEDWriter():WriteAllTimeSteps(0),NumberOfTimeSteps(0),CurrentTimeIndex(0),FileName(0)
-{
-}
-
-vtkMEDWriter::~vtkMEDWriter()
-{
-}
+using MEDCoupling::MEDFileData;
+using MEDCoupling::MCAuto;
+using VTKToMEDMem::Grp;
+using VTKToMEDMem::Fam;
 
 vtkInformationDataObjectMetaDataKey *GetMEDReaderMetaDataIfAny()
 {
@@ -879,37 +117,6 @@ bool IsInformationOK(vtkInformation *info)
   return false;
 }
 
-class Grp
-{
-public:
-  Grp(const std::string& name):_name(name) { }
-  void setFamilies(const std::vector<std::string>& fams) { _fams=fams; }
-  std::string getName() const { return _name; }
-  std::vector<std::string> getFamilies() const { return _fams; }
-private:
-  std::string _name;
-  std::vector<std::string> _fams;
-};
-
-class Fam
-{
-public:
-  Fam(const std::string& name)
-  {
-    static const char ZE_SEP[]="@@][@@";
-    std::size_t pos(name.find(ZE_SEP));
-    std::string name0(name.substr(0,pos)),name1(name.substr(pos+strlen(ZE_SEP)));
-    std::istringstream iss(name1);
-    iss >> _id;
-    _name=name0;
-  }
-  std::string getName() const { return _name; }
-  int getID() const { return _id; }
-private:
-  std::string _name;
-  int _id;
-};
-
 void LoadFamGrpMapInfo(vtkMutableDirectedGraph *sil, std::string& meshName, std::vector<Grp>& groups, std::vector<Fam>& fams)
 {
   if(!sil)
@@ -975,6 +182,14 @@ void LoadFamGrpMapInfo(vtkMutableDirectedGraph *sil, std::string& meshName, std:
   it0->Delete();
 }
 
+vtkMEDWriter::vtkMEDWriter():WriteAllTimeSteps(0),NumberOfTimeSteps(0),CurrentTimeIndex(0),FileName(0)
+{
+}
+
+vtkMEDWriter::~vtkMEDWriter()
+{
+}
+
 int vtkMEDWriter::RequestInformation(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector)
 { 
   //std::cerr << "########################################## vtkMEDWriter::RequestInformation ########################################## " << (const char *) this->FileName << std::endl;
@@ -997,128 +212,6 @@ int vtkMEDWriter::RequestUpdateExtent(vtkInformation* vtkNotUsed(request), vtkIn
   return 1;
 }
 
-void WriteMEDFileFromVTKDataSet(MEDFileData *mfd, vtkDataSet *ds, const std::vector<int>& context, double timeStep, int tsId)
-{
-  if(!ds || !mfd)
-    throw MZCException("Internal error in WriteMEDFileFromVTKDataSet.");
-  vtkPolyData *ds2(vtkPolyData::SafeDownCast(ds));
-  vtkUnstructuredGrid *ds3(vtkUnstructuredGrid::SafeDownCast(ds));
-  vtkRectilinearGrid *ds4(vtkRectilinearGrid::SafeDownCast(ds));
-  if(ds2)
-    {
-      ConvertFromPolyData(mfd,ds2,context,timeStep,tsId);
-    }
-  else if(ds3)
-    {
-      ConvertFromUnstructuredGrid(mfd,ds3,context,timeStep,tsId);
-    }
-  else if(ds4)
-    {
-      ConvertFromRectilinearGrid(mfd,ds4,context,timeStep,tsId);
-    }
-  else
-    throw MZCException("Unrecognized vtkDataSet ! Sorry ! Try to convert it to UnstructuredGrid to be able to write it !");
-}
-
-void WriteMEDFileFromVTKMultiBlock(MEDFileData *mfd, vtkMultiBlockDataSet *ds, const std::vector<int>& context, double timeStep, int tsId)
-{
-  if(!ds || !mfd)
-    throw MZCException("Internal error in WriteMEDFileFromVTKMultiBlock.");
-  int nbBlocks(ds->GetNumberOfBlocks());
-  if(nbBlocks==1 && context.empty())
-    {
-      vtkDataObject *uniqueElt(ds->GetBlock(0));
-      if(!uniqueElt)
-        throw MZCException("Unique elt in multiblock is NULL !");
-      vtkDataSet *uniqueEltc(vtkDataSet::SafeDownCast(uniqueElt));
-      if(uniqueEltc)
-        {
-          WriteMEDFileFromVTKDataSet(mfd,uniqueEltc,context,timeStep,tsId);
-          return ;
-        }
-    }
-  for(int i=0;i<nbBlocks;i++)
-    {
-      vtkDataObject *elt(ds->GetBlock(i));
-      std::vector<int> context2;
-      context2.push_back(i);
-      if(!elt)
-        {
-          std::ostringstream oss; oss << "In context ";
-          std::copy(context.begin(),context.end(),std::ostream_iterator<int>(oss," "));
-          oss << " at pos #" << i << " elt is NULL !";
-          throw MZCException(oss.str());
-        }
-      vtkDataSet *elt1(vtkDataSet::SafeDownCast(elt));
-      if(elt1)
-        {
-          WriteMEDFileFromVTKDataSet(mfd,elt1,context,timeStep,tsId);
-          continue;
-        }
-      vtkMultiBlockDataSet *elt2(vtkMultiBlockDataSet::SafeDownCast(elt));
-      if(elt2)
-        {
-          WriteMEDFileFromVTKMultiBlock(mfd,elt2,context,timeStep,tsId);
-          continue;
-        }
-      std::ostringstream oss; oss << "In context ";
-      std::copy(context.begin(),context.end(),std::ostream_iterator<int>(oss," "));
-      oss << " at pos #" << i << " elt not recognized data type !";
-      throw MZCException(oss.str());
-    }
-}
-
-void WriteMEDFileFromVTKGDS(MEDFileData *mfd, vtkDataObject *input, double timeStep, int tsId)
-{
-  if(!input || !mfd)
-    throw MZCException("WriteMEDFileFromVTKGDS : internal error !");
-  std::vector<int> context;
-  vtkDataSet *input1(vtkDataSet::SafeDownCast(input));
-  if(input1)
-    {
-      WriteMEDFileFromVTKDataSet(mfd,input1,context,timeStep,tsId);
-      return ;
-    }
-  vtkMultiBlockDataSet *input2(vtkMultiBlockDataSet::SafeDownCast(input));
-  if(input2)
-    {
-      WriteMEDFileFromVTKMultiBlock(mfd,input2,context,timeStep,tsId);
-      return ;
-    }
-  throw MZCException("WriteMEDFileFromVTKGDS : not recognized data type !");
-}
-
-void PutFamGrpInfoIfAny(MEDFileData *mfd, const std::string& meshName, const std::vector<Grp>& groups, const std::vector<Fam>& fams)
-{
-  if(!mfd)
-    return ;
-  if(meshName.empty())
-    return ;
-  MEDFileMeshes *meshes(mfd->getMeshes());
-  if(!meshes)
-    return ;
-  if(meshes->getNumberOfMeshes()!=1)
-    return ;
-  MEDFileMesh *mm(meshes->getMeshAtPos(0));
-  if(!mm)
-    return ;
-  mm->setName(meshName);
-  for(std::vector<Fam>::const_iterator it=fams.begin();it!=fams.end();it++)
-    mm->setFamilyId((*it).getName(),(*it).getID());
-  for(std::vector<Grp>::const_iterator it=groups.begin();it!=groups.end();it++)
-    mm->setFamiliesOnGroup((*it).getName(),(*it).getFamilies());
-  MEDFileFields *fields(mfd->getFields());
-  if(!fields)
-    return ;
-  for(int i=0;i<fields->getNumberOfFields();i++)
-    {
-      MEDFileAnyTypeFieldMultiTS *fmts(fields->getFieldAtPos(i));
-      if(!fmts)
-        continue;
-      fmts->setMeshName(meshName);
-    }
-}
-
 int vtkMEDWriter::RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector)
 {
   //std::cerr << "########################################## vtkMEDWriter::RequestData        ########################################## " << (const char *) this->FileName << std::endl;