Back to index

salome-med  6.5.0
SauvWriter.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 // File      : SauvWriter.cxx
00020 // Created   : Wed Aug 24 12:55:55 2011
00021 // Author    : Edward AGAPOV (eap)
00022 
00023 #include "SauvWriter.hxx"
00024 
00025 #include "InterpKernelException.hxx"
00026 #include "MEDFileMesh.hxx"
00027 #include "MEDFileField.hxx"
00028 #include "MEDFileData.hxx"
00029 #include "CellModel.hxx"
00030 
00031 #include <fstream>
00032 #include <sstream>
00033 #include <iostream>
00034 #include <cstdlib>
00035 #include <iomanip>
00036 
00037 using namespace ParaMEDMEM;
00038 using namespace SauvUtilities;
00039 using namespace std;
00040 
00041 #define INFOS_MED(txt) cout << txt << endl;
00042 
00043 namespace
00044 {
00045   const char* zeroI8 = "       0"; // FORMAT(I8)
00046 
00047   // ============================================================
00048   // the class writes endl to the file as soon as <limit> fields
00049   // have been written after the last endl
00050   // ============================================================
00051 
00052   class TFieldCounter
00053   {
00054     fstream& _file;
00055     int _count, _limit;
00056   public:
00057     TFieldCounter(fstream& f, int limit=0): _file(f), _limit(limit) { init(); }
00058     void init(int limit=0) // init, is done by stop() as well
00059     { if (limit) _limit = limit; _count = 0; }
00060     void operator++(int) // next
00061     { if ( ++_count == _limit ) { _file << endl; init(); }}
00062     void stop() // init() and write endl if there was no endl after the last written field
00063     { if ( _count ) _file << endl; init(); }
00064     ~TFieldCounter() { stop(); }
00065   };
00066 
00067   //================================================================================
00071   //================================================================================
00072 
00073   string noProfileName( INTERP_KERNEL::NormalizedCellType type )
00074   {
00075     return "INTERP_KERNEL::NormalizedCellType_" + SauvUtilities::toString( type );
00076   }
00077 
00078   //================================================================================
00082   //================================================================================
00083 
00084   string cleanName( const string& theName )
00085   {
00086     string name = theName;
00087     if ( !name.empty() )
00088       {
00089         // cut off leading white spaces
00090         string::size_type firstChar = name.find_first_not_of(" \t");
00091         if (firstChar < name.length())
00092           {
00093             name = name.substr(firstChar);
00094           }
00095         else
00096           {
00097             name = ""; // only whitespaces there - remove them
00098           }
00099         // cut off trailing white spaces
00100         string::size_type lastChar = name.find_last_not_of(" \t");
00101         if (lastChar < name.length())
00102           name = name.substr(0, lastChar + 1);
00103       }
00104     return name;
00105   }
00106 
00107   //================================================================================
00111   //================================================================================
00112 
00113   string addName (map<string,int>& nameMap,
00114                   map<string,int>& namePrefixesMap,
00115                   const string&    theName,
00116                   const int        index)
00117   {
00118     // Converts names like:
00119     // MED:                       GIBI:     
00120     //   TEMPERATURE_FLUIDE   ->    TEMPE001
00121     //   TEMPERATURE_SOLIDE   ->    TEMPE002
00122     //   PRESSION             ->    PRESSION
00123     //   NU                   ->    NU      
00124     //   VOLUM001             ->    VOLUM001
00125     //   VOLUMOFOBJECT        ->    VOLUM003
00126     //   VOLUM002             ->    VOLUM002
00127     string healedName = cleanName(theName);
00128     int ind = index;
00129 
00130     if (!healedName.empty())
00131       {
00132         string name = healedName;
00133         int len = name.length();
00134         for (int i = 0; i < len; ++i)
00135           name[i] = toupper(name[i]);
00136 
00137         bool doResave = false; // only for tracing
00138 
00139         // I. Save a short name as it is
00140         if (len <= 8)
00141           {
00142             INFOS_MED("Save <" << theName << "> as <" << name << ">");
00143 
00144             map<string,int>::iterator it = nameMap.find(name);
00145             if (it != nameMap.end())
00146               {
00147                 // There is already such name in the map.
00148 
00149                 // a. Replace in the map the old pair by the current one
00150                 int old_ind = nameMap[name];
00151                 nameMap[name] = ind;
00152                 // b. Rebuild the old pair (which was in the map,
00153                 //    it seems to be built automatically by step II)
00154                 ind = old_ind;
00155                 // continue with step II
00156                 doResave = true; // only for tracing
00157               }
00158             else
00159               {
00160                 // Save in the map
00161                 nameMap.insert(make_pair(name, ind));
00162 
00163                 // Update loc_index for this name (if last free characters represents a number)
00164                 // to avoid conflicts with long names, same in first 5 characters
00165                 if (len == 8)
00166                   {
00167                     int new_loc_index = atoi(name.c_str() + 5);
00168                     if (new_loc_index > 0)
00169                       {
00170                         // prefix
00171                         string str = name.substr(0,5);
00172                         if (namePrefixesMap.find(str) != namePrefixesMap.end())
00173                           {
00174                             int old_loc_index = namePrefixesMap[str];
00175                             if (new_loc_index < old_loc_index) new_loc_index = old_loc_index;
00176                           }
00177                         namePrefixesMap[str] = new_loc_index;
00178                       }
00179                   }
00180                 return healedName;
00181               }
00182           } // if (len <= 8)
00183 
00184         // II. Cut long name and add a numeric suffix
00185 
00186         // first 5 or less characters of the name
00187         if (len > 5) name = name.substr(0,5);
00188 
00189         // numeric suffix
00190         map<string,int>::iterator name2ind = namePrefixesMap.insert( make_pair( name, 0 )).first;
00191         string numSuffix = SauvUtilities::toString( ++(name2ind->second) );
00192 
00193         if ( numSuffix.size() + name.size() > 8 )
00194           THROW_IK_EXCEPTION("Can't write not unique name: " << healedName);
00195 
00196         if ( numSuffix.size() < 3 )
00197           numSuffix.insert( 0, 3 - numSuffix.size(), '0' );
00198 
00199         name += numSuffix;
00200         nameMap.insert(make_pair(name, ind));
00201 
00202         if (doResave)
00203           {
00204             INFOS_MED("Resave previous <" << healedName << "> as <" << name << ">");
00205           }
00206         else
00207           {
00208             INFOS_MED("Save <" << theName << "> as <" << name << ">");
00209           }
00210       }
00211     return healedName;
00212   }
00213 }
00214 
00215 //================================================================================
00219 //================================================================================
00220 
00221 SauvWriter* SauvWriter::New()
00222 {
00223   return new SauvWriter;
00224 }
00225 
00226 //================================================================================
00230 //================================================================================
00231 
00232 void SauvWriter::setMEDFileDS(const MEDFileData* medData,
00233                               unsigned           meshIndex)
00234 {
00235   if ( !medData) THROW_IK_EXCEPTION("NULL MEDFileData");
00236 
00237   MEDFileMeshes * meshes = medData->getMeshes();
00238   MEDFileFields * fields = medData->getFields();
00239   if ( !meshes) THROW_IK_EXCEPTION("No meshes in MEDFileData");
00240 
00241   _fileMesh = meshes->getMeshAtPos( meshIndex );
00242   _fileMesh->incrRef();
00243 
00244   if ( fields )
00245     for ( int i = 0; i < fields->getNumberOfFields(); ++i )
00246       {
00247         MEDFileFieldMultiTS * f = fields->getFieldAtPos(i);
00248         if ( f->getMeshName() == _fileMesh->getName() )
00249           {
00250             vector< vector<TypeOfField> > fTypes = f->getTypesOfFieldAvailable();
00251             if ( fTypes[0].size() == 1 && fTypes[0][0] == ON_NODES )
00252               _nodeFields.push_back( f );
00253             else
00254               _cellFields.push_back( f );
00255           }
00256       }
00257 }
00258 
00259 //================================================================================
00263 //================================================================================
00264 
00265 SauvWriter::SubMesh* SauvWriter::addSubMesh(const std::string& name, int dimRelExt)
00266 {
00267   if ( _subs.capacity() < _subs.size() + 1 )
00268     THROW_IK_EXCEPTION("SauvWriter: INTERNAL error, wrong evaluation of nb of sub-meshes");
00269   _subs.resize( _subs.size() + 1 );
00270   SubMesh& sm = _subs.back();
00271   sm._name = name;
00272   sm._dimRelExt = dimRelExt;
00273   return &sm;
00274 }
00275 //================================================================================
00279 //================================================================================
00280 
00281 int SauvWriter::SubMesh::nbTypes() const
00282 {
00283   int nb = 0;
00284   for (int i = 0; i < cellIDsByTypeSize(); ++i )
00285     nb += int( !_cellIDsByType[i].empty() );
00286   return nb;
00287 }
00288 
00289 //================================================================================
00293 //================================================================================
00294 
00295 void SauvWriter::fillSubMeshes( int& nbSauvObjects, map<string,int>& nameNbMap )
00296 {
00297   // evaluate nb of _subs in order to avoid re-allocation of _subs
00298   int nbSubs = 1; // for the very mesh
00299   nbSubs += _fileMesh->getFamilyInfo().size() + 4;  // + 4 zero families (for each dimRelExt)
00300   nbSubs += _fileMesh->getGroupInfo().size();
00301   nbSubs += evaluateNbProfileSubMeshes();
00302   _subs.clear();
00303   _subs.reserve( nbSubs );
00304 
00305   fillFamilySubMeshes();
00306   fillGroupSubMeshes();
00307   fillProfileSubMeshes();
00308 
00309   // fill names of SubMesh'es and count nb of sauv sub-meshes they will be stored into
00310   nbSauvObjects = 0;
00311   map<string,int> namePrefixMap;
00312   for ( size_t i = 0; i < _subs.size(); ++i )
00313     {
00314       SubMesh& sm = _subs[i];
00315 
00316       sm._nbSauvObjects = 0;
00317       if ( sm._subs.empty() )
00318         {
00319           sm._nbSauvObjects = sm.nbTypes();
00320         }
00321       else
00322         {
00323           sm._nbSauvObjects = 1;
00324         }
00325 
00326       sm._id = nbSauvObjects+1;
00327       nbSauvObjects += sm._nbSauvObjects;
00328 
00329       if ( sm._nbSauvObjects )
00330         sm._name = addName( nameNbMap, namePrefixMap, sm._name, sm._id );
00331 
00332       if ( sm._nbSauvObjects && !sm._name.empty() )
00333         {
00334           nameGIBItoMED aMEDName;
00335           aMEDName.gibi_pile = PILE_SOUS_MAILLAGE;
00336           aMEDName.gibi_id   = sm._id;
00337           aMEDName.med_name  = sm._name;
00338           _longNames[ LN_MAIL ].push_back(aMEDName);
00339         }
00340     }
00341 }
00342 
00343 //================================================================================
00347 //================================================================================
00348 
00349 void SauvWriter::fillFamilySubMeshes()
00350 {
00351   SubMesh* nilSm = (SubMesh*) 0;
00352   std::vector<int> dims = _fileMesh->getNonEmptyLevelsExt();
00353   for ( size_t iDim = 0; iDim < dims.size(); ++iDim )
00354     {
00355       int dimRelExt = dims[ iDim ];
00356       MEDCouplingAutoRefCountObjectPtr< MEDCouplingMesh > mesh = _fileMesh->getGenMeshAtLevel(dimRelExt);
00357       const DataArrayInt * famIds = _fileMesh->getFamilyFieldAtLevel(dimRelExt);
00358 
00359       int curFamID = 0;
00360       SubMesh* curSubMesh = addSubMesh( "", dimRelExt ); // submesh of zero family
00361       _famIDs2Sub[0] = curSubMesh;
00362       int sub0Index = _subs.size()-1;
00363 
00364       const int * famID = famIds->begin(), * famIDEnd = famIds->end();
00365       for ( int cellID = 0; famID < famIDEnd; ++famID, cellID++ )
00366         {
00367           if ( *famID != curFamID )
00368             {
00369               curFamID = *famID;
00370               map< int, SubMesh* >::iterator f2s = _famIDs2Sub.insert( make_pair( curFamID, nilSm )).first;
00371               if ( !f2s->second )
00372                 f2s->second = addSubMesh( "", dimRelExt ); // no names for families
00373               curSubMesh = f2s->second;
00374             }
00375           INTERP_KERNEL::NormalizedCellType cellType =
00376             dimRelExt == 1 ? INTERP_KERNEL::NORM_POINT1 : mesh->getTypeOfCell( cellID );
00377           curSubMesh->_cellIDsByType[ cellType ].push_back( cellID );
00378         }
00379 
00380       if ( dimRelExt == 1 )
00381         {
00382           // clear submesh of nodal zero family
00383           _famIDs2Sub[0]->_cellIDsByType[ INTERP_KERNEL::NORM_POINT1 ].clear();
00384         }
00385       else if ( dimRelExt == 0 )
00386         {
00387           // make a submesh including all cells
00388           if ( sub0Index == (int)(_subs.size()-1) )
00389             {
00390               _famIDs2Sub[0]->_name = _fileMesh->getName(); // there is the zero family only
00391             }
00392           else
00393             {
00394               curSubMesh = addSubMesh( _fileMesh->getName(), dimRelExt );
00395               if ( _famIDs2Sub[0]->nbTypes() == 0 )
00396                 sub0Index++; // skip an empty zero family
00397               for ( size_t i = sub0Index; i < _subs.size()-1; ++i )
00398                 curSubMesh->_subs.push_back( & _subs[i] );
00399             }
00400         }
00401     }
00402 }
00403 
00404 //================================================================================
00408 //================================================================================
00409 
00410 void SauvWriter::fillGroupSubMeshes()
00411 {
00412   const map<string, vector<string> >& grpFams = _fileMesh->getGroupInfo();
00413   map<string, vector<string> >::const_iterator g2ff = grpFams.begin();
00414   for ( ; g2ff != grpFams.end(); ++g2ff )
00415     {
00416       const string&        groupName = g2ff->first;
00417       const vector<string>& famNames = g2ff->second;
00418       if ( famNames.empty() ) continue;
00419       std::vector<SubMesh*> famSubMeshes( famNames.size() );
00420       for ( size_t i = 0; i < famNames.size(); ++i )
00421         {
00422           int famID = _fileMesh->getFamilyId( famNames[i].c_str() );
00423           map< int, SubMesh* >::iterator i2f = _famIDs2Sub.find( famID );
00424           if ( i2f == _famIDs2Sub.end() )
00425             THROW_IK_EXCEPTION("SauvWriter::fillGroupSubMeshes(): unknown family ID: " << famID);
00426           famSubMeshes[ i ] = i2f->second;
00427         }
00428       SubMesh* grpSubMesh = addSubMesh( groupName, famSubMeshes[0]->_dimRelExt );
00429       grpSubMesh->_subs.swap( famSubMeshes );
00430     }
00431 }
00432 
00433 //================================================================================
00437 //================================================================================
00438 
00439 void SauvWriter::fillProfileSubMeshes()
00440 {
00441   _profile2Sub.clear();
00442   SubMesh* nilSm = (SubMesh*) 0;
00443   for ( int isOnNodes = 0; isOnNodes < 2; ++isOnNodes )
00444     {
00445       vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldMultiTS > >
00446         fields = isOnNodes ? _nodeFields : _cellFields;
00447       for ( size_t i = 0; i < fields.size(); ++i )
00448         {
00449           vector< pair<int,int> > iters = fields[i]->getIterations();
00450 
00451           vector<INTERP_KERNEL::NormalizedCellType> types;
00452           vector< vector<TypeOfField> > typesF;
00453           vector< vector<string> > pfls, locs;
00454           fields[i]->getFieldSplitedByType( iters[0].first, iters[0].second,
00455                                             _fileMesh->getName(), types, typesF, pfls, locs);
00456           int dimRelExt;
00457           for ( size_t iType = 0; iType < types.size(); ++iType )
00458             {
00459               if ( types[iType] == INTERP_KERNEL::NORM_ERROR )
00460                 dimRelExt = 1; // on nodes
00461               else
00462                 dimRelExt = getDimension( types[iType] ) - _fileMesh->getMeshDimension();
00463               for ( size_t iPfl = 0; iPfl < pfls[iType].size(); ++iPfl )
00464                 {
00465                   bool isOnAll = pfls[iType][iPfl].empty();
00466                   if ( isOnAll ) pfls[iType][iPfl] = noProfileName( types[iType] );
00467                   map< string, SubMesh* >::iterator pfl2sm =
00468                     _profile2Sub.insert( make_pair( pfls[iType][iPfl], nilSm )).first;
00469                   if ( !pfl2sm->second )
00470                     {
00471                       SubMesh* sm = pfl2sm->second = addSubMesh( "", dimRelExt ); // no names for profiles
00472                       const DataArrayInt * pfl = isOnAll ? 0 : fields[i]->getProfile( pfls[iType][iPfl].c_str() );
00473                       makeProfileIDs( sm, types[iType], pfl );
00474                     }
00475                 }
00476             }
00477         }
00478     }
00479 }
00480 
00481 //================================================================================
00485 //================================================================================
00486 
00487 int SauvWriter::evaluateNbProfileSubMeshes() const
00488 {
00489   int nb = 0;
00490   for ( size_t i = 0; i < _nodeFields.size(); ++i )
00491     nb += 1 + _nodeFields[i]->getPflsReallyUsed2().size();
00492 
00493   for ( size_t i = 0; i < _cellFields.size(); ++i )
00494     {
00495       nb += _cellFields[i]->getPflsReallyUsed2().size();
00496 
00497       vector< pair<int,int> > iters = _cellFields[i]->getIterations();
00498 
00499       vector<INTERP_KERNEL::NormalizedCellType> types;
00500       vector< vector<TypeOfField> > typesF;
00501       vector< vector<string> > pfls, locs;
00502       _cellFields[i]->getFieldSplitedByType( iters[0].first, iters[0].second,
00503                                              _fileMesh->getName(), types, typesF, pfls, locs);
00504       nb += 2 * types.size(); // x 2 - a type can be on nodes and on cells at the same time
00505     }
00506 
00507   return nb;
00508 }
00509 
00510 //================================================================================
00514 //================================================================================
00515 
00516 void SauvWriter::makeProfileIDs( SubMesh*                          sm,
00517                                  INTERP_KERNEL::NormalizedCellType type,
00518                                  const DataArrayInt*               profile )
00519 {
00520   MEDCouplingAutoRefCountObjectPtr< MEDCouplingMesh >
00521     mesh = _fileMesh->getGenMeshAtLevel(sm->_dimRelExt);
00522   const MEDCouplingUMesh* uMesh = dynamic_cast< const MEDCouplingUMesh* > ((const MEDCouplingMesh*) mesh );
00523 
00524   if ( sm->_dimRelExt == 1 ) type = INTERP_KERNEL::NORM_POINT1;
00525   vector< int >& ids = sm->_cellIDsByType[ type ];
00526 
00527   if ( sm->_dimRelExt == 1 || !uMesh )
00528     {
00529       // profile on nodes or mesh is CARTESIAN
00530       if ( profile )
00531         {
00532           ids.assign( profile->begin(), profile->end() );
00533         }
00534       else // on all
00535         {
00536           ids.resize( sm->_dimRelExt == 1 ? mesh->getNumberOfNodes() : mesh->getNumberOfCells() );
00537           for ( size_t i = 0; i < ids.size(); ++i )
00538             ids[i]=i;
00539         }
00540     }
00541   else
00542     {
00543       // profile on cells
00544       vector<int> code(3);
00545       code[0] = type;
00546       if ( profile ) // on profile
00547         {
00548           code[1] = profile->getNumberOfTuples();
00549           code[2] = 0;
00550         }
00551       else // on all cells
00552         {
00553           code[1] = mesh->getNumberOfCellsWithType( type );
00554           code[2] = -1;
00555         }
00556       vector<const DataArrayInt *> idsPerType( 1, profile );
00557       MEDCouplingAutoRefCountObjectPtr<DataArrayInt>
00558         resIDs = uMesh->checkTypeConsistencyAndContig( code, idsPerType );
00559       ids.assign( resIDs->begin(), resIDs->end() );
00560     }
00561 }
00562 
00563 //================================================================================
00567 //================================================================================
00568 
00569 void SauvWriter::write(const char* fileName)
00570 {
00571   std::fstream fileStream;
00572   fileStream.open( fileName, ios::out);
00573   if
00574 #ifdef WNT
00575     ( !fileStream || !fileStream.is_open() )
00576 #else
00577     ( !fileStream || !fileStream.rdbuf()->is_open() )
00578 #endif
00579       THROW_IK_EXCEPTION("Can't open the file |"<<fileName<<"|");
00580   _sauvFile = &fileStream;
00581 
00582   _subs.clear();
00583   _famIDs2Sub.clear();
00584   _profile2Sub.clear();
00585   _longNames[ LN_MAIL ].clear();
00586   _longNames[ LN_CHAM ].clear();
00587   _longNames[ LN_COMP ].clear();
00588 
00589   map<string,int> fldNamePrefixMap;
00590 
00591   writeFileHead();
00592   writeSubMeshes();
00593   writeNodes();
00594   writeNodalFields(fldNamePrefixMap);
00595   writeElemFields(fldNamePrefixMap);
00596   writeLongNames();
00597   writeLastRecord();
00598 
00599   _sauvFile->close();
00600 }
00601 //================================================================================
00605 //================================================================================
00606 
00607 void SauvWriter::writeFileHead()
00608 {
00609   MEDCouplingAutoRefCountObjectPtr< MEDCouplingMesh > mesh = _fileMesh->getGenMeshAtLevel(0);
00610 
00611   *_sauvFile
00612     << " ENREGISTREMENT DE TYPE   4" << endl
00613     << " NIVEAU  16 NIVEAU ERREUR   0 DIMENSION   " << mesh->getSpaceDimension() <<endl
00614     << " DENSITE 0.00000E+00" << endl
00615     << " ENREGISTREMENT DE TYPE   7" << endl
00616     << " NOMBRE INFO CASTEM2000   8" <<endl
00617     << " IFOUR  -1 NIFOUR   0 IFOMOD  -1 IECHO   1 IIMPI   0 IOSPI   0 ISOTYP   1" << endl
00618     << " NSDPGE     0" << endl;
00619 }
00620 
00621 //================================================================================
00625 //================================================================================
00626 
00627 void SauvWriter::writeNames( const map<string,int>& nameNbMap )
00628 {
00629   if ( !nameNbMap.empty() )
00630   {
00631     // write names of objects
00632     // * 8001       FORMAT(8(1X,A8))
00633     TFieldCounter fcount( *_sauvFile, 8 );
00634     *_sauvFile << left;
00635     map<string,int>::const_iterator nameNbIt = nameNbMap.begin();
00636     for ( ; nameNbIt != nameNbMap.end(); nameNbIt++, fcount++ )
00637       *_sauvFile << " " << setw(8) << nameNbIt->first;
00638     fcount.stop();
00639     *_sauvFile << right;
00640 
00641     // write IDs of named objects in the pile
00642     // *  8000 FORMAT(10I8)
00643     nameNbIt = nameNbMap.begin();
00644     for ( fcount.init(10); nameNbIt != nameNbMap.end(); nameNbIt++, fcount++ )
00645       *_sauvFile << setw(8) << nameNbIt->second;
00646   }
00647 }
00648 
00649 //================================================================================
00653 //================================================================================
00654 
00655 void SauvWriter::writeSubMeshes()
00656 {
00657   int nbSauvObjects;
00658   map<string,int> nameNbMap;
00659   fillSubMeshes( nbSauvObjects, nameNbMap );
00660 
00661   // * 800   FORMAT (' ENREGISTREMENT DE TYPE', I4)
00662   *_sauvFile << " ENREGISTREMENT DE TYPE   2" << endl;
00663   // * 801     FORMAT(' PILE NUMERO',I4,'NBRE OBJETS NOMMES',I8,'NBRE OBJETS',I8)
00664   *_sauvFile << " PILE NUMERO   1NBRE OBJETS NOMMES" << setw(8) << nameNbMap.size() <<
00665     "NBRE OBJETS" << setw(8) << nbSauvObjects <<endl;
00666 
00667   writeNames( nameNbMap );
00668 
00669   TFieldCounter fcount( *_sauvFile, 10 ); // 10 intergers per line
00670 
00671   for ( size_t iSub = 0; iSub < _subs.size(); ++iSub )
00672     {
00673       SubMesh& sm = _subs[iSub];
00674       if ( sm._nbSauvObjects < 1 ) continue;
00675 
00676       // The first record of each sub-mesh writes
00677       // - type of cells; zero means a compound object whose the 2nd record enumerates its components
00678       // - number of components of a compound object
00679       // - number of references; each reference means a "pointer" to this sub-mesh
00680       // - number of nodes per cell
00681       // - number of cells
00682 
00683       if ( !sm._subs.empty() )
00684         {
00685           writeCompoundSubMesh(iSub);
00686         }
00687       else
00688         {
00689           // write each sub-type as a SAUV sub-mesh
00690           MEDCouplingAutoRefCountObjectPtr< MEDCouplingMesh >
00691             mesh = _fileMesh->getGenMeshAtLevel( sm._dimRelExt );
00692           MEDCouplingAutoRefCountObjectPtr< MEDCouplingUMesh>
00693             umesh = mesh->buildUnstructured();
00694 
00695           for ( int iType=0; iType < sm.cellIDsByTypeSize(); ++iType )
00696             {
00697               const vector<int>& cellIDs = sm._cellIDsByType[iType];
00698               if ( cellIDs.empty() ) continue;
00699 
00700               INTERP_KERNEL::NormalizedCellType
00701                 cellType = INTERP_KERNEL::NormalizedCellType( iType );
00702               const INTERP_KERNEL::CellModel &
00703                 cell = INTERP_KERNEL::CellModel::GetCellModel( cellType );
00704               int castemType       = SauvUtilities::med2gibiGeom( cellType );
00705               unsigned nbElemNodes = cell.getNumberOfNodes();
00706               unsigned nbElems     = cellIDs.size();
00707 
00708               *_sauvFile << setw(8) << castemType
00709                         << zeroI8
00710                         << zeroI8
00711                         << setw(8) << nbElemNodes
00712                         << setw(8) << nbElems << endl;
00713 
00714               // write color of each element
00715               // * 8000 FORMAT(10I8)
00716               for ( size_t i = 0; i < nbElems; ++i, fcount++ ) *_sauvFile << zeroI8;
00717               fcount.stop();
00718 
00719               // write connectivity
00720               // gibi IDs are in FORTRAN mode while MEDCoupling IDs are in C mode
00721               if ( sm._dimRelExt == 1 ) // nodes
00722                 {
00723                   for ( size_t i = 0; i < nbElems; ++i, fcount++ )
00724                     *_sauvFile << setw(8) << ( cellIDs[i] + 1 );
00725                 }
00726               else
00727                 {
00728                   // indices to transform MED connectivity to GIBI one
00729                   const int * toMedConn = getGibi2MedQuadraticInterlace( cellType );
00730 
00731                   vector< int > cellConn( nbElemNodes ), transformedConn( nbElemNodes );
00732                   for ( size_t i = 0; i < nbElems; ++i )
00733                     {
00734                       cellConn.clear();
00735                       umesh->getNodeIdsOfCell( cellIDs[i], cellConn );
00736                       if ( toMedConn )
00737                         {
00738                           for ( unsigned j = 0; j < nbElemNodes; ++j )
00739                             transformedConn[ j ] = cellConn[ toMedConn[ j ]];
00740                           cellConn.swap( transformedConn );
00741                         }
00742                       for ( unsigned j = 0; j < nbElemNodes; ++j, fcount++ )
00743                         *_sauvFile << setw(8) << ( cellConn[j] + 1 );
00744                     }
00745                 }
00746               fcount.stop();
00747 
00748             } // loop on cell types
00749         } // not a compound object
00750     } // loop on sub-meshes
00751 }
00752 
00753 //================================================================================
00758 //================================================================================
00759 
00760 void SauvWriter::writeCompoundSubMesh(int iSub)
00761 {
00762   SubMesh& sm = _subs[iSub];
00763   if ( sm._nbSauvObjects < 1 || sm._subs.empty()) return;
00764 
00765   vector< int > subIDs;
00766   for ( size_t i = 0; i < sm._subs.size(); ++i ) // loop on sub-meshes of families
00767     for ( int j = 0; j < sm._subs[i]->_nbSauvObjects; ++j )
00768       subIDs.push_back( sm._subs[i]->_id + j );
00769       
00770   *_sauvFile << zeroI8
00771              << setw(8) << subIDs.size()
00772              << zeroI8
00773              << zeroI8
00774              << zeroI8 << endl;
00775 
00776   TFieldCounter fcount( *_sauvFile, 10 ); // 10 intergers per line
00777   for ( size_t i = 0; i < subIDs.size(); ++i, fcount++ )
00778     *_sauvFile << setw(8) << subIDs[i];
00779 }
00780 
00781 //================================================================================
00785 //================================================================================
00786 
00787 void SauvWriter::writeNodes()
00788 {
00789   MEDCouplingAutoRefCountObjectPtr< MEDCouplingMesh > mesh = _fileMesh->getGenMeshAtLevel( 1 );
00790   MEDCouplingAutoRefCountObjectPtr< MEDCouplingUMesh > umesh = mesh->buildUnstructured();
00791 
00792   // write the index connecting nodes with their coodrinates
00793 
00794   const int nbNodes = umesh->getNumberOfNodes();
00795   *_sauvFile << " ENREGISTREMENT DE TYPE   2" << endl
00796              << " PILE NUMERO  32NBRE OBJETS NOMMES       0NBRE OBJETS" << setw(8) << nbNodes << endl;
00797   *_sauvFile << setw(8) << nbNodes << endl;
00798   //
00799   TFieldCounter fcount( *_sauvFile, 10 );// * 8000 FORMAT(10I8)
00800   for ( int i = 0; i < nbNodes; ++i, fcount++ )
00801     *_sauvFile << setw(8) << i + 1; 
00802   fcount.stop();
00803 
00804   // write coordinates and density of nodes
00805 
00806   *_sauvFile << " ENREGISTREMENT DE TYPE   2" << endl;
00807   *_sauvFile << " PILE NUMERO  33NBRE OBJETS NOMMES       0NBRE OBJETS       1" << endl;
00808   // 
00809   const int dim = umesh->getSpaceDimension();
00810   const int nbValues = nbNodes * ( dim + 1 );
00811   *_sauvFile << setw(8) << nbValues << endl;
00812 
00813   // * 8003   FORMAT(1P,3E22.14)
00814   const char* density = "  0.00000000000000E+00";
00815   fcount.init(3);
00816   _sauvFile->precision(14);
00817   _sauvFile->setf( ios_base::scientific, ios_base::floatfield );
00818   _sauvFile->setf( ios_base::uppercase );
00819   MEDCouplingAutoRefCountObjectPtr< DataArrayDouble> coordArray = umesh->getCoordinatesAndOwner();
00820   const double precision = 1.e-99; // PAL12077
00821   for ( int i = 0; i < nbNodes; ++i)
00822   {
00823     for ( int j = 0; j < dim; ++j, fcount++ )
00824       {
00825         double coo = coordArray->getIJ( i, j );
00826         bool  zero = ( -precision < coo && coo < precision );
00827         *_sauvFile << setw(22) << ( zero ? 0.0 : coo );
00828       }
00829     *_sauvFile << density;
00830     fcount++;
00831   }
00832 }
00833 
00834 //================================================================================
00842 //================================================================================
00843 
00844 void SauvWriter::writeLongNames()
00845 {
00846   int nbTables =
00847     3 - _longNames[ LN_MAIL ].empty() - _longNames[ LN_CHAM ].empty() - _longNames[ LN_COMP ].empty();
00848   if (nbTables == 0) return;
00849 
00850   // ---------------------
00851   // Write the TABLE pile
00852   // ---------------------
00853 
00854   *_sauvFile << " ENREGISTREMENT DE TYPE   2" << endl
00855         << " PILE NUMERO  10NBRE OBJETS NOMMES" << setw(8) << nbTables
00856         << "NBRE OBJETS" << setw(8) << nbTables << endl;
00857   // table names
00858   if (!_longNames[ LN_MAIL ].empty()) *_sauvFile << " MED_MAIL";
00859   if (!_longNames[ LN_CHAM ].empty()) *_sauvFile << " MED_CHAM";
00860   if (!_longNames[ LN_COMP ].empty()) *_sauvFile << " MED_COMP";
00861   *_sauvFile << endl;
00862   // table indices
00863   for ( int i = 0; i < nbTables; ++i ) *_sauvFile << setw(8) << i+1;
00864   *_sauvFile << endl;
00865 
00866   string theWholeString; // concatenated long names
00867   vector<int> theOffsets;
00868   int iStr = 1;
00869   TFieldCounter fcount (*_sauvFile, 10);
00870 
00871   for ( int iTbl = 0; iTbl < LN_NB; ++iTbl )
00872     {
00873       vector<nameGIBItoMED>& longNames = _longNames[ iTbl ];
00874       if ( longNames.empty() ) continue;
00875       const bool isComp = ( iTbl == LN_COMP);
00876 
00877       // to assure unique MED names
00878       set<string> medUniqueNames;
00879 
00880       *_sauvFile << setw(8) << longNames.size()*4 << endl; // Nb of table values
00881 
00882       vector<nameGIBItoMED>::iterator itGIBItoMED = longNames.begin();
00883       for (; itGIBItoMED != longNames.end(); itGIBItoMED++, iStr++)
00884         {
00885           // PILE of i-th key (med name)
00886           *_sauvFile << setw(8) << PILE_STRINGS;
00887           fcount++;
00888           // ID of i-th key (med name)
00889           *_sauvFile << setw(8) << iStr;
00890           fcount++;
00891           // PILE of i-th value (gibi name)
00892           *_sauvFile << setw(8) << itGIBItoMED->gibi_pile;
00893           fcount++;
00894           // ID of i-th value (gibi name)
00895           *_sauvFile << setw(8) << ( isComp ? ++iStr : itGIBItoMED->gibi_id );
00896           fcount++;
00897 
00898           // add a MED name to the string (while making it be unique for sub-meshes and fields)
00899           string aMedName = itGIBItoMED->med_name;
00900           if ( !isComp )
00901             for (int ind = 1; !medUniqueNames.insert(aMedName).second; ++ind )
00902               aMedName = itGIBItoMED->med_name + "_" + SauvUtilities::toString( ind );
00903           theWholeString += aMedName;
00904 
00905           // add an offset
00906           theOffsets.push_back( theWholeString.size() );
00907           if ( isComp )
00908             {
00909               theWholeString += itGIBItoMED->gibi_name;
00910               theOffsets.push_back( theWholeString.size() );
00911             }
00912         }
00913       fcount.stop();
00914     }
00915 
00916   // ----------------------
00917   // Write the STRING pile
00918   // ----------------------
00919 
00920   const int nbNames = theOffsets.size();
00921   *_sauvFile << " ENREGISTREMENT DE TYPE   2" << endl
00922         << " PILE NUMERO  27NBRE OBJETS NOMMES" << zeroI8 << "NBRE OBJETS" << setw(8) << nbNames << endl
00923         << setw(8) << theWholeString.length() << setw(8) << nbNames << endl;
00924 
00925   // write the whole string
00926   const int fixedLength = 71;
00927   for ( string::size_type aPos = 0; aPos < theWholeString.length(); aPos += fixedLength)
00928     *_sauvFile << setw(72) << theWholeString.substr(aPos, fixedLength) << endl;
00929 
00930   // write the offsets
00931   for ( size_t i = 0; i < theOffsets.size(); ++i, fcount++ )
00932     *_sauvFile << setw(8) << theOffsets[i];
00933 }
00934 
00935 //================================================================================
00939 //================================================================================
00940 
00941 void SauvWriter::writeFieldNames( const bool                 isNodal,
00942                                   std::map<std::string,int>& fldNamePrefixMap)
00943 {
00944   vector< MEDCouplingAutoRefCountObjectPtr< MEDFileFieldMultiTS > >&
00945     flds = isNodal ? _nodeFields : _cellFields;
00946   map<string,int> nameNbMap;
00947 
00948   for ( size_t iF = 0; iF < flds.size(); ++iF )
00949     {
00950       string name = addName( nameNbMap, fldNamePrefixMap, flds[iF]->getName(), iF+1 );
00951       nameGIBItoMED aMEDName;
00952       aMEDName.gibi_pile = isNodal ? PILE_NODES_FIELD : PILE_FIELD;
00953       aMEDName.gibi_id   = iF+1;
00954       aMEDName.med_name  = name;
00955       _longNames[ LN_CHAM ].push_back(aMEDName);
00956     }
00957 
00958   *_sauvFile << " ENREGISTREMENT DE TYPE   2" << endl
00959              << ( isNodal ? " PILE NUMERO   2" : " PILE NUMERO  39")
00960              << "NBRE OBJETS NOMMES" << setw(8) << nameNbMap.size()
00961              << "NBRE OBJETS"        << setw(8) << flds.size() << endl;
00962   writeNames( nameNbMap );
00963 }
00964 
00965 //================================================================================
00971 //================================================================================
00972 
00973 void SauvWriter::makeCompNames(const string&         fieldName,
00974                                const vector<string>& compInfo,
00975                                map<string, string>&  mapMedToGibi)
00976 {
00977   for ( size_t i = 0; i < compInfo.size(); ++i )
00978     mapMedToGibi[compInfo[i]] = cleanName( compInfo[i] );
00979 
00980   int compIndex = 1;
00981   map<string, string>::iterator namesIt = mapMedToGibi.begin();
00982   for (; namesIt != mapMedToGibi.end(); namesIt++)
00983     {
00984       string & compGibiName = (*namesIt).second;
00985       if (compGibiName.size() > 4) {
00986         // use new name in form "CXXX", where "XXX" is a number
00987         do
00988           {
00989             compGibiName = SauvUtilities::toString( compIndex++ );
00990             if ( compGibiName.size() < 3 )
00991               compGibiName.insert( 0, 3 - compGibiName.size(), '0' );
00992             compGibiName = "C" + compGibiName;
00993           }
00994         while (mapMedToGibi.count(compGibiName) > 0); // real component name could be CXXX
00995       }
00996 
00997       string compMedName = fieldName + "." + namesIt->first;
00998       nameGIBItoMED aMEDName;
00999       aMEDName.med_name  = compMedName;
01000       aMEDName.gibi_pile = PILE_STRINGS;
01001       aMEDName.gibi_name = compGibiName;
01002       _longNames[ LN_COMP ].push_back(aMEDName);
01003     }
01004 }
01005 
01006 //================================================================================
01010 //================================================================================
01011 
01012 void SauvWriter::writeNodalFields(map<string,int>& fldNamePrefixMap)
01013 {
01014   writeFieldNames( /*isNodal=*/true, fldNamePrefixMap );
01015 
01016   TFieldCounter fcount (*_sauvFile, 10);
01017 
01018   // EXAMPLE ( with no values )
01019 
01020   // (1)       4       7       2       1
01021   // (2)     -88       0       3     -89       0       1     -90       0       2     -91
01022   // (2)       0       1
01023   // (3) FX   FY   FZ   FZ   FX   FY   FLX
01024   // (4)       0       0       0       0       0       0       0
01025   // (5)           cree  par  muc pri
01026   // (6)
01027   // (7)       2
01028   for ( size_t iF = 0; iF < _nodeFields.size(); ++iF )
01029     {
01030       // (1) write nb subcomponents, nb components(total)
01031       vector< pair<int,int> >  iters = _nodeFields[iF]->getIterations();
01032       const vector<string>& compInfo = _nodeFields[iF]->getInfo();
01033       const int nbSub = iters.size();
01034       const int nbComp = compInfo.size();
01035       const int totalNbComp = nbSub * nbComp;
01036       *_sauvFile << setw(8) << nbSub
01037                  << setw(8) << totalNbComp
01038                  << setw(8) << -1         // IFOUR
01039                  << setw(8) << 0 << endl; // nb attributes
01040 
01041       // (2) for each sub-component (iteration)
01042       // write support, number of values and number of components
01043       fcount.init(10);
01044       vector< int > vals(3);
01045       for ( std::size_t iIt = 0; iIt < iters.size(); ++iIt )
01046         {
01047           pair<int,int> it = iters[iIt];
01048 
01049           vector<INTERP_KERNEL::NormalizedCellType> types;
01050           vector< vector<TypeOfField> > typesF;
01051           vector< vector<string> > pfls, locs;
01052           vector< vector< std::pair<int,int> > > valsVec;
01053           valsVec=_nodeFields[iF]->getFieldSplitedByType( it.first, it.second, _fileMesh->getName(),
01054                                                           types, typesF, pfls, locs);
01055           // believe that there can be only one type in a nodal field,
01056           // so do not use a loop on types
01057           if ( pfls[0][0].empty() ) pfls[0][0] = noProfileName( types[0] );
01058           map< string, SubMesh* >::iterator pfl2Sub = _profile2Sub.find( pfls[0][0] );
01059           if ( pfl2Sub == _profile2Sub.end() )
01060             THROW_IK_EXCEPTION( "SauvWriter::writeNodalFields(): no sub-mesh for profile |"
01061                                 << pfls[0][0] << "|");
01062           vals[0] = -pfl2Sub->second->_id;
01063           vals[1] = (valsVec[0][0].second-valsVec[0][0].first);
01064           vals[2] = compInfo.size();
01065           for ( size_t i = 0; i < vals.size(); ++i, fcount++ )
01066             *_sauvFile << setw(8) << vals[i];
01067         }
01068       fcount.stop();
01069 
01070       // (3) Write names of components
01071       map<string, string> mapMedToGibi;
01072       makeCompNames( _nodeFields[iF]->getName(), compInfo, mapMedToGibi );
01073       fcount.init(8);
01074       *_sauvFile << left;
01075       for ( std::size_t iIt = 0; iIt < iters.size(); ++iIt )
01076         for ( size_t i = 0; i < compInfo.size(); ++i, fcount++ )
01077           *_sauvFile << " "  << setw(4) << mapMedToGibi[compInfo[i]];
01078       *_sauvFile << right;
01079       fcount.stop();
01080 
01081       // (4) nb harmonics
01082       fcount.init(10);
01083       for ( size_t i = 0; i < (std::size_t)totalNbComp; ++i, fcount++ )
01084         *_sauvFile << " "  << setw(8) << 0;
01085       fcount.stop();
01086 
01087       string description = _nodeFields[iF]->getName();
01088       *_sauvFile << endl;                                         // (5) TYPE
01089       *_sauvFile << setw(72) << description.substr(0,71) << endl; // (6) TITRE
01090       //*_sauvFile << endl;                                         // (7) 0 attributes
01091 
01092       // write values of each component
01093       fcount.init( 3 ); // 3 values per a line
01094       for ( std::size_t iIt = 0; iIt < iters.size(); ++iIt )
01095         {
01096           pair<int,int> it = iters[iIt];
01097 
01098           vector<INTERP_KERNEL::NormalizedCellType> types;
01099           vector< vector<TypeOfField> > typesF;
01100           vector< vector<string> > pfls, locs;
01101           vector< vector< std::pair<int,int> > > valsVec;
01102           valsVec = _nodeFields[iF]->getFieldSplitedByType( it.first, it.second, _fileMesh->getName(),
01103                                                             types, typesF, pfls, locs);
01104           // believe that there can be only one type in a nodal field,
01105           // so do not perform a loop on types
01106           const DataArrayDouble* valsArray = _nodeFields[iF]->getUndergroundDataArray(it.first, it.second);
01107           for ( size_t j = 0; j < compInfo.size(); ++j )
01108             {
01109               for ( size_t i = valsVec[0][0].first; i < (std::size_t)valsVec[0][0].second; ++i, fcount++ )
01110                 *_sauvFile << setw(22) << valsArray->getIJ( i, j );
01111               fcount.stop();
01112             }
01113         }
01114     } // loop on fiels
01115 }
01116 
01117 //================================================================================
01121 //================================================================================
01122 
01123 void SauvWriter::writeElemFields(map<string,int>& fldNamePrefixMap)
01124 {
01125   writeFieldNames( /*isNodal=*/false, fldNamePrefixMap );
01126 
01127   TFieldCounter fcount (*_sauvFile, 10);
01128 
01129   // REAL EXAMPLE
01130 
01131   // (1)        1       2       6      16
01132   // (2)                                                         CARACTERISTIQUES
01133   // (3)      -15  317773       4       0       0       0      -2       0       3
01134   // (4)             317581
01135   // (5)  0
01136   // (6)   317767  317761  317755  317815
01137   // (7)  YOUN     NU       H        SIGY
01138   // (8)  REAL*8            REAL*8            REAL*8            REAL*8
01139   // (9)        1       1       0       0
01140   // (10)  2.00000000000000E+05
01141   // (9)       1       1       0       0
01142   // (10)  3.30000000000000E-01
01143   // (9)       1       1       0       0
01144   // (10)  1.00000000000000E+04
01145   // (9)       6     706       0       0
01146   // (10)  1.00000000000000E+02  1.00000000000000E+02  1.00000000000000E+02
01147   // (10)  1.00000000000000E+02  1.00000000000000E+02  1.00000000000000E+02
01148   // (10)  ...
01149 
01150   for ( size_t iF = 0; iF < _cellFields.size(); ++iF )
01151     {
01152       // count nb of sub-components
01153       int iSub, nbSub = 0;
01154       vector< pair<int,int> >  iters = _cellFields[iF]->getIterations();
01155       for ( std::size_t iIt = 0; iIt < iters.size(); ++iIt )
01156         {
01157           pair<int,int> it = iters[iIt];
01158 
01159           vector<INTERP_KERNEL::NormalizedCellType> types;
01160           vector< vector<TypeOfField> > typesF;
01161           vector< vector<string> > pfls, locs;
01162           vector< vector< std::pair<int,int> > > valsVec;
01163           valsVec = _cellFields[iF]->getFieldSplitedByType( it.first, it.second, _fileMesh->getName(),
01164                                                             types, typesF, pfls, locs);
01165           for ( size_t i = 0; i < valsVec.size(); ++i )
01166             nbSub += valsVec[i].size();
01167         }
01168       // (1) write nb sub-components, title length
01169       *_sauvFile << setw(8) << nbSub
01170                  << setw(8) << -1 // whatever
01171                  << setw(8) << 6  // whatever
01172                  << setw(8) << 72 << endl; // title length
01173       // (2) title
01174       string title = _cellFields[iF]->getName();
01175       *_sauvFile << setw(72) << title.substr(0,71) << endl;
01176       *_sauvFile << setw(72) << " " << endl;
01177 
01178       // (3) support, nb components
01179       vector<int> vals(9, 0);
01180       const vector<string>& compInfo = _cellFields[iF]->getInfo();
01181       vals[2] = compInfo.size();
01182       fcount.init(10);
01183       for ( std::size_t iIt = 0; iIt < iters.size(); ++iIt )
01184         {
01185           pair<int,int> it = iters[iIt];
01186 
01187           vector<INTERP_KERNEL::NormalizedCellType> types;
01188           vector< vector<TypeOfField> > typesF;
01189           vector< vector<string> > pfls, locs;
01190           _cellFields[iF]->getFieldSplitedByType( it.first, it.second, _fileMesh->getName(),
01191                                                   types, typesF, pfls, locs);
01192           for ( size_t iType = 0; iType < pfls.size(); ++iType )
01193             for ( size_t iP = 0; iP < pfls[iType].size(); ++iP )
01194               {
01195                 if ( pfls[iType][iP].empty() ) pfls[iType][iP] = noProfileName( types[iType] );
01196                 map< string, SubMesh* >::iterator pfl2Sub = _profile2Sub.find( pfls[iType][iP] );
01197                 if ( pfl2Sub == _profile2Sub.end() )
01198                   THROW_IK_EXCEPTION( "SauvWriter::writeElemFields(): no sub-mesh for profile |"
01199                                       << pfls[iType][iP] << "|");
01200                 const int supportID = pfl2Sub->second->_id;
01201                 vals[0] = -supportID;
01202 
01203                 for ( size_t i = 0; i < vals.size(); ++i, fcount++ )
01204                   *_sauvFile << setw(8) << vals[ i ];
01205               }
01206         }
01207       fcount.stop();
01208 
01209       // (4) dummy strings
01210       for ( fcount.init(4), iSub = 0; iSub < nbSub; ++iSub, fcount++ )
01211         *_sauvFile << "                  ";
01212       fcount.stop();
01213 
01214       // (5) dummy strings
01215       for ( fcount.init(8), iSub = 0; iSub < nbSub; ++iSub, fcount++ )
01216         *_sauvFile << "         ";
01217       fcount.stop();
01218 
01219       // loop on sub-components of a field, each of which refers to
01220       // a certain support and has its own number of components
01221       for ( std::size_t iIt = 0; iIt < iters.size(); ++iIt )
01222         {
01223           pair<int,int> it = iters[iIt];
01224           writeElemTimeStamp( iF, it.first, it.second );
01225         }
01226     } // loop on cell fields
01227 }
01228 
01229 //================================================================================
01233 //================================================================================
01234 
01235 void SauvWriter::writeElemTimeStamp(int iF, int iter, int order)
01236 {
01237   // (6)   317767  317761  317755  317815
01238   // (7)  YOUN     NU       H        SIGY
01239   // (8)  REAL*8            REAL*8            REAL*8            REAL*8
01240   // (9)        1       1       0       0
01241   // (10)  2.00000000000000E+05
01242   // (9)       1       1       0       0
01243   // (10)  3.30000000000000E-01
01244   // (9)       1       1       0       0
01245   // (10)  1.00000000000000E+04
01246   // (9)       6     706       0       0
01247   // (10)  1.00000000000000E+02  1.00000000000000E+02  1.00000000000000E+02
01248   // (10)  1.00000000000000E+02  1.00000000000000E+02  1.00000000000000E+02
01249 
01250   TFieldCounter fcount (*_sauvFile, 10);
01251 
01252   vector<INTERP_KERNEL::NormalizedCellType> types;
01253   vector< vector<TypeOfField> > typesF;
01254   vector< vector<string> > pfls, locs;
01255   vector< vector< std::pair<int,int> > > valsVec;
01256   valsVec = _cellFields[iF]->getFieldSplitedByType( iter, order, _fileMesh->getName(),
01257                                                     types, typesF, pfls, locs);
01258   for ( size_t iType = 0; iType < pfls.size(); ++iType )
01259     for ( size_t iP = 0; iP < pfls[iType].size(); ++iP )
01260       {
01261         const vector<string>& compInfo = _cellFields[iF]->getInfo();
01262 
01263         // (6) component addresses
01264         int iComp = 0, nbComp = compInfo.size();
01265         for ( fcount.init(10); iComp < nbComp; ++iComp, fcount++ )
01266           *_sauvFile << setw(8) << 777; // a good number
01267         fcount.stop();
01268 
01269         // (7) component names
01270         map<string, string> mapMedToGibi;
01271         makeCompNames( _cellFields[iF]->getName(), compInfo, mapMedToGibi );
01272         *_sauvFile << left;
01273         for ( fcount.init(8), iComp = 0; iComp < nbComp; ++iComp, fcount++ )
01274           *_sauvFile << " "  << setw(8) << mapMedToGibi[compInfo[iComp]];
01275         fcount.stop();
01276 
01277         // (8) component types
01278         for ( fcount.init(4), iComp = 0; iComp < nbComp; ++iComp, fcount++ )
01279           *_sauvFile << " "  << setw(17) << "REAL*8";
01280         fcount.stop();
01281         *_sauvFile << right;
01282 
01283         // (9) nb values per element, nb of elements
01284         int nbPntPerCell = 1;
01285         if ( !locs[iType][iP].empty() )
01286           {
01287             int locID = _cellFields[iF]->getLocalizationId( locs[iType][iP].c_str() );
01288             nbPntPerCell = _cellFields[iF]->getNbOfGaussPtPerCell( locID );
01289           }
01290         else if ( typesF[iType][iP] == ON_GAUSS_NE )
01291           {
01292             nbPntPerCell = INTERP_KERNEL::CellModel::GetCellModel(types[iType]).getNumberOfNodes();
01293           }
01294 
01295         // (10) values
01296         const std::pair<int,int>& bgEnd = valsVec[iType][iP];
01297         const DataArrayDouble* valArray = _cellFields[iF]->getUndergroundDataArray(iter, order);
01298         for ( iComp = 0; iComp < nbComp; ++iComp )
01299           {
01300             *_sauvFile << setw(8) << nbPntPerCell
01301                        << setw(8) << (bgEnd.second-bgEnd.first) / nbPntPerCell
01302                        << setw(8) << 0
01303                        << setw(8) << 0
01304                        << endl;
01305             fcount.init(3);
01306             for ( size_t i = bgEnd.first; i < (size_t) bgEnd.second; ++i, fcount++ )
01307               *_sauvFile << setw(22) << valArray->getIJ( i, iComp );
01308             fcount.stop();
01309           }
01310       }
01311 }
01312 
01313 //================================================================================
01317 //================================================================================
01318 
01319 void SauvWriter::writeLastRecord()
01320 {
01321   *_sauvFile << " ENREGISTREMENT DE TYPE   5" << endl;
01322   *_sauvFile << "LABEL AUTOMATIQUE :   1" << endl;
01323 }