Salome HOME
Overload of MEDLoader.ReadField method to ease access of medcoupling for new comers
[tools/medcoupling.git] / src / MEDLoader / SauvWriter.cxx
index b4f44f55422088f6ac5fbf42e98dc2a45ba288df..a337b1778f13c370689649e1939bbc1430cb22e4 100644 (file)
@@ -1,9 +1,9 @@
-// Copyright (C) 2007-2012  CEA/DEN, EDF R&D
+// Copyright (C) 2007-2016  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.
+// 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
@@ -34,7 +34,7 @@
 #include <cstdlib>
 #include <iomanip>
 
-using namespace ParaMEDMEM;
+using namespace MEDCoupling;
 using namespace SauvUtilities;
 using namespace std;
 
@@ -212,17 +212,35 @@ namespace
   }
 }
 
-//================================================================================
-/*!
- * \brief Creates SauvWriter
- */
-//================================================================================
+SauvWriter::SauvWriter():_cpy_grp_if_on_single_family(false)
+{
+}
 
 SauvWriter* SauvWriter::New()
 {
   return new SauvWriter;
 }
 
+std::size_t SauvWriter::getHeapMemorySizeWithoutChildren() const
+{
+  return 0;
+}
+
+std::vector<const BigMemoryObject *> SauvWriter::getDirectChildrenWithNull() const
+{
+  return std::vector<const BigMemoryObject *>();
+}
+
+void SauvWriter::setCpyGrpIfOnASingleFamilyStatus(bool status)
+{
+  _cpy_grp_if_on_single_family=status;
+}
+
+bool SauvWriter::getCpyGrpIfOnASingleFamilyStatus() const
+{
+  return _cpy_grp_if_on_single_family;
+}
+
 //================================================================================
 /*!
  * \brief Fills own DS by MEDFileData
@@ -244,7 +262,10 @@ void SauvWriter::setMEDFileDS(const MEDFileData* medData,
   if ( fields )
     for ( int i = 0; i < fields->getNumberOfFields(); ++i )
       {
-        MEDFileFieldMultiTS * f = fields->getFieldAtPos(i);
+        MEDFileAnyTypeFieldMultiTS * fB = fields->getFieldAtPos(i);
+        MEDFileFieldMultiTS * f = dynamic_cast<MEDFileFieldMultiTS *>(fB);
+        if(!f)
+          continue;// fields on int32 not managed
         if ( f->getMeshName() == _fileMesh->getName() )
           {
             vector< vector<TypeOfField> > fTypes = f->getTypesOfFieldAvailable();
@@ -353,7 +374,7 @@ void SauvWriter::fillFamilySubMeshes()
   for ( size_t iDim = 0; iDim < dims.size(); ++iDim )
     {
       int dimRelExt = dims[ iDim ];
-      MEDCouplingAutoRefCountObjectPtr< MEDCouplingMesh > mesh = _fileMesh->getGenMeshAtLevel(dimRelExt);
+      MCAuto< MEDCouplingMesh > mesh = _fileMesh->getMeshAtLevel(dimRelExt);
       const DataArrayInt * famIds = _fileMesh->getFamilyFieldAtLevel(dimRelExt);
       if ( !famIds ) continue;
 
@@ -404,7 +425,7 @@ void SauvWriter::fillFamilySubMeshes()
 
 //================================================================================
 /*!
- * \brief fill sub-mehses of groups
+ * \brief fill sub-meshes of groups
  */
 //================================================================================
 
@@ -418,22 +439,50 @@ void SauvWriter::fillGroupSubMeshes()
       const vector<string>& famNames = g2ff->second;
       if ( famNames.empty() ) continue;
       std::vector<SubMesh*> famSubMeshes( famNames.size() );
