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