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