+      std::size_t k = 0;
       for ( size_t i = 0; i < famNames.size(); ++i )
         {
           int famID = _fileMesh->getFamilyId( famNames[i].c_str() );
           map< int, SubMesh* >::iterator i2f = _famIDs2Sub.find( famID );
-          if ( i2f == _famIDs2Sub.end() )
-            THROW_IK_EXCEPTION("SauvWriter::fillGroupSubMeshes(): unknown family ID: " << famID);
-          famSubMeshes[ i ] = i2f->second;
+          if ( i2f != _famIDs2Sub.end() )
+            {
+              famSubMeshes[ k ] = i2f->second;
+              ++k;
+            }
         }
+      if ( k == 0 )
+        continue;
+      // if a family exists but has no element, no submesh has been found for this family
+      // => we have to resize famSubMeshes with the number of submeshes stored
+      if (k != famNames.size())
+        famSubMeshes.resize(k);
       SubMesh* grpSubMesh = addSubMesh( groupName, famSubMeshes[0]->_dimRelExt );
-      grpSubMesh->_subs.swap( famSubMeshes );
+      if( ! _cpy_grp_if_on_single_family )
+        {
+          grpSubMesh->_subs.swap( famSubMeshes );
+        }
+      else
+        {
+          /* If a group sub mesh consists of only one family, the group is written as
+           * a copy of this family.
+           * A mesh composed of only one submesh may cause an issue with some Gibi operators.*/
+          if (famSubMeshes.size() == 1)
+            {
+              for(int i = 0; i < famSubMeshes[0]->cellIDsByTypeSize() ; i++)
+                {
+                  grpSubMesh->_cellIDsByType[i] = famSubMeshes[0]->_cellIDsByType[i];
+                }
+            }
+          else
+            grpSubMesh->_subs.swap( famSubMeshes );
+        }
     }
 }
 
+
 //================================================================================
 /*!
- * \brief fill sub-mehses of profiles
+ * \brief fill sub-meshes of profiles
  */
 //================================================================================
 
@@ -443,7 +492,7 @@ void SauvWriter::fillProfileSubMeshes()
   SubMesh* nilSm = (SubMesh*) 0;
   for ( int isOnNodes = 0; isOnNodes < 2; ++isOnNodes )
     {
-      vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldMultiTS > >
+      vector< MCAuto< MEDFileFieldMultiTS > >
         fields = isOnNodes ? _nodeFields : _cellFields;
       for ( size_t i = 0; i < fields.size(); ++i )
         {
@@ -453,7 +502,7 @@ void SauvWriter::fillProfileSubMeshes()
           vector< vector<TypeOfField> > typesF;
           vector< vector<string> > pfls, locs;
           fields[i]->getFieldSplitedByType( iters[0].first, iters[0].second,
-                                            _fileMesh->getName(), types, typesF, pfls, locs);
+                                            _fileMesh->getName().c_str(), types, typesF, pfls, locs);
           int dimRelExt;
           for ( size_t iType = 0; iType < types.size(); ++iType )
             {
@@ -501,7 +550,7 @@ int SauvWriter::evaluateNbProfileSubMeshes() const
       vector< vector<TypeOfField> > typesF;
       vector< vector<string> > pfls, locs;
       _cellFields[i]->getFieldSplitedByType( iters[0].first, iters[0].second,
-                                             _fileMesh->getName(), types, typesF, pfls, locs);
+                                             _fileMesh->getName().c_str(), types, typesF, pfls, locs);
       nb += 2 * types.size(); // x 2 - a type can be on nodes and on cells at the same time
     }
 
