Salome HOME
Suppress memory leak when using Kernel_Utils::decode()
[modules/smesh.git] / src / SMESH / MG_ADAPT.cxx
1 // Copyright (C) 2020-2021  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "MG_ADAPT.hxx"
21
22 #include "SMESH_File.hxx"
23 #include "SMESH_Comment.hxx"
24
25 #include <MEDFileData.hxx>
26 #include <MEDFileField.hxx>
27 #include <MEDFileMesh.hxx>
28 #include <MeshFormatReader.hxx>
29 #include <MeshFormatWriter.hxx>
30
31 #include <Utils_SALOME_Exception.hxx>
32 #include <Basics_Utils.hxx>
33
34 #ifndef WIN32
35 #include <unistd.h> // getpid()
36 #else
37 #include <process.h>
38 #endif
39 #include <fcntl.h>
40 #include <array>
41 #include <memory>   // unique_ptr
42
43 typedef SMESH_Comment ToComment;
44
45 using namespace MG_ADAPT;
46 static std::string removeFile(std::string fileName, int& notOk)
47 {
48   std::string errStr;
49   notOk = std::remove(fileName.c_str());
50   if (notOk) errStr = ToComment("\n error while removing file : ") << fileName;
51   else       errStr = ToComment("\n file : ") << fileName << " succesfully deleted! \n ";
52
53   return errStr;
54 }
55 std::string MG_ADAPT::remove_extension(const std::string& filename)
56 {
57   size_t lastdot = filename.find_last_of(".");
58   if (lastdot == std::string::npos) return filename;
59   return filename.substr(0, lastdot);
60 }
61 namespace
62 {
63
64   bool isFileExist( const std::string& fName )
65   {
66     return SMESH_File( fName ).exists();
67   }
68
69   // =======================================================================
70   med_idt openMedFile(const std::string aFile)
71   // =======================================================================
72   // renvoie le medId associe au fichier Med apres ouverture
73   {
74     med_idt medIdt = MEDfileOpen(aFile.c_str(),MED_ACC_RDONLY);
75     if (medIdt <0)
76     {
77       THROW_SALOME_EXCEPTION("\nThe med file " << aFile << " cannot be opened.\n");
78     }
79     return medIdt;
80   }
81
82   // =======================================================================
83   void getTimeStepInfos(std::string aFile, med_int& numdt, med_int& numit, std::string fieldName)
84   // =======================================================================
85   {
86     // Il faut voir si plusieurs maillages
87
88     herr_t erreur = 0 ;
89     med_idt medIdt ;
90
91     // Ouverture du fichier
92     //~SCRUTE(aFile.toStdString());
93     medIdt = openMedFile(aFile);
94     if ( medIdt < 0 ) return ;
95     // Lecture du nombre de champs
96     med_int ncha = MEDnField(medIdt) ;
97     if (ncha < 1 )
98     {
99       //~addMessage( ToComment(" error: there is no field in  ") << aFile, /*fatal=*/true );
100       return;
101     }
102     // Lecture des caracteristiques du champs
103
104     //       Lecture du type du champ, des noms des composantes et du nom de l'unite
105     char nomcha  [MED_NAME_SIZE+1];
106     strcpy(nomcha, fieldName.c_str());
107     //       Lecture du nombre de composantes
108     med_int ncomp = MEDfieldnComponentByName(medIdt, nomcha);
109     char meshname[MED_NAME_SIZE+1];
110     char * comp = (char*) malloc(ncomp*MED_SNAME_SIZE+1);
111     char * unit = (char*) malloc(ncomp*MED_SNAME_SIZE+1);
112     char dtunit[MED_SNAME_SIZE+1];
113     med_bool local;
114     med_field_type typcha;
115     med_int nbofcstp;
116     erreur =  MEDfieldInfoByName (medIdt, nomcha, meshname,&local,&typcha,comp,unit,dtunit, &nbofcstp);
117     free(comp);
118     free(unit);
119     if ( erreur < 0 )
120     {
121       //~addMessage( ToComment(" error: error while reading field  ") << nomcha << " in file " << aFile , /*fatal=*/true );
122       return;
123     }
124
125     med_float dt;
126     med_int tmp_numdt, tmp_numit;
127
128     //~med_int step = data->myUseLastTimeStep ? nbofcstp : data->myTimeStep+1;
129     //~myPrint("step ", step);
130     erreur = MEDfieldComputingStepInfo ( medIdt, nomcha, 1, &numdt, &numit, &dt );
131     for( int step = 1; step <= nbofcstp; step++ )
132     {
133       erreur = MEDfieldComputingStepInfo ( medIdt, nomcha, step, &tmp_numdt, &tmp_numit, &dt );
134       if(tmp_numdt > numdt)
135       {
136         numdt = tmp_numdt;
137         numit = tmp_numit;
138       }
139     }
140     if ( erreur < 0 )
141     {
142       //~addMessage( ToComment(" error: error while reading field ") << nomcha << "step (numdt, numit) = " <<"("<< numdt<< ", "
143       //numit<< ")" <<" in file " << aFile , /*fatal=*/true );
144       return;
145     }
146
147     // Fermeture du fichier
148     if ( medIdt > 0 ) MEDfileClose(medIdt);
149
150   }
151
152   struct GET_DEFAULT // struct used to get default value from GetOptionValue()
153   {
154     bool isDefault;
155     operator bool* () {
156       return &isDefault;
157     }
158   };
159
160   class outFileStream : public std::ofstream{
161   public:
162     ~outFileStream(){close();} //to close file at dtor
163   };
164
165 } // anonymous namespace
166
167 //----------------------------------------------------------------------------------------
168 MgAdapt::MgAdapt()
169 {
170   data = new MgAdaptHypothesisData();
171   data->myInMeshName = "";
172   data->fromMedFile = defaultFromMedFile();
173   data->myFileInDir = defaultWorkingDirectory();
174   data->myMeshFileIn = "";
175   data->myFileOutDir = defaultWorkingDirectory();
176   data->myOutMeshName = "";
177   data->myMeshFileOut = "";
178   data->myMeshOutMed = defaultMeshOutMed();
179   data->myPublish = defaultPublish();
180   data->myUseLocalMap = defaultUseLocalMap();
181   data->myUseBackgroundMap = defaultUseBackgroundMap();
182   data->myFileSizeMapDir = defaultWorkingDirectory();
183   data->myMeshFileBackground = "";
184   data->myUseConstantValue = defaultUseConstantValue();
185   data->myConstantValue = 0.0;
186   data->myFieldName = "";
187   data->myUseNoTimeStep = defaultUseNoTimeStep();
188   data->myUseLastTimeStep = defaultUseLastTimeStep();
189   data->myUseChosenTimeStep = defaultUseChosenTimeStep();
190   data->myTimeStep = -2;
191   data->myRank =  -2;
192   data->myWorkingDir = defaultWorkingDirectory();
193   data->myLogFile = defaultLogFile();
194   data->myVerboseLevel = defaultVerboseLevel();
195   data->myPrintLogInFile = defaultPrintLogInFile();
196   data->myKeepFiles = defaultKeepFiles();
197   data->myRemoveLogOnSuccess = defaultRemoveLogOnSuccess();
198
199   buildModel();
200   setAll();
201 }
202 MgAdapt::MgAdapt(MgAdaptHypothesisData* myData)
203 {
204   data = new MgAdaptHypothesisData();
205   setData(myData);
206   buildModel();
207 }
208
209 MgAdapt::MgAdapt( const MgAdapt& copy)
210 {
211   data = new MgAdaptHypothesisData();
212   MgAdaptHypothesisData *copyData = copy.getData();
213   copyMgAdaptHypothesisData(copyData);
214   setAll();
215
216   this->_option2value = copy._option2value;
217   this->_customOption2value = copy._customOption2value;
218   this->_defaultOptionValues = copy._defaultOptionValues;
219   this->_doubleOptions = copy._doubleOptions;
220   this->_charOptions = copy._charOptions;
221   this->_boolOptions = copy._boolOptions;
222 }
223
224 //-----------------------------------------------------------------------------------------
225 MgAdapt::~MgAdapt()
226 {
227   delete data;
228 }
229 void MgAdapt::buildModel()
230 {
231
232   const char* boolOptionNames[] = { "compute_ridges", // yes
233                                     "" // mark of end
234                                   };
235   // const char* intOptionNames[] = { "max_number_of_errors_printed", // 1
236   //                                  "max_number_of_threads",        // 4
237   //                                  "" // mark of end
238   // };
239   const char* doubleOptionNames[] = { "max_memory",  // 0
240                                       "" // mark of end
241                                     };
242   const char* charOptionNames[] = { "components",  // "yes"
243                                     "adaptation",  // both
244                                     "" // mark of end
245                                   };
246
247   int i = 0;
248   while (boolOptionNames[i][0])
249   {
250     _boolOptions.insert( boolOptionNames[i] );
251     _option2value[boolOptionNames[i++]].clear();
252   }
253   // i = 0;
254   // while (intOptionNames[i][0])
255   //   _option2value[intOptionNames[i++]].clear();
256
257   i = 0;
258   while (doubleOptionNames[i][0]) {
259     _doubleOptions.insert(doubleOptionNames[i]);
260     _option2value[doubleOptionNames[i++]].clear();
261   }
262   i = 0;
263   while (charOptionNames[i][0]) {
264     _charOptions.insert(charOptionNames[i]);
265     _option2value[charOptionNames[i++]].clear();
266   }
267
268   // default values to be used while MG-Adapt
269
270   _defaultOptionValues["adaptation"    ] = "both";
271   _defaultOptionValues["components"    ] = "outside components";
272   _defaultOptionValues["compute_ridges"] = "yes";
273   _defaultOptionValues["max_memory"    ] = ToComment(defaultMaximumMemory());
274 }
275
276 //=============================================================================
277 TOptionValues MgAdapt::getOptionValues() const
278 {
279   TOptionValues vals;
280   TOptionValues::const_iterator op_val = _option2value.begin();
281   for ( ; op_val != _option2value.end(); ++op_val )
282     vals.insert( make_pair( op_val->first, getOptionValue( op_val->first, GET_DEFAULT() )));
283
284   return vals;
285 }
286
287 std::vector <std::string> MgAdapt::getOptionValuesStrVec() const
288 {
289   std::vector <std::string> vals;
290   TOptionValues::const_iterator op_val = _option2value.begin();
291   for ( ; op_val != _option2value.end(); ++op_val )
292     vals.push_back(op_val->first+":"+getOptionValue( op_val->first, GET_DEFAULT() ));
293
294   return vals;
295 }
296
297 std::vector <std::string> MgAdapt::getCustomOptionValuesStrVec() const
298 {
299   std::vector <std::string> vals;
300   TOptionValues::const_iterator op_val;
301   for ( op_val = _customOption2value.begin(); op_val != _customOption2value.end(); ++op_val )
302   {
303     vals.push_back(op_val->first+":"+getOptionValue( op_val->first, GET_DEFAULT() ));
304   }
305   return vals;
306 }
307 const TOptionValues& MgAdapt::getCustomOptionValues() const
308 {
309   return _customOption2value;
310 }
311 void MgAdapt::setData(MgAdaptHypothesisData* myData)
312 {
313   copyMgAdaptHypothesisData(myData);
314   setAll();
315 }
316 MgAdaptHypothesisData* MgAdapt::getData() const
317 {
318   return data;
319 }
320 void MgAdapt::setMedFileIn(std::string fileName)
321 {
322   if ( isFileExist(fileName) )
323   {
324     medFileIn = fileName;
325
326     if (medFileOut == "") // default MED file Out
327       medFileOut = remove_extension( fileName )+ ".adapt.med";
328   }
329   else
330   {
331     THROW_SALOME_EXCEPTION("\nThe file "<< fileName <<" does not exist.\n");
332   }
333 }
334
335 std::string MgAdapt::getMedFileIn()
336 {
337   return medFileIn;
338 }
339
340 void MgAdapt::setMedFileOut(std::string fileOut)
341 {
342   medFileOut = fileOut;
343 }
344 std::string MgAdapt::getMedFileOut()
345 {
346   return medFileOut;
347 }
348 void MgAdapt::setMeshOutMed(bool mybool)
349 {
350   meshOutMed = mybool;
351 }
352 bool MgAdapt::getMeshOutMed()
353 {
354   return meshOutMed;
355 }
356 void MgAdapt::setPublish(bool mybool)
357 {
358   publish = mybool;
359 }
360 bool MgAdapt::getPublish()
361 {
362   return publish;
363 }
364 void MgAdapt::setFieldName(std::string myFieldName)
365 {
366   fieldName = myFieldName;
367 }
368 std::string MgAdapt::getFieldName()
369 {
370   return fieldName;
371 }
372 void MgAdapt::setTimeStep(int time)
373 {
374   timeStep = time;
375 }
376 int MgAdapt::getTimeStep() const
377 {
378   return timeStep;
379 }
380
381 void MgAdapt::setRankTimeStep(int time, int myRank)
382 {
383   timeStep = time;
384   rank = myRank;
385 }
386
387 int MgAdapt::getRank()
388 {
389   return rank;
390 }
391 void MgAdapt::setTimeStepRankLast()
392 {
393   myUseLastTimeStep = true;
394   myUseChosenTimeStep = false;
395   myUseNoTimeStep = false;
396   //~med_int aRank, tmst;
397      //~std::string fieldFile = useBackgroundMap ? sizeMapFile : medFileIn;
398   //~getTimeStepInfos(fieldFile, tmst, aRank);
399   //~setRankTimeStep((int) tmst, (int) aRank);
400 }
401 void MgAdapt::setNoTimeStep()
402 {
403   myUseLastTimeStep = false;
404   myUseChosenTimeStep = false;
405   myUseNoTimeStep = true;
406   //~int aRank = (int)MED_NO_IT;
407   //~int tmst  = (int)MED_NO_DT ;
408   //~setRankTimeStep(tmst, aRank);
409 }
410 void MgAdapt::setChosenTimeStepRank()
411 {
412   myUseLastTimeStep = false;
413   myUseChosenTimeStep = true;
414   myUseNoTimeStep = false;
415   //~int aRank = (int)MED_NO_IT;
416   //~int tmst  = (int)MED_NO_DT ;
417   //~setRankTimeStep(tmst, aRank);
418 }
419 void MgAdapt::setUseLocalMap(bool myLocal)
420 {
421   useLocalMap = myLocal;
422 }
423
424 bool MgAdapt::getUseLocalMap()
425 {
426   return useLocalMap;
427 }
428
429 void MgAdapt::setUseBackgroundMap(bool bckg)
430 {
431   useBackgroundMap = bckg;
432 }
433
434 bool MgAdapt::getUseBackgroundMap()
435 {
436   return useBackgroundMap;
437 }
438
439 void MgAdapt::setUseConstantValue(bool cnst)
440 {
441   useConstantValue = cnst;
442 }
443 bool MgAdapt::getUseConstantValue()
444 {
445   return useConstantValue;
446 }
447 void MgAdapt::setLogFile(std::string myLogFile)
448 {
449   logFile = myLogFile;
450 }
451 std::string MgAdapt::getLogFile()
452 {
453   return logFile;
454 }
455 void MgAdapt::setVerbosityLevel(int verboLevel)
456 {
457   verbosityLevel = verboLevel;
458 }
459 int MgAdapt::getVerbosityLevel()
460 {
461   return verbosityLevel;
462 }
463 void MgAdapt::setRemoveOnSuccess(bool rmons)
464 {
465   removeOnSuccess = rmons;
466 }
467 bool MgAdapt::getRemoveOnSuccess()
468 {
469   return removeOnSuccess;
470 }
471 void MgAdapt::setSizeMapFile(std::string mapFile)
472 {
473   if ( mapFile == "" || isFileExist(mapFile) )
474   {
475     sizeMapFile = mapFile;
476   }
477   else
478   {
479     THROW_SALOME_EXCEPTION("\nThe file "<< mapFile <<" does not exist.\n");
480   }
481 }
482 std::string MgAdapt::getSizeMapFile()
483 {
484   return sizeMapFile;
485 }
486
487 void MgAdapt::setMeshName(std::string name)
488 {
489   meshName = name;
490 }
491 std::string MgAdapt::getMeshName()
492 {
493   return meshName;
494 }
495 void MgAdapt::setMeshNameOut(std::string name)
496 {
497   meshNameOut = name;
498 }
499 std::string MgAdapt::getMeshNameOut()
500 {
501   return meshNameOut;
502 }
503 void MgAdapt::setFromMedFile(bool mybool)
504 {
505   fromMedFile = mybool;
506 }
507 bool MgAdapt::isFromMedFile()
508 {
509   return fromMedFile;
510 }
511 void MgAdapt::setConstantValue(double cnst)
512 {
513   constantValue = cnst;
514 }
515 double MgAdapt::getConstantValue() const
516 {
517   return constantValue;
518 }
519
520 void MgAdapt::setWorkingDir(std::string dir)
521 {
522   workingDir = dir;
523 }
524 std::string MgAdapt::getWorkingDir() const
525 {
526   return workingDir;
527 }
528 void MgAdapt::setKeepWorkingFiles(bool mybool)
529 {
530   toKeepWorkingFiles = mybool;
531 }
532 bool MgAdapt::getKeepWorkingFiles()
533 {
534   return toKeepWorkingFiles;
535 }
536 void MgAdapt::setPrintLogInFile(bool print)
537 {
538   printLogInFile = print;
539 }
540 bool MgAdapt::getPrintLogInFile()
541 {
542   return printLogInFile;
543 }
544
545 bool MgAdapt::setAll()
546 {
547
548   setFromMedFile(data->fromMedFile);
549   std::string file;
550   checkDirPath(data->myFileInDir);
551   file = data->myFileInDir+data->myMeshFileIn;
552   setMedFileIn(file);
553   setMeshName(data->myInMeshName);
554   setMeshNameOut(data->myOutMeshName);
555   checkDirPath(data->myFileOutDir);
556   std::string out = data->myFileOutDir+data->myMeshFileOut;
557   setMedFileOut(out);
558   setPublish(data->myPublish);
559   setMeshOutMed(data->myMeshOutMed);
560   setUseLocalMap(data->myUseLocalMap);
561   setUseBackgroundMap(data->myUseBackgroundMap);
562   setUseConstantValue(data->myUseConstantValue);
563
564   std::string mapfile;
565   if (useBackgroundMap)
566   {
567     checkDirPath(data->myFileSizeMapDir);
568     mapfile = data->myFileSizeMapDir+data->myMeshFileBackground;
569     setFieldName(data->myFieldName);
570   }
571   else if (useConstantValue)
572   {
573     setConstantValue(data->myConstantValue);
574   }
575   else
576   {
577     mapfile ="";
578     setConstantValue(0.0);
579     setFieldName(data->myFieldName);
580   }
581
582   setSizeMapFile(mapfile);
583   if (data->myUseNoTimeStep)
584     setNoTimeStep();
585   else if (data->myUseLastTimeStep)
586     setTimeStepRankLast();
587   else
588   {
589     setChosenTimeStepRank();
590     setRankTimeStep(data->myTimeStep, data->myRank);
591   }
592   /* Advanced options */
593   setWorkingDir(data->myWorkingDir);
594   checkDirPath(data->myWorkingDir);
595   setLogFile(data->myWorkingDir+defaultLogFile());
596   setVerbosityLevel(data->myVerboseLevel);
597   setRemoveOnSuccess(data->myRemoveLogOnSuccess);
598   setPrintLogInFile(data->myPrintLogInFile);
599   setKeepWorkingFiles(data->myKeepFiles);
600
601   return true;
602 }
603
604 void MgAdapt::checkDirPath(std::string& dirPath)
605 {
606   const char lastChar = *dirPath.rbegin();
607 #ifdef WIN32
608   if(lastChar != '\\') dirPath+='\\';
609 #else
610   if(lastChar != '/') dirPath+='/';
611 #endif
612 }
613 //=============================================================================
614 void MgAdapt::setOptionValue(const std::string& optionName,
615                              const std::string& optionValue)
616 {
617 //   INFOS("setOptionValue");
618 //   std::cout << "optionName: " << optionName << ", optionValue: " << optionValue << std::endl;
619   TOptionValues::iterator op_val = _option2value.find(optionName);
620   if (op_val == _option2value.end())
621   {
622     op_val = _customOption2value.find( optionName );
623     _customOption2value[ optionName ] = optionValue;
624     return;
625   }
626
627   if (op_val->second != optionValue)
628   {
629     std::string lowerOptionValue = toLowerStr(optionValue);
630     const char* ptr = lowerOptionValue.c_str();
631     // strip white spaces
632     while (ptr[0] == ' ')
633       ptr++;
634     size_t i = strlen(ptr);
635     while (i != 0 && ptr[i - 1] == ' ')
636       i--;
637     // check value type
638     bool typeOk = true;
639     std::string typeName;
640     if (i == 0)
641     {
642       // empty string
643     }
644     else if (_charOptions.count(optionName))
645     {
646       // do not check strings
647     }
648     else if (_doubleOptions.count(optionName))
649     {
650       // check if value is double
651       toDbl(ptr, &typeOk);
652       typeName = "real";
653     }
654     else if (_boolOptions.count(optionName))
655     {
656       // check if value is bool
657       toBool(ptr, &typeOk);
658       typeName = "bool";
659     }
660     else
661     {
662       // check if value is int
663       toInt(ptr, &typeOk);
664       typeName = "integer";
665     }
666     if ( typeOk ) // check some specific values ?
667     {
668     }
669     if ( !typeOk )
670     {
671       std::string msg = "Advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
672       throw std::invalid_argument(msg);
673     }
674     std::string value( ptr, i );
675 //     std::cout << "==> value: " << value << std::endl;
676     if ( _defaultOptionValues[ optionName ] == value ) value.clear();
677
678 //     std::cout << "==> value: " << value << std::endl;
679     op_val->second = value;
680   }
681 }
682 //=============================================================================
683 //! Return option value. If isDefault provided, it can be a default value,
684 //  then *isDefault == true. If isDefault is not provided, the value will be
685 //  empty if it equals a default one.
686 std::string MgAdapt::getOptionValue(const std::string& optionName, bool* isDefault) const
687 {
688 //   INFOS("getOptionValue");
689 //   std::cout << "optionName: " << optionName << ", isDefault: " << isDefault << std::endl;
690   TOptionValues::const_iterator op_val = _option2value.find(optionName);
691   if (op_val == _option2value.end())
692   {
693     op_val = _customOption2value.find(optionName);
694     if (op_val == _customOption2value.end())
695     {
696       std::string msg = "Unknown MG-Adapt option: <" + optionName + ">";
697       throw std::invalid_argument(msg);
698     }
699   }
700   std::string val = op_val->second;
701   if ( isDefault ) *isDefault = ( val.empty() );
702
703   if ( val.empty() && isDefault )
704   {
705     op_val = _defaultOptionValues.find( optionName );
706     if (op_val != _defaultOptionValues.end()) val = op_val->second;
707   }
708 //   std::cout << "==> val: " << val << std::endl;
709
710   return val;
711 }
712 //================================================================================
713 /*!
714  * \brief Converts a string to a real value
715  */
716 //================================================================================
717
718 double MgAdapt::toDbl(const std::string& str, bool* isOk )
719 {
720   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
721
722   char * endPtr;
723   double val = strtod(&str[0], &endPtr);
724   bool ok = (&str[0] != endPtr);
725
726   if ( isOk ) *isOk = ok;
727
728   if ( !ok )
729   {
730     std::string msg = "Not a real value:'" + str + "'";
731     throw std::invalid_argument(msg);
732   }
733   return val;
734 }
735 //================================================================================
736 /*!
737  * \brief Converts a string to a lower
738  */
739 //================================================================================
740 std::string MgAdapt::toLowerStr(const std::string& str)
741 {
742   std::string s = str;
743   for ( size_t i = 0; i <= s.size(); ++i )
744     s[i] = (char) tolower( s[i] );
745   return s;
746 }
747 //================================================================================
748 /*!
749  * \brief Converts a string to a bool
750  */
751 //================================================================================
752
753 bool MgAdapt::toBool(const std::string& str, bool* isOk )
754 {
755   std::string s = str;
756   if ( isOk ) *isOk = true;
757
758   for ( size_t i = 0; i <= s.size(); ++i )
759     s[i] = (char) tolower( s[i] );
760
761   if ( s == "1" || s == "true" || s == "active" || s == "yes" )
762     return true;
763
764   if ( s == "0" || s == "false" || s == "inactive" || s == "no" )
765     return false;
766
767   if ( isOk )
768     *isOk = false;
769   else
770   {
771     std::string msg = "Not a Boolean value:'" + str + "'";
772     throw std::invalid_argument(msg);
773   }
774   return false;
775 }
776 //================================================================================
777 /*!
778  * \brief Converts a string to a integer value
779  */
780 //================================================================================
781
782 int MgAdapt::toInt(const std::string& str, bool* isOk )
783 {
784   if ( str.empty() ) throw std::invalid_argument("Empty value provided");
785
786   char * endPtr;
787   int val = (int)strtol( &str[0], &endPtr, 10);
788   bool ok = (&str[0] != endPtr);
789
790   if ( isOk ) *isOk = ok;
791
792   if ( !ok )
793   {
794     std::string msg = "Not an integer value:'" + str + "'";
795     throw std::invalid_argument(msg);
796   }
797   return val;
798 }
799 //=============================================================================
800 bool MgAdapt::hasOptionDefined( const std::string& optionName ) const
801 {
802   bool isDefault = false;
803   try
804   {
805     getOptionValue( optionName, &isDefault );
806   }
807   catch ( std::invalid_argument )
808   {
809     return false;
810   }
811   return !isDefault;
812 }
813 //================================================================================
814 /*!
815  * \brief Return command to run MG-Adapt mesher excluding file prefix (-f)
816  */
817 //================================================================================
818
819 std::string MgAdapt::getCommandToRun(MgAdapt* hyp)
820 {
821   return hyp ? hyp->getCommandToRun() : ToComment("error with hypothesis!");
822 }
823
824 int MgAdapt::compute(std::string& errStr)
825 {
826   std::string cmd = getCommandToRun();
827 //   std::cout << cmd << std::endl;
828
829   int err = 0;
830   execCmd( cmd.c_str(), err ); // run
831
832   if ( err )
833   {
834     errStr = ToComment("system(mg-adapt.exe ...) command failed with error: ") << strerror( errno );
835   }
836   else if ( !isFileExist( meshFormatOutputMesh ))
837   {
838     errStr = ToComment(" failed to find file ") << meshFormatOutputMesh
839                                                 << " output from MG-Adapt run";
840   }
841   else
842   {
843     convertMeshFile(meshFormatOutputMesh, solFormatOutput);
844   }
845   if (!err) cleanUp();
846   return err;
847 }
848
849 void MgAdapt::execCmd( const char* cmd, int& err)
850 {
851   err = 1;
852   std::array <char, 128> buffer;
853   std::streambuf* buf;
854   outFileStream fileStream;
855   if (printLogInFile)
856   {
857     fileStream.open(logFile);
858     buf = fileStream.rdbuf();
859   }
860   else
861   {
862     buf = std::cout.rdbuf();
863   }
864   std::ostream logStream(buf);
865
866
867 #if defined(WIN32)
868 #  if defined(UNICODE)
869   const wchar_t * aCmd = Kernel_Utils::utf8_decode(cmd);
870   SMESHUtils::ArrayDeleter<const wchar_t> deleter( aCmd );
871   std::unique_ptr <FILE, decltype(&_pclose)> pipe(_wpopen(aCmd, O_RDONLY), _pclose );
872 #  else
873   std::unique_ptr <FILE, decltype(&_pclose)> pipe(_popen(cmd, "r"), _pclose );
874 #  endif
875 #else
876   std::unique_ptr <FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose );
877 #endif
878
879   if(!pipe)
880   {
881     throw std::runtime_error("popen() failed!");
882   }
883   while(fgets(buffer.data(), buffer.size(), pipe.get()) !=nullptr )
884   {
885     logStream<<buffer.data() ;
886   }
887   err = 0;
888 }
889 /*
890  * to delete tmp files .mesh, .sol and if needed
891  * the log file
892  *
893  */
894 void MgAdapt::cleanUp()
895 {
896   int notOk;
897   std::string errStr;
898   if(toKeepWorkingFiles)
899     return;
900   if(removeOnSuccess && printLogInFile)
901     tmpFilesToBeDeleted.push_back(logFile);
902
903   std::vector< std::string>::iterator it = tmpFilesToBeDeleted.begin();
904   for (; it!=tmpFilesToBeDeleted.end(); ++it)
905   {
906     errStr=removeFile(*it, notOk);
907     if (notOk)
908     {
909       appendMsgToLogFile(errStr);
910     }
911
912   }
913 }
914
915 void MgAdapt::appendMsgToLogFile(std::string& msg)
916 {
917   std::ofstream logStream;
918   logStream.open(logFile, std::ofstream::out | std::ofstream::app);
919   logStream<< msg;
920   logStream.close();
921 }
922 //================================================================================
923 /*!
924  * \brief Return command to run MG-Tetra mesher excluding file prefix (-f)
925  */
926 //================================================================================
927
928 std::string MgAdapt::getCommandToRun()
929 {
930   /*
931   || return system command with args and options
932   ||
933   */
934   std::string errStr;
935   std::string cmd = getExeName();
936   std::string meshIn(""), sizeMapIn(""), solFileIn("");
937   updateTimeStepRank();
938   convertMedFile(meshIn, solFileIn, sizeMapIn);
939   if (!isFileExist(meshIn) || !isFileExist(solFileIn))
940   {
941     errStr = ToComment(" failed to find .mesh or .sol file from converter ")<< strerror( errno );
942     return errStr;
943   }
944   tmpFilesToBeDeleted.push_back(meshIn);
945   tmpFilesToBeDeleted.push_back(solFileIn);
946   if(useBackgroundMap && !isFileExist(sizeMapIn))
947   {
948     errStr = ToComment(" failed to find .mesh size map file from converter ")<< strerror( errno );
949     return errStr;
950   }
951
952   cmd+= " --in "+ meshIn;
953   meshFormatOutputMesh = getFileName()+".mesh";
954   tmpFilesToBeDeleted.push_back(meshFormatOutputMesh);
955   cmd+= " --out "+ meshFormatOutputMesh;
956   if (useLocalMap || useConstantValue) cmd+= " --sizemap "+ solFileIn;
957   else //  (useBackgroundMap)
958   {
959     cmd+= " --background_mesh "+ sizeMapIn ;
960     cmd+= " --background_sizemap "+ solFileIn;
961     tmpFilesToBeDeleted.push_back(sizeMapIn);
962   }
963   //~else
964   //~{
965   //~// constant value TODO
966   //~}
967   // Check coherence between mesh dimension and option fo adaptation
968   checkDimensionOptionAdaptation();
969
970   //   sizemap file is written only if level is higher than 3
971   if ( verbosityLevel > 3)
972   {
973     std::string solFileOut = getFileName()+".sol";
974     cmd+= " --write_sizemap "+ solFileOut;
975     solFormatOutput.push_back(solFileOut);
976     tmpFilesToBeDeleted.push_back(solFileOut);
977   }
978
979   std::string option, value;
980   bool isDefault;
981   const TOptionValues* options[] = { &_option2value, &_customOption2value };
982   for ( int iOp = 0; iOp < 2; ++iOp )
983   {
984     TOptionValues::const_iterator o2v = options[iOp]->begin();
985     for ( ; o2v != options[iOp]->end(); ++o2v )
986     {
987       option = o2v->first;
988       value = getOptionValue( option, &isDefault );
989
990       if ( isDefault )
991         continue;
992       if ( value.empty() )//value == NoValue() )
993       {
994         if ( _defaultOptionValues.count( option ))
995           continue; // non-custom option with no value
996         //value.clear();
997       }
998       if ( strncmp( "no", option.c_str(), 2 ) == 0 ) // options w/o values: --no_*
999       {
1000         if ( !value.empty() && toBool( value ) == false )
1001           continue;
1002         value.clear();
1003       }
1004       if ( option[0] != '-' )
1005         cmd += " --";
1006       else
1007         cmd += " ";
1008 //       std::cout << "--- option: '" << option << ", value: '" << value <<"'"<< std::endl;
1009       cmd += option + " " + value;
1010     }
1011   }
1012
1013   // Verbosity Level
1014   if (verbosityLevel != defaultVerboseLevel())
1015   {
1016     cmd+= " --verbose "+ ToComment(verbosityLevel);
1017   }
1018     //~}
1019 //~cmd+= " >"
1020 #ifdef WIN32
1021     cmd += " < NUL";
1022 #endif
1023 //   std::cout << "--- cmd :"<< std::endl;
1024 //   std::cout << cmd << std::endl;
1025
1026   return cmd;
1027 }
1028
1029 //=======================================================================
1030 //function : defaultMaximumMemory
1031 //=======================================================================
1032
1033 #if defined(WIN32)
1034 #include <windows.h>
1035 #elif !defined(__APPLE__)
1036 #include <sys/sysinfo.h>
1037 #endif
1038
1039 double MgAdapt::defaultMaximumMemory()
1040 {
1041 #if defined(WIN32)
1042   // See http://msdn.microsoft.com/en-us/library/aa366589.aspx
1043   MEMORYSTATUSEX statex;
1044   statex.dwLength = sizeof (statex);
1045   long err = GlobalMemoryStatusEx (&statex);
1046   if (err != 0)
1047   {
1048     double totMB = (double)statex.ullAvailPhys / 1024. / 1024.;
1049     return (double)( 0.7 * totMB );
1050   }
1051 #elif !defined(__APPLE__)
1052   struct sysinfo si;
1053   long err = sysinfo( &si );
1054   if ( err == 0 )
1055   {
1056     long ramMB = si.totalram * si.mem_unit / 1024 / 1024;
1057     return ( 0.7 * double( ramMB ));
1058   }
1059 #endif
1060   return 1024;
1061 }
1062
1063 //=======================================================================
1064 //function : defaultWorkingDirectory
1065 //=======================================================================
1066
1067 std::string MgAdapt::defaultWorkingDirectory()
1068 {
1069   std::string aTmpDir;
1070
1071   char *Tmp_dir = getenv("SALOME_TMP_DIR");
1072   if(Tmp_dir != NULL)
1073   {
1074     aTmpDir = Tmp_dir;
1075   }
1076   else {
1077 #ifdef WIN32
1078     aTmpDir = "C:\\";
1079 #else
1080     aTmpDir = "/tmp/";
1081 #endif
1082   }
1083   return aTmpDir;
1084 }
1085 //================================================================================
1086 /*!
1087  * \brief Return a unique file name
1088  */
1089 //================================================================================
1090
1091 std::string MgAdapt::getFileName() const
1092 {
1093   std::string aTmpDir = workingDir;
1094   const char lastChar = *aTmpDir.rbegin();
1095 #ifdef WIN32
1096   if(lastChar != '\\') aTmpDir+='\\';
1097 #else
1098   if(lastChar != '/') aTmpDir+='/';
1099 #endif
1100
1101   SMESH_Comment aGenericName( aTmpDir );
1102   aGenericName << "MgAdapt_";
1103 #ifndef WIN32
1104   aGenericName << getpid();
1105 #else
1106 aGenericName << _getpid();
1107 #endif
1108   aGenericName << "_";
1109   aGenericName << std::abs((int)(long) aGenericName.data());
1110
1111   return aGenericName;
1112 }
1113 //=======================================================================
1114 //function : defaultLogFile
1115 //=======================================================================
1116
1117 std::string MgAdapt::defaultLogFile()
1118 {
1119   std::string alogFile("MG_ADAPT.log");
1120   return alogFile;
1121 }
1122 //=======================================================================
1123 //function : defaultUseConstantValue
1124 //=======================================================================
1125
1126 bool MgAdapt::defaultUseConstantValue()
1127 {
1128   return false;
1129 }
1130 //=======================================================================
1131 //function : defaultUseNoTimeStep
1132 //=======================================================================
1133
1134 bool MgAdapt::defaultUseNoTimeStep()
1135 {
1136   return true;
1137 }
1138 //=======================================================================
1139 //function : defaultRemoveLogOnSuccess
1140 //=======================================================================
1141
1142 bool MgAdapt::defaultRemoveLogOnSuccess()
1143 {
1144   return true;
1145 }
1146 //=======================================================================
1147 //function : defaultPrintLogInFile
1148 //=======================================================================
1149
1150 bool MgAdapt::defaultPrintLogInFile()
1151 {
1152   return false;
1153 }
1154 //=======================================================================
1155 //function : defaultUseChosenTimeStep
1156 //=======================================================================
1157
1158 bool MgAdapt::defaultUseChosenTimeStep()
1159 {
1160   return false;
1161 }
1162 //=======================================================================
1163 //function : UseLastTimeStep
1164 //=======================================================================
1165
1166 bool MgAdapt::defaultUseLastTimeStep()
1167 {
1168   return false;
1169 }
1170 //=======================================================================
1171 //function : defaultUseBackgroundMap
1172 //=======================================================================
1173
1174 bool MgAdapt::defaultUseBackgroundMap()
1175 {
1176   return false;
1177 }
1178 //=======================================================================
1179 //function : defaultKeepFiles
1180 //=======================================================================
1181
1182 bool MgAdapt::defaultKeepFiles()
1183 {
1184   return false;
1185 }
1186 //=======================================================================
1187 //function : defaultUseLocalMap
1188 //=======================================================================
1189
1190 bool MgAdapt::defaultUseLocalMap()
1191 {
1192   return true;
1193 }
1194 //=======================================================================
1195 //function : defaultPublish
1196 //=======================================================================
1197
1198 bool MgAdapt::defaultPublish()
1199 {
1200   return false;
1201 }
1202 //=======================================================================
1203 //function : defaultMeshOutMed
1204 //=======================================================================
1205
1206 bool MgAdapt::defaultMeshOutMed()
1207 {
1208   return true;
1209 }
1210 //=======================================================================
1211 //function : defaultFromMedFile
1212 //=======================================================================
1213
1214 bool MgAdapt::defaultFromMedFile()
1215 {
1216   return true;
1217 }
1218 //=======================================================================
1219 //function : defaultVerboseLevel
1220 //=======================================================================
1221
1222 int  MgAdapt::defaultVerboseLevel()
1223 {
1224   return 3;
1225 }
1226 std::string MgAdapt::getExeName()
1227 {
1228   return "mg-adapt.exe";
1229 }
1230 void MgAdapt::copyMgAdaptHypothesisData( const MgAdaptHypothesisData* from)
1231 {
1232   data->myFileInDir = from->myFileInDir;
1233   data->myMeshFileIn = from->myMeshFileIn;
1234   data->myMeshFileBackground = from->myMeshFileBackground;
1235   data->myOutMeshName = from->myOutMeshName;
1236   data->myMeshFileOut = from->myMeshFileOut;
1237   data->myFileOutDir = from->myFileOutDir;
1238   data->myFileSizeMapDir = from->myFileSizeMapDir;
1239   data->myFieldName = from->myFieldName;
1240   data->fromMedFile = from->fromMedFile;
1241   data->myPublish = from->myPublish;
1242   data->myMeshOutMed = from->myMeshOutMed;
1243   data->myUseLocalMap = from->myUseLocalMap;
1244   data->myUseBackgroundMap = from->myUseBackgroundMap;
1245   data->myUseConstantValue = from->myUseConstantValue;
1246   data->myConstantValue = from->myConstantValue;
1247   data->myTimeStep = from->myTimeStep;
1248   data->myRank = from->myRank;
1249   data->myUseNoTimeStep = from->myUseNoTimeStep;
1250   data->myUseLastTimeStep = from->myUseLastTimeStep;
1251   data->myUseChosenTimeStep = from->myUseChosenTimeStep;
1252   data->myWorkingDir = from->myWorkingDir;
1253   data->myLogFile = from->myLogFile;
1254   data->myPrintLogInFile = from->myPrintLogInFile;
1255   data->myKeepFiles = from->myKeepFiles;
1256   data->myRemoveLogOnSuccess = from->myRemoveLogOnSuccess;
1257   data->myVerboseLevel = from->myVerboseLevel;
1258 }
1259
1260 std::vector<std::string> MgAdapt::getListFieldsNames(std::string fileIn)
1261 {
1262   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(fileIn);
1263   std::vector<std::string> listFieldsNames(mfd->getFields()->getFieldsNames());
1264   return listFieldsNames ;
1265 }
1266
1267 void MgAdapt::checkDimensionOptionAdaptation()
1268 {
1269   // Quand le maillage est 3D, tout est possible
1270   // Quand le maillage est 2D, il faut 'surface' sauf si carte de fonds 3D
1271   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(medFileIn);
1272   int meshdim = mfd->getMeshes()->getMeshAtPos(0)->getMeshDimension() ;
1273 //   std::cout << "meshdim = " << meshdim << std::endl;
1274
1275   if ( meshdim == 2 )
1276   {
1277     std::string optionName   = "adaptation";
1278     std::string optionValue = getOptionValue(optionName);
1279 //     std::cout << "optionValue = '" << optionValue <<"'"<< std::endl;
1280     bool a_tester = false ;
1281     // carte locale ou constante : impératif d'avoir "surface"
1282     if ( useLocalMap || useConstantValue) a_tester = true ;
1283     // carte de fond : impératif d'avoir "surface" si le fonds est aussi 2D
1284     else
1285     {
1286       MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfdbg = MEDCoupling::MEDFileData::New(sizeMapFile);
1287       int meshdimbg = mfdbg->getMeshes()->getMeshAtPos(0)->getMeshDimension() ;
1288 //       std::cout << "meshdimbg = " << meshdimbg << std::endl;
1289       if ( meshdimbg == 2 ) a_tester = true ;
1290     }
1291     if ( a_tester )
1292     {
1293       if ( optionValue == "" ) setOptionValue (optionName, "surface");
1294       else
1295       {
1296         if ( optionValue != "surface" )
1297         {
1298           THROW_SALOME_EXCEPTION("Mesh dimension is 2; the option should be 'surface'"
1299                                  " instead of '" << optionValue << "'.");
1300         }
1301       }
1302     }
1303   }
1304 }
1305
1306 void MgAdapt::checkFieldName(std::string fileIn)
1307 {
1308   bool ret = false ;
1309   std::vector<std::string> listFieldsNames = getListFieldsNames(fileIn);
1310   std::size_t jaux(listFieldsNames.size());
1311   for(std::size_t j=0;j<jaux;j++)
1312   {
1313     if ( fieldName == listFieldsNames[j] )
1314     {
1315       ret = true ;
1316       break ;
1317     }
1318   }
1319   if ( ! ret )
1320   {
1321     std::cout << "Available field names:" << std::endl;
1322     for(std::size_t j=0;j<jaux;j++)
1323     { std::cout << listFieldsNames[j] << std::endl;}
1324     THROW_SALOME_EXCEPTION( "Field " << fieldName << " is not found.");
1325   }
1326 }
1327
1328 void MgAdapt::checkTimeStepRank(std::string fileIn)
1329 {
1330   bool ret = false ;
1331   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(fileIn);
1332   MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeFieldMultiTS> fts( mfd->getFields()->getFieldWithName(fieldName) );
1333   std::vector<double> timevalue;
1334   std::vector< std::pair<int,int> > timesteprank = fts->getTimeSteps(timevalue);
1335   std::size_t jaux(timesteprank.size());
1336   for(std::size_t j=0;j<jaux;j++)
1337   {
1338     if ( ( timeStep == timesteprank[j].first ) & ( rank == timesteprank[j].second ) )
1339     {
1340       ret = true ;
1341       break ;
1342     }
1343   }
1344   if ( ! ret )
1345   {
1346     std::cout << "Available (Time step, Rank):" << std::endl;
1347     for(std::size_t j=0;j<jaux;j++)
1348     { std::cout << "(Time step = " << timesteprank[j].first << ", Rank = " << timesteprank[j].second << ")" << std::endl;}
1349     THROW_SALOME_EXCEPTION("(Time step = " << timeStep << ", Rank = " << rank << ") is not found.");
1350   }
1351 }
1352
1353 void MgAdapt::convertMedFile(std::string& meshFormatMeshFileName, std::string& solFormatFieldFileName, std::string& meshFormatsizeMapFile)
1354 {
1355   std::vector<std::string> fieldFileNames;
1356   MEDCoupling::MeshFormatWriter writer;
1357   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(medFileIn);
1358   MEDCoupling::MEDFileMeshes* meshes = mfd->getMeshes();
1359   MEDCoupling::MEDFileMesh* fileMesh = meshes->getMeshAtPos(0); // ok only one mesh in file!
1360   if (meshNameOut =="")
1361     meshNameOut = fileMesh->getName();
1362   storeGroupsAndFams(fileMesh);
1363
1364   MEDCoupling::MCAuto<MEDCoupling::MEDFileFields> fields = MEDCoupling::MEDFileFields::New();
1365   solFormatFieldFileName = getFileName();
1366   solFormatFieldFileName+=".sol";
1367   fieldFileNames.push_back(solFormatFieldFileName);
1368
1369   if (useBackgroundMap)
1370   {
1371     checkFieldName(sizeMapFile) ;
1372     checkTimeStepRank(sizeMapFile) ;
1373     meshFormatsizeMapFile = getFileName();
1374     meshFormatsizeMapFile += ".mesh";
1375     buildBackGroundMeshAndSolFiles(fieldFileNames, meshFormatsizeMapFile);
1376   }
1377   else if(useLocalMap)
1378   {
1379     checkFieldName(medFileIn) ;
1380     checkTimeStepRank(medFileIn) ;
1381     MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeFieldMultiTS> fts( mfd->getFields()->getFieldWithName(fieldName) );
1382     MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeField1TS> f = fts->getTimeStep(timeStep, rank);
1383     MEDCoupling::MCAuto<MEDCoupling::MEDFileFieldMultiTS> tmFts = MEDCoupling::MEDFileFieldMultiTS::New();
1384     tmFts->pushBackTimeStep(f);
1385
1386     fields->pushField(tmFts);
1387
1388     writer.setFieldFileNames( fieldFileNames);
1389   }
1390   else
1391   {
1392     MEDCoupling::MCAuto<MEDCoupling::MEDCouplingMesh> mesh = fileMesh->getMeshAtLevel(1); // nodes mesh
1393     MEDCoupling::MCAuto<MEDCoupling::MEDCouplingUMesh> umesh = mesh->buildUnstructured(); // nodes mesh
1394     int dim  =  umesh->getSpaceDimension();
1395     int version =  sizeof(double) < 8 ? 1 : 2;
1396     mcIdType nbNodes =  umesh->getNumberOfNodes();
1397     buildConstantSizeMapSolFile(solFormatFieldFileName, dim, version, nbNodes);
1398   }
1399
1400   mfd->setFields( fields );
1401   meshFormatMeshFileName = getFileName();
1402   meshFormatMeshFileName+=".mesh";
1403   writer.setMeshFileName(meshFormatMeshFileName);
1404   writer.setMEDFileDS( mfd);
1405   writer.write();
1406
1407 }
1408
1409 void MgAdapt::convertMeshFile(std::string& meshFormatIn, std::vector< std::string>& solFieldFileNames) const
1410 {
1411   MEDCoupling::MeshFormatReader reader(meshFormatIn, solFieldFileNames);
1412
1413   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = reader.loadInMedFileDS();
1414   // write MED
1415   MEDCoupling::MEDFileMeshes* meshes = mfd->getMeshes();
1416   MEDCoupling::MEDFileMesh* fileMesh = meshes->getMeshAtPos(0); // ok only one mesh in file!
1417   fileMesh->setName(meshNameOut);
1418   restoreGroupsAndFams(fileMesh);
1419   mfd->write(medFileOut, 2);
1420 }
1421
1422 void MgAdapt::storeGroupsAndFams(MEDCoupling::MEDFileMesh* fileMesh)
1423 {
1424   storefams(fileMesh);
1425   storeGroups(fileMesh);
1426 }
1427
1428 void MgAdapt::restoreGroupsAndFams(MEDCoupling::MEDFileMesh* fileMesh) const
1429 {
1430   restorefams(fileMesh);
1431   restoreGroups(fileMesh);
1432 }
1433 void MgAdapt::storeGroups(MEDCoupling::MEDFileMesh* fileMesh)
1434 {
1435   std::map<std::string, std::vector<std::string> > grpFams = fileMesh->getGroupInfo();
1436   std::map<std::string, std::vector<std::string> >::iterator g2ff = grpFams.begin();
1437
1438   for ( ; g2ff != grpFams.end(); ++g2ff )
1439   {
1440     std::string             groupName = g2ff->first;
1441     std::vector<std::string> famNames = g2ff->second;
1442
1443     if ( famNames.empty() ) continue;
1444     std::vector< int> famListId;
1445     for ( size_t i = 0; i < famNames.size(); ++i )
1446     {
1447       famListId.push_back( FromIdType<int>( fileMesh->getFamilyId( famNames[i].c_str() )));
1448     }
1449     group grp(groupName, famListId, famNames);
1450     groupVec.push_back(grp);
1451   }
1452 }
1453
1454 void MgAdapt::storefams(MEDCoupling::MEDFileMesh* fileMesh)
1455 {
1456   std::map<std::string, mcIdType> grpFams = fileMesh->getFamilyInfo();
1457   std::map<std::string, mcIdType >::iterator f = grpFams.begin();
1458
1459   for ( ; f != grpFams.end(); ++f )
1460   {
1461     if(!f->second) continue;  // FAMILLE_ZERO
1462     family fs(f->first, FromIdType<int>( f->second ));
1463     famVec.push_back(fs);
1464   }
1465
1466 }
1467
1468 void MgAdapt::restorefams(MEDCoupling::MEDFileMesh* fileMesh) const
1469 {
1470   std::vector<family>::const_iterator fIt = famVec.begin();
1471
1472   for (; fIt!=famVec.end(); ++fIt)
1473   {
1474     try  //
1475     {
1476       std::string givenFamNameFromMeshGemConverter = fileMesh->getFamilyNameGivenId( std::abs(fIt->_famId) );
1477       fileMesh->changeFamilyId(std::abs(fIt->_famId), fIt->_famId);
1478       fileMesh->changeFamilyName(givenFamNameFromMeshGemConverter, fIt->_famName);
1479     }
1480     catch (const std::exception& e)
1481     {
1482       std::cerr<<e.what();
1483     }
1484   }
1485 }
1486
1487 void MgAdapt::restoreGroups(MEDCoupling::MEDFileMesh* fileMesh) const
1488 {
1489   std::map<std::string, std::vector<std::string> > info;
1490   std::vector <group>::const_iterator grpFams = groupVec.begin();
1491
1492   for (; grpFams!=groupVec.end(); ++grpFams)
1493   {
1494     info.insert(std::pair <std::string, std::vector<std::string> > (grpFams->_name, grpFams->_famNames) );
1495   }
1496
1497   fileMesh->setGroupInfo(info);
1498 }
1499
1500 void MgAdapt::buildConstantSizeMapSolFile(const std::string& solFormatFieldFileName, const int dim, const int version, const size_t nbNodes) const
1501 {
1502   MeshFormat::Localizer loc;
1503   MeshFormat::MeshFormatParser writer;
1504   int fileId = writer.GmfOpenMesh( solFormatFieldFileName.c_str(), GmfWrite, version, dim);
1505   int typTab[] = {GmfSca};
1506   writer.GmfSetKwd(fileId, MeshFormat::GmfSolAtVertices, (int)nbNodes, 1, typTab);
1507   for (size_t i = 0; i<nbNodes; i++)
1508   {
1509     double valTab[1] = {constantValue};
1510     writer.GmfSetLin( fileId, MeshFormat::GmfSolAtVertices, valTab);
1511   }
1512   writer.GmfCloseMesh(fileId);
1513 }
1514
1515 void MgAdapt::buildBackGroundMeshAndSolFiles(const std::vector<std::string>& fieldFileNames, const std::string& meshFormatsizeMapFile) const
1516 {
1517   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> tmpMfd = MEDCoupling::MEDFileData::New(sizeMapFile);
1518   MEDCoupling::MEDFileFields* tmpFields = tmpMfd->getFields();
1519   MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeFieldMultiTS> fts( tmpFields->getFieldWithName(fieldName) );
1520   MEDCoupling::MCAuto<MEDCoupling::MEDFileFieldMultiTS>  fts1 = MEDCoupling::DynamicCastSafe<MEDCoupling::MEDFileAnyTypeFieldMultiTS,MEDCoupling::MEDFileFieldMultiTS>(fts);
1521   MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeField1TS> f = fts1->getTimeStep(timeStep, rank);
1522   MEDCoupling::MCAuto<MEDCoupling::MEDFileFieldMultiTS> tmFts = MEDCoupling::MEDFileFieldMultiTS::New();
1523   tmFts->pushBackTimeStep(f);
1524
1525   MEDCoupling::MCAuto<MEDCoupling::MEDFileFields> tmp_fields = MEDCoupling::MEDFileFields::New();
1526   tmp_fields->pushField(tmFts);
1527
1528   tmpMfd->setFields( tmp_fields );
1529   MEDCoupling::MeshFormatWriter tmpWriter;
1530   tmpWriter.setMeshFileName(meshFormatsizeMapFile);
1531   tmpWriter.setFieldFileNames( fieldFileNames);
1532   tmpWriter.setMEDFileDS(tmpMfd);
1533   tmpWriter.write();
1534 }
1535
1536 MgAdapt::Status MgAdapt::addMessage(const std::string& msg,
1537                                     const bool         isFatal/*=false*/)
1538 {
1539   if ( isFatal )
1540     _errorMessages.clear(); // warnings are useless if a fatal error encounters
1541
1542   _errorMessages.push_back( msg );
1543
1544   //~MESSAGE(msg);
1545 #ifdef _DEBUG_
1546   std::cout << msg << std::endl;
1547 #endif
1548   return ( _status = isFatal ? MgAdapt::DRS_FAIL : MgAdapt::DRS_WARN_SKIP_ELEM );
1549 }
1550
1551 void MgAdapt::updateTimeStepRank()
1552 {
1553
1554   med_int arank;
1555   med_int tmst;
1556   if (myUseNoTimeStep)
1557   {
1558     arank = MED_NO_IT;
1559     tmst  = MED_NO_DT ;
1560     setRankTimeStep((int)tmst, (int)arank);
1561   }
1562   else if (myUseLastTimeStep)
1563   {
1564     std::string fieldFile = useBackgroundMap ? sizeMapFile : medFileIn;
1565     getTimeStepInfos(fieldFile, tmst, arank, fieldName);
1566     setRankTimeStep((int)tmst, (int)arank);
1567   }
1568 }