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