// Copyright (C) 2020-2023 CEA, EDF // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include "MG_ADAPT.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include "SMESH_TypeDefs.hxx" #ifndef WIN32 #include // getpid() #else #include #endif #include #include #include // unique_ptr typedef SMESH_Comment ToComment; using namespace MG_ADAPT; static std::string removeFile(std::string fileName, int& notOk) { std::string errStr; notOk = std::remove(fileName.c_str()); if (notOk) errStr = ToComment("\n error while removing file : ") << fileName; else errStr = ToComment("\n file : ") << fileName << " succesfully deleted! \n "; return errStr; } std::string MG_ADAPT::remove_extension(const std::string& filename) { size_t lastdot = filename.find_last_of("."); if (lastdot == std::string::npos) return filename; return filename.substr(0, lastdot); } namespace { bool isFileExist( const std::string& fName ) { return SMESH_File( fName ).exists(); } // ======================================================================= med_idt openMedFile(const std::string aFile) // ======================================================================= // renvoie le medId associe au fichier Med apres ouverture { med_idt medIdt = MEDfileOpen(aFile.c_str(),MED_ACC_RDONLY); if (medIdt <0) { THROW_SALOME_EXCEPTION("\nThe med file " << aFile << " cannot be opened.\n"); } return medIdt; } // ======================================================================= void getTimeStepInfos(std::string aFile, med_int& numdt, med_int& numit, std::string fieldName) // ======================================================================= { // Il faut voir si plusieurs maillages herr_t erreur = 0 ; med_idt medIdt ; // Ouverture du fichier //~SCRUTE(aFile.toStdString()); medIdt = openMedFile(aFile); if ( medIdt < 0 ) return ; // Lecture du nombre de champs med_int ncha = MEDnField(medIdt) ; if (ncha < 1 ) { //~addMessage( ToComment(" error: there is no field in ") << aFile, /*fatal=*/true ); return; } // Lecture des caracteristiques du champs // Lecture du type du champ, des noms des composantes et du nom de l'unite char nomcha [MED_NAME_SIZE+1]; strcpy(nomcha, fieldName.c_str()); // Lecture du nombre de composantes med_int ncomp = MEDfieldnComponentByName(medIdt, nomcha); char meshname[MED_NAME_SIZE+1]; char * comp = (char*) malloc(ncomp*MED_SNAME_SIZE+1); char * unit = (char*) malloc(ncomp*MED_SNAME_SIZE+1); char dtunit[MED_SNAME_SIZE+1]; med_bool local; med_field_type typcha; med_int nbofcstp; erreur = MEDfieldInfoByName (medIdt, nomcha, meshname,&local,&typcha,comp,unit,dtunit, &nbofcstp); free(comp); free(unit); if ( erreur < 0 ) { //~addMessage( ToComment(" error: error while reading field ") << nomcha << " in file " << aFile , /*fatal=*/true ); return; } med_float dt; med_int tmp_numdt, tmp_numit; //~med_int step = data->myUseLastTimeStep ? nbofcstp : data->myTimeStep+1; //~myPrint("step ", step); erreur = MEDfieldComputingStepInfo ( medIdt, nomcha, 1, &numdt, &numit, &dt ); for( int step = 1; step <= nbofcstp; step++ ) { erreur = MEDfieldComputingStepInfo ( medIdt, nomcha, step, &tmp_numdt, &tmp_numit, &dt ); if(tmp_numdt > numdt) { numdt = tmp_numdt; numit = tmp_numit; } } if ( erreur < 0 ) { //~addMessage( ToComment(" error: error while reading field ") << nomcha << "step (numdt, numit) = " <<"("<< numdt<< ", " //numit<< ")" <<" in file " << aFile , /*fatal=*/true ); return; } // Fermeture du fichier if ( medIdt > 0 ) MEDfileClose(medIdt); } struct GET_DEFAULT // struct used to get default value from GetOptionValue() { bool isDefault; operator bool* () { return &isDefault; } }; class outFileStream : public std::ofstream{ public: ~outFileStream(){close();} //to close file at dtor }; } // anonymous namespace //---------------------------------------------------------------------------------------- MgAdapt::MgAdapt() { data = new MgAdaptHypothesisData(); data->myInMeshName = ""; data->fromMedFile = defaultFromMedFile(); data->myFileInDir = defaultWorkingDirectory(); data->myMeshFileIn = ""; data->myFileOutDir = defaultWorkingDirectory(); data->myOutMeshName = ""; data->myMeshFileOut = ""; data->myMeshOutMed = defaultMeshOutMed(); data->myPublish = defaultPublish(); data->myUseLocalMap = defaultUseLocalMap(); data->myUseBackgroundMap = defaultUseBackgroundMap(); data->myFileSizeMapDir = defaultWorkingDirectory(); data->myMeshFileBackground = ""; data->myUseConstantValue = defaultUseConstantValue(); data->myConstantValue = 0.0; data->myFieldName = ""; data->myUseNoTimeStep = defaultUseNoTimeStep(); data->myUseLastTimeStep = defaultUseLastTimeStep(); data->myUseChosenTimeStep = defaultUseChosenTimeStep(); data->myTimeStep = -2; data->myRank = -2; data->myWorkingDir = defaultWorkingDirectory(); data->myLogFile = defaultLogFile(); data->myVerboseLevel = defaultVerboseLevel(); data->myPrintLogInFile = defaultPrintLogInFile(); data->myKeepFiles = defaultKeepFiles(); data->myRemoveLogOnSuccess = defaultRemoveLogOnSuccess(); buildModel(); setAll(); } MgAdapt::MgAdapt(MgAdaptHypothesisData* myData) { data = new MgAdaptHypothesisData(); setData(myData); buildModel(); } MgAdapt::MgAdapt( const MgAdapt& copy) { data = new MgAdaptHypothesisData(); MgAdaptHypothesisData *copyData = copy.getData(); copyMgAdaptHypothesisData(copyData); setAll(); this->_option2value = copy._option2value; this->_customOption2value = copy._customOption2value; this->_defaultOptionValues = copy._defaultOptionValues; this->_doubleOptions = copy._doubleOptions; this->_charOptions = copy._charOptions; this->_boolOptions = copy._boolOptions; } //----------------------------------------------------------------------------------------- MgAdapt::~MgAdapt() { delete data; } void MgAdapt::buildModel() { const char* boolOptionNames[] = { "compute_ridges", // yes "" // mark of end }; // const char* intOptionNames[] = { "max_number_of_errors_printed", // 1 // "max_number_of_threads", // 4 // "" // mark of end // }; const char* doubleOptionNames[] = { "max_memory", // 0 "" // mark of end }; const char* charOptionNames[] = { "components", // "yes" "adaptation", // both "" // mark of end }; int i = 0; while (boolOptionNames[i][0]) { _boolOptions.insert( boolOptionNames[i] ); _option2value[boolOptionNames[i++]].clear(); } // i = 0; // while (intOptionNames[i][0]) // _option2value[intOptionNames[i++]].clear(); i = 0; while (doubleOptionNames[i][0]) { _doubleOptions.insert(doubleOptionNames[i]); _option2value[doubleOptionNames[i++]].clear(); } i = 0; while (charOptionNames[i][0]) { _charOptions.insert(charOptionNames[i]); _option2value[charOptionNames[i++]].clear(); } // default values to be used while MG-Adapt _defaultOptionValues["adaptation" ] = "both"; _defaultOptionValues["components" ] = "outside components"; _defaultOptionValues["compute_ridges"] = "yes"; _defaultOptionValues["max_memory" ] = ToComment(defaultMaximumMemory()); } //============================================================================= TOptionValues MgAdapt::getOptionValues() const { TOptionValues vals; TOptionValues::const_iterator op_val = _option2value.begin(); for ( ; op_val != _option2value.end(); ++op_val ) vals.insert( make_pair( op_val->first, getOptionValue( op_val->first, GET_DEFAULT() ))); return vals; } std::vector MgAdapt::getOptionValuesStrVec() const { std::vector vals; TOptionValues::const_iterator op_val = _option2value.begin(); for ( ; op_val != _option2value.end(); ++op_val ) vals.push_back(op_val->first+":"+getOptionValue( op_val->first, GET_DEFAULT() )); return vals; } std::vector MgAdapt::getCustomOptionValuesStrVec() const { std::vector vals; TOptionValues::const_iterator op_val; for ( op_val = _customOption2value.begin(); op_val != _customOption2value.end(); ++op_val ) { vals.push_back(op_val->first+":"+getOptionValue( op_val->first, GET_DEFAULT() )); } return vals; } const TOptionValues& MgAdapt::getCustomOptionValues() const { return _customOption2value; } void MgAdapt::setData(MgAdaptHypothesisData* myData) { copyMgAdaptHypothesisData(myData); setAll(); } MgAdaptHypothesisData* MgAdapt::getData() const { return data; } void MgAdapt::setMedFileIn(std::string fileName) { if ( isFileExist( fileName )) { medFileIn = fileName; if (medFileOut == "") // default MED file Out medFileOut = remove_extension( fileName )+ ".adapt.med"; } else { THROW_SALOME_EXCEPTION("\nThe file "<< fileName <<" does not exist.\n"); } } std::string MgAdapt::getMedFileIn() { return medFileIn; } void MgAdapt::setMedFileOut(std::string fileOut) { medFileOut = fileOut; } std::string MgAdapt::getMedFileOut() { return medFileOut; } void MgAdapt::setMeshOutMed(bool mybool) { meshOutMed = mybool; } bool MgAdapt::getMeshOutMed() { return meshOutMed; } void MgAdapt::setPublish(bool mybool) { publish = mybool; } bool MgAdapt::getPublish() { return publish; } void MgAdapt::setFieldName(std::string myFieldName) { fieldName = myFieldName; } std::string MgAdapt::getFieldName() { return fieldName; } void MgAdapt::setTimeStep(int time) { timeStep = time; } int MgAdapt::getTimeStep() const { return timeStep; } void MgAdapt::setRankTimeStep(int time, int myRank) { timeStep = time; rank = myRank; } int MgAdapt::getRank() { return rank; } void MgAdapt::setTimeStepRankLast() { myUseLastTimeStep = true; myUseChosenTimeStep = false; myUseNoTimeStep = false; //~med_int aRank, tmst; //~std::string fieldFile = useBackgroundMap ? sizeMapFile : medFileIn; //~getTimeStepInfos(fieldFile, tmst, aRank); //~setRankTimeStep((int) tmst, (int) aRank); } void MgAdapt::setNoTimeStep() { myUseLastTimeStep = false; myUseChosenTimeStep = false; myUseNoTimeStep = true; //~int aRank = (int)MED_NO_IT; //~int tmst = (int)MED_NO_DT ; //~setRankTimeStep(tmst, aRank); } void MgAdapt::setChosenTimeStepRank() { myUseLastTimeStep = false; myUseChosenTimeStep = true; myUseNoTimeStep = false; //~int aRank = (int)MED_NO_IT; //~int tmst = (int)MED_NO_DT ; //~setRankTimeStep(tmst, aRank); } void MgAdapt::setUseLocalMap(bool myLocal) { useLocalMap = myLocal; } bool MgAdapt::getUseLocalMap() { return useLocalMap; } void MgAdapt::setUseBackgroundMap(bool bckg) { useBackgroundMap = bckg; } bool MgAdapt::getUseBackgroundMap() { return useBackgroundMap; } void MgAdapt::setUseConstantValue(bool cnst) { useConstantValue = cnst; } bool MgAdapt::getUseConstantValue() { return useConstantValue; } void MgAdapt::setLogFile(std::string myLogFile) { logFile = myLogFile; } std::string MgAdapt::getLogFile() { return logFile; } void MgAdapt::setVerbosityLevel(int verboLevel) { verbosityLevel = verboLevel; } int MgAdapt::getVerbosityLevel() { return verbosityLevel; } void MgAdapt::setRemoveOnSuccess(bool rmons) { removeOnSuccess = rmons; } bool MgAdapt::getRemoveOnSuccess() { return removeOnSuccess; } void MgAdapt::setSizeMapFile(std::string mapFile) { if ( mapFile == "" || isFileExist(mapFile) ) { sizeMapFile = mapFile; } else { THROW_SALOME_EXCEPTION("\nThe file "<< mapFile <<" does not exist.\n"); } } std::string MgAdapt::getSizeMapFile() { return sizeMapFile; } void MgAdapt::setMeshName(std::string name) { meshName = name; } std::string MgAdapt::getMeshName() { return meshName; } void MgAdapt::setMeshNameOut(std::string name) { meshNameOut = name; } std::string MgAdapt::getMeshNameOut() { return meshNameOut; } void MgAdapt::setFromMedFile(bool mybool) { fromMedFile = mybool; } bool MgAdapt::isFromMedFile() { return fromMedFile; } void MgAdapt::setConstantValue(double cnst) { constantValue = cnst; } double MgAdapt::getConstantValue() const { return constantValue; } void MgAdapt::setWorkingDir(std::string dir) { workingDir = dir; } std::string MgAdapt::getWorkingDir() const { return workingDir; } void MgAdapt::setKeepWorkingFiles(bool mybool) { toKeepWorkingFiles = mybool; } bool MgAdapt::getKeepWorkingFiles() { return toKeepWorkingFiles; } void MgAdapt::setPrintLogInFile(bool print) { printLogInFile = print; } bool MgAdapt::getPrintLogInFile() { return printLogInFile; } bool MgAdapt::setAll() { setFromMedFile(data->fromMedFile); std::string file; checkDirPath(data->myFileInDir); file = data->myFileInDir+data->myMeshFileIn; setMedFileIn(file); setMeshName(data->myInMeshName); setMeshNameOut(data->myOutMeshName); checkDirPath(data->myFileOutDir); std::string out = data->myFileOutDir+data->myMeshFileOut; setMedFileOut(out); setPublish(data->myPublish); setMeshOutMed(data->myMeshOutMed); setUseLocalMap(data->myUseLocalMap); setUseBackgroundMap(data->myUseBackgroundMap); setUseConstantValue(data->myUseConstantValue); std::string mapfile; if (useBackgroundMap) { checkDirPath(data->myFileSizeMapDir); mapfile = data->myFileSizeMapDir+data->myMeshFileBackground; setFieldName(data->myFieldName); } else if (useConstantValue) { setConstantValue(data->myConstantValue); } else { mapfile =""; setConstantValue(0.0); setFieldName(data->myFieldName); } setSizeMapFile(mapfile); if (data->myUseNoTimeStep) setNoTimeStep(); else if (data->myUseLastTimeStep) setTimeStepRankLast(); else { setChosenTimeStepRank(); setRankTimeStep(data->myTimeStep, data->myRank); } /* Advanced options */ setWorkingDir(data->myWorkingDir); checkDirPath(data->myWorkingDir); setLogFile(data->myWorkingDir+defaultLogFile()); setVerbosityLevel(data->myVerboseLevel); setRemoveOnSuccess(data->myRemoveLogOnSuccess); setPrintLogInFile(data->myPrintLogInFile); setKeepWorkingFiles(data->myKeepFiles); return true; } void MgAdapt::checkDirPath(std::string& dirPath) { const char lastChar = *dirPath.rbegin(); #ifdef WIN32 if(lastChar != '\\') dirPath+='\\'; #else if(lastChar != '/') dirPath+='/'; #endif } //============================================================================= void MgAdapt::setOptionValue(const std::string& optionName, const std::string& optionValue) { // INFOS("setOptionValue"); // std::cout << "optionName: " << optionName << ", optionValue: " << optionValue << std::endl; TOptionValues::iterator op_val = _option2value.find(optionName); if (op_val == _option2value.end()) { op_val = _customOption2value.find( optionName ); _customOption2value[ optionName ] = optionValue; return; } if (op_val->second != optionValue) { std::string lowerOptionValue = toLowerStr(optionValue); const char* ptr = lowerOptionValue.c_str(); // strip white spaces while (ptr[0] == ' ') ptr++; size_t i = strlen(ptr); while (i != 0 && ptr[i - 1] == ' ') i--; // check value type bool typeOk = true; std::string typeName; if (i == 0) { // empty string } else if (_charOptions.count(optionName)) { // do not check strings } else if (_doubleOptions.count(optionName)) { // check if value is double toDbl(ptr, &typeOk); typeName = "real"; } else if (_boolOptions.count(optionName)) { // check if value is bool toBool(ptr, &typeOk); typeName = "bool"; } else { // check if value is int toInt(ptr, &typeOk); typeName = "integer"; } if ( typeOk ) // check some specific values ? { } if ( !typeOk ) { std::string msg = "Advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName; throw std::invalid_argument(msg); } std::string value( ptr, i ); // std::cout << "==> value: " << value << std::endl; if ( _defaultOptionValues[ optionName ] == value ) value.clear(); // std::cout << "==> value: " << value << std::endl; op_val->second = value; } } //============================================================================= //! Return option value. If isDefault provided, it can be a default value, // then *isDefault == true. If isDefault is not provided, the value will be // empty if it equals a default one. std::string MgAdapt::getOptionValue(const std::string& optionName, bool* isDefault) const { // INFOS("getOptionValue"); // std::cout << "optionName: " << optionName << ", isDefault: " << isDefault << std::endl; TOptionValues::const_iterator op_val = _option2value.find(optionName); if (op_val == _option2value.end()) { op_val = _customOption2value.find(optionName); if (op_val == _customOption2value.end()) { std::string msg = "Unknown MG-Adapt option: <" + optionName + ">"; throw std::invalid_argument(msg); } } std::string val = op_val->second; if ( isDefault ) *isDefault = ( val.empty() ); if ( val.empty() && isDefault ) { op_val = _defaultOptionValues.find( optionName ); if (op_val != _defaultOptionValues.end()) val = op_val->second; } // std::cout << "==> val: " << val << std::endl; return val; } //================================================================================ /*! * \brief Converts a string to a real value */ //================================================================================ double MgAdapt::toDbl(const std::string& str, bool* isOk ) { if ( str.empty() ) throw std::invalid_argument("Empty value provided"); char * endPtr; double val = strtod(&str[0], &endPtr); bool ok = (&str[0] != endPtr); if ( isOk ) *isOk = ok; if ( !ok ) { std::string msg = "Not a real value:'" + str + "'"; throw std::invalid_argument(msg); } return val; } //================================================================================ /*! * \brief Converts a string to a lower */ //================================================================================ std::string MgAdapt::toLowerStr(const std::string& str) { std::string s = str; for ( size_t i = 0; i <= s.size(); ++i ) s[i] = (char) tolower( s[i] ); return s; } //================================================================================ /*! * \brief Converts a string to a bool */ //================================================================================ bool MgAdapt::toBool(const std::string& str, bool* isOk ) { std::string s = str; if ( isOk ) *isOk = true; for ( size_t i = 0; i <= s.size(); ++i ) s[i] = (char) tolower( s[i] ); if ( s == "1" || s == "true" || s == "active" || s == "yes" ) return true; if ( s == "0" || s == "false" || s == "inactive" || s == "no" ) return false; if ( isOk ) *isOk = false; else { std::string msg = "Not a Boolean value:'" + str + "'"; throw std::invalid_argument(msg); } return false; } //================================================================================ /*! * \brief Converts a string to a integer value */ //================================================================================ int MgAdapt::toInt(const std::string& str, bool* isOk ) { if ( str.empty() ) throw std::invalid_argument("Empty value provided"); char * endPtr; int val = (int)strtol( &str[0], &endPtr, 10); bool ok = (&str[0] != endPtr); if ( isOk ) *isOk = ok; if ( !ok ) { std::string msg = "Not an integer value:'" + str + "'"; throw std::invalid_argument(msg); } return val; } //============================================================================= bool MgAdapt::hasOptionDefined( const std::string& optionName ) const { bool isDefault = false; try { getOptionValue( optionName, &isDefault ); } catch ( std::invalid_argument ) { return false; } return !isDefault; } //================================================================================ /*! * \brief Return command to run MG-Adapt mesher excluding file prefix (-f) */ //================================================================================ std::string MgAdapt::getCommandToRun(MgAdapt* hyp) { return hyp ? hyp->getCommandToRun() : ToComment("error with hypothesis!"); } int MgAdapt::compute(std::string& errStr) { std::string cmd = getCommandToRun(); // std::cout << cmd << std::endl; int err = 0; execCmd( cmd.c_str(), err ); // run if ( err ) { errStr = ToComment("system(mg-adapt.exe ...) command failed with error: ") << strerror( errno ); } else if ( !isFileExist( meshFormatOutputMesh )) { errStr = ToComment(" failed to find file ") << meshFormatOutputMesh << " output from MG-Adapt run"; } else { convertMeshFile(meshFormatOutputMesh, solFormatOutput); } if (!err) cleanUp(); return err; } void MgAdapt::execCmd( const char* cmd, int& err) { err = 1; std::array buffer; std::streambuf* buf; outFileStream fileStream; if (printLogInFile) { fileStream.open(logFile); buf = fileStream.rdbuf(); } else { buf = std::cout.rdbuf(); } std::ostream logStream(buf); #if defined(WIN32) # if defined(UNICODE) const wchar_t * aCmd = Kernel_Utils::utf8_decode(cmd); SMESHUtils::ArrayDeleter deleter( aCmd ); std::unique_ptr pipe(_wpopen(aCmd, O_RDONLY), _pclose ); # else std::unique_ptr pipe(_popen(cmd, "r"), _pclose ); # endif #else std::unique_ptr pipe(popen(cmd, "r"), pclose ); #endif if(!pipe) { throw std::runtime_error("popen() failed!"); } while(fgets(buffer.data(), buffer.size(), pipe.get()) !=nullptr ) { logStream<::iterator it = tmpFilesToBeDeleted.begin(); for (; it!=tmpFilesToBeDeleted.end(); ++it) { errStr=removeFile(*it, notOk); if (notOk) { appendMsgToLogFile(errStr); } } } void MgAdapt::appendMsgToLogFile(std::string& msg) { std::ofstream logStream; logStream.open(logFile, std::ofstream::out | std::ofstream::app); logStream<< msg; logStream.close(); } //================================================================================ /*! * \brief Return command to run MG-Tetra mesher excluding file prefix (-f) */ //================================================================================ std::string MgAdapt::getCommandToRun() { /* || return system command with args and options || */ std::string errStr; std::string cmd = getExeName(); std::string meshIn(""), sizeMapIn(""), solFileIn(""); updateTimeStepRank(); convertMedFile(meshIn, solFileIn, sizeMapIn); if (!isFileExist(meshIn) || !isFileExist(solFileIn)) { errStr = ToComment(" failed to find .mesh or .sol file from converter ")<< strerror( errno ); return errStr; } tmpFilesToBeDeleted.push_back(meshIn); tmpFilesToBeDeleted.push_back(solFileIn); if(useBackgroundMap && !isFileExist(sizeMapIn)) { errStr = ToComment(" failed to find .mesh size map file from converter ")<< strerror( errno ); return errStr; } cmd+= " --in "+ meshIn; meshFormatOutputMesh = getFileName()+".mesh"; tmpFilesToBeDeleted.push_back(meshFormatOutputMesh); if ( isFileExist( meshFormatOutputMesh )){ int notOk; errStr=removeFile(meshFormatOutputMesh , notOk); if (notOk) { appendMsgToLogFile(errStr); } } cmd+= " --out "+ meshFormatOutputMesh; if (useLocalMap || useConstantValue) cmd+= " --sizemap "+ solFileIn; else // (useBackgroundMap) { cmd+= " --background_mesh "+ sizeMapIn ; cmd+= " --background_sizemap "+ solFileIn; tmpFilesToBeDeleted.push_back(sizeMapIn); } //~else //~{ //~// constant value TODO //~} // Check coherence between mesh dimension and option fo adaptation checkDimensionOptionAdaptation(); // sizemap file is written only if level is higher than 3 if ( verbosityLevel > 3) { std::string solFileOut = getFileName()+".sol"; cmd+= " --write_sizemap "+ solFileOut; solFormatOutput.push_back(solFileOut); tmpFilesToBeDeleted.push_back(solFileOut); } std::string option, value; bool isDefault; const TOptionValues* options[] = { &_option2value, &_customOption2value }; for ( int iOp = 0; iOp < 2; ++iOp ) { TOptionValues::const_iterator o2v = options[iOp]->begin(); for ( ; o2v != options[iOp]->end(); ++o2v ) { option = o2v->first; value = getOptionValue( option, &isDefault ); if ( isDefault ) continue; if ( value.empty() )//value == NoValue() ) { if ( _defaultOptionValues.count( option )) continue; // non-custom option with no value //value.clear(); } if ( strncmp( "no", option.c_str(), 2 ) == 0 ) // options w/o values: --no_* { if ( !value.empty() && toBool( value ) == false ) continue; value.clear(); } if ( option[0] != '-' ) cmd += " --"; else cmd += " "; // std::cout << "--- option: '" << option << ", value: '" << value <<"'"<< std::endl; cmd += option + " " + value; } } // Verbosity Level if (verbosityLevel != defaultVerboseLevel()) { cmd+= " --verbose "+ ToComment(verbosityLevel); } // get license key { smIdType nbVertex, nbEdge, nbFace, nbVol; DriverGMF_Read gmfReader; gmfReader.SetFile( meshIn ); gmfReader.GetMeshInfo( nbVertex, nbEdge, nbFace, nbVol ); std::string errorTxt; std::string key = SMESHUtils_MGLicenseKeyGen::GetKey( meshIn, FromSmIdType( nbVertex ), FromSmIdType( nbEdge ), FromSmIdType( nbFace ), FromSmIdType( nbVol ), errorTxt ); if ( key.empty() ) return ToComment( "Problem with library SalomeMeshGemsKeyGenerator: " + errorTxt ); if ( key!="0" ) cmd += " --key " + key; } #ifdef WIN32 cmd += " < NUL"; #endif if (SALOME::VerbosityActivated()) { std::cout << "--- cmd :"<< std::endl; std::cout << cmd << std::endl; } return cmd; } //======================================================================= //function : defaultMaximumMemory //======================================================================= #if defined(WIN32) #include #elif !defined(__APPLE__) #include #endif double MgAdapt::defaultMaximumMemory() { #if defined(WIN32) // See http://msdn.microsoft.com/en-us/library/aa366589.aspx MEMORYSTATUSEX statex; statex.dwLength = sizeof (statex); long err = GlobalMemoryStatusEx (&statex); if (err != 0) { double totMB = (double)statex.ullAvailPhys / 1024. / 1024.; return (double)( 0.7 * totMB ); } #elif !defined(__APPLE__) struct sysinfo si; long err = sysinfo( &si ); if ( err == 0 ) { long ramMB = si.totalram * si.mem_unit / 1024 / 1024; return ( 0.7 * double( ramMB )); } #endif return 1024; } //======================================================================= //function : defaultWorkingDirectory //======================================================================= std::string MgAdapt::defaultWorkingDirectory() { std::string aTmpDir; char *Tmp_dir = getenv("SALOME_TMP_DIR"); if(Tmp_dir != NULL) { aTmpDir = Tmp_dir; } if ( ! isFileExist( aTmpDir )) { #ifdef WIN32 aTmpDir = "C:\\"; #else aTmpDir = "/tmp/"; #endif } return aTmpDir; } //================================================================================ /*! * \brief Return a unique file name */ //================================================================================ std::string MgAdapt::getFileName() const { std::string aTmpDir = workingDir; const char lastChar = *aTmpDir.rbegin(); #ifdef WIN32 if(lastChar != '\\') aTmpDir+='\\'; #else if(lastChar != '/') aTmpDir+='/'; #endif SMESH_Comment aGenericName( aTmpDir ); aGenericName << "MgAdapt_"; #ifndef WIN32 aGenericName << getpid(); #else aGenericName << _getpid(); #endif aGenericName << "_"; aGenericName << std::abs((int)(long) aGenericName.data()); return aGenericName; } //======================================================================= //function : defaultLogFile //======================================================================= std::string MgAdapt::defaultLogFile() { std::string alogFile("MG_ADAPT.log"); return alogFile; } //======================================================================= //function : defaultUseConstantValue //======================================================================= bool MgAdapt::defaultUseConstantValue() { return false; } //======================================================================= //function : defaultUseNoTimeStep //======================================================================= bool MgAdapt::defaultUseNoTimeStep() { return true; } //======================================================================= //function : defaultRemoveLogOnSuccess //======================================================================= bool MgAdapt::defaultRemoveLogOnSuccess() { return true; } //======================================================================= //function : defaultPrintLogInFile //======================================================================= bool MgAdapt::defaultPrintLogInFile() { return false; } //======================================================================= //function : defaultUseChosenTimeStep //======================================================================= bool MgAdapt::defaultUseChosenTimeStep() { return false; } //======================================================================= //function : UseLastTimeStep //======================================================================= bool MgAdapt::defaultUseLastTimeStep() { return false; } //======================================================================= //function : defaultUseBackgroundMap //======================================================================= bool MgAdapt::defaultUseBackgroundMap() { return false; } //======================================================================= //function : defaultKeepFiles //======================================================================= bool MgAdapt::defaultKeepFiles() { return false; } //======================================================================= //function : defaultUseLocalMap //======================================================================= bool MgAdapt::defaultUseLocalMap() { return true; } //======================================================================= //function : defaultPublish //======================================================================= bool MgAdapt::defaultPublish() { return false; } //======================================================================= //function : defaultMeshOutMed //======================================================================= bool MgAdapt::defaultMeshOutMed() { return true; } //======================================================================= //function : defaultFromMedFile //======================================================================= bool MgAdapt::defaultFromMedFile() { return true; } //======================================================================= //function : defaultVerboseLevel //======================================================================= int MgAdapt::defaultVerboseLevel() { return 3; } std::string MgAdapt::getExeName() { return "mg-adapt.exe"; } void MgAdapt::copyMgAdaptHypothesisData( const MgAdaptHypothesisData* from) { data->myFileInDir = from->myFileInDir; data->myMeshFileIn = from->myMeshFileIn; data->myMeshFileBackground = from->myMeshFileBackground; data->myOutMeshName = from->myOutMeshName; data->myMeshFileOut = from->myMeshFileOut; data->myFileOutDir = from->myFileOutDir; data->myFileSizeMapDir = from->myFileSizeMapDir; data->myFieldName = from->myFieldName; data->fromMedFile = from->fromMedFile; data->myPublish = from->myPublish; data->myMeshOutMed = from->myMeshOutMed; data->myUseLocalMap = from->myUseLocalMap; data->myUseBackgroundMap = from->myUseBackgroundMap; data->myUseConstantValue = from->myUseConstantValue; data->myConstantValue = from->myConstantValue; data->myTimeStep = from->myTimeStep; data->myRank = from->myRank; data->myUseNoTimeStep = from->myUseNoTimeStep; data->myUseLastTimeStep = from->myUseLastTimeStep; data->myUseChosenTimeStep = from->myUseChosenTimeStep; data->myWorkingDir = from->myWorkingDir; data->myLogFile = from->myLogFile; data->myPrintLogInFile = from->myPrintLogInFile; data->myKeepFiles = from->myKeepFiles; data->myRemoveLogOnSuccess = from->myRemoveLogOnSuccess; data->myVerboseLevel = from->myVerboseLevel; } std::vector MgAdapt::getListFieldsNames(std::string fileIn) { MEDCoupling::MCAuto mfd = MEDCoupling::MEDFileData::New(fileIn); std::vector listFieldsNames(mfd->getFields()->getFieldsNames()); return listFieldsNames ; } void MgAdapt::checkDimensionOptionAdaptation() { // Quand le maillage est 3D, tout est possible // Quand le maillage est 2D, il faut 'surface' sauf si carte de fonds 3D MEDCoupling::MCAuto mfd = MEDCoupling::MEDFileData::New(medFileIn); int meshdim = mfd->getMeshes()->getMeshAtPos(0)->getMeshDimension() ; // std::cout << "meshdim = " << meshdim << std::endl; if ( meshdim == 2 ) { std::string optionName = "adaptation"; std::string optionValue = getOptionValue(optionName); // std::cout << "optionValue = '" << optionValue <<"'"<< std::endl; bool a_tester = false ; // carte locale ou constante : impératif d'avoir "surface" if ( useLocalMap || useConstantValue) a_tester = true ; // carte de fond : impératif d'avoir "surface" si le fonds est aussi 2D else { MEDCoupling::MCAuto mfdbg = MEDCoupling::MEDFileData::New(sizeMapFile); int meshdimbg = mfdbg->getMeshes()->getMeshAtPos(0)->getMeshDimension() ; // std::cout << "meshdimbg = " << meshdimbg << std::endl; if ( meshdimbg == 2 ) a_tester = true ; } if ( a_tester ) { if ( optionValue == "" ) setOptionValue (optionName, "surface"); else { if ( optionValue != "surface" ) { THROW_SALOME_EXCEPTION("Mesh dimension is 2; the option should be 'surface'" " instead of '" << optionValue << "'."); } } } } } void MgAdapt::checkFieldName(std::string fileIn) { bool ret = false ; std::vector listFieldsNames = getListFieldsNames(fileIn); std::size_t jaux(listFieldsNames.size()); for(std::size_t j=0;j mfd = MEDCoupling::MEDFileData::New(fileIn); MEDCoupling::MCAuto fts( mfd->getFields()->getFieldWithName(fieldName) ); std::vector timevalue; std::vector< std::pair > timesteprank = fts->getTimeSteps(timevalue); std::size_t jaux(timesteprank.size()); for(std::size_t j=0;j fieldFileNames; MEDCoupling::MeshFormatWriter writer; MEDCoupling::MCAuto mfd = MEDCoupling::MEDFileData::New(medFileIn); MEDCoupling::MEDFileMeshes* meshes = mfd->getMeshes(); MEDCoupling::MEDFileMesh* fileMesh = meshes->getMeshAtPos(0); // ok only one mesh in file! if (meshNameOut =="") meshNameOut = fileMesh->getName(); storeGroupsAndFams(fileMesh); MEDCoupling::MCAuto fields = MEDCoupling::MEDFileFields::New(); solFormatFieldFileName = getFileName(); solFormatFieldFileName+=".sol"; fieldFileNames.push_back(solFormatFieldFileName); if (useBackgroundMap) { checkFieldName(sizeMapFile) ; checkTimeStepRank(sizeMapFile) ; meshFormatsizeMapFile = getFileName(); meshFormatsizeMapFile += ".mesh"; buildBackGroundMeshAndSolFiles(fieldFileNames, meshFormatsizeMapFile); } else if(useLocalMap) { checkFieldName(medFileIn) ; checkTimeStepRank(medFileIn) ; MEDCoupling::MCAuto fts( mfd->getFields()->getFieldWithName(fieldName) ); MEDCoupling::MCAuto f = fts->getTimeStep(timeStep, rank); MEDCoupling::MCAuto tmFts = MEDCoupling::DynamicCast(fts); // if not able to cast to double field, try float field if (!tmFts) { MEDCoupling::MCAuto tmFtsFloat = MEDCoupling::DynamicCast(fts); if (!tmFtsFloat) THROW_SALOME_EXCEPTION("\nUnexpected field type.\n"); // convert float field to double tmFts = tmFtsFloat->convertToDouble(); } fields->pushField(tmFts); writer.setFieldFileNames( fieldFileNames); } else { MEDCoupling::MCAuto mesh = fileMesh->getMeshAtLevel(1); // nodes mesh MEDCoupling::MCAuto umesh = mesh->buildUnstructured(); // nodes mesh int dim = umesh->getSpaceDimension(); int version = sizeof(double) < 8 ? 1 : 2; mcIdType nbNodes = umesh->getNumberOfNodes(); buildConstantSizeMapSolFile(solFormatFieldFileName, dim, version, nbNodes); } mfd->setFields( fields ); meshFormatMeshFileName = getFileName(); meshFormatMeshFileName+=".mesh"; writer.setMeshFileName(meshFormatMeshFileName); writer.setMEDFileDS( mfd); writer.write(); } void MgAdapt::convertMeshFile(std::string& meshFormatIn, std::vector< std::string>& solFieldFileNames) const { MEDCoupling::MeshFormatReader reader(meshFormatIn, solFieldFileNames); MEDCoupling::MCAuto mfd = reader.loadInMedFileDS(); // write MED MEDCoupling::MEDFileMeshes* meshes = mfd->getMeshes(); MEDCoupling::MEDFileMesh* fileMesh = meshes->getMeshAtPos(0); // ok only one mesh in file! fileMesh->setName(meshNameOut); restoreGroupsAndFams(fileMesh); mfd->write(medFileOut, 2); } void MgAdapt::storeGroupsAndFams(MEDCoupling::MEDFileMesh* fileMesh) { storefams(fileMesh); storeGroups(fileMesh); } void MgAdapt::restoreGroupsAndFams(MEDCoupling::MEDFileMesh* fileMesh) const { restorefams(fileMesh); restoreGroups(fileMesh); } void MgAdapt::storeGroups(MEDCoupling::MEDFileMesh* fileMesh) { std::map > grpFams = fileMesh->getGroupInfo(); std::map >::iterator g2ff = grpFams.begin(); for ( ; g2ff != grpFams.end(); ++g2ff ) { std::string groupName = g2ff->first; std::vector famNames = g2ff->second; if ( famNames.empty() ) continue; std::vector< int> famListId; for ( size_t i = 0; i < famNames.size(); ++i ) { famListId.push_back( FromIdType( fileMesh->getFamilyId( famNames[i].c_str() ))); } group grp(groupName, famListId, famNames); groupVec.push_back(grp); } } void MgAdapt::storefams(MEDCoupling::MEDFileMesh* fileMesh) { std::map grpFams = fileMesh->getFamilyInfo(); std::map::iterator f = grpFams.begin(); for ( ; f != grpFams.end(); ++f ) { if(!f->second) continue; // FAMILLE_ZERO family fs(f->first, FromIdType( f->second )); famVec.push_back(fs); } } void MgAdapt::restorefams(MEDCoupling::MEDFileMesh* fileMesh) const { std::vector::const_iterator fIt = famVec.begin(); for (; fIt!=famVec.end(); ++fIt) { try // { std::string givenFamNameFromMeshGemConverter = fileMesh->getFamilyNameGivenId( std::abs(fIt->_famId) ); fileMesh->changeFamilyId(std::abs(fIt->_famId), fIt->_famId); fileMesh->changeFamilyName(givenFamNameFromMeshGemConverter, fIt->_famName); } catch (const std::exception& e) { std::cerr< > info; std::vector ::const_iterator grpFams = groupVec.begin(); for (; grpFams!=groupVec.end(); ++grpFams) { info.insert(std::pair > (grpFams->_name, grpFams->_famNames) ); } fileMesh->setGroupInfo(info); } void MgAdapt::buildConstantSizeMapSolFile(const std::string& solFormatFieldFileName, const int dim, const int version, const size_t nbNodes) const { MeshFormat::Localizer loc; MeshFormat::MeshFormatParser writer; int fileId = writer.GmfOpenMesh( solFormatFieldFileName.c_str(), GmfWrite, version, dim); int typTab[] = {GmfSca}; writer.GmfSetKwd(fileId, MeshFormat::GmfSolAtVertices, (int)nbNodes, 1, typTab); for (size_t i = 0; i& fieldFileNames, const std::string& meshFormatsizeMapFile) const { MEDCoupling::MCAuto tmpMfd = MEDCoupling::MEDFileData::New(sizeMapFile); MEDCoupling::MEDFileFields* tmpFields = tmpMfd->getFields(); MEDCoupling::MCAuto fts( tmpFields->getFieldWithName(fieldName) ); MEDCoupling::MCAuto fts1 = MEDCoupling::DynamicCastSafe(fts); MEDCoupling::MCAuto f = fts1->getTimeStep(timeStep, rank); MEDCoupling::MCAuto tmFts = MEDCoupling::MEDFileFieldMultiTS::New(); tmFts->pushBackTimeStep(f); MEDCoupling::MCAuto tmp_fields = MEDCoupling::MEDFileFields::New(); tmp_fields->pushField(tmFts); tmpMfd->setFields( tmp_fields ); MEDCoupling::MeshFormatWriter tmpWriter; tmpWriter.setMeshFileName(meshFormatsizeMapFile); tmpWriter.setFieldFileNames( fieldFileNames); tmpWriter.setMEDFileDS(tmpMfd); tmpWriter.write(); } MgAdapt::Status MgAdapt::addMessage(const std::string& msg, const bool isFatal/*=false*/) { if ( isFatal ) _errorMessages.clear(); // warnings are useless if a fatal error encounters _errorMessages.push_back( msg ); //~MESSAGE(msg); if (SALOME::VerbosityActivated()) std::cout << msg << std::endl; return ( _status = isFatal ? MgAdapt::DRS_FAIL : MgAdapt::DRS_WARN_SKIP_ELEM ); } void MgAdapt::updateTimeStepRank() { med_int arank; med_int tmst; if (myUseNoTimeStep) { arank = MED_NO_IT; tmst = MED_NO_DT ; setRankTimeStep((int)tmst, (int)arank); } else if (myUseLastTimeStep) { std::string fieldFile = useBackgroundMap ? sizeMapFile : medFileIn; getTimeStepInfos(fieldFile, tmst, arank, fieldName); setRankTimeStep((int)tmst, (int)arank); } }