1 // Copyright (C) 2020-2024 CEA, EDF
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "MG_ADAPT.hxx"
22 #include <DriverGMF_Read.hxx>
23 #include <SMESH_Comment.hxx>
24 #include <SMESH_File.hxx>
25 #include <SMESH_MGLicenseKeyGen.hxx>
26 #include <SMESH_TypeDefs.hxx>
28 #include <MEDFileData.hxx>
29 #include <MEDFileField.hxx>
30 #include <MEDFileMesh.hxx>
31 #include <MeshFormatReader.hxx>
32 #include <MeshFormatWriter.hxx>
34 #include <Utils_SALOME_Exception.hxx>
35 #include <Basics_Utils.hxx>
36 #include "SMESH_TypeDefs.hxx"
39 #include <unistd.h> // getpid()
45 #include <memory> // unique_ptr
48 typedef SMESH_Comment ToComment;
50 using namespace MG_ADAPT;
51 static std::string removeFile(std::string fileName, int& notOk)
54 notOk = std::remove(fileName.c_str());
55 if (notOk) errStr = ToComment("\n error while removing file : ") << fileName;
56 else errStr = ToComment("\n file : ") << fileName << " succesfully deleted! \n ";
60 std::string MG_ADAPT::remove_extension(const std::string& filename)
62 size_t lastdot = filename.find_last_of(".");
63 if (lastdot == std::string::npos) return filename;
64 return filename.substr(0, lastdot);
69 bool isFileExist( const std::string& fName )
71 return SMESH_File( fName ).exists();
74 // =======================================================================
75 med_idt openMedFile(const std::string aFile)
76 // =======================================================================
77 // renvoie le medId associe au fichier Med apres ouverture
79 med_idt medIdt = MEDfileOpen(aFile.c_str(),MED_ACC_RDONLY);
82 THROW_SALOME_EXCEPTION("\nThe med file " << aFile << " cannot be opened.\n");
87 // =======================================================================
88 void getTimeStepInfos(std::string aFile, med_int& numdt, med_int& numit, std::string fieldName)
89 // =======================================================================
91 // Il faut voir si plusieurs maillages
96 // Ouverture du fichier
97 //~SCRUTE(aFile.toStdString());
98 medIdt = openMedFile(aFile);
99 if ( medIdt < 0 ) return ;
100 // Lecture du nombre de champs
101 med_int ncha = MEDnField(medIdt) ;
104 //~addMessage( ToComment(" error: there is no field in ") << aFile, /*fatal=*/true );
107 // Lecture des caracteristiques du champs
109 // Lecture du type du champ, des noms des composantes et du nom de l'unite
110 char nomcha [MED_NAME_SIZE+1];
111 strcpy(nomcha, fieldName.c_str());
112 // Lecture du nombre de composantes
113 med_int ncomp = MEDfieldnComponentByName(medIdt, nomcha);
114 char meshname[MED_NAME_SIZE+1];
115 char * comp = (char*) malloc(ncomp*MED_SNAME_SIZE+1);
116 char * unit = (char*) malloc(ncomp*MED_SNAME_SIZE+1);
117 char dtunit[MED_SNAME_SIZE+1];
119 med_field_type typcha;
121 erreur = MEDfieldInfoByName (medIdt, nomcha, meshname,&local,&typcha,comp,unit,dtunit, &nbofcstp);
126 //~addMessage( ToComment(" error: error while reading field ") << nomcha << " in file " << aFile , /*fatal=*/true );
131 med_int tmp_numdt, tmp_numit;
133 //~med_int step = data->myUseLastTimeStep ? nbofcstp : data->myTimeStep+1;
134 //~myPrint("step ", step);
135 erreur = MEDfieldComputingStepInfo ( medIdt, nomcha, 1, &numdt, &numit, &dt );
136 for( int step = 1; step <= nbofcstp; step++ )
138 erreur = MEDfieldComputingStepInfo ( medIdt, nomcha, step, &tmp_numdt, &tmp_numit, &dt );
139 if(tmp_numdt > numdt)
147 //~addMessage( ToComment(" error: error while reading field ") << nomcha << "step (numdt, numit) = " <<"("<< numdt<< ", "
148 //numit<< ")" <<" in file " << aFile , /*fatal=*/true );
152 // Fermeture du fichier
153 if ( medIdt > 0 ) MEDfileClose(medIdt);
157 struct GET_DEFAULT // struct used to get default value from GetOptionValue()
165 class outFileStream : public std::ofstream{
167 ~outFileStream(){close();} //to close file at dtor
170 } // anonymous namespace
172 //----------------------------------------------------------------------------------------
175 data = new MgAdaptHypothesisData();
176 data->myInMeshName = "";
177 data->fromMedFile = defaultFromMedFile();
178 data->myFileInDir = defaultWorkingDirectory();
179 data->myMeshFileIn = "";
180 data->myFileOutDir = defaultWorkingDirectory();
181 data->myOutMeshName = "";
182 data->myMeshFileOut = "";
183 data->myMeshOutMed = defaultMeshOutMed();
184 data->myPublish = defaultPublish();
185 data->myUseLocalMap = defaultUseLocalMap();
186 data->myUseBackgroundMap = defaultUseBackgroundMap();
187 data->myFileSizeMapDir = defaultWorkingDirectory();
188 data->myMeshFileBackground = "";
189 data->myUseConstantValue = defaultUseConstantValue();
190 data->myConstantValue = 0.0;
191 data->myFieldName = "";
192 data->myUseNoTimeStep = defaultUseNoTimeStep();
193 data->myUseLastTimeStep = defaultUseLastTimeStep();
194 data->myUseChosenTimeStep = defaultUseChosenTimeStep();
195 data->myTimeStep = -2;
197 data->myWorkingDir = defaultWorkingDirectory();
198 data->myLogFile = defaultLogFile();
199 data->myVerboseLevel = defaultVerboseLevel();
200 data->myPrintLogInFile = defaultPrintLogInFile();
201 data->myKeepFiles = defaultKeepFiles();
202 data->myRemoveLogOnSuccess = defaultRemoveLogOnSuccess();
207 MgAdapt::MgAdapt(MgAdaptHypothesisData* myData)
209 data = new MgAdaptHypothesisData();
214 MgAdapt::MgAdapt( const MgAdapt& copy)
216 data = new MgAdaptHypothesisData();
217 MgAdaptHypothesisData *copyData = copy.getData();
218 copyMgAdaptHypothesisData(copyData);
221 this->_option2value = copy._option2value;
222 this->_customOption2value = copy._customOption2value;
223 this->_defaultOptionValues = copy._defaultOptionValues;
224 this->_doubleOptions = copy._doubleOptions;
225 this->_charOptions = copy._charOptions;
226 this->_boolOptions = copy._boolOptions;
229 //-----------------------------------------------------------------------------------------
234 void MgAdapt::buildModel()
237 const char* boolOptionNames[] = { "compute_ridges", // yes
240 // const char* intOptionNames[] = { "max_number_of_errors_printed", // 1
241 // "max_number_of_threads", // 4
244 const char* doubleOptionNames[] = { "max_memory", // 0
247 const char* charOptionNames[] = { "components", // "yes"
248 "adaptation", // both
253 while (boolOptionNames[i][0])
255 _boolOptions.insert( boolOptionNames[i] );
256 _option2value[boolOptionNames[i++]].clear();
259 // while (intOptionNames[i][0])
260 // _option2value[intOptionNames[i++]].clear();
263 while (doubleOptionNames[i][0]) {
264 _doubleOptions.insert(doubleOptionNames[i]);
265 _option2value[doubleOptionNames[i++]].clear();
268 while (charOptionNames[i][0]) {
269 _charOptions.insert(charOptionNames[i]);
270 _option2value[charOptionNames[i++]].clear();
273 // default values to be used while MG-Adapt
275 _defaultOptionValues["adaptation" ] = "both";
276 _defaultOptionValues["components" ] = "outside components";
277 _defaultOptionValues["compute_ridges"] = "yes";
278 _defaultOptionValues["max_memory" ] = ToComment(defaultMaximumMemory());
281 //=============================================================================
282 TOptionValues MgAdapt::getOptionValues() const
285 TOptionValues::const_iterator op_val = _option2value.begin();
286 for ( ; op_val != _option2value.end(); ++op_val )
287 vals.insert( make_pair( op_val->first, getOptionValue( op_val->first, GET_DEFAULT() )));
292 std::vector <std::string> MgAdapt::getOptionValuesStrVec() const
294 std::vector <std::string> vals;
295 TOptionValues::const_iterator op_val = _option2value.begin();
296 for ( ; op_val != _option2value.end(); ++op_val )
297 vals.push_back(op_val->first+":"+getOptionValue( op_val->first, GET_DEFAULT() ));
302 std::vector <std::string> MgAdapt::getCustomOptionValuesStrVec() const
304 std::vector <std::string> vals;
305 TOptionValues::const_iterator op_val;
306 for ( op_val = _customOption2value.begin(); op_val != _customOption2value.end(); ++op_val )
308 vals.push_back(op_val->first+":"+getOptionValue( op_val->first, GET_DEFAULT() ));
312 const TOptionValues& MgAdapt::getCustomOptionValues() const
314 return _customOption2value;
316 void MgAdapt::setData(MgAdaptHypothesisData* myData)
318 copyMgAdaptHypothesisData(myData);
321 MgAdaptHypothesisData* MgAdapt::getData() const
325 void MgAdapt::setMedFileIn(std::string fileName)
327 if ( isFileExist( fileName ))
329 medFileIn = fileName;
331 if (medFileOut == "") // default MED file Out
332 medFileOut = remove_extension( fileName )+ ".adapt.med";
336 THROW_SALOME_EXCEPTION("\nThe file "<< fileName <<" does not exist.\n");
340 std::string MgAdapt::getMedFileIn()
345 void MgAdapt::setMedFileOut(std::string fileOut)
347 medFileOut = fileOut;
349 std::string MgAdapt::getMedFileOut()
353 void MgAdapt::setMeshOutMed(bool mybool)
357 bool MgAdapt::getMeshOutMed()
361 void MgAdapt::setPublish(bool mybool)
365 bool MgAdapt::getPublish()
369 void MgAdapt::setFieldName(std::string myFieldName)
371 fieldName = myFieldName;
373 std::string MgAdapt::getFieldName()
377 void MgAdapt::setTimeStep(int time)
381 int MgAdapt::getTimeStep() const
386 void MgAdapt::setRankTimeStep(int time, int myRank)
392 int MgAdapt::getRank()
396 void MgAdapt::setTimeStepRankLast()
398 myUseLastTimeStep = true;
399 myUseChosenTimeStep = false;
400 myUseNoTimeStep = false;
401 //~med_int aRank, tmst;
402 //~std::string fieldFile = useBackgroundMap ? sizeMapFile : medFileIn;
403 //~getTimeStepInfos(fieldFile, tmst, aRank);
404 //~setRankTimeStep((int) tmst, (int) aRank);
406 void MgAdapt::setNoTimeStep()
408 myUseLastTimeStep = false;
409 myUseChosenTimeStep = false;
410 myUseNoTimeStep = true;
411 //~int aRank = (int)MED_NO_IT;
412 //~int tmst = (int)MED_NO_DT ;
413 //~setRankTimeStep(tmst, aRank);
415 void MgAdapt::setChosenTimeStepRank()
417 myUseLastTimeStep = false;
418 myUseChosenTimeStep = true;
419 myUseNoTimeStep = false;
420 //~int aRank = (int)MED_NO_IT;
421 //~int tmst = (int)MED_NO_DT ;
422 //~setRankTimeStep(tmst, aRank);
424 void MgAdapt::setUseLocalMap(bool myLocal)
426 useLocalMap = myLocal;
429 bool MgAdapt::getUseLocalMap()
434 void MgAdapt::setUseBackgroundMap(bool bckg)
436 useBackgroundMap = bckg;
439 bool MgAdapt::getUseBackgroundMap()
441 return useBackgroundMap;
444 void MgAdapt::setUseConstantValue(bool cnst)
446 useConstantValue = cnst;
448 bool MgAdapt::getUseConstantValue()
450 return useConstantValue;
452 void MgAdapt::setLogFile(std::string myLogFile)
456 std::string MgAdapt::getLogFile()
460 void MgAdapt::setVerbosityLevel(int verboLevel)
462 verbosityLevel = verboLevel;
464 int MgAdapt::getVerbosityLevel()
466 return verbosityLevel;
468 void MgAdapt::setRemoveOnSuccess(bool rmons)
470 removeOnSuccess = rmons;
472 bool MgAdapt::getRemoveOnSuccess()
474 return removeOnSuccess;
476 void MgAdapt::setSizeMapFile(std::string mapFile)
478 if ( mapFile == "" || isFileExist(mapFile) )
480 sizeMapFile = mapFile;
484 THROW_SALOME_EXCEPTION("\nThe file "<< mapFile <<" does not exist.\n");
487 std::string MgAdapt::getSizeMapFile()
492 void MgAdapt::setMeshName(std::string name)
496 std::string MgAdapt::getMeshName()
500 void MgAdapt::setMeshNameOut(std::string name)
504 std::string MgAdapt::getMeshNameOut()
508 void MgAdapt::setFromMedFile(bool mybool)
510 fromMedFile = mybool;
512 bool MgAdapt::isFromMedFile()
516 void MgAdapt::setConstantValue(double cnst)
518 constantValue = cnst;
520 double MgAdapt::getConstantValue() const
522 return constantValue;
525 void MgAdapt::setWorkingDir(std::string dir)
529 std::string MgAdapt::getWorkingDir() const
533 void MgAdapt::setKeepWorkingFiles(bool mybool)
535 toKeepWorkingFiles = mybool;
537 bool MgAdapt::getKeepWorkingFiles()
539 return toKeepWorkingFiles;
541 void MgAdapt::setPrintLogInFile(bool print)
543 printLogInFile = print;
545 bool MgAdapt::getPrintLogInFile()
547 return printLogInFile;
550 bool MgAdapt::setAll()
553 setFromMedFile(data->fromMedFile);
555 checkDirPath(data->myFileInDir);
556 file = data->myFileInDir+data->myMeshFileIn;
558 setMeshName(data->myInMeshName);
559 setMeshNameOut(data->myOutMeshName);
560 checkDirPath(data->myFileOutDir);
561 std::string out = data->myFileOutDir+data->myMeshFileOut;
563 setPublish(data->myPublish);
564 setMeshOutMed(data->myMeshOutMed);
565 setUseLocalMap(data->myUseLocalMap);
566 setUseBackgroundMap(data->myUseBackgroundMap);
567 setUseConstantValue(data->myUseConstantValue);
570 if (useBackgroundMap)
572 checkDirPath(data->myFileSizeMapDir);
573 mapfile = data->myFileSizeMapDir+data->myMeshFileBackground;
574 setFieldName(data->myFieldName);
576 else if (useConstantValue)
578 setConstantValue(data->myConstantValue);
583 setConstantValue(0.0);
584 setFieldName(data->myFieldName);
587 setSizeMapFile(mapfile);
588 if (data->myUseNoTimeStep)
590 else if (data->myUseLastTimeStep)
591 setTimeStepRankLast();
594 setChosenTimeStepRank();
595 setRankTimeStep(data->myTimeStep, data->myRank);
597 /* Advanced options */
598 setWorkingDir(data->myWorkingDir);
599 checkDirPath(data->myWorkingDir);
600 setLogFile(data->myWorkingDir+defaultLogFile());
601 setVerbosityLevel(data->myVerboseLevel);
602 setRemoveOnSuccess(data->myRemoveLogOnSuccess);
603 setPrintLogInFile(data->myPrintLogInFile);
604 setKeepWorkingFiles(data->myKeepFiles);
609 void MgAdapt::checkDirPath(std::string& dirPath)
611 const char lastChar = *dirPath.rbegin();
613 if(lastChar != '\\') dirPath+='\\';
615 if(lastChar != '/') dirPath+='/';
618 //=============================================================================
619 void MgAdapt::setOptionValue(const std::string& optionName,
620 const std::string& optionValue)
622 // INFOS("setOptionValue");
623 // std::cout << "optionName: " << optionName << ", optionValue: " << optionValue << std::endl;
624 TOptionValues::iterator op_val = _option2value.find(optionName);
625 if (op_val == _option2value.end())
627 op_val = _customOption2value.find( optionName );
628 _customOption2value[ optionName ] = optionValue;
632 if (op_val->second != optionValue)
634 std::string lowerOptionValue = toLowerStr(optionValue);
635 const char* ptr = lowerOptionValue.c_str();
636 // strip white spaces
637 while (ptr[0] == ' ')
639 size_t i = strlen(ptr);
640 while (i != 0 && ptr[i - 1] == ' ')
644 std::string typeName;
649 else if (_charOptions.count(optionName))
651 // do not check strings
653 else if (_doubleOptions.count(optionName))
655 // check if value is double
659 else if (_boolOptions.count(optionName))
661 // check if value is bool
662 toBool(ptr, &typeOk);
667 // check if value is int
669 typeName = "integer";
671 if ( typeOk ) // check some specific values ?
676 std::string msg = "Advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
677 throw std::invalid_argument(msg);
679 std::string value( ptr, i );
680 // std::cout << "==> value: " << value << std::endl;
681 if ( _defaultOptionValues[ optionName ] == value ) value.clear();
683 // std::cout << "==> value: " << value << std::endl;
684 op_val->second = value;
687 //=============================================================================
688 //! Return option value. If isDefault provided, it can be a default value,
689 // then *isDefault == true. If isDefault is not provided, the value will be
690 // empty if it equals a default one.
691 std::string MgAdapt::getOptionValue(const std::string& optionName, bool* isDefault) const
693 // INFOS("getOptionValue");
694 // std::cout << "optionName: " << optionName << ", isDefault: " << isDefault << std::endl;
695 TOptionValues::const_iterator op_val = _option2value.find(optionName);
696 if (op_val == _option2value.end())
698 op_val = _customOption2value.find(optionName);
699 if (op_val == _customOption2value.end())
701 std::string msg = "Unknown MG-Adapt option: <" + optionName + ">";
702 throw std::invalid_argument(msg);
705 std::string val = op_val->second;
706 if ( isDefault ) *isDefault = ( val.empty() );
708 if ( val.empty() && isDefault )
710 op_val = _defaultOptionValues.find( optionName );
711 if (op_val != _defaultOptionValues.end()) val = op_val->second;
713 // std::cout << "==> val: " << val << std::endl;
717 //================================================================================
719 * \brief Converts a string to a real value
721 //================================================================================
723 double MgAdapt::toDbl(const std::string& str, bool* isOk )
725 if ( str.empty() ) throw std::invalid_argument("Empty value provided");
728 double val = strtod(&str[0], &endPtr);
729 bool ok = (&str[0] != endPtr);
731 if ( isOk ) *isOk = ok;
735 std::string msg = "Not a real value:'" + str + "'";
736 throw std::invalid_argument(msg);
740 //================================================================================
742 * \brief Converts a string to a lower
744 //================================================================================
745 std::string MgAdapt::toLowerStr(const std::string& str)
748 for ( size_t i = 0; i <= s.size(); ++i )
749 s[i] = (char) tolower( s[i] );
752 //================================================================================
754 * \brief Converts a string to a bool
756 //================================================================================
758 bool MgAdapt::toBool(const std::string& str, bool* isOk )
761 if ( isOk ) *isOk = true;
763 for ( size_t i = 0; i <= s.size(); ++i )
764 s[i] = (char) tolower( s[i] );
766 if ( s == "1" || s == "true" || s == "active" || s == "yes" )
769 if ( s == "0" || s == "false" || s == "inactive" || s == "no" )
776 std::string msg = "Not a Boolean value:'" + str + "'";
777 throw std::invalid_argument(msg);
781 //================================================================================
783 * \brief Converts a string to a integer value
785 //================================================================================
787 int MgAdapt::toInt(const std::string& str, bool* isOk )
789 if ( str.empty() ) throw std::invalid_argument("Empty value provided");
792 int val = (int)strtol( &str[0], &endPtr, 10);
793 bool ok = (&str[0] != endPtr);
795 if ( isOk ) *isOk = ok;
799 std::string msg = "Not an integer value:'" + str + "'";
800 throw std::invalid_argument(msg);
804 //=============================================================================
805 bool MgAdapt::hasOptionDefined( const std::string& optionName ) const
807 bool isDefault = false;
810 getOptionValue( optionName, &isDefault );
812 catch ( std::invalid_argument )
818 //================================================================================
820 * \brief Return command to run MG-Adapt mesher excluding file prefix (-f)
822 //================================================================================
824 std::string MgAdapt::getCommandToRun(MgAdapt* hyp)
826 return hyp ? hyp->getCommandToRun() : ToComment("error with hypothesis!");
829 int MgAdapt::compute(std::string& errStr)
831 std::string cmd = getCommandToRun();
832 // std::cout << cmd << std::endl;
835 execCmd( cmd.c_str(), err ); // run
839 errStr = ToComment("system(mg-adapt.exe ...) command failed with error: ") << strerror( errno );
841 else if ( !isFileExist( meshFormatOutputMesh ))
843 errStr = ToComment(" failed to find file ") << meshFormatOutputMesh
844 << " output from MG-Adapt run";
848 convertMeshFile(meshFormatOutputMesh, solFormatOutput);
854 void MgAdapt::execCmd( const char* cmd, int& err)
857 std::array <char, 128> buffer;
859 outFileStream fileStream;
862 fileStream.open(logFile);
863 buf = fileStream.rdbuf();
867 buf = std::cout.rdbuf();
869 std::ostream logStream(buf);
873 # if defined(UNICODE)
874 const wchar_t * aCmd = Kernel_Utils::utf8_decode(cmd);
875 SMESHUtils::ArrayDeleter<const wchar_t> deleter( aCmd );
876 std::unique_ptr <FILE, decltype(&_pclose)> pipe(_wpopen(aCmd, O_RDONLY), _pclose );
878 std::unique_ptr <FILE, decltype(&_pclose)> pipe(_popen(cmd, "r"), _pclose );
881 std::unique_ptr <FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose );
886 throw std::runtime_error("popen() failed!");
888 while(fgets(buffer.data(), buffer.size(), pipe.get()) !=nullptr )
890 logStream<<buffer.data() ;
895 * to delete tmp files .mesh, .sol and if needed
899 void MgAdapt::cleanUp()
903 if(toKeepWorkingFiles)
905 if(removeOnSuccess && printLogInFile)
906 tmpFilesToBeDeleted.push_back(logFile);
908 std::vector< std::string>::iterator it = tmpFilesToBeDeleted.begin();
909 for (; it!=tmpFilesToBeDeleted.end(); ++it)
911 errStr=removeFile(*it, notOk);
914 appendMsgToLogFile(errStr);
920 void MgAdapt::appendMsgToLogFile(std::string& msg)
922 std::ofstream logStream;
923 logStream.open(logFile, std::ofstream::out | std::ofstream::app);
927 //================================================================================
929 * \brief Return command to run MG-Tetra mesher excluding file prefix (-f)
931 //================================================================================
933 std::string MgAdapt::getCommandToRun()
936 || return system command with args and options
940 std::string cmd = getExeName();
941 std::string meshIn(""), sizeMapIn(""), solFileIn("");
942 updateTimeStepRank();
943 convertMedFile(meshIn, solFileIn, sizeMapIn);
944 if (!isFileExist(meshIn) || !isFileExist(solFileIn))
946 errStr = ToComment(" failed to find .mesh or .sol file from converter ")<< strerror( errno );
949 tmpFilesToBeDeleted.push_back(meshIn);
950 tmpFilesToBeDeleted.push_back(solFileIn);
951 if(useBackgroundMap && !isFileExist(sizeMapIn))
953 errStr = ToComment(" failed to find .mesh size map file from converter ")<< strerror( errno );
957 cmd+= " --in "+ meshIn;
958 meshFormatOutputMesh = getFileName()+".mesh";
959 tmpFilesToBeDeleted.push_back(meshFormatOutputMesh);
961 cmd+= " --out "+ meshFormatOutputMesh;
962 if (useLocalMap || useConstantValue) cmd+= " --sizemap "+ solFileIn;
963 else // (useBackgroundMap)
965 cmd+= " --background_mesh "+ sizeMapIn ;
966 cmd+= " --background_sizemap "+ solFileIn;
967 tmpFilesToBeDeleted.push_back(sizeMapIn);
971 //~// constant value TODO
973 // Check coherence between mesh dimension and option fo adaptation
974 checkDimensionOptionAdaptation();
976 // sizemap file is written only if level is higher than 3
977 if ( verbosityLevel > 3)
979 std::string solFileOut = getFileName()+".sol";
980 cmd+= " --write_sizemap "+ solFileOut;
981 solFormatOutput.push_back(solFileOut);
982 tmpFilesToBeDeleted.push_back(solFileOut);
985 std::string option, value;
987 const TOptionValues* options[] = { &_option2value, &_customOption2value };
988 for ( int iOp = 0; iOp < 2; ++iOp )
990 TOptionValues::const_iterator o2v = options[iOp]->begin();
991 for ( ; o2v != options[iOp]->end(); ++o2v )
994 value = getOptionValue( option, &isDefault );
998 if ( value.empty() )//value == NoValue() )
1000 if ( _defaultOptionValues.count( option ))
1001 continue; // non-custom option with no value
1004 if ( strncmp( "no", option.c_str(), 2 ) == 0 ) // options w/o values: --no_*
1006 if ( !value.empty() && toBool( value ) == false )
1010 if ( option[0] != '-' )
1014 // std::cout << "--- option: '" << option << ", value: '" << value <<"'"<< std::endl;
1015 cmd += option + " " + value;
1020 if (verbosityLevel != defaultVerboseLevel())
1022 cmd+= " --verbose "+ ToComment(verbosityLevel);
1026 smIdType nbVertex, nbEdge, nbFace, nbVol;
1027 DriverGMF_Read gmfReader;
1028 gmfReader.SetFile( meshIn );
1029 gmfReader.GetMeshInfo( nbVertex, nbEdge, nbFace, nbVol );
1031 std::string errorTxt;
1032 std::string key = SMESHUtils_MGLicenseKeyGen::GetKey( meshIn,
1033 FromSmIdType<int>( nbVertex ),
1034 FromSmIdType<int>( nbEdge ),
1035 FromSmIdType<int>( nbFace ),
1036 FromSmIdType<int>( nbVol ),
1039 return ToComment( "Problem with library SalomeMeshGemsKeyGenerator: " + errorTxt );
1042 cmd += " --key " + key;
1049 if (SALOME::VerbosityActivated())
1051 std::cout << "--- cmd :"<< std::endl;
1052 std::cout << cmd << std::endl;
1058 //=======================================================================
1059 //function : defaultMaximumMemory
1060 //=======================================================================
1063 #include <windows.h>
1064 #elif !defined(__APPLE__)
1065 #include <sys/sysinfo.h>
1068 double MgAdapt::defaultMaximumMemory()
1071 // See http://msdn.microsoft.com/en-us/library/aa366589.aspx
1072 MEMORYSTATUSEX statex;
1073 statex.dwLength = sizeof (statex);
1074 long err = GlobalMemoryStatusEx (&statex);
1077 double totMB = (double)statex.ullAvailPhys / 1024. / 1024.;
1078 return (double)( 0.7 * totMB );
1080 #elif !defined(__APPLE__)
1082 long err = sysinfo( &si );
1085 long ramMB = si.totalram * si.mem_unit / 1024 / 1024;
1086 return ( 0.7 * double( ramMB ));
1092 //=======================================================================
1093 //function : defaultWorkingDirectory
1094 //=======================================================================
1096 std::string MgAdapt::defaultWorkingDirectory()
1098 std::string aTmpDir;
1100 char *Tmp_dir = getenv("SALOME_TMP_DIR");
1106 if ( ! isFileExist( aTmpDir ))
1116 //================================================================================
1118 * \brief Return a unique file name
1120 //================================================================================
1122 std::string MgAdapt::getFileName() const
1124 std::string aTmpDir = workingDir;
1125 const char lastChar = *aTmpDir.rbegin();
1127 if(lastChar != '\\') aTmpDir+='\\';
1129 if(lastChar != '/') aTmpDir+='/';
1132 SMESH_Comment aGenericName( aTmpDir );
1133 aGenericName << "MgAdapt_";
1135 aGenericName << getpid();
1137 aGenericName << _getpid();
1139 aGenericName << "_";
1140 aGenericName << std::chrono::system_clock::now().time_since_epoch().count();
1142 return aGenericName;
1144 //=======================================================================
1145 //function : defaultLogFile
1146 //=======================================================================
1148 std::string MgAdapt::defaultLogFile()
1150 std::string alogFile("MG_ADAPT.log");
1153 //=======================================================================
1154 //function : defaultUseConstantValue
1155 //=======================================================================
1157 bool MgAdapt::defaultUseConstantValue()
1161 //=======================================================================
1162 //function : defaultUseNoTimeStep
1163 //=======================================================================
1165 bool MgAdapt::defaultUseNoTimeStep()
1169 //=======================================================================
1170 //function : defaultRemoveLogOnSuccess
1171 //=======================================================================
1173 bool MgAdapt::defaultRemoveLogOnSuccess()
1177 //=======================================================================
1178 //function : defaultPrintLogInFile
1179 //=======================================================================
1181 bool MgAdapt::defaultPrintLogInFile()
1185 //=======================================================================
1186 //function : defaultUseChosenTimeStep
1187 //=======================================================================
1189 bool MgAdapt::defaultUseChosenTimeStep()
1193 //=======================================================================
1194 //function : UseLastTimeStep
1195 //=======================================================================
1197 bool MgAdapt::defaultUseLastTimeStep()
1201 //=======================================================================
1202 //function : defaultUseBackgroundMap
1203 //=======================================================================
1205 bool MgAdapt::defaultUseBackgroundMap()
1209 //=======================================================================
1210 //function : defaultKeepFiles
1211 //=======================================================================
1213 bool MgAdapt::defaultKeepFiles()
1217 //=======================================================================
1218 //function : defaultUseLocalMap
1219 //=======================================================================
1221 bool MgAdapt::defaultUseLocalMap()
1225 //=======================================================================
1226 //function : defaultPublish
1227 //=======================================================================
1229 bool MgAdapt::defaultPublish()
1233 //=======================================================================
1234 //function : defaultMeshOutMed
1235 //=======================================================================
1237 bool MgAdapt::defaultMeshOutMed()
1241 //=======================================================================
1242 //function : defaultFromMedFile
1243 //=======================================================================
1245 bool MgAdapt::defaultFromMedFile()
1249 //=======================================================================
1250 //function : defaultVerboseLevel
1251 //=======================================================================
1253 int MgAdapt::defaultVerboseLevel()
1257 std::string MgAdapt::getExeName()
1259 return "mg-adapt.exe";
1261 void MgAdapt::copyMgAdaptHypothesisData( const MgAdaptHypothesisData* from)
1263 data->myFileInDir = from->myFileInDir;
1264 data->myMeshFileIn = from->myMeshFileIn;
1265 data->myMeshFileBackground = from->myMeshFileBackground;
1266 data->myOutMeshName = from->myOutMeshName;
1267 data->myMeshFileOut = from->myMeshFileOut;
1268 data->myFileOutDir = from->myFileOutDir;
1269 data->myFileSizeMapDir = from->myFileSizeMapDir;
1270 data->myFieldName = from->myFieldName;
1271 data->fromMedFile = from->fromMedFile;
1272 data->myPublish = from->myPublish;
1273 data->myMeshOutMed = from->myMeshOutMed;
1274 data->myUseLocalMap = from->myUseLocalMap;
1275 data->myUseBackgroundMap = from->myUseBackgroundMap;
1276 data->myUseConstantValue = from->myUseConstantValue;
1277 data->myConstantValue = from->myConstantValue;
1278 data->myTimeStep = from->myTimeStep;
1279 data->myRank = from->myRank;
1280 data->myUseNoTimeStep = from->myUseNoTimeStep;
1281 data->myUseLastTimeStep = from->myUseLastTimeStep;
1282 data->myUseChosenTimeStep = from->myUseChosenTimeStep;
1283 data->myWorkingDir = from->myWorkingDir;
1284 data->myLogFile = from->myLogFile;
1285 data->myPrintLogInFile = from->myPrintLogInFile;
1286 data->myKeepFiles = from->myKeepFiles;
1287 data->myRemoveLogOnSuccess = from->myRemoveLogOnSuccess;
1288 data->myVerboseLevel = from->myVerboseLevel;
1291 std::vector<std::string> MgAdapt::getListFieldsNames(std::string fileIn)
1293 MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(fileIn);
1294 std::vector<std::string> listFieldsNames(mfd->getFields()->getFieldsNames());
1295 return listFieldsNames ;
1298 void MgAdapt::checkDimensionOptionAdaptation()
1300 // Quand le maillage est 3D, tout est possible
1301 // Quand le maillage est 2D, il faut 'surface' sauf si carte de fonds 3D
1302 MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(medFileIn);
1303 int meshdim = mfd->getMeshes()->getMeshAtPos(0)->getMeshDimension() ;
1304 // std::cout << "meshdim = " << meshdim << std::endl;
1308 std::string optionName = "adaptation";
1309 std::string optionValue = getOptionValue(optionName);
1310 // std::cout << "optionValue = '" << optionValue <<"'"<< std::endl;
1311 bool a_tester = false ;
1312 // carte locale ou constante : impératif d'avoir "surface"
1313 if ( useLocalMap || useConstantValue) a_tester = true ;
1314 // carte de fond : impératif d'avoir "surface" si le fonds est aussi 2D
1317 MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfdbg = MEDCoupling::MEDFileData::New(sizeMapFile);
1318 int meshdimbg = mfdbg->getMeshes()->getMeshAtPos(0)->getMeshDimension() ;
1319 // std::cout << "meshdimbg = " << meshdimbg << std::endl;
1320 if ( meshdimbg == 2 ) a_tester = true ;
1324 if ( optionValue == "" ) setOptionValue (optionName, "surface");
1327 if ( optionValue != "surface" )
1329 THROW_SALOME_EXCEPTION("Mesh dimension is 2; the option should be 'surface'"
1330 " instead of '" << optionValue << "'.");
1337 void MgAdapt::checkFieldName(std::string fileIn)
1340 std::vector<std::string> listFieldsNames = getListFieldsNames(fileIn);
1341 std::size_t jaux(listFieldsNames.size());
1342 for(std::size_t j=0;j<jaux;j++)
1344 if ( fieldName == listFieldsNames[j] )
1352 std::cout << "Available field names:" << std::endl;
1353 for(std::size_t j=0;j<jaux;j++)
1354 { std::cout << listFieldsNames[j] << std::endl;}
1355 THROW_SALOME_EXCEPTION( "Field " << fieldName << " is not found.");
1359 void MgAdapt::checkTimeStepRank(std::string fileIn)
1362 MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(fileIn);
1363 MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeFieldMultiTS> fts( mfd->getFields()->getFieldWithName(fieldName) );
1364 std::vector<double> timevalue;
1365 std::vector< std::pair<int,int> > timesteprank = fts->getTimeSteps(timevalue);
1366 std::size_t jaux(timesteprank.size());
1367 for(std::size_t j=0;j<jaux;j++)
1369 if ( ( timeStep == timesteprank[j].first ) & ( rank == timesteprank[j].second ) )
1377 std::cout << "Available (Time step, Rank):" << std::endl;
1378 for(std::size_t j=0;j<jaux;j++)
1379 { std::cout << "(Time step = " << timesteprank[j].first << ", Rank = " << timesteprank[j].second << ")" << std::endl;}
1380 THROW_SALOME_EXCEPTION("(Time step = " << timeStep << ", Rank = " << rank << ") is not found.");
1384 void MgAdapt::convertMedFile(std::string& meshFormatMeshFileName, std::string& solFormatFieldFileName, std::string& meshFormatsizeMapFile)
1386 std::vector<std::string> fieldFileNames;
1387 MEDCoupling::MeshFormatWriter writer;
1388 MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(medFileIn);
1389 MEDCoupling::MEDFileMeshes* meshes = mfd->getMeshes();
1390 MEDCoupling::MEDFileMesh* fileMesh = meshes->getMeshAtPos(0); // ok only one mesh in file!
1391 if (meshNameOut =="")
1392 meshNameOut = fileMesh->getName();
1393 storeGroupsAndFams(fileMesh);
1395 MEDCoupling::MCAuto<MEDCoupling::MEDFileFields> fields = MEDCoupling::MEDFileFields::New();
1396 solFormatFieldFileName = getFileName();
1397 solFormatFieldFileName+=".sol";
1398 fieldFileNames.push_back(solFormatFieldFileName);
1400 if (useBackgroundMap)
1402 checkFieldName(sizeMapFile) ;
1403 checkTimeStepRank(sizeMapFile) ;
1404 meshFormatsizeMapFile = getFileName();
1405 meshFormatsizeMapFile += ".mesh";
1406 buildBackGroundMeshAndSolFiles(fieldFileNames, meshFormatsizeMapFile);
1408 else if(useLocalMap)
1410 checkFieldName(medFileIn) ;
1411 checkTimeStepRank(medFileIn) ;
1412 MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeFieldMultiTS> fts( mfd->getFields()->getFieldWithName(fieldName) );
1413 MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeField1TS> f = fts->getTimeStep(timeStep, rank);
1414 MEDCoupling::MCAuto<MEDCoupling::MEDFileFieldMultiTS> tmFts = MEDCoupling::DynamicCast<MEDCoupling::MEDFileAnyTypeFieldMultiTS,MEDCoupling::MEDFileFieldMultiTS>(fts);
1416 // if not able to cast to double field, try float field
1419 MEDCoupling::MCAuto<MEDCoupling::MEDFileFloatFieldMultiTS> tmFtsFloat = MEDCoupling::DynamicCast<MEDCoupling::MEDFileAnyTypeFieldMultiTS,MEDCoupling::MEDFileFloatFieldMultiTS>(fts);
1421 THROW_SALOME_EXCEPTION("\nUnexpected field type.\n");
1422 // convert float field to double
1423 tmFts = tmFtsFloat->convertToDouble();
1426 fields->pushField(tmFts);
1428 writer.setFieldFileNames( fieldFileNames);
1432 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingMesh> mesh = fileMesh->getMeshAtLevel(1); // nodes mesh
1433 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingUMesh> umesh = mesh->buildUnstructured(); // nodes mesh
1434 int dim = umesh->getSpaceDimension();
1435 int version = sizeof(double) < 8 ? 1 : 2;
1436 mcIdType nbNodes = umesh->getNumberOfNodes();
1437 buildConstantSizeMapSolFile(solFormatFieldFileName, dim, version, nbNodes);
1440 mfd->setFields( fields );
1441 meshFormatMeshFileName = getFileName();
1442 meshFormatMeshFileName+=".mesh";
1443 writer.setMeshFileName(meshFormatMeshFileName);
1444 writer.setMEDFileDS( mfd);
1449 void MgAdapt::convertMeshFile(std::string& meshFormatIn, std::vector< std::string>& solFieldFileNames) const
1451 MEDCoupling::MeshFormatReader reader(meshFormatIn, solFieldFileNames);
1453 MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = reader.loadInMedFileDS();
1455 MEDCoupling::MEDFileMeshes* meshes = mfd->getMeshes();
1456 MEDCoupling::MEDFileMesh* fileMesh = meshes->getMeshAtPos(0); // ok only one mesh in file!
1457 fileMesh->setName(meshNameOut);
1458 restoreGroupsAndFams(fileMesh);
1459 mfd->write(medFileOut, 2);
1462 void MgAdapt::storeGroupsAndFams(MEDCoupling::MEDFileMesh* fileMesh)
1464 storefams(fileMesh);
1465 storeGroups(fileMesh);
1468 void MgAdapt::restoreGroupsAndFams(MEDCoupling::MEDFileMesh* fileMesh) const
1470 restorefams(fileMesh);
1471 restoreGroups(fileMesh);
1473 void MgAdapt::storeGroups(MEDCoupling::MEDFileMesh* fileMesh)
1475 std::map<std::string, std::vector<std::string> > grpFams = fileMesh->getGroupInfo();
1476 std::map<std::string, std::vector<std::string> >::iterator g2ff = grpFams.begin();
1478 for ( ; g2ff != grpFams.end(); ++g2ff )
1480 std::string groupName = g2ff->first;
1481 std::vector<std::string> famNames = g2ff->second;
1483 if ( famNames.empty() ) continue;
1484 std::vector< int> famListId;
1485 for ( size_t i = 0; i < famNames.size(); ++i )
1487 famListId.push_back( FromIdType<int>( fileMesh->getFamilyId( famNames[i].c_str() )));
1489 group grp(groupName, famListId, famNames);
1490 groupVec.push_back(grp);
1494 void MgAdapt::storefams(MEDCoupling::MEDFileMesh* fileMesh)
1496 std::map<std::string, mcIdType> grpFams = fileMesh->getFamilyInfo();
1497 std::map<std::string, mcIdType >::iterator f = grpFams.begin();
1499 for ( ; f != grpFams.end(); ++f )
1501 if(!f->second) continue; // FAMILLE_ZERO
1502 family fs(f->first, FromIdType<int>( f->second ));
1503 famVec.push_back(fs);
1508 void MgAdapt::restorefams(MEDCoupling::MEDFileMesh* fileMesh) const
1510 std::vector<family>::const_iterator fIt = famVec.begin();
1512 for (; fIt!=famVec.end(); ++fIt)
1516 std::string givenFamNameFromMeshGemConverter = fileMesh->getFamilyNameGivenId( std::abs(fIt->_famId) );
1517 fileMesh->changeFamilyId(std::abs(fIt->_famId), fIt->_famId);
1518 fileMesh->changeFamilyName(givenFamNameFromMeshGemConverter, fIt->_famName);
1520 catch (const std::exception& e)
1522 std::cerr<<e.what();
1527 void MgAdapt::restoreGroups(MEDCoupling::MEDFileMesh* fileMesh) const
1529 std::map<std::string, std::vector<std::string> > info;
1530 std::vector <group>::const_iterator grpFams = groupVec.begin();
1532 for (; grpFams!=groupVec.end(); ++grpFams)
1534 info.insert(std::pair <std::string, std::vector<std::string> > (grpFams->_name, grpFams->_famNames) );
1537 fileMesh->setGroupInfo(info);
1540 void MgAdapt::buildConstantSizeMapSolFile(const std::string& solFormatFieldFileName, const int dim, const int version, const size_t nbNodes) const
1542 MeshFormat::Localizer loc;
1543 MeshFormat::MeshFormatParser writer;
1544 int fileId = writer.GmfOpenMesh( solFormatFieldFileName.c_str(), GmfWrite, version, dim);
1545 int typTab[] = {GmfSca};
1546 writer.GmfSetKwd(fileId, MeshFormat::GmfSolAtVertices, (int)nbNodes, 1, typTab);
1547 for (size_t i = 0; i<nbNodes; i++)
1549 double valTab[1] = {constantValue};
1550 writer.GmfSetLin( fileId, MeshFormat::GmfSolAtVertices, valTab);
1552 writer.GmfCloseMesh(fileId);
1555 void MgAdapt::buildBackGroundMeshAndSolFiles(const std::vector<std::string>& fieldFileNames, const std::string& meshFormatsizeMapFile) const
1557 MEDCoupling::MCAuto<MEDCoupling::MEDFileData> tmpMfd = MEDCoupling::MEDFileData::New(sizeMapFile);
1558 MEDCoupling::MEDFileFields* tmpFields = tmpMfd->getFields();
1559 MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeFieldMultiTS> fts( tmpFields->getFieldWithName(fieldName) );
1560 MEDCoupling::MCAuto<MEDCoupling::MEDFileFieldMultiTS> fts1 = MEDCoupling::DynamicCastSafe<MEDCoupling::MEDFileAnyTypeFieldMultiTS,MEDCoupling::MEDFileFieldMultiTS>(fts);
1561 MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeField1TS> f = fts1->getTimeStep(timeStep, rank);
1562 MEDCoupling::MCAuto<MEDCoupling::MEDFileFieldMultiTS> tmFts = MEDCoupling::MEDFileFieldMultiTS::New();
1563 tmFts->pushBackTimeStep(f);
1565 MEDCoupling::MCAuto<MEDCoupling::MEDFileFields> tmp_fields = MEDCoupling::MEDFileFields::New();
1566 tmp_fields->pushField(tmFts);
1568 tmpMfd->setFields( tmp_fields );
1569 MEDCoupling::MeshFormatWriter tmpWriter;
1570 tmpWriter.setMeshFileName(meshFormatsizeMapFile);
1571 tmpWriter.setFieldFileNames( fieldFileNames);
1572 tmpWriter.setMEDFileDS(tmpMfd);
1576 MgAdapt::Status MgAdapt::addMessage(const std::string& msg,
1577 const bool isFatal/*=false*/)
1580 _errorMessages.clear(); // warnings are useless if a fatal error encounters
1582 _errorMessages.push_back( msg );
1585 if (SALOME::VerbosityActivated())
1586 std::cout << msg << std::endl;
1588 return ( _status = isFatal ? MgAdapt::DRS_FAIL : MgAdapt::DRS_WARN_SKIP_ELEM );
1591 void MgAdapt::updateTimeStepRank()
1596 if (myUseNoTimeStep)
1600 setRankTimeStep((int)tmst, (int)arank);
1602 else if (myUseLastTimeStep)
1604 std::string fieldFile = useBackgroundMap ? sizeMapFile : medFileIn;
1605 getTimeStepInfos(fieldFile, tmst, arank, fieldName);
1606 setRankTimeStep((int)tmst, (int)arank);