Salome HOME
bos #24400 [CEA] Option in SALOME for not storing in med files the indices (number...
[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   size_t lastdot = filename.find_last_of(".");
57   if (lastdot == std::string::npos) return filename;
58   return filename.substr(0, lastdot);
59 }
60 namespace
61 {
62
63   bool isFileExist( const std::string& fName )
64   {
65     return SMESH_File( fName ).exists();
66   }
67
68 // =======================================================================
69 med_idt openMedFile(const std::string aFile)
70 // =======================================================================
71 // renvoie le medId associe au fichier Med apres ouverture
72 {
73   med_idt medIdt = MEDfileOpen(aFile.c_str(),MED_ACC_RDONLY);
74   if (medIdt <0)
75   {
76     THROW_SALOME_EXCEPTION("\nThe med file " << aFile << " cannot be opened.\n");
77   }
78   return medIdt;
79 }
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
92   // Ouverture du fichier
93   //~SCRUTE(aFile.toStdString());
94   medIdt = openMedFile(aFile);
95   if ( medIdt < 0 ) return ;
96   // Lecture du nombre de champs
97   med_int ncha = MEDnField(medIdt) ;
98   if (ncha < 1 )
99   {
100     //~addMessage( ToComment(" error: there is no field in  ") << aFile, /*fatal=*/true );
101     return;
102   }
103   // Lecture des caracteristiques du champs
104
105   //       Lecture du type du champ, des noms des composantes et du nom de l'unite
106   char nomcha  [MED_NAME_SIZE+1];
107   strcpy(nomcha, fieldName.c_str());
108 //       Lecture du nombre de composantes
109   med_int ncomp = MEDfieldnComponentByName(medIdt, nomcha);
110   char meshname[MED_NAME_SIZE+1];
111   char * comp = (char*) malloc(ncomp*MED_SNAME_SIZE+1);
112   char * unit = (char*) malloc(ncomp*MED_SNAME_SIZE+1);
113   char dtunit[MED_SNAME_SIZE+1];
114   med_bool local;
115   med_field_type typcha;
116   med_int nbofcstp;
117   erreur =  MEDfieldInfoByName (medIdt, nomcha, meshname,&local,&typcha,comp,unit,dtunit, &nbofcstp);
118   free(comp);
119   free(unit);
120   if ( erreur < 0 )
121   {
122       //~addMessage( ToComment(" error: error while reading field  ") << nomcha << " in file " << aFile , /*fatal=*/true );
123     return;
124   }
125
126   med_float dt;
127   med_int tmp_numdt, tmp_numit;
128
129   //~med_int step = data->myUseLastTimeStep ? nbofcstp : data->myTimeStep+1;
130   //~myPrint("step ", step);
131   erreur = MEDfieldComputingStepInfo ( medIdt, nomcha, 1, &numdt, &numit, &dt );
132   for( int step = 1; step <= nbofcstp; step++ )
133   {
134     erreur = MEDfieldComputingStepInfo ( medIdt, nomcha, step, &tmp_numdt, &tmp_numit, &dt );
135     if(tmp_numdt > numdt)
136     {
137       numdt = tmp_numdt;
138       numit = tmp_numit;
139     }
140   }
141   if ( erreur < 0 )
142   {
143     //~addMessage( ToComment(" error: error while reading field ") << nomcha << "step (numdt, numit) = " <<"("<< numdt<< ", " 
144     //numit<< ")" <<" in file " << aFile , /*fatal=*/true );
145     return;
146   }
147
148   // Fermeture du fichier
149   if ( medIdt > 0 ) MEDfileClose(medIdt);
150
151 }
152   
153 struct GET_DEFAULT // struct used to get default value from GetOptionValue()
154 {
155   bool isDefault;
156   operator bool* () {
157       return &isDefault;
158   }
159 };
160
161 class outFileStream : public std::ofstream{
162 public:
163     ~outFileStream(){close();} //to close file at dtor
164 };
165 }
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   std::unique_ptr <FILE, decltype(&_pclose)> pipe(_wpopen(aCmd, O_RDONLY), _pclose );
871 #else
872   std::unique_ptr <FILE, decltype(&_pclose)> pipe(_popen(cmd, "r"), _pclose );
873 #endif
874 #else
875   std::unique_ptr <FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose );
876 #endif
877
878   if(!pipe)
879   {
880     throw std::runtime_error("popen() failed!");
881   }
882   while(fgets(buffer.data(), buffer.size(), pipe.get()) !=nullptr )
883   {
884     logStream<<buffer.data() ;
885   }
886   err = 0;
887 }
888 /*
889  * to delete tmp files .mesh, .sol and if needed
890  * the log file
891  *
892  */
893 void MgAdapt::cleanUp()
894 {
895   int notOk;
896   std::string errStr;
897   if(toKeepWorkingFiles)
898     return;
899   if(removeOnSuccess && printLogInFile)
900     tmpFilesToBeDeleted.push_back(logFile);
901
902   std::vector< std::string>::iterator it = tmpFilesToBeDeleted.begin();
903   for (; it!=tmpFilesToBeDeleted.end(); ++it)
904   {
905     errStr=removeFile(*it, notOk);
906     if (notOk)
907     {
908       appendMsgToLogFile(errStr);
909     }
910
911   }
912 }
913
914 void MgAdapt::appendMsgToLogFile(std::string& msg)
915 {
916   std::ofstream logStream;
917   logStream.open(logFile, std::ofstream::out | std::ofstream::app);
918   logStream<< msg;
919   logStream.close();
920 }
921 //================================================================================
922 /*!
923  * \brief Return command to run MG-Tetra mesher excluding file prefix (-f)
924  */
925 //================================================================================
926
927 std::string MgAdapt::getCommandToRun()
928 {
929   /*
930   || return system command with args and options
931   ||
932   */
933   std::string errStr;
934   std::string cmd = getExeName();
935   std::string meshIn(""), sizeMapIn(""), solFileIn("");
936   updateTimeStepRank();
937   convertMedFile(meshIn, solFileIn, sizeMapIn);
938   if (!isFileExist(meshIn) || !isFileExist(solFileIn))
939   {
940     errStr = ToComment(" failed to find .mesh or .sol file from converter ")<< strerror( errno );
941     return errStr;
942   }
943   tmpFilesToBeDeleted.push_back(meshIn);
944   tmpFilesToBeDeleted.push_back(solFileIn);
945   if(useBackgroundMap && !isFileExist(sizeMapIn))
946   {
947     errStr = ToComment(" failed to find .mesh size map file from converter ")<< strerror( errno );
948     return errStr;
949   }
950
951   cmd+= " --in "+ meshIn;
952   meshFormatOutputMesh = getFileName()+".mesh";
953   tmpFilesToBeDeleted.push_back(meshFormatOutputMesh);
954   cmd+= " --out "+ meshFormatOutputMesh;
955   if (useLocalMap || useConstantValue) cmd+= " --sizemap "+ solFileIn;
956   else //  (useBackgroundMap)
957   {
958     cmd+= " --background_mesh "+ sizeMapIn ;
959     cmd+= " --background_sizemap "+ solFileIn;
960     tmpFilesToBeDeleted.push_back(sizeMapIn);
961   }
962   //~else
963   //~{
964       //~// constant value TODO
965   //~}
966   // Check coherence between mesh dimension and option fo adaptation
967   checkDimensionOptionAdaptation();
968
969 //   sizemap file is written only if level is higher than 3
970   if ( verbosityLevel > 3)
971   {
972     std::string solFileOut = getFileName()+".sol";
973     cmd+= " --write_sizemap "+ solFileOut;
974     solFormatOutput.push_back(solFileOut);
975     tmpFilesToBeDeleted.push_back(solFileOut);
976   }
977
978   std::string option, value;
979   bool isDefault;
980   const TOptionValues* options[] = { &_option2value, &_customOption2value };
981   for ( int iOp = 0; iOp < 2; ++iOp )
982   {
983     TOptionValues::const_iterator o2v = options[iOp]->begin();
984     for ( ; o2v != options[iOp]->end(); ++o2v )
985     {
986       option = o2v->first;
987       value = getOptionValue( option, &isDefault );
988
989       if ( isDefault )
990         continue;
991       if ( value.empty() )//value == NoValue() )
992       {
993         if ( _defaultOptionValues.count( option ))
994           continue; // non-custom option with no value
995         //value.clear();
996       }
997       if ( strncmp( "no", option.c_str(), 2 ) == 0 ) // options w/o values: --no_*
998       {
999         if ( !value.empty() && toBool( value ) == false )
1000           continue;
1001         value.clear();
1002       }
1003       if ( option[0] != '-' )
1004         cmd += " --";
1005       else
1006         cmd += " ";
1007 //       std::cout << "--- option: '" << option << ", value: '" << value <<"'"<< std::endl;
1008       cmd += option + " " + value;
1009     }
1010   }
1011
1012   // Verbosity Level
1013   if (verbosityLevel != defaultVerboseLevel())
1014   {
1015     cmd+= " --verbose "+ ToComment(verbosityLevel);
1016   }
1017     //~}
1018 //~cmd+= " >"
1019 #ifdef WIN32
1020     cmd += " < NUL";
1021 #endif
1022 //   std::cout << "--- cmd :"<< std::endl;
1023 //   std::cout << cmd << std::endl;
1024
1025   return cmd;
1026 }
1027
1028 //=======================================================================
1029 //function : defaultMaximumMemory
1030 //=======================================================================
1031
1032 #if defined(WIN32)
1033 #include <windows.h>
1034 #elif !defined(__APPLE__)
1035 #include <sys/sysinfo.h>
1036 #endif
1037
1038 double MgAdapt::defaultMaximumMemory()
1039 {
1040 #if defined(WIN32)
1041   // See http://msdn.microsoft.com/en-us/library/aa366589.aspx
1042   MEMORYSTATUSEX statex;
1043   statex.dwLength = sizeof (statex);
1044   long err = GlobalMemoryStatusEx (&statex);
1045   if (err != 0)
1046   {
1047     double totMB = (double)statex.ullAvailPhys / 1024. / 1024.;
1048     return (double)( 0.7 * totMB );
1049   }
1050 #elif !defined(__APPLE__)
1051   struct sysinfo si;
1052   long err = sysinfo( &si );
1053   if ( err == 0 )
1054   {
1055     long ramMB = si.totalram * si.mem_unit / 1024 / 1024;
1056     return ( 0.7 * double( ramMB ));
1057   }
1058 #endif
1059   return 1024;
1060 }
1061
1062 //=======================================================================
1063 //function : defaultWorkingDirectory
1064 //=======================================================================
1065
1066 std::string MgAdapt::defaultWorkingDirectory()
1067 {
1068   std::string aTmpDir;
1069
1070   char *Tmp_dir = getenv("SALOME_TMP_DIR");
1071   if(Tmp_dir != NULL)
1072   {
1073     aTmpDir = Tmp_dir;
1074   }
1075   else {
1076 #ifdef WIN32
1077     aTmpDir = "C:\\";
1078 #else
1079     aTmpDir = "/tmp/";
1080 #endif
1081   }
1082   return aTmpDir;
1083 }
1084 //================================================================================
1085 /*!
1086  * \brief Return a unique file name
1087  */
1088 //================================================================================
1089
1090 std::string MgAdapt::getFileName() const
1091 {
1092   std::string aTmpDir = workingDir;
1093   const char lastChar = *aTmpDir.rbegin();
1094 #ifdef WIN32
1095   if(lastChar != '\\') aTmpDir+='\\';
1096 #else
1097   if(lastChar != '/') aTmpDir+='/';
1098 #endif
1099
1100   SMESH_Comment aGenericName( aTmpDir );
1101   aGenericName << "MgAdapt_";
1102 #ifndef WIN32
1103   aGenericName << getpid();
1104 #else
1105 aGenericName << _getpid();
1106 #endif
1107   aGenericName << "_";
1108   aGenericName << std::abs((int)(long) aGenericName.data());
1109
1110   return aGenericName;
1111 }
1112 //=======================================================================
1113 //function : defaultLogFile
1114 //=======================================================================
1115
1116 std::string MgAdapt::defaultLogFile()
1117 {
1118   std::string alogFile("MG_ADAPT.log");
1119   return alogFile;
1120 }
1121 //=======================================================================
1122 //function : defaultUseConstantValue
1123 //=======================================================================
1124
1125 bool MgAdapt::defaultUseConstantValue()
1126 {
1127   return false;
1128 }
1129 //=======================================================================
1130 //function : defaultUseNoTimeStep
1131 //=======================================================================
1132
1133 bool MgAdapt::defaultUseNoTimeStep()
1134 {
1135   return true;
1136 }
1137 //=======================================================================
1138 //function : defaultRemoveLogOnSuccess
1139 //=======================================================================
1140
1141 bool MgAdapt::defaultRemoveLogOnSuccess()
1142 {
1143   return true;
1144 }
1145 //=======================================================================
1146 //function : defaultPrintLogInFile
1147 //=======================================================================
1148
1149 bool MgAdapt::defaultPrintLogInFile()
1150 {
1151   return false;
1152 }
1153 //=======================================================================
1154 //function : defaultUseChosenTimeStep
1155 //=======================================================================
1156
1157 bool MgAdapt::defaultUseChosenTimeStep()
1158 {
1159   return false;
1160 }
1161 //=======================================================================
1162 //function : UseLastTimeStep
1163 //=======================================================================
1164
1165 bool MgAdapt::defaultUseLastTimeStep()
1166 {
1167   return false;
1168 }
1169 //=======================================================================
1170 //function : defaultUseBackgroundMap
1171 //=======================================================================
1172
1173 bool MgAdapt::defaultUseBackgroundMap()
1174 {
1175   return false;
1176 }
1177 //=======================================================================
1178 //function : defaultKeepFiles
1179 //=======================================================================
1180
1181 bool MgAdapt::defaultKeepFiles()
1182 {
1183   return false;
1184 }
1185 //=======================================================================
1186 //function : defaultUseLocalMap
1187 //=======================================================================
1188
1189 bool MgAdapt::defaultUseLocalMap()
1190 {
1191   return true;
1192 }
1193 //=======================================================================
1194 //function : defaultPublish
1195 //=======================================================================
1196
1197 bool MgAdapt::defaultPublish()
1198 {
1199   return false;
1200 }
1201 //=======================================================================
1202 //function : defaultMeshOutMed
1203 //=======================================================================
1204
1205 bool MgAdapt::defaultMeshOutMed()
1206 {
1207   return true;
1208 }
1209 //=======================================================================
1210 //function : defaultFromMedFile
1211 //=======================================================================
1212
1213 bool MgAdapt::defaultFromMedFile()
1214 {
1215   return true;
1216 }
1217 //=======================================================================
1218 //function : defaultVerboseLevel
1219 //=======================================================================
1220
1221 int  MgAdapt::defaultVerboseLevel()
1222 {
1223   return 3;
1224 }
1225 std::string MgAdapt::getExeName()
1226 {
1227   return "mg-adapt.exe";
1228 }
1229 void MgAdapt::copyMgAdaptHypothesisData( const MgAdaptHypothesisData* from)
1230 {
1231   data->myFileInDir = from->myFileInDir;
1232   data->myMeshFileIn = from->myMeshFileIn;
1233   data->myMeshFileBackground = from->myMeshFileBackground;
1234   data->myOutMeshName = from->myOutMeshName;
1235   data->myMeshFileOut = from->myMeshFileOut;
1236   data->myFileOutDir = from->myFileOutDir;
1237   data->myFileSizeMapDir = from->myFileSizeMapDir;
1238   data->myFieldName = from->myFieldName;
1239   data->fromMedFile = from->fromMedFile;
1240   data->myPublish = from->myPublish;
1241   data->myMeshOutMed = from->myMeshOutMed;
1242   data->myUseLocalMap = from->myUseLocalMap;
1243   data->myUseBackgroundMap = from->myUseBackgroundMap;
1244   data->myUseConstantValue = from->myUseConstantValue;
1245   data->myConstantValue = from->myConstantValue;
1246   data->myTimeStep = from->myTimeStep;
1247   data->myRank = from->myRank;
1248   data->myUseNoTimeStep = from->myUseNoTimeStep;
1249   data->myUseLastTimeStep = from->myUseLastTimeStep;
1250   data->myUseChosenTimeStep = from->myUseChosenTimeStep;
1251   data->myWorkingDir = from->myWorkingDir;
1252   data->myLogFile = from->myLogFile;
1253   data->myPrintLogInFile = from->myPrintLogInFile;
1254   data->myKeepFiles = from->myKeepFiles;
1255   data->myRemoveLogOnSuccess = from->myRemoveLogOnSuccess;
1256   data->myVerboseLevel = from->myVerboseLevel;
1257 }
1258
1259 std::vector<std::string> MgAdapt::getListFieldsNames(std::string fileIn)
1260 {
1261   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(fileIn);
1262   std::vector<std::string> listFieldsNames(mfd->getFields()->getFieldsNames());
1263   return listFieldsNames ;
1264 }
1265
1266 void MgAdapt::checkDimensionOptionAdaptation()
1267 {
1268   // Quand le maillage est 3D, tout est possible
1269   // Quand le maillage est 2D, il faut 'surface' sauf si carte de fonds 3D
1270   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(medFileIn);
1271   int meshdim = mfd->getMeshes()->getMeshAtPos(0)->getMeshDimension() ;
1272 //   std::cout << "meshdim = " << meshdim << std::endl;
1273
1274   if ( meshdim == 2 )
1275   {
1276     std::string optionName   = "adaptation";
1277     std::string optionValue = getOptionValue(optionName);
1278 //     std::cout << "optionValue = '" << optionValue <<"'"<< std::endl;
1279     bool a_tester = false ;
1280     // carte locale ou constante : impératif d'avoir "surface"
1281     if ( useLocalMap || useConstantValue) a_tester = true ;
1282     // carte de fond : impératif d'avoir "surface" si le fonds est aussi 2D
1283     else
1284     {
1285       MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfdbg = MEDCoupling::MEDFileData::New(sizeMapFile);
1286       int meshdimbg = mfdbg->getMeshes()->getMeshAtPos(0)->getMeshDimension() ;
1287 //       std::cout << "meshdimbg = " << meshdimbg << std::endl;
1288       if ( meshdimbg == 2 ) a_tester = true ;
1289     }
1290     if ( a_tester )
1291     {
1292       if ( optionValue == "" ) setOptionValue (optionName, "surface");
1293       else
1294       {
1295         if ( optionValue != "surface" )
1296         {
1297           THROW_SALOME_EXCEPTION("Mesh dimension is 2; the option should be 'surface'"
1298                                  " instead of '" << optionValue << "'.");
1299         }
1300       }
1301     }
1302   }
1303 }
1304
1305 void MgAdapt::checkFieldName(std::string fileIn)
1306 {
1307   bool ret = false ;
1308   std::vector<std::string> listFieldsNames = getListFieldsNames(fileIn);
1309   std::size_t jaux(listFieldsNames.size());
1310   for(std::size_t j=0;j<jaux;j++)
1311   {
1312     if ( fieldName == listFieldsNames[j] )
1313     {
1314       ret = true ;
1315       break ;
1316     }
1317   }
1318   if ( ! ret )
1319   {
1320     std::cout << "Available field names:" << std::endl;
1321     for(std::size_t j=0;j<jaux;j++)
1322     { std::cout << listFieldsNames[j] << std::endl;}
1323     THROW_SALOME_EXCEPTION( "Field " << fieldName << " is not found.");
1324   }
1325 }
1326
1327 void MgAdapt::checkTimeStepRank(std::string fileIn)
1328 {
1329   bool ret = false ;
1330   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(fileIn);
1331   MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeFieldMultiTS> fts( mfd->getFields()->getFieldWithName(fieldName) );
1332   std::vector<double> timevalue;
1333   std::vector< std::pair<int,int> > timesteprank = fts->getTimeSteps(timevalue);
1334   std::size_t jaux(timesteprank.size());
1335   for(std::size_t j=0;j<jaux;j++)
1336   {
1337     if ( ( timeStep == timesteprank[j].first ) & ( rank == timesteprank[j].second ) )
1338     {
1339       ret = true ;
1340       break ;
1341     }
1342   }
1343   if ( ! ret )
1344   {
1345     std::cout << "Available (Time step, Rank):" << std::endl;
1346     for(std::size_t j=0;j<jaux;j++)
1347     { std::cout << "(Time step = " << timesteprank[j].first << ", Rank = " << timesteprank[j].second << ")" << std::endl;}
1348     THROW_SALOME_EXCEPTION("(Time step = " << timeStep << ", Rank = " << rank << ") is not found.");
1349   }
1350 }
1351
1352 void MgAdapt::convertMedFile(std::string& meshFormatMeshFileName, std::string& solFormatFieldFileName, std::string& meshFormatsizeMapFile)
1353 {
1354   std::vector<std::string> fieldFileNames;
1355   MEDCoupling::MeshFormatWriter writer;
1356   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(medFileIn);
1357   MEDCoupling::MEDFileMeshes* meshes = mfd->getMeshes();
1358   MEDCoupling::MEDFileMesh* fileMesh = meshes->getMeshAtPos(0); // ok only one mesh in file!
1359   if (meshNameOut =="")
1360       meshNameOut = fileMesh->getName();
1361   storeGroupsAndFams(fileMesh);
1362
1363   MEDCoupling::MCAuto<MEDCoupling::MEDFileFields> fields = MEDCoupling::MEDFileFields::New();
1364   solFormatFieldFileName = getFileName();
1365   solFormatFieldFileName+=".sol";
1366   fieldFileNames.push_back(solFormatFieldFileName);
1367
1368   if (useBackgroundMap)
1369   {
1370     checkFieldName(sizeMapFile) ;
1371     checkTimeStepRank(sizeMapFile) ;
1372     meshFormatsizeMapFile = getFileName();
1373     meshFormatsizeMapFile += ".mesh";
1374     buildBackGroundMeshAndSolFiles(fieldFileNames, meshFormatsizeMapFile);
1375   }
1376   else if(useLocalMap)
1377   {
1378     checkFieldName(medFileIn) ;
1379     checkTimeStepRank(medFileIn) ;
1380     MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeFieldMultiTS> fts( mfd->getFields()->getFieldWithName(fieldName) );
1381     MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeField1TS> f = fts->getTimeStep(timeStep, rank);
1382     MEDCoupling::MCAuto<MEDCoupling::MEDFileFieldMultiTS> tmFts = MEDCoupling::MEDFileFieldMultiTS::New();
1383     tmFts->pushBackTimeStep(f);
1384
1385     fields->pushField(tmFts);
1386
1387     writer.setFieldFileNames( fieldFileNames);
1388   }
1389   else
1390   {
1391     MEDCoupling::MCAuto<MEDCoupling::MEDCouplingMesh> mesh = fileMesh->getMeshAtLevel(1); // nodes mesh
1392     MEDCoupling::MCAuto<MEDCoupling::MEDCouplingUMesh> umesh = mesh->buildUnstructured(); // nodes mesh
1393     int dim  =  umesh->getSpaceDimension();
1394     int version =  sizeof(double) < 8 ? 1 : 2;
1395     mcIdType nbNodes =  umesh->getNumberOfNodes();
1396     buildConstantSizeMapSolFile(solFormatFieldFileName, dim, version, nbNodes);
1397   }
1398
1399   mfd->setFields( fields );
1400   meshFormatMeshFileName = getFileName();
1401   meshFormatMeshFileName+=".mesh";
1402   writer.setMeshFileName(meshFormatMeshFileName);
1403   writer.setMEDFileDS( mfd);
1404   writer.write();
1405
1406 }
1407
1408 void MgAdapt::convertMeshFile(std::string& meshFormatIn, std::vector< std::string>& solFieldFileNames) const
1409 {
1410   MEDCoupling::MeshFormatReader reader(meshFormatIn, solFieldFileNames);
1411
1412   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = reader.loadInMedFileDS();
1413   // write MED
1414   MEDCoupling::MEDFileMeshes* meshes = mfd->getMeshes();
1415   MEDCoupling::MEDFileMesh* fileMesh = meshes->getMeshAtPos(0); // ok only one mesh in file!
1416   fileMesh->setName(meshNameOut);
1417   restoreGroupsAndFams(fileMesh);
1418   mfd->write(medFileOut, 2);
1419 }
1420
1421 void MgAdapt::storeGroupsAndFams(MEDCoupling::MEDFileMesh* fileMesh)
1422 {
1423   storefams(fileMesh);
1424   storeGroups(fileMesh);
1425 }
1426
1427 void MgAdapt::restoreGroupsAndFams(MEDCoupling::MEDFileMesh* fileMesh) const
1428 {
1429   restorefams(fileMesh);
1430   restoreGroups(fileMesh);
1431 }
1432 void MgAdapt::storeGroups(MEDCoupling::MEDFileMesh* fileMesh)
1433 {
1434   std::map<std::string, std::vector<std::string> > grpFams = fileMesh->getGroupInfo();
1435   std::map<std::string, std::vector<std::string> >::iterator g2ff = grpFams.begin();
1436
1437   for ( ; g2ff != grpFams.end(); ++g2ff )
1438   {
1439     std::string             groupName = g2ff->first;
1440     std::vector<std::string> famNames = g2ff->second;
1441
1442     if ( famNames.empty() ) continue;
1443     std::vector< int> famListId;
1444     for ( size_t i = 0; i < famNames.size(); ++i )
1445     {
1446       famListId.push_back( FromIdType<int>( fileMesh->getFamilyId( famNames[i].c_str() )));
1447     }
1448     group grp(groupName, famListId, famNames);
1449     groupVec.push_back(grp);
1450   }
1451 }
1452
1453 void MgAdapt::storefams(MEDCoupling::MEDFileMesh* fileMesh)
1454 {
1455   std::map<std::string, mcIdType> grpFams = fileMesh->getFamilyInfo();
1456   std::map<std::string, mcIdType >::iterator f = grpFams.begin();
1457
1458   for ( ; f != grpFams.end(); ++f )
1459   {
1460     if(!f->second) continue;  // FAMILLE_ZERO
1461     family fs(f->first, FromIdType<int>( f->second ));
1462     famVec.push_back(fs);
1463   }
1464
1465 }
1466
1467 void MgAdapt::restorefams(MEDCoupling::MEDFileMesh* fileMesh) const
1468 {
1469   std::vector<family>::const_iterator fIt = famVec.begin();
1470
1471   for (; fIt!=famVec.end(); ++fIt)
1472   {
1473     try  //
1474     {
1475       std::string givenFamNameFromMeshGemConverter = fileMesh->getFamilyNameGivenId( std::abs(fIt->_famId) );
1476       fileMesh->changeFamilyId(std::abs(fIt->_famId), fIt->_famId);
1477       fileMesh->changeFamilyName(givenFamNameFromMeshGemConverter, fIt->_famName);
1478     }
1479     catch (const std::exception& e)
1480     {
1481       std::cerr<<e.what();
1482     }
1483   }
1484 }
1485
1486 void MgAdapt::restoreGroups(MEDCoupling::MEDFileMesh* fileMesh) const
1487 {
1488   std::map<std::string, std::vector<std::string> > info;
1489   std::vector <group>::const_iterator grpFams = groupVec.begin();
1490
1491   for (; grpFams!=groupVec.end(); ++grpFams)
1492   {
1493     info.insert(std::pair <std::string, std::vector<std::string> > (grpFams->_name, grpFams->_famNames) );
1494   }
1495
1496   fileMesh->setGroupInfo(info);
1497 }
1498
1499 void MgAdapt::buildConstantSizeMapSolFile(const std::string& solFormatFieldFileName, const int dim, const int version, const size_t nbNodes) const
1500 {
1501   MeshFormat::Localizer loc;
1502   MeshFormat::MeshFormatParser writer;
1503   int fileId = writer.GmfOpenMesh( solFormatFieldFileName.c_str(), GmfWrite, version, dim);
1504   int typTab[] = {GmfSca};
1505   writer.GmfSetKwd(fileId, MeshFormat::GmfSolAtVertices, (int)nbNodes, 1, typTab);
1506   for (size_t i = 0; i<nbNodes; i++)
1507   {
1508     double valTab[1] = {constantValue};
1509     writer.GmfSetLin( fileId, MeshFormat::GmfSolAtVertices, valTab);
1510   }
1511   writer.GmfCloseMesh(fileId);
1512 }
1513
1514 void MgAdapt::buildBackGroundMeshAndSolFiles(const std::vector<std::string>& fieldFileNames, const std::string& meshFormatsizeMapFile) const
1515 {
1516   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> tmpMfd = MEDCoupling::MEDFileData::New(sizeMapFile);
1517   MEDCoupling::MEDFileFields* tmpFields = tmpMfd->getFields();
1518   MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeFieldMultiTS> fts( tmpFields->getFieldWithName(fieldName) );
1519   MEDCoupling::MCAuto<MEDCoupling::MEDFileFieldMultiTS>  fts1 = MEDCoupling::DynamicCastSafe<MEDCoupling::MEDFileAnyTypeFieldMultiTS,MEDCoupling::MEDFileFieldMultiTS>(fts);
1520   MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeField1TS> f = fts1->getTimeStep(timeStep, rank);
1521   MEDCoupling::MCAuto<MEDCoupling::MEDFileFieldMultiTS> tmFts = MEDCoupling::MEDFileFieldMultiTS::New();
1522   tmFts->pushBackTimeStep(f);
1523
1524   MEDCoupling::MCAuto<MEDCoupling::MEDFileFields> tmp_fields = MEDCoupling::MEDFileFields::New();
1525   tmp_fields->pushField(tmFts);
1526
1527   tmpMfd->setFields( tmp_fields );
1528   MEDCoupling::MeshFormatWriter tmpWriter;
1529   tmpWriter.setMeshFileName(meshFormatsizeMapFile);
1530   tmpWriter.setFieldFileNames( fieldFileNames);
1531   tmpWriter.setMEDFileDS(tmpMfd);
1532   tmpWriter.write();
1533 }
1534
1535 MgAdapt::Status MgAdapt::addMessage(const std::string& msg,
1536                                     const bool         isFatal/*=false*/)
1537 {
1538   if ( isFatal )
1539     _errorMessages.clear(); // warnings are useless if a fatal error encounters
1540
1541   _errorMessages.push_back( msg );
1542
1543   //~MESSAGE(msg);
1544 #ifdef _DEBUG_
1545   std::cout << msg << std::endl;
1546 #endif
1547   return ( _status = isFatal ? MgAdapt::DRS_FAIL : MgAdapt::DRS_WARN_SKIP_ELEM );
1548 }
1549
1550 void MgAdapt::updateTimeStepRank()
1551 {
1552
1553   med_int arank;
1554   med_int tmst;
1555   if (myUseNoTimeStep)
1556   {
1557     arank = MED_NO_IT;
1558     tmst  = MED_NO_DT ;
1559     setRankTimeStep((int)tmst, (int)arank);
1560   }
1561   else if (myUseLastTimeStep)
1562   {
1563     std::string fieldFile = useBackgroundMap ? sizeMapFile : medFileIn;
1564     getTimeStepInfos(fieldFile, tmst, arank, fieldName);
1565     setRankTimeStep((int)tmst, (int)arank);
1566   }
1567 }