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