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