@@ -518,8 +567,8 @@ void SauvWriter::makeProfileIDs( SubMesh*                          sm,
                                  INTERP_KERNEL::NormalizedCellType type,
                                  const DataArrayInt*               profile )
 {
-  MEDCouplingAutoRefCountObjectPtr< MEDCouplingMesh >
-    mesh = _fileMesh->getGenMeshAtLevel(sm->_dimRelExt);
+  MCAuto< MEDCouplingMesh >
+    mesh = _fileMesh->getMeshAtLevel(sm->_dimRelExt);
   const MEDCouplingUMesh* uMesh = dynamic_cast< const MEDCouplingUMesh* > ((const MEDCouplingMesh*) mesh );
 
   if ( sm->_dimRelExt == 1 ) type = INTERP_KERNEL::NORM_POINT1;
@@ -555,9 +604,18 @@ void SauvWriter::makeProfileIDs( SubMesh*                          sm,
           code[2] = -1;
         }
       vector<const DataArrayInt *> idsPerType( 1, profile );
-      MEDCouplingAutoRefCountObjectPtr<DataArrayInt>
+      MCAuto<DataArrayInt>
         resIDs = uMesh->checkTypeConsistencyAndContig( code, idsPerType );
-      ids.assign( resIDs->begin(), resIDs->end() );
+      if (( const DataArrayInt *) resIDs )
+      {
+        ids.assign( resIDs->begin(), resIDs->end() );
+      }
+      else // mesh includes only one type
+      {
+        int nbE = code[1];
+        for ( ids.resize( nbE ); nbE; --nbE )
+          ids[ nbE-1 ] = nbE-1;
+      }
     }
 }
 
