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