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