@@ -567,10 +625,10 @@ void SauvWriter::makeProfileIDs( SubMesh*                          sm,
  */
 //================================================================================
 
-void SauvWriter::write(const char* fileName)
+void SauvWriter::write(const std::string& fileName)
 {
   std::fstream fileStream;
-  fileStream.open( fileName, ios::out);
+  fileStream.open( fileName.c_str(), ios::out);
   if
 #ifdef WIN32
     ( !fileStream || !fileStream.is_open() )
@@ -607,7 +665,7 @@ void SauvWriter::write(const char* fileName)
 
 void SauvWriter::writeFileHead()
 {
-  MEDCouplingAutoRefCountObjectPtr< MEDCouplingMesh > mesh = _fileMesh->getGenMeshAtLevel(0);
+  MCAuto< MEDCouplingMesh > mesh = _fileMesh->getMeshAtLevel(0);
 
   *_sauvFile
     << " ENREGISTREMENT DE TYPE   4" << endl
@@ -688,9 +746,9 @@ void SauvWriter::writeSubMeshes()
       else
         {
           // write each sub-type as a SAUV sub-mesh
-          MEDCouplingAutoRefCountObjectPtr< MEDCouplingMesh >
-            mesh = _fileMesh->getGenMeshAtLevel( sm._dimRelExt );
-          MEDCouplingAutoRefCountObjectPtr< MEDCouplingUMesh>
+          MCAuto< MEDCouplingMesh >
+            mesh = _fileMesh->getMeshAtLevel( sm._dimRelExt );
+          MCAuto< MEDCouplingUMesh>
             umesh = mesh->buildUnstructured();
 
           for ( int iType=0; iType < sm.cellIDsByTypeSize(); ++iType )
@@ -787,8 +845,8 @@ void SauvWriter::writeCompoundSubMesh(int iSub)
 
 void SauvWriter::writeNodes()
 {
-  MEDCouplingAutoRefCountObjectPtr< MEDCouplingMesh > mesh = _fileMesh->getGenMeshAtLevel( 1 );
-  MEDCouplingAutoRefCountObjectPtr< MEDCouplingUMesh > umesh = mesh->buildUnstructured();
+  MCAuto< MEDCouplingMesh > mesh = _fileMesh->getMeshAtLevel( 1 );
+  MCAuto< MEDCouplingUMesh > umesh = mesh->buildUnstructured();
 
   // write the index connecting nodes with their coodrinates
 
@@ -817,7 +875,7 @@ void SauvWriter::writeNodes()
   _sauvFile->precision(14);
   _sauvFile->setf( ios_base::scientific, ios_base::floatfield );
   _sauvFile->setf( ios_base::uppercase );
-  MEDCouplingAutoRefCountObjectPtr< DataArrayDouble> coordArray = umesh->getCoordinatesAndOwner();
+  MCAuto< DataArrayDouble> coordArray = umesh->getCoordinatesAndOwner();
   const double precision = 1.e-99; // PAL12077
   for ( int i = 0; i < nbNodes; ++i)
   {
@@ -942,7 +1000,7 @@ void SauvWriter::writeLongNames()
 void SauvWriter::writeFieldNames( const bool                 isNodal,
                                   std::map<std::string,int>& fldNamePrefixMap)
 {
-  vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldMultiTS > >&
+  vector< MCAuto< MEDFileFieldMultiTS > >&
     flds = isNodal ? _nodeFields : _cellFields;
   map<string,int> nameNbMap;
 
@@ -1051,7 +1109,7 @@ void SauvWriter::writeNodalFields(map<string,int>& fldNamePrefixMap)
           vector< vector<TypeOfField> > typesF;
           vector< vector<string> > pfls, locs;
           vector< vector< std::pair<int,int> > > valsVec;
-          valsVec=_nodeFields[iF]->getFieldSplitedByType( it.first, it.second, _fileMesh->getName(),
+          valsVec=_nodeFields[iF]->getFieldSplitedByType( it.first, it.second, _fileMesh->getName().c_str(),
                                                           types, typesF, pfls, locs);
           // believe that there can be only one type in a nodal field,
           // so do not use a loop on types
@@ -1100,7 +1158,7 @@ void SauvWriter::writeNodalFields(map<string,int>& fldNamePrefixMap)
           vector< vector<TypeOfField> > typesF;
           vector< vector<string> > pfls, locs;
           vector< vector< std::pair<int,int> > > valsVec;
-          valsVec = _nodeFields[iF]->getFieldSplitedByType( it.first, it.second, _fileMesh->getName(),
+          valsVec = _nodeFields[iF]->getFieldSplitedByType( it.first, it.second, _fileMesh->getName().c_str(),
                                                             types, typesF, pfls, locs);
           // believe that there can be only one type in a nodal field,
           // so do not perform a loop on types
@@ -1161,7 +1219,7 @@ void SauvWriter::writeElemFields(map<string,int>& fldNamePrefixMap)
           vector< vector<TypeOfField> > typesF;
           vector< vector<string> > pfls, locs;
           vector< vector< std::pair<int,int> > > valsVec;
-          valsVec = _cellFields[iF]->getFieldSplitedByType( it.first, it.second, _fileMesh->getName(),
+          valsVec = _cellFields[iF]->getFieldSplitedByType( it.first, it.second, _fileMesh->getName().c_str(),
                                                             types, typesF, pfls, locs);
           for ( size_t i = 0; i < valsVec.size(); ++i )
             nbSub += valsVec[i].size();
@@ -1188,7 +1246,7 @@ void SauvWriter::writeElemFields(map<string,int>& fldNamePrefixMap)
           vector<INTERP_KERNEL::NormalizedCellType> types;
           vector< vector<TypeOfField> > typesF;
           vector< vector<string> > pfls, locs;
-          _cellFields[iF]->getFieldSplitedByType( it.first, it.second, _fileMesh->getName(),
+          _cellFields[iF]->getFieldSplitedByType( it.first, it.second, _fileMesh->getName().c_str(),
                                                   types, typesF, pfls, locs);
           for ( size_t iType = 0; iType < pfls.size(); ++iType )
             for ( size_t iP = 0; iP < pfls[iType].size(); ++iP )
@@ -1254,7 +1312,7 @@ void SauvWriter::writeElemTimeStamp(int iF, int iter, int order)
   vector< vector<TypeOfField> > typesF;
   vector< vector<string> > pfls, locs;
   vector< vector< std::pair<int,int> > > valsVec;
-  valsVec = _cellFields[iF]->getFieldSplitedByType( iter, order, _fileMesh->getName(),
+  valsVec = _cellFields[iF]->getFieldSplitedByType( iter, order, _fileMesh->getName().c_str(),
                                                     types, typesF, pfls, locs);
   for ( size_t iType = 0; iType < pfls.size(); ++iType )
     for ( size_t iP = 0; iP < pfls[iType].size(); ++iP )