Salome HOME
Forcing removal of temporary output file for MG_adapt
[modules/smesh.git] / src / SMESH / MG_ADAPT.cxx
1 // Copyright (C) 2020-2023  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
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   if ( isFileExist( meshFormatOutputMesh )){
960     int notOk;
961     errStr=removeFile(meshFormatOutputMesh , notOk);
962     if (notOk)
963     {
964       appendMsgToLogFile(errStr);
965     }
966   }
967
968   cmd+= " --out "+ meshFormatOutputMesh;
969   if (useLocalMap || useConstantValue) cmd+= " --sizemap "+ solFileIn;
970   else //  (useBackgroundMap)
971   {
972     cmd+= " --background_mesh "+ sizeMapIn ;
973     cmd+= " --background_sizemap "+ solFileIn;
974     tmpFilesToBeDeleted.push_back(sizeMapIn);
975   }
976   //~else
977   //~{
978   //~// constant value TODO
979   //~}
980   // Check coherence between mesh dimension and option fo adaptation
981   checkDimensionOptionAdaptation();
982
983   //   sizemap file is written only if level is higher than 3
984   if ( verbosityLevel > 3)
985   {
986     std::string solFileOut = getFileName()+".sol";
987     cmd+= " --write_sizemap "+ solFileOut;
988     solFormatOutput.push_back(solFileOut);
989     tmpFilesToBeDeleted.push_back(solFileOut);
990   }
991
992   std::string option, value;
993   bool isDefault;
994   const TOptionValues* options[] = { &_option2value, &_customOption2value };
995   for ( int iOp = 0; iOp < 2; ++iOp )
996   {
997     TOptionValues::const_iterator o2v = options[iOp]->begin();
998     for ( ; o2v != options[iOp]->end(); ++o2v )
999     {
1000       option = o2v->first;
1001       value = getOptionValue( option, &isDefault );
1002
1003       if ( isDefault )
1004         continue;
1005       if ( value.empty() )//value == NoValue() )
1006       {
1007         if ( _defaultOptionValues.count( option ))
1008           continue; // non-custom option with no value
1009         //value.clear();
1010       }
1011       if ( strncmp( "no", option.c_str(), 2 ) == 0 ) // options w/o values: --no_*
1012       {
1013         if ( !value.empty() && toBool( value ) == false )
1014           continue;
1015         value.clear();
1016       }
1017       if ( option[0] != '-' )
1018         cmd += " --";
1019       else
1020         cmd += " ";
1021       //       std::cout << "--- option: '" << option << ", value: '" << value <<"'"<< std::endl;
1022       cmd += option + " " + value;
1023     }
1024   }
1025
1026   // Verbosity Level
1027   if (verbosityLevel != defaultVerboseLevel())
1028   {
1029     cmd+= " --verbose "+ ToComment(verbosityLevel);
1030   }
1031   // get license key
1032   {
1033     smIdType nbVertex, nbEdge, nbFace, nbVol;
1034     DriverGMF_Read gmfReader;
1035     gmfReader.SetFile( meshIn );
1036     gmfReader.GetMeshInfo( nbVertex, nbEdge, nbFace, nbVol );
1037
1038     std::string errorTxt;
1039     std::string key = SMESHUtils_MGLicenseKeyGen::GetKey( meshIn,
1040                                                           FromSmIdType<int>( nbVertex ),
1041                                                           FromSmIdType<int>( nbEdge ),
1042                                                           FromSmIdType<int>( nbFace ),
1043                                                           FromSmIdType<int>( nbVol ),
1044                                                           errorTxt );
1045     if ( key.empty() )
1046       return ToComment( "Problem with library SalomeMeshGemsKeyGenerator: " + errorTxt );
1047
1048     if ( key!="0" )
1049       cmd += " --key " + key;
1050   }
1051
1052 #ifdef WIN32
1053   cmd += " < NUL";
1054 #endif
1055
1056   if (SALOME::VerbosityActivated())
1057     {
1058       std::cout << "--- cmd :"<< std::endl;
1059       std::cout << cmd << std::endl;
1060     }
1061
1062   return cmd;
1063 }
1064
1065 //=======================================================================
1066 //function : defaultMaximumMemory
1067 //=======================================================================
1068
1069 #if defined(WIN32)
1070 #include <windows.h>
1071 #elif !defined(__APPLE__)
1072 #include <sys/sysinfo.h>
1073 #endif
1074
1075 double MgAdapt::defaultMaximumMemory()
1076 {
1077 #if defined(WIN32)
1078   // See http://msdn.microsoft.com/en-us/library/aa366589.aspx
1079   MEMORYSTATUSEX statex;
1080   statex.dwLength = sizeof (statex);
1081   long err = GlobalMemoryStatusEx (&statex);
1082   if (err != 0)
1083   {
1084     double totMB = (double)statex.ullAvailPhys / 1024. / 1024.;
1085     return (double)( 0.7 * totMB );
1086   }
1087 #elif !defined(__APPLE__)
1088   struct sysinfo si;
1089   long err = sysinfo( &si );
1090   if ( err == 0 )
1091   {
1092     long ramMB = si.totalram * si.mem_unit / 1024 / 1024;
1093     return ( 0.7 * double( ramMB ));
1094   }
1095 #endif
1096   return 1024;
1097 }
1098
1099 //=======================================================================
1100 //function : defaultWorkingDirectory
1101 //=======================================================================
1102
1103 std::string MgAdapt::defaultWorkingDirectory()
1104 {
1105   std::string aTmpDir;
1106
1107   char *Tmp_dir = getenv("SALOME_TMP_DIR");
1108   if(Tmp_dir != NULL)
1109   {
1110     aTmpDir = Tmp_dir;
1111   }
1112
1113   if ( ! isFileExist( aTmpDir ))
1114   {
1115 #ifdef WIN32
1116     aTmpDir = "C:\\";
1117 #else
1118     aTmpDir = "/tmp/";
1119 #endif
1120   }
1121   return aTmpDir;
1122 }
1123 //================================================================================
1124 /*!
1125  * \brief Return a unique file name
1126  */
1127 //================================================================================
1128
1129 std::string MgAdapt::getFileName() const
1130 {
1131   std::string aTmpDir = workingDir;
1132   const char lastChar = *aTmpDir.rbegin();
1133 #ifdef WIN32
1134   if(lastChar != '\\') aTmpDir+='\\';
1135 #else
1136   if(lastChar != '/') aTmpDir+='/';
1137 #endif
1138
1139   SMESH_Comment aGenericName( aTmpDir );
1140   aGenericName << "MgAdapt_";
1141 #ifndef WIN32
1142   aGenericName << getpid();
1143 #else
1144 aGenericName << _getpid();
1145 #endif
1146   aGenericName << "_";
1147   aGenericName << std::abs((int)(long) aGenericName.data());
1148
1149   return aGenericName;
1150 }
1151 //=======================================================================
1152 //function : defaultLogFile
1153 //=======================================================================
1154
1155 std::string MgAdapt::defaultLogFile()
1156 {
1157   std::string alogFile("MG_ADAPT.log");
1158   return alogFile;
1159 }
1160 //=======================================================================
1161 //function : defaultUseConstantValue
1162 //=======================================================================
1163
1164 bool MgAdapt::defaultUseConstantValue()
1165 {
1166   return false;
1167 }
1168 //=======================================================================
1169 //function : defaultUseNoTimeStep
1170 //=======================================================================
1171
1172 bool MgAdapt::defaultUseNoTimeStep()
1173 {
1174   return true;
1175 }
1176 //=======================================================================
1177 //function : defaultRemoveLogOnSuccess
1178 //=======================================================================
1179
1180 bool MgAdapt::defaultRemoveLogOnSuccess()
1181 {
1182   return true;
1183 }
1184 //=======================================================================
1185 //function : defaultPrintLogInFile
1186 //=======================================================================
1187
1188 bool MgAdapt::defaultPrintLogInFile()
1189 {
1190   return false;
1191 }
1192 //=======================================================================
1193 //function : defaultUseChosenTimeStep
1194 //=======================================================================
1195
1196 bool MgAdapt::defaultUseChosenTimeStep()
1197 {
1198   return false;
1199 }
1200 //=======================================================================
1201 //function : UseLastTimeStep
1202 //=======================================================================
1203
1204 bool MgAdapt::defaultUseLastTimeStep()
1205 {
1206   return false;
1207 }
1208 //=======================================================================
1209 //function : defaultUseBackgroundMap
1210 //=======================================================================
1211
1212 bool MgAdapt::defaultUseBackgroundMap()
1213 {
1214   return false;
1215 }
1216 //=======================================================================
1217 //function : defaultKeepFiles
1218 //=======================================================================
1219
1220 bool MgAdapt::defaultKeepFiles()
1221 {
1222   return false;
1223 }
1224 //=======================================================================
1225 //function : defaultUseLocalMap
1226 //=======================================================================
1227
1228 bool MgAdapt::defaultUseLocalMap()
1229 {
1230   return true;
1231 }
1232 //=======================================================================
1233 //function : defaultPublish
1234 //=======================================================================
1235
1236 bool MgAdapt::defaultPublish()
1237 {
1238   return false;
1239 }
1240 //=======================================================================
1241 //function : defaultMeshOutMed
1242 //=======================================================================
1243
1244 bool MgAdapt::defaultMeshOutMed()
1245 {
1246   return true;
1247 }
1248 //=======================================================================
1249 //function : defaultFromMedFile
1250 //=======================================================================
1251
1252 bool MgAdapt::defaultFromMedFile()
1253 {
1254   return true;
1255 }
1256 //=======================================================================
1257 //function : defaultVerboseLevel
1258 //=======================================================================
1259
1260 int  MgAdapt::defaultVerboseLevel()
1261 {
1262   return 3;
1263 }
1264 std::string MgAdapt::getExeName()
1265 {
1266   return "mg-adapt.exe";
1267 }
1268 void MgAdapt::copyMgAdaptHypothesisData( const MgAdaptHypothesisData* from)
1269 {
1270   data->myFileInDir = from->myFileInDir;
1271   data->myMeshFileIn = from->myMeshFileIn;
1272   data->myMeshFileBackground = from->myMeshFileBackground;
1273   data->myOutMeshName = from->myOutMeshName;
1274   data->myMeshFileOut = from->myMeshFileOut;
1275   data->myFileOutDir = from->myFileOutDir;
1276   data->myFileSizeMapDir = from->myFileSizeMapDir;
1277   data->myFieldName = from->myFieldName;
1278   data->fromMedFile = from->fromMedFile;
1279   data->myPublish = from->myPublish;
1280   data->myMeshOutMed = from->myMeshOutMed;
1281   data->myUseLocalMap = from->myUseLocalMap;
1282   data->myUseBackgroundMap = from->myUseBackgroundMap;
1283   data->myUseConstantValue = from->myUseConstantValue;
1284   data->myConstantValue = from->myConstantValue;
1285   data->myTimeStep = from->myTimeStep;
1286   data->myRank = from->myRank;
1287   data->myUseNoTimeStep = from->myUseNoTimeStep;
1288   data->myUseLastTimeStep = from->myUseLastTimeStep;
1289   data->myUseChosenTimeStep = from->myUseChosenTimeStep;
1290   data->myWorkingDir = from->myWorkingDir;
1291   data->myLogFile = from->myLogFile;
1292   data->myPrintLogInFile = from->myPrintLogInFile;
1293   data->myKeepFiles = from->myKeepFiles;
1294   data->myRemoveLogOnSuccess = from->myRemoveLogOnSuccess;
1295   data->myVerboseLevel = from->myVerboseLevel;
1296 }
1297
1298 std::vector<std::string> MgAdapt::getListFieldsNames(std::string fileIn)
1299 {
1300   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(fileIn);
1301   std::vector<std::string> listFieldsNames(mfd->getFields()->getFieldsNames());
1302   return listFieldsNames ;
1303 }
1304
1305 void MgAdapt::checkDimensionOptionAdaptation()
1306 {
1307   // Quand le maillage est 3D, tout est possible
1308   // Quand le maillage est 2D, il faut 'surface' sauf si carte de fonds 3D
1309   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(medFileIn);
1310   int meshdim = mfd->getMeshes()->getMeshAtPos(0)->getMeshDimension() ;
1311 //   std::cout << "meshdim = " << meshdim << std::endl;
1312
1313   if ( meshdim == 2 )
1314   {
1315     std::string optionName   = "adaptation";
1316     std::string optionValue = getOptionValue(optionName);
1317 //     std::cout << "optionValue = '" << optionValue <<"'"<< std::endl;
1318     bool a_tester = false ;
1319     // carte locale ou constante : impératif d'avoir "surface"
1320     if ( useLocalMap || useConstantValue) a_tester = true ;
1321     // carte de fond : impératif d'avoir "surface" si le fonds est aussi 2D
1322     else
1323     {
1324       MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfdbg = MEDCoupling::MEDFileData::New(sizeMapFile);
1325       int meshdimbg = mfdbg->getMeshes()->getMeshAtPos(0)->getMeshDimension() ;
1326 //       std::cout << "meshdimbg = " << meshdimbg << std::endl;
1327       if ( meshdimbg == 2 ) a_tester = true ;
1328     }
1329     if ( a_tester )
1330     {
1331       if ( optionValue == "" ) setOptionValue (optionName, "surface");
1332       else
1333       {
1334         if ( optionValue != "surface" )
1335         {
1336           THROW_SALOME_EXCEPTION("Mesh dimension is 2; the option should be 'surface'"
1337                                  " instead of '" << optionValue << "'.");
1338         }
1339       }
1340     }
1341   }
1342 }
1343
1344 void MgAdapt::checkFieldName(std::string fileIn)
1345 {
1346   bool ret = false ;
1347   std::vector<std::string> listFieldsNames = getListFieldsNames(fileIn);
1348   std::size_t jaux(listFieldsNames.size());
1349   for(std::size_t j=0;j<jaux;j++)
1350   {
1351     if ( fieldName == listFieldsNames[j] )
1352     {
1353       ret = true ;
1354       break ;
1355     }
1356   }
1357   if ( ! ret )
1358   {
1359     std::cout << "Available field names:" << std::endl;
1360     for(std::size_t j=0;j<jaux;j++)
1361     { std::cout << listFieldsNames[j] << std::endl;}
1362     THROW_SALOME_EXCEPTION( "Field " << fieldName << " is not found.");
1363   }
1364 }
1365
1366 void MgAdapt::checkTimeStepRank(std::string fileIn)
1367 {
1368   bool ret = false ;
1369   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(fileIn);
1370   MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeFieldMultiTS> fts( mfd->getFields()->getFieldWithName(fieldName) );
1371   std::vector<double> timevalue;
1372   std::vector< std::pair<int,int> > timesteprank = fts->getTimeSteps(timevalue);
1373   std::size_t jaux(timesteprank.size());
1374   for(std::size_t j=0;j<jaux;j++)
1375   {
1376     if ( ( timeStep == timesteprank[j].first ) & ( rank == timesteprank[j].second ) )
1377     {
1378       ret = true ;
1379       break ;
1380     }
1381   }
1382   if ( ! ret )
1383   {
1384     std::cout << "Available (Time step, Rank):" << std::endl;
1385     for(std::size_t j=0;j<jaux;j++)
1386     { std::cout << "(Time step = " << timesteprank[j].first << ", Rank = " << timesteprank[j].second << ")" << std::endl;}
1387     THROW_SALOME_EXCEPTION("(Time step = " << timeStep << ", Rank = " << rank << ") is not found.");
1388   }
1389 }
1390
1391 void MgAdapt::convertMedFile(std::string& meshFormatMeshFileName, std::string& solFormatFieldFileName, std::string& meshFormatsizeMapFile)
1392 {
1393   std::vector<std::string> fieldFileNames;
1394   MEDCoupling::MeshFormatWriter writer;
1395   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(medFileIn);
1396   MEDCoupling::MEDFileMeshes* meshes = mfd->getMeshes();
1397   MEDCoupling::MEDFileMesh* fileMesh = meshes->getMeshAtPos(0); // ok only one mesh in file!
1398   if (meshNameOut =="")
1399     meshNameOut = fileMesh->getName();
1400   storeGroupsAndFams(fileMesh);
1401
1402   MEDCoupling::MCAuto<MEDCoupling::MEDFileFields> fields = MEDCoupling::MEDFileFields::New();
1403   solFormatFieldFileName = getFileName();
1404   solFormatFieldFileName+=".sol";
1405   fieldFileNames.push_back(solFormatFieldFileName);
1406
1407   if (useBackgroundMap)
1408   {
1409     checkFieldName(sizeMapFile) ;
1410     checkTimeStepRank(sizeMapFile) ;
1411     meshFormatsizeMapFile = getFileName();
1412     meshFormatsizeMapFile += ".mesh";
1413     buildBackGroundMeshAndSolFiles(fieldFileNames, meshFormatsizeMapFile);
1414   }
1415   else if(useLocalMap)
1416   {
1417     checkFieldName(medFileIn) ;
1418     checkTimeStepRank(medFileIn) ;
1419     MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeFieldMultiTS> fts( mfd->getFields()->getFieldWithName(fieldName) );
1420     MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeField1TS> f = fts->getTimeStep(timeStep, rank);
1421     MEDCoupling::MCAuto<MEDCoupling::MEDFileFieldMultiTS> tmFts = MEDCoupling::DynamicCast<MEDCoupling::MEDFileAnyTypeFieldMultiTS,MEDCoupling::MEDFileFieldMultiTS>(fts);
1422
1423     // if not able to cast to double field, try float field
1424     if (!tmFts)
1425     {
1426       MEDCoupling::MCAuto<MEDCoupling::MEDFileFloatFieldMultiTS>  tmFtsFloat = MEDCoupling::DynamicCast<MEDCoupling::MEDFileAnyTypeFieldMultiTS,MEDCoupling::MEDFileFloatFieldMultiTS>(fts);
1427       if (!tmFtsFloat)
1428         THROW_SALOME_EXCEPTION("\nUnexpected field type.\n");
1429       // convert float field to double
1430       tmFts = tmFtsFloat->convertToDouble();
1431     }
1432
1433     fields->pushField(tmFts);
1434
1435     writer.setFieldFileNames( fieldFileNames);
1436   }
1437   else
1438   {
1439     MEDCoupling::MCAuto<MEDCoupling::MEDCouplingMesh> mesh = fileMesh->getMeshAtLevel(1); // nodes mesh
1440     MEDCoupling::MCAuto<MEDCoupling::MEDCouplingUMesh> umesh = mesh->buildUnstructured(); // nodes mesh
1441     int dim  =  umesh->getSpaceDimension();
1442     int version =  sizeof(double) < 8 ? 1 : 2;
1443     mcIdType nbNodes =  umesh->getNumberOfNodes();
1444     buildConstantSizeMapSolFile(solFormatFieldFileName, dim, version, nbNodes);
1445   }
1446
1447   mfd->setFields( fields );
1448   meshFormatMeshFileName = getFileName();
1449   meshFormatMeshFileName+=".mesh";
1450   writer.setMeshFileName(meshFormatMeshFileName);
1451   writer.setMEDFileDS( mfd);
1452   writer.write();
1453
1454 }
1455
1456 void MgAdapt::convertMeshFile(std::string& meshFormatIn, std::vector< std::string>& solFieldFileNames) const
1457 {
1458   MEDCoupling::MeshFormatReader reader(meshFormatIn, solFieldFileNames);
1459
1460   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = reader.loadInMedFileDS();
1461   // write MED
1462   MEDCoupling::MEDFileMeshes* meshes = mfd->getMeshes();
1463   MEDCoupling::MEDFileMesh* fileMesh = meshes->getMeshAtPos(0); // ok only one mesh in file!
1464   fileMesh->setName(meshNameOut);
1465   restoreGroupsAndFams(fileMesh);
1466   mfd->write(medFileOut, 2);
1467 }
1468
1469 void MgAdapt::storeGroupsAndFams(MEDCoupling::MEDFileMesh* fileMesh)
1470 {
1471   storefams(fileMesh);
1472   storeGroups(fileMesh);
1473 }
1474
1475 void MgAdapt::restoreGroupsAndFams(MEDCoupling::MEDFileMesh* fileMesh) const
1476 {
1477   restorefams(fileMesh);
1478   restoreGroups(fileMesh);
1479 }
1480 void MgAdapt::storeGroups(MEDCoupling::MEDFileMesh* fileMesh)
1481 {
1482   std::map<std::string, std::vector<std::string> > grpFams = fileMesh->getGroupInfo();
1483   std::map<std::string, std::vector<std::string> >::iterator g2ff = grpFams.begin();
1484
1485   for ( ; g2ff != grpFams.end(); ++g2ff )
1486   {
1487     std::string             groupName = g2ff->first;
1488     std::vector<std::string> famNames = g2ff->second;
1489
1490     if ( famNames.empty() ) continue;
1491     std::vector< int> famListId;
1492     for ( size_t i = 0; i < famNames.size(); ++i )
1493     {
1494       famListId.push_back( FromIdType<int>( fileMesh->getFamilyId( famNames[i].c_str() )));
1495     }
1496     group grp(groupName, famListId, famNames);
1497     groupVec.push_back(grp);
1498   }
1499 }
1500
1501 void MgAdapt::storefams(MEDCoupling::MEDFileMesh* fileMesh)
1502 {
1503   std::map<std::string, mcIdType> grpFams = fileMesh->getFamilyInfo();
1504   std::map<std::string, mcIdType >::iterator f = grpFams.begin();
1505
1506   for ( ; f != grpFams.end(); ++f )
1507   {
1508     if(!f->second) continue;  // FAMILLE_ZERO
1509     family fs(f->first, FromIdType<int>( f->second ));
1510     famVec.push_back(fs);
1511   }
1512
1513 }
1514
1515 void MgAdapt::restorefams(MEDCoupling::MEDFileMesh* fileMesh) const
1516 {
1517   std::vector<family>::const_iterator fIt = famVec.begin();
1518
1519   for (; fIt!=famVec.end(); ++fIt)
1520   {
1521     try  //
1522     {
1523       std::string givenFamNameFromMeshGemConverter = fileMesh->getFamilyNameGivenId( std::abs(fIt->_famId) );
1524       fileMesh->changeFamilyId(std::abs(fIt->_famId), fIt->_famId);
1525       fileMesh->changeFamilyName(givenFamNameFromMeshGemConverter, fIt->_famName);
1526     }
1527     catch (const std::exception& e)
1528     {
1529       std::cerr<<e.what();
1530     }
1531   }
1532 }
1533
1534 void MgAdapt::restoreGroups(MEDCoupling::MEDFileMesh* fileMesh) const
1535 {
1536   std::map<std::string, std::vector<std::string> > info;
1537   std::vector <group>::const_iterator grpFams = groupVec.begin();
1538
1539   for (; grpFams!=groupVec.end(); ++grpFams)
1540   {
1541     info.insert(std::pair <std::string, std::vector<std::string> > (grpFams->_name, grpFams->_famNames) );
1542   }
1543
1544   fileMesh->setGroupInfo(info);
1545 }
1546
1547 void MgAdapt::buildConstantSizeMapSolFile(const std::string& solFormatFieldFileName, const int dim, const int version, const size_t nbNodes) const
1548 {
1549   MeshFormat::Localizer loc;
1550   MeshFormat::MeshFormatParser writer;
1551   int fileId = writer.GmfOpenMesh( solFormatFieldFileName.c_str(), GmfWrite, version, dim);
1552   int typTab[] = {GmfSca};
1553   writer.GmfSetKwd(fileId, MeshFormat::GmfSolAtVertices, (int)nbNodes, 1, typTab);
1554   for (size_t i = 0; i<nbNodes; i++)
1555   {
1556     double valTab[1] = {constantValue};
1557     writer.GmfSetLin( fileId, MeshFormat::GmfSolAtVertices, valTab);
1558   }
1559   writer.GmfCloseMesh(fileId);
1560 }
1561
1562 void MgAdapt::buildBackGroundMeshAndSolFiles(const std::vector<std::string>& fieldFileNames, const std::string& meshFormatsizeMapFile) const
1563 {
1564   MEDCoupling::MCAuto<MEDCoupling::MEDFileData> tmpMfd = MEDCoupling::MEDFileData::New(sizeMapFile);
1565   MEDCoupling::MEDFileFields* tmpFields = tmpMfd->getFields();
1566   MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeFieldMultiTS> fts( tmpFields->getFieldWithName(fieldName) );
1567   MEDCoupling::MCAuto<MEDCoupling::MEDFileFieldMultiTS>  fts1 = MEDCoupling::DynamicCastSafe<MEDCoupling::MEDFileAnyTypeFieldMultiTS,MEDCoupling::MEDFileFieldMultiTS>(fts);
1568   MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeField1TS> f = fts1->getTimeStep(timeStep, rank);
1569   MEDCoupling::MCAuto<MEDCoupling::MEDFileFieldMultiTS> tmFts = MEDCoupling::MEDFileFieldMultiTS::New();
1570   tmFts->pushBackTimeStep(f);
1571
1572   MEDCoupling::MCAuto<MEDCoupling::MEDFileFields> tmp_fields = MEDCoupling::MEDFileFields::New();
1573   tmp_fields->pushField(tmFts);
1574
1575   tmpMfd->setFields( tmp_fields );
1576   MEDCoupling::MeshFormatWriter tmpWriter;
1577   tmpWriter.setMeshFileName(meshFormatsizeMapFile);
1578   tmpWriter.setFieldFileNames( fieldFileNames);
1579   tmpWriter.setMEDFileDS(tmpMfd);
1580   tmpWriter.write();
1581 }
1582
1583 MgAdapt::Status MgAdapt::addMessage(const std::string& msg,
1584                                     const bool         isFatal/*=false*/)
1585 {
1586   if ( isFatal )
1587     _errorMessages.clear(); // warnings are useless if a fatal error encounters
1588
1589   _errorMessages.push_back( msg );
1590
1591   //~MESSAGE(msg);
1592   if (SALOME::VerbosityActivated())
1593     std::cout << msg << std::endl;
1594
1595   return ( _status = isFatal ? MgAdapt::DRS_FAIL : MgAdapt::DRS_WARN_SKIP_ELEM );
1596 }
1597
1598 void MgAdapt::updateTimeStepRank()
1599 {
1600
1601   med_int arank;
1602   med_int tmst;
1603   if (myUseNoTimeStep)
1604   {
1605     arank = MED_NO_IT;
1606     tmst  = MED_NO_DT ;
1607     setRankTimeStep((int)tmst, (int)arank);
1608   }
1609   else if (myUseLastTimeStep)
1610   {
1611     std::string fieldFile = useBackgroundMap ? sizeMapFile : medFileIn;
1612     getTimeStepInfos(fieldFile, tmst, arank, fieldName);
1613     setRankTimeStep((int)tmst, (int)arank);
1614   }
1615 }