1 // Copyright (C) 2020-2021 CEA/DEN, EDF R&D
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 "SMESH_File.hxx"
23 #include "SMESH_Comment.hxx"
25 #include <MEDFileData.hxx>
26 #include <MEDFileField.hxx>
27 #include <MEDFileMesh.hxx>
28 #include <MeshFormatReader.hxx>
29 #include <MeshFormatWriter.hxx>
31 #include <Utils_SALOME_Exception.hxx>
32 #include <Basics_Utils.hxx>
33 #include "SMESH_TypeDefs.hxx"
36 #include <unistd.h> // getpid()
42 #include <memory> // unique_ptr
44 typedef SMESH_Comment ToComment;
46 using namespace MG_ADAPT;
47 static std::string removeFile(std::string fileName, int& notOk)
50 notOk = std::remove(fileName.c_str());
51 if (notOk) errStr = ToComment("\n error while removing file : ") << fileName;
52 else errStr = ToComment("\n file : ") << fileName << " succesfully deleted! \n ";
56 std::string MG_ADAPT::remove_extension(const std::string& filename)
58 size_t lastdot = filename.find_last_of(".");
59 if (lastdot == std::string::npos) return filename;
60 return filename.substr(0, lastdot);
65 bool isFileExist( const std::string& fName )
67 return SMESH_File( fName ).exists();
70 // =======================================================================
71 med_idt openMedFile(const std::string aFile)
72 // =======================================================================
73 // renvoie le medId associe au fichier Med apres ouverture
75 med_idt medIdt = MEDfileOpen(aFile.c_str(),MED_ACC_RDONLY);
78 THROW_SALOME_EXCEPTION("\nThe med file " << aFile << " cannot be opened.\n");
83 // =======================================================================
84 void getTimeStepInfos(std::string aFile, med_int& numdt, med_int& numit, std::string fieldName)
85 // =======================================================================
87 // Il faut voir si plusieurs maillages
92 // Ouverture du fichier
93 //~SCRUTE(aFile.toStdString());
94 medIdt = openMedFile(aFile);
95 if ( medIdt < 0 ) return ;
96 // Lecture du nombre de champs
97 med_int ncha = MEDnField(medIdt) ;
100 //~addMessage( ToComment(" error: there is no field in ") << aFile, /*fatal=*/true );
103 // Lecture des caracteristiques du champs
105 // Lecture du type du champ, des noms des composantes et du nom de l'unite
106 char nomcha [MED_NAME_SIZE+1];
107 strcpy(nomcha, fieldName.c_str());
108 // Lecture du nombre de composantes
109 med_int ncomp = MEDfieldnComponentByName(medIdt, nomcha);
110 char meshname[MED_NAME_SIZE+1];
111 char * comp = (char*) malloc(ncomp*MED_SNAME_SIZE+1);
112 char * unit = (char*) malloc(ncomp*MED_SNAME_SIZE+1);
113 char dtunit[MED_SNAME_SIZE+1];
115 med_field_type typcha;
117 erreur = MEDfieldInfoByName (medIdt, nomcha, meshname,&local,&typcha,comp,unit,dtunit, &nbofcstp);
122 //~addMessage( ToComment(" error: error while reading field ") << nomcha << " in file " << aFile , /*fatal=*/true );
127 med_int tmp_numdt, tmp_numit;
129 //~med_int step = data->myUseLastTimeStep ? nbofcstp : data->myTimeStep+1;
130 //~myPrint("step ", step);
131 erreur = MEDfieldComputingStepInfo ( medIdt, nomcha, 1, &numdt, &numit, &dt );
132 for( int step = 1; step <= nbofcstp; step++ )
134 erreur = MEDfieldComputingStepInfo ( medIdt, nomcha, step, &tmp_numdt, &tmp_numit, &dt );
135 if(tmp_numdt > numdt)
143 //~addMessage( ToComment(" error: error while reading field ") << nomcha << "step (numdt, numit) = " <<"("<< numdt<< ", "
144 //numit<< ")" <<" in file " << aFile , /*fatal=*/true );
148 // Fermeture du fichier
149 if ( medIdt > 0 ) MEDfileClose(medIdt);
153 struct GET_DEFAULT // struct used to get default value from GetOptionValue()
161 class outFileStream : public std::ofstream{
163 ~outFileStream(){close();} //to close file at dtor
166 } // anonymous namespace
168 //----------------------------------------------------------------------------------------
171 data = new MgAdaptHypothesisData();
172 data->myInMeshName = "";
173 data->fromMedFile = defaultFromMedFile();
174 data->myFileInDir = defaultWorkingDirectory();
175 data->myMeshFileIn = "";
176 data->myFileOutDir = defaultWorkingDirectory();
177 data->myOutMeshName = "";
178 data->myMeshFileOut = "";
179 data->myMeshOutMed = defaultMeshOutMed();
180 data->myPublish = defaultPublish();
181 data->myUseLocalMap = defaultUseLocalMap();
182 data->myUseBackgroundMap = defaultUseBackgroundMap();
183 data->myFileSizeMapDir = defaultWorkingDirectory();
184 data->myMeshFileBackground = "";
185 data->myUseConstantValue = defaultUseConstantValue();
186 data->myConstantValue = 0.0;
187 data->myFieldName = "";
188 data->myUseNoTimeStep = defaultUseNoTimeStep();
189 data->myUseLastTimeStep = defaultUseLastTimeStep();
190 data->myUseChosenTimeStep = defaultUseChosenTimeStep();
191 data->myTimeStep = -2;
193 data->myWorkingDir = defaultWorkingDirectory();
194 data->myLogFile = defaultLogFile();
195 data->myVerboseLevel = defaultVerboseLevel();
196 data->myPrintLogInFile = defaultPrintLogInFile();
197 data->myKeepFiles = defaultKeepFiles();
198 data->myRemoveLogOnSuccess = defaultRemoveLogOnSuccess();
203 MgAdapt::MgAdapt(MgAdaptHypothesisData* myData)
205 data = new MgAdaptHypothesisData();
210 MgAdapt::MgAdapt( const MgAdapt& copy)
212 data = new MgAdaptHypothesisData();
213 MgAdaptHypothesisData *copyData = copy.getData();
214 copyMgAdaptHypothesisData(copyData);
217 this->_option2value = copy._option2value;
218 this->_customOption2value = copy._customOption2value;
219 this->_defaultOptionValues = copy._defaultOptionValues;
220 this->_doubleOptions = copy._doubleOptions;
221 this->_charOptions = copy._charOptions;
222 this->_boolOptions = copy._boolOptions;
225 //-----------------------------------------------------------------------------------------
230 void MgAdapt::buildModel()
233 const char* boolOptionNames[] = { "compute_ridges", // yes
236 // const char* intOptionNames[] = { "max_number_of_errors_printed", // 1
237 // "max_number_of_threads", // 4
240 const char* doubleOptionNames[] = { "max_memory", // 0
243 const char* charOptionNames[] = { "components", // "yes"
244 "adaptation", // both
249 while (boolOptionNames[i][0])
251 _boolOptions.insert( boolOptionNames[i] );
252 _option2value[boolOptionNames[i++]].clear();
255 // while (intOptionNames[i][0])
256 // _option2value[intOptionNames[i++]].clear();
259 while (doubleOptionNames[i][0]) {
260 _doubleOptions.insert(doubleOptionNames[i]);
261 _option2value[doubleOptionNames[i++]].clear();
264 while (charOptionNames[i][0]) {
265 _charOptions.insert(charOptionNames[i]);
266 _option2value[charOptionNames[i++]].clear();
269 // default values to be used while MG-Adapt
271 _defaultOptionValues["adaptation" ] = "both";
272 _defaultOptionValues["components" ] = "outside components";
273 _defaultOptionValues["compute_ridges"] = "yes";
274 _defaultOptionValues["max_memory" ] = ToComment(defaultMaximumMemory());
277 //=============================================================================
278 TOptionValues MgAdapt::getOptionValues() const
281 TOptionValues::const_iterator op_val = _option2value.begin();
282 for ( ; op_val != _option2value.end(); ++op_val )
283 vals.insert( make_pair( op_val->first, getOptionValue( op_val->first, GET_DEFAULT() )));
288 std::vector <std::string> MgAdapt::getOptionValuesStrVec() const
290 std::vector <std::string> vals;
291 TOptionValues::const_iterator op_val = _option2value.begin();
292 for ( ; op_val != _option2value.end(); ++op_val )
293 vals.push_back(op_val->first+":"+getOptionValue( op_val->first, GET_DEFAULT() ));
298 std::vector <std::string> MgAdapt::getCustomOptionValuesStrVec() const
300 std::vector <std::string> vals;
301 TOptionValues::const_iterator op_val;
302 for ( op_val = _customOption2value.begin(); op_val != _customOption2value.end(); ++op_val )
304 vals.push_back(op_val->first+":"+getOptionValue( op_val->first, GET_DEFAULT() ));
308 const TOptionValues& MgAdapt::getCustomOptionValues() const
310 return _customOption2value;
312 void MgAdapt::setData(MgAdaptHypothesisData* myData)
314 copyMgAdaptHypothesisData(myData);
317 MgAdaptHypothesisData* MgAdapt::getData() const
321 void MgAdapt::setMedFileIn(std::string fileName)
323 if ( isFileExist(fileName) )
325 medFileIn = fileName;
327 if (medFileOut == "") // default MED file Out
328 medFileOut = remove_extension( fileName )+ ".adapt.med";
332 THROW_SALOME_EXCEPTION("\nThe file "<< fileName <<" does not exist.\n");
336 std::string MgAdapt::getMedFileIn()
341 void MgAdapt::setMedFileOut(std::string fileOut)
343 medFileOut = fileOut;
345 std::string MgAdapt::getMedFileOut()
349 void MgAdapt::setMeshOutMed(bool mybool)
353 bool MgAdapt::getMeshOutMed()
357 void MgAdapt::setPublish(bool mybool)
361 bool MgAdapt::getPublish()
365 void MgAdapt::setFieldName(std::string myFieldName)
367 fieldName = myFieldName;
369 std::string MgAdapt::getFieldName()
373 void MgAdapt::setTimeStep(int time)
377 int MgAdapt::getTimeStep() const
382 void MgAdapt::setRankTimeStep(int time, int myRank)
388 int MgAdapt::getRank()
392 void MgAdapt::setTimeStepRankLast()
394 myUseLastTimeStep = true;
395 myUseChosenTimeStep = false;
396 myUseNoTimeStep = false;
397 //~med_int aRank, tmst;
398 //~std::string fieldFile = useBackgroundMap ? sizeMapFile : medFileIn;
399 //~getTimeStepInfos(fieldFile, tmst, aRank);
400 //~setRankTimeStep((int) tmst, (int) aRank);
402 void MgAdapt::setNoTimeStep()
404 myUseLastTimeStep = false;
405 myUseChosenTimeStep = false;
406 myUseNoTimeStep = true;
407 //~int aRank = (int)MED_NO_IT;
408 //~int tmst = (int)MED_NO_DT ;
409 //~setRankTimeStep(tmst, aRank);
411 void MgAdapt::setChosenTimeStepRank()
413 myUseLastTimeStep = false;
414 myUseChosenTimeStep = true;
415 myUseNoTimeStep = false;
416 //~int aRank = (int)MED_NO_IT;
417 //~int tmst = (int)MED_NO_DT ;
418 //~setRankTimeStep(tmst, aRank);
420 void MgAdapt::setUseLocalMap(bool myLocal)
422 useLocalMap = myLocal;
425 bool MgAdapt::getUseLocalMap()
430 void MgAdapt::setUseBackgroundMap(bool bckg)
432 useBackgroundMap = bckg;
435 bool MgAdapt::getUseBackgroundMap()
437 return useBackgroundMap;
440 void MgAdapt::setUseConstantValue(bool cnst)
442 useConstantValue = cnst;
444 bool MgAdapt::getUseConstantValue()
446 return useConstantValue;
448 void MgAdapt::setLogFile(std::string myLogFile)
452 std::string MgAdapt::getLogFile()
456 void MgAdapt::setVerbosityLevel(int verboLevel)
458 verbosityLevel = verboLevel;
460 int MgAdapt::getVerbosityLevel()
462 return verbosityLevel;
464 void MgAdapt::setRemoveOnSuccess(bool rmons)
466 removeOnSuccess = rmons;
468 bool MgAdapt::getRemoveOnSuccess()
470 return removeOnSuccess;
472 void MgAdapt::setSizeMapFile(std::string mapFile)
474 if ( mapFile == "" || isFileExist(mapFile) )
476 sizeMapFile = mapFile;
480 THROW_SALOME_EXCEPTION("\nThe file "<< mapFile <<" does not exist.\n");
483 std::string MgAdapt::getSizeMapFile()
488 void MgAdapt::setMeshName(std::string name)
492 std::string MgAdapt::getMeshName()
496 void MgAdapt::setMeshNameOut(std::string name)
500 std::string MgAdapt::getMeshNameOut()
504 void MgAdapt::setFromMedFile(bool mybool)
506 fromMedFile = mybool;
508 bool MgAdapt::isFromMedFile()
512 void MgAdapt::setConstantValue(double cnst)
514 constantValue = cnst;
516 double MgAdapt::getConstantValue() const
518 return constantValue;
521 void MgAdapt::setWorkingDir(std::string dir)
525 std::string MgAdapt::getWorkingDir() const
529 void MgAdapt::setKeepWorkingFiles(bool mybool)
531 toKeepWorkingFiles = mybool;
533 bool MgAdapt::getKeepWorkingFiles()
535 return toKeepWorkingFiles;
537 void MgAdapt::setPrintLogInFile(bool print)
539 printLogInFile = print;
541 bool MgAdapt::getPrintLogInFile()
543 return printLogInFile;
546 bool MgAdapt::setAll()
549 setFromMedFile(data->fromMedFile);
551 checkDirPath(data->myFileInDir);
552 file = data->myFileInDir+data->myMeshFileIn;
554 setMeshName(data->myInMeshName);
555 setMeshNameOut(data->myOutMeshName);
556 checkDirPath(data->myFileOutDir);
557 std::string out = data->myFileOutDir+data->myMeshFileOut;
559 setPublish(data->myPublish);
560 setMeshOutMed(data->myMeshOutMed);
561 setUseLocalMap(data->myUseLocalMap);
562 setUseBackgroundMap(data->myUseBackgroundMap);
563 setUseConstantValue(data->myUseConstantValue);
566 if (useBackgroundMap)
568 checkDirPath(data->myFileSizeMapDir);
569 mapfile = data->myFileSizeMapDir+data->myMeshFileBackground;
570 setFieldName(data->myFieldName);
572 else if (useConstantValue)
574 setConstantValue(data->myConstantValue);
579 setConstantValue(0.0);
580 setFieldName(data->myFieldName);
583 setSizeMapFile(mapfile);
584 if (data->myUseNoTimeStep)
586 else if (data->myUseLastTimeStep)
587 setTimeStepRankLast();
590 setChosenTimeStepRank();
591 setRankTimeStep(data->myTimeStep, data->myRank);
593 /* Advanced options */
594 setWorkingDir(data->myWorkingDir);
595 checkDirPath(data->myWorkingDir);
596 setLogFile(data->myWorkingDir+defaultLogFile());
597 setVerbosityLevel(data->myVerboseLevel);
598 setRemoveOnSuccess(data->myRemoveLogOnSuccess);
599 setPrintLogInFile(data->myPrintLogInFile);
600 setKeepWorkingFiles(data->myKeepFiles);
605 void MgAdapt::checkDirPath(std::string& dirPath)
607 const char lastChar = *dirPath.rbegin();
609 if(lastChar != '\\') dirPath+='\\';
611 if(lastChar != '/') dirPath+='/';
614 //=============================================================================
615 void MgAdapt::setOptionValue(const std::string& optionName,
616 const std::string& optionValue)
618 // INFOS("setOptionValue");
619 // std::cout << "optionName: " << optionName << ", optionValue: " << optionValue << std::endl;
620 TOptionValues::iterator op_val = _option2value.find(optionName);
621 if (op_val == _option2value.end())
623 op_val = _customOption2value.find( optionName );
624 _customOption2value[ optionName ] = optionValue;
628 if (op_val->second != optionValue)
630 std::string lowerOptionValue = toLowerStr(optionValue);
631 const char* ptr = lowerOptionValue.c_str();
632 // strip white spaces
633 while (ptr[0] == ' ')
635 size_t i = strlen(ptr);
636 while (i != 0 && ptr[i - 1] == ' ')
640 std::string typeName;
645 else if (_charOptions.count(optionName))
647 // do not check strings
649 else if (_doubleOptions.count(optionName))
651 // check if value is double
655 else if (_boolOptions.count(optionName))
657 // check if value is bool
658 toBool(ptr, &typeOk);
663 // check if value is int
665 typeName = "integer";
667 if ( typeOk ) // check some specific values ?
672 std::string msg = "Advanced option '" + optionName + "' = '" + optionValue + "' but must be " + typeName;
673 throw std::invalid_argument(msg);
675 std::string value( ptr, i );
676 // std::cout << "==> value: " << value << std::endl;
677 if ( _defaultOptionValues[ optionName ] == value ) value.clear();
679 // std::cout << "==> value: " << value << std::endl;
680 op_val->second = value;
683 //=============================================================================
684 //! Return option value. If isDefault provided, it can be a default value,
685 // then *isDefault == true. If isDefault is not provided, the value will be
686 // empty if it equals a default one.
687 std::string MgAdapt::getOptionValue(const std::string& optionName, bool* isDefault) const
689 // INFOS("getOptionValue");
690 // std::cout << "optionName: " << optionName << ", isDefault: " << isDefault << std::endl;
691 TOptionValues::const_iterator op_val = _option2value.find(optionName);
692 if (op_val == _option2value.end())
694 op_val = _customOption2value.find(optionName);
695 if (op_val == _customOption2value.end())
697 std::string msg = "Unknown MG-Adapt option: <" + optionName + ">";
698 throw std::invalid_argument(msg);
701 std::string val = op_val->second;
702 if ( isDefault ) *isDefault = ( val.empty() );
704 if ( val.empty() && isDefault )
706 op_val = _defaultOptionValues.find( optionName );
707 if (op_val != _defaultOptionValues.end()) val = op_val->second;
709 // std::cout << "==> val: " << val << std::endl;
713 //================================================================================
715 * \brief Converts a string to a real value
717 //================================================================================
719 double MgAdapt::toDbl(const std::string& str, bool* isOk )
721 if ( str.empty() ) throw std::invalid_argument("Empty value provided");
724 double val = strtod(&str[0], &endPtr);
725 bool ok = (&str[0] != endPtr);
727 if ( isOk ) *isOk = ok;
731 std::string msg = "Not a real value:'" + str + "'";
732 throw std::invalid_argument(msg);
736 //================================================================================
738 * \brief Converts a string to a lower
740 //================================================================================
741 std::string MgAdapt::toLowerStr(const std::string& str)
744 for ( size_t i = 0; i <= s.size(); ++i )
745 s[i] = (char) tolower( s[i] );
748 //================================================================================
750 * \brief Converts a string to a bool
752 //================================================================================
754 bool MgAdapt::toBool(const std::string& str, bool* isOk )
757 if ( isOk ) *isOk = true;
759 for ( size_t i = 0; i <= s.size(); ++i )
760 s[i] = (char) tolower( s[i] );
762 if ( s == "1" || s == "true" || s == "active" || s == "yes" )
765 if ( s == "0" || s == "false" || s == "inactive" || s == "no" )
772 std::string msg = "Not a Boolean value:'" + str + "'";
773 throw std::invalid_argument(msg);
777 //================================================================================
779 * \brief Converts a string to a integer value
781 //================================================================================
783 int MgAdapt::toInt(const std::string& str, bool* isOk )
785 if ( str.empty() ) throw std::invalid_argument("Empty value provided");
788 int val = (int)strtol( &str[0], &endPtr, 10);
789 bool ok = (&str[0] != endPtr);
791 if ( isOk ) *isOk = ok;
795 std::string msg = "Not an integer value:'" + str + "'";
796 throw std::invalid_argument(msg);
800 //=============================================================================
801 bool MgAdapt::hasOptionDefined( const std::string& optionName ) const
803 bool isDefault = false;
806 getOptionValue( optionName, &isDefault );
808 catch ( std::invalid_argument )
814 //================================================================================
816 * \brief Return command to run MG-Adapt mesher excluding file prefix (-f)
818 //================================================================================
820 std::string MgAdapt::getCommandToRun(MgAdapt* hyp)
822 return hyp ? hyp->getCommandToRun() : ToComment("error with hypothesis!");
825 int MgAdapt::compute(std::string& errStr)
827 std::string cmd = getCommandToRun();
828 // std::cout << cmd << std::endl;
831 execCmd( cmd.c_str(), err ); // run
835 errStr = ToComment("system(mg-adapt.exe ...) command failed with error: ") << strerror( errno );
837 else if ( !isFileExist( meshFormatOutputMesh ))
839 errStr = ToComment(" failed to find file ") << meshFormatOutputMesh
840 << " output from MG-Adapt run";
844 convertMeshFile(meshFormatOutputMesh, solFormatOutput);
850 void MgAdapt::execCmd( const char* cmd, int& err)
853 std::array <char, 128> buffer;
855 outFileStream fileStream;
858 fileStream.open(logFile);
859 buf = fileStream.rdbuf();
863 buf = std::cout.rdbuf();
865 std::ostream logStream(buf);
869 # if defined(UNICODE)
870 const wchar_t * aCmd = Kernel_Utils::utf8_decode(cmd);
871 SMESHUtils::ArrayDeleter<const wchar_t> deleter( aCmd );
872 std::unique_ptr <FILE, decltype(&_pclose)> pipe(_wpopen(aCmd, O_RDONLY), _pclose );
874 std::unique_ptr <FILE, decltype(&_pclose)> pipe(_popen(cmd, "r"), _pclose );
877 std::unique_ptr <FILE, decltype(&pclose)> pipe(popen(cmd, "r"), pclose );
882 throw std::runtime_error("popen() failed!");
884 while(fgets(buffer.data(), buffer.size(), pipe.get()) !=nullptr )
886 logStream<<buffer.data() ;
891 * to delete tmp files .mesh, .sol and if needed
895 void MgAdapt::cleanUp()
899 if(toKeepWorkingFiles)
901 if(removeOnSuccess && printLogInFile)
902 tmpFilesToBeDeleted.push_back(logFile);
904 std::vector< std::string>::iterator it = tmpFilesToBeDeleted.begin();
905 for (; it!=tmpFilesToBeDeleted.end(); ++it)
907 errStr=removeFile(*it, notOk);
910 appendMsgToLogFile(errStr);
916 void MgAdapt::appendMsgToLogFile(std::string& msg)
918 std::ofstream logStream;
919 logStream.open(logFile, std::ofstream::out | std::ofstream::app);
923 //================================================================================
925 * \brief Return command to run MG-Tetra mesher excluding file prefix (-f)
927 //================================================================================
929 std::string MgAdapt::getCommandToRun()
932 || return system command with args and options
936 std::string cmd = getExeName();
937 std::string meshIn(""), sizeMapIn(""), solFileIn("");
938 updateTimeStepRank();
939 convertMedFile(meshIn, solFileIn, sizeMapIn);
940 if (!isFileExist(meshIn) || !isFileExist(solFileIn))
942 errStr = ToComment(" failed to find .mesh or .sol file from converter ")<< strerror( errno );
945 tmpFilesToBeDeleted.push_back(meshIn);
946 tmpFilesToBeDeleted.push_back(solFileIn);
947 if(useBackgroundMap && !isFileExist(sizeMapIn))
949 errStr = ToComment(" failed to find .mesh size map file from converter ")<< strerror( errno );
953 cmd+= " --in "+ meshIn;
954 meshFormatOutputMesh = getFileName()+".mesh";
955 tmpFilesToBeDeleted.push_back(meshFormatOutputMesh);
956 cmd+= " --out "+ meshFormatOutputMesh;
957 if (useLocalMap || useConstantValue) cmd+= " --sizemap "+ solFileIn;
958 else // (useBackgroundMap)
960 cmd+= " --background_mesh "+ sizeMapIn ;
961 cmd+= " --background_sizemap "+ solFileIn;
962 tmpFilesToBeDeleted.push_back(sizeMapIn);
966 //~// constant value TODO
968 // Check coherence between mesh dimension and option fo adaptation
969 checkDimensionOptionAdaptation();
971 // sizemap file is written only if level is higher than 3
972 if ( verbosityLevel > 3)
974 std::string solFileOut = getFileName()+".sol";
975 cmd+= " --write_sizemap "+ solFileOut;
976 solFormatOutput.push_back(solFileOut);
977 tmpFilesToBeDeleted.push_back(solFileOut);
980 std::string option, value;
982 const TOptionValues* options[] = { &_option2value, &_customOption2value };
983 for ( int iOp = 0; iOp < 2; ++iOp )
985 TOptionValues::const_iterator o2v = options[iOp]->begin();
986 for ( ; o2v != options[iOp]->end(); ++o2v )
989 value = getOptionValue( option, &isDefault );
993 if ( value.empty() )//value == NoValue() )
995 if ( _defaultOptionValues.count( option ))
996 continue; // non-custom option with no value
999 if ( strncmp( "no", option.c_str(), 2 ) == 0 ) // options w/o values: --no_*
1001 if ( !value.empty() && toBool( value ) == false )
1005 if ( option[0] != '-' )
1009 // std::cout << "--- option: '" << option << ", value: '" << value <<"'"<< std::endl;
1010 cmd += option + " " + value;
1015 if (verbosityLevel != defaultVerboseLevel())
1017 cmd+= " --verbose "+ ToComment(verbosityLevel);
1024 // std::cout << "--- cmd :"<< std::endl;
1025 // std::cout << cmd << std::endl;
1030 //=======================================================================
1031 //function : defaultMaximumMemory
1032 //=======================================================================
1035 #include <windows.h>
1036 #elif !defined(__APPLE__)
1037 #include <sys/sysinfo.h>
1040 double MgAdapt::defaultMaximumMemory()
1043 // See http://msdn.microsoft.com/en-us/library/aa366589.aspx
1044 MEMORYSTATUSEX statex;
1045 statex.dwLength = sizeof (statex);
1046 long err = GlobalMemoryStatusEx (&statex);
1049 double totMB = (double)statex.ullAvailPhys / 1024. / 1024.;
1050 return (double)( 0.7 * totMB );
1052 #elif !defined(__APPLE__)
1054 long err = sysinfo( &si );
1057 long ramMB = si.totalram * si.mem_unit / 1024 / 1024;
1058 return ( 0.7 * double( ramMB ));
1064 //=======================================================================
1065 //function : defaultWorkingDirectory
1066 //=======================================================================
1068 std::string MgAdapt::defaultWorkingDirectory()
1070 std::string aTmpDir;
1072 char *Tmp_dir = getenv("SALOME_TMP_DIR");
1086 //================================================================================
1088 * \brief Return a unique file name
1090 //================================================================================
1092 std::string MgAdapt::getFileName() const
1094 std::string aTmpDir = workingDir;
1095 const char lastChar = *aTmpDir.rbegin();
1097 if(lastChar != '\\') aTmpDir+='\\';
1099 if(lastChar != '/') aTmpDir+='/';
1102 SMESH_Comment aGenericName( aTmpDir );
1103 aGenericName << "MgAdapt_";
1105 aGenericName << getpid();
1107 aGenericName << _getpid();
1109 aGenericName << "_";
1110 aGenericName << std::abs((int)(long) aGenericName.data());
1112 return aGenericName;
1114 //=======================================================================
1115 //function : defaultLogFile
1116 //=======================================================================
1118 std::string MgAdapt::defaultLogFile()
1120 std::string alogFile("MG_ADAPT.log");
1123 //=======================================================================
1124 //function : defaultUseConstantValue
1125 //=======================================================================
1127 bool MgAdapt::defaultUseConstantValue()
1131 //=======================================================================
1132 //function : defaultUseNoTimeStep
1133 //=======================================================================
1135 bool MgAdapt::defaultUseNoTimeStep()
1139 //=======================================================================
1140 //function : defaultRemoveLogOnSuccess
1141 //=======================================================================
1143 bool MgAdapt::defaultRemoveLogOnSuccess()
1147 //=======================================================================
1148 //function : defaultPrintLogInFile
1149 //=======================================================================
1151 bool MgAdapt::defaultPrintLogInFile()
1155 //=======================================================================
1156 //function : defaultUseChosenTimeStep
1157 //=======================================================================
1159 bool MgAdapt::defaultUseChosenTimeStep()
1163 //=======================================================================
1164 //function : UseLastTimeStep
1165 //=======================================================================
1167 bool MgAdapt::defaultUseLastTimeStep()
1171 //=======================================================================
1172 //function : defaultUseBackgroundMap
1173 //=======================================================================
1175 bool MgAdapt::defaultUseBackgroundMap()
1179 //=======================================================================
1180 //function : defaultKeepFiles
1181 //=======================================================================
1183 bool MgAdapt::defaultKeepFiles()
1187 //=======================================================================
1188 //function : defaultUseLocalMap
1189 //=======================================================================
1191 bool MgAdapt::defaultUseLocalMap()
1195 //=======================================================================
1196 //function : defaultPublish
1197 //=======================================================================
1199 bool MgAdapt::defaultPublish()
1203 //=======================================================================
1204 //function : defaultMeshOutMed
1205 //=======================================================================
1207 bool MgAdapt::defaultMeshOutMed()
1211 //=======================================================================
1212 //function : defaultFromMedFile
1213 //=======================================================================
1215 bool MgAdapt::defaultFromMedFile()
1219 //=======================================================================
1220 //function : defaultVerboseLevel
1221 //=======================================================================
1223 int MgAdapt::defaultVerboseLevel()
1227 std::string MgAdapt::getExeName()
1229 return "mg-adapt.exe";
1231 void MgAdapt::copyMgAdaptHypothesisData( const MgAdaptHypothesisData* from)
1233 data->myFileInDir = from->myFileInDir;
1234 data->myMeshFileIn = from->myMeshFileIn;
1235 data->myMeshFileBackground = from->myMeshFileBackground;
1236 data->myOutMeshName = from->myOutMeshName;
1237 data->myMeshFileOut = from->myMeshFileOut;
1238 data->myFileOutDir = from->myFileOutDir;
1239 data->myFileSizeMapDir = from->myFileSizeMapDir;
1240 data->myFieldName = from->myFieldName;
1241 data->fromMedFile = from->fromMedFile;
1242 data->myPublish = from->myPublish;
1243 data->myMeshOutMed = from->myMeshOutMed;
1244 data->myUseLocalMap = from->myUseLocalMap;
1245 data->myUseBackgroundMap = from->myUseBackgroundMap;
1246 data->myUseConstantValue = from->myUseConstantValue;
1247 data->myConstantValue = from->myConstantValue;
1248 data->myTimeStep = from->myTimeStep;
1249 data->myRank = from->myRank;
1250 data->myUseNoTimeStep = from->myUseNoTimeStep;
1251 data->myUseLastTimeStep = from->myUseLastTimeStep;
1252 data->myUseChosenTimeStep = from->myUseChosenTimeStep;
1253 data->myWorkingDir = from->myWorkingDir;
1254 data->myLogFile = from->myLogFile;
1255 data->myPrintLogInFile = from->myPrintLogInFile;
1256 data->myKeepFiles = from->myKeepFiles;
1257 data->myRemoveLogOnSuccess = from->myRemoveLogOnSuccess;
1258 data->myVerboseLevel = from->myVerboseLevel;
1261 std::vector<std::string> MgAdapt::getListFieldsNames(std::string fileIn)
1263 MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(fileIn);
1264 std::vector<std::string> listFieldsNames(mfd->getFields()->getFieldsNames());
1265 return listFieldsNames ;
1268 void MgAdapt::checkDimensionOptionAdaptation()
1270 // Quand le maillage est 3D, tout est possible
1271 // Quand le maillage est 2D, il faut 'surface' sauf si carte de fonds 3D
1272 MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(medFileIn);
1273 int meshdim = mfd->getMeshes()->getMeshAtPos(0)->getMeshDimension() ;
1274 // std::cout << "meshdim = " << meshdim << std::endl;
1278 std::string optionName = "adaptation";
1279 std::string optionValue = getOptionValue(optionName);
1280 // std::cout << "optionValue = '" << optionValue <<"'"<< std::endl;
1281 bool a_tester = false ;
1282 // carte locale ou constante : impératif d'avoir "surface"
1283 if ( useLocalMap || useConstantValue) a_tester = true ;
1284 // carte de fond : impératif d'avoir "surface" si le fonds est aussi 2D
1287 MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfdbg = MEDCoupling::MEDFileData::New(sizeMapFile);
1288 int meshdimbg = mfdbg->getMeshes()->getMeshAtPos(0)->getMeshDimension() ;
1289 // std::cout << "meshdimbg = " << meshdimbg << std::endl;
1290 if ( meshdimbg == 2 ) a_tester = true ;
1294 if ( optionValue == "" ) setOptionValue (optionName, "surface");
1297 if ( optionValue != "surface" )
1299 THROW_SALOME_EXCEPTION("Mesh dimension is 2; the option should be 'surface'"
1300 " instead of '" << optionValue << "'.");
1307 void MgAdapt::checkFieldName(std::string fileIn)
1310 std::vector<std::string> listFieldsNames = getListFieldsNames(fileIn);
1311 std::size_t jaux(listFieldsNames.size());
1312 for(std::size_t j=0;j<jaux;j++)
1314 if ( fieldName == listFieldsNames[j] )
1322 std::cout << "Available field names:" << std::endl;
1323 for(std::size_t j=0;j<jaux;j++)
1324 { std::cout << listFieldsNames[j] << std::endl;}
1325 THROW_SALOME_EXCEPTION( "Field " << fieldName << " is not found.");
1329 void MgAdapt::checkTimeStepRank(std::string fileIn)
1332 MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(fileIn);
1333 MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeFieldMultiTS> fts( mfd->getFields()->getFieldWithName(fieldName) );
1334 std::vector<double> timevalue;
1335 std::vector< std::pair<int,int> > timesteprank = fts->getTimeSteps(timevalue);
1336 std::size_t jaux(timesteprank.size());
1337 for(std::size_t j=0;j<jaux;j++)
1339 if ( ( timeStep == timesteprank[j].first ) & ( rank == timesteprank[j].second ) )
1347 std::cout << "Available (Time step, Rank):" << std::endl;
1348 for(std::size_t j=0;j<jaux;j++)
1349 { std::cout << "(Time step = " << timesteprank[j].first << ", Rank = " << timesteprank[j].second << ")" << std::endl;}
1350 THROW_SALOME_EXCEPTION("(Time step = " << timeStep << ", Rank = " << rank << ") is not found.");
1354 void MgAdapt::convertMedFile(std::string& meshFormatMeshFileName, std::string& solFormatFieldFileName, std::string& meshFormatsizeMapFile)
1356 std::vector<std::string> fieldFileNames;
1357 MEDCoupling::MeshFormatWriter writer;
1358 MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = MEDCoupling::MEDFileData::New(medFileIn);
1359 MEDCoupling::MEDFileMeshes* meshes = mfd->getMeshes();
1360 MEDCoupling::MEDFileMesh* fileMesh = meshes->getMeshAtPos(0); // ok only one mesh in file!
1361 if (meshNameOut =="")
1362 meshNameOut = fileMesh->getName();
1363 storeGroupsAndFams(fileMesh);
1365 MEDCoupling::MCAuto<MEDCoupling::MEDFileFields> fields = MEDCoupling::MEDFileFields::New();
1366 solFormatFieldFileName = getFileName();
1367 solFormatFieldFileName+=".sol";
1368 fieldFileNames.push_back(solFormatFieldFileName);
1370 if (useBackgroundMap)
1372 checkFieldName(sizeMapFile) ;
1373 checkTimeStepRank(sizeMapFile) ;
1374 meshFormatsizeMapFile = getFileName();
1375 meshFormatsizeMapFile += ".mesh";
1376 buildBackGroundMeshAndSolFiles(fieldFileNames, meshFormatsizeMapFile);
1378 else if(useLocalMap)
1380 checkFieldName(medFileIn) ;
1381 checkTimeStepRank(medFileIn) ;
1382 MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeFieldMultiTS> fts( mfd->getFields()->getFieldWithName(fieldName) );
1383 MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeField1TS> f = fts->getTimeStep(timeStep, rank);
1384 MEDCoupling::MCAuto<MEDCoupling::MEDFileFieldMultiTS> tmFts = MEDCoupling::MEDFileFieldMultiTS::New();
1385 tmFts->pushBackTimeStep(f);
1387 fields->pushField(tmFts);
1389 writer.setFieldFileNames( fieldFileNames);
1393 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingMesh> mesh = fileMesh->getMeshAtLevel(1); // nodes mesh
1394 MEDCoupling::MCAuto<MEDCoupling::MEDCouplingUMesh> umesh = mesh->buildUnstructured(); // nodes mesh
1395 int dim = umesh->getSpaceDimension();
1396 int version = sizeof(double) < 8 ? 1 : 2;
1397 mcIdType nbNodes = umesh->getNumberOfNodes();
1398 buildConstantSizeMapSolFile(solFormatFieldFileName, dim, version, nbNodes);
1401 mfd->setFields( fields );
1402 meshFormatMeshFileName = getFileName();
1403 meshFormatMeshFileName+=".mesh";
1404 writer.setMeshFileName(meshFormatMeshFileName);
1405 writer.setMEDFileDS( mfd);
1410 void MgAdapt::convertMeshFile(std::string& meshFormatIn, std::vector< std::string>& solFieldFileNames) const
1412 MEDCoupling::MeshFormatReader reader(meshFormatIn, solFieldFileNames);
1414 MEDCoupling::MCAuto<MEDCoupling::MEDFileData> mfd = reader.loadInMedFileDS();
1416 MEDCoupling::MEDFileMeshes* meshes = mfd->getMeshes();
1417 MEDCoupling::MEDFileMesh* fileMesh = meshes->getMeshAtPos(0); // ok only one mesh in file!
1418 fileMesh->setName(meshNameOut);
1419 restoreGroupsAndFams(fileMesh);
1420 mfd->write(medFileOut, 2);
1423 void MgAdapt::storeGroupsAndFams(MEDCoupling::MEDFileMesh* fileMesh)
1425 storefams(fileMesh);
1426 storeGroups(fileMesh);
1429 void MgAdapt::restoreGroupsAndFams(MEDCoupling::MEDFileMesh* fileMesh) const
1431 restorefams(fileMesh);
1432 restoreGroups(fileMesh);
1434 void MgAdapt::storeGroups(MEDCoupling::MEDFileMesh* fileMesh)
1436 std::map<std::string, std::vector<std::string> > grpFams = fileMesh->getGroupInfo();
1437 std::map<std::string, std::vector<std::string> >::iterator g2ff = grpFams.begin();
1439 for ( ; g2ff != grpFams.end(); ++g2ff )
1441 std::string groupName = g2ff->first;
1442 std::vector<std::string> famNames = g2ff->second;
1444 if ( famNames.empty() ) continue;
1445 std::vector< int> famListId;
1446 for ( size_t i = 0; i < famNames.size(); ++i )
1448 famListId.push_back( FromIdType<int>( fileMesh->getFamilyId( famNames[i].c_str() )));
1450 group grp(groupName, famListId, famNames);
1451 groupVec.push_back(grp);
1455 void MgAdapt::storefams(MEDCoupling::MEDFileMesh* fileMesh)
1457 std::map<std::string, mcIdType> grpFams = fileMesh->getFamilyInfo();
1458 std::map<std::string, mcIdType >::iterator f = grpFams.begin();
1460 for ( ; f != grpFams.end(); ++f )
1462 if(!f->second) continue; // FAMILLE_ZERO
1463 family fs(f->first, FromIdType<int>( f->second ));
1464 famVec.push_back(fs);
1469 void MgAdapt::restorefams(MEDCoupling::MEDFileMesh* fileMesh) const
1471 std::vector<family>::const_iterator fIt = famVec.begin();
1473 for (; fIt!=famVec.end(); ++fIt)
1477 std::string givenFamNameFromMeshGemConverter = fileMesh->getFamilyNameGivenId( std::abs(fIt->_famId) );
1478 fileMesh->changeFamilyId(std::abs(fIt->_famId), fIt->_famId);
1479 fileMesh->changeFamilyName(givenFamNameFromMeshGemConverter, fIt->_famName);
1481 catch (const std::exception& e)
1483 std::cerr<<e.what();
1488 void MgAdapt::restoreGroups(MEDCoupling::MEDFileMesh* fileMesh) const
1490 std::map<std::string, std::vector<std::string> > info;
1491 std::vector <group>::const_iterator grpFams = groupVec.begin();
1493 for (; grpFams!=groupVec.end(); ++grpFams)
1495 info.insert(std::pair <std::string, std::vector<std::string> > (grpFams->_name, grpFams->_famNames) );
1498 fileMesh->setGroupInfo(info);
1501 void MgAdapt::buildConstantSizeMapSolFile(const std::string& solFormatFieldFileName, const int dim, const int version, const size_t nbNodes) const
1503 MeshFormat::Localizer loc;
1504 MeshFormat::MeshFormatParser writer;
1505 int fileId = writer.GmfOpenMesh( solFormatFieldFileName.c_str(), GmfWrite, version, dim);
1506 int typTab[] = {GmfSca};
1507 writer.GmfSetKwd(fileId, MeshFormat::GmfSolAtVertices, (int)nbNodes, 1, typTab);
1508 for (size_t i = 0; i<nbNodes; i++)
1510 double valTab[1] = {constantValue};
1511 writer.GmfSetLin( fileId, MeshFormat::GmfSolAtVertices, valTab);
1513 writer.GmfCloseMesh(fileId);
1516 void MgAdapt::buildBackGroundMeshAndSolFiles(const std::vector<std::string>& fieldFileNames, const std::string& meshFormatsizeMapFile) const
1518 MEDCoupling::MCAuto<MEDCoupling::MEDFileData> tmpMfd = MEDCoupling::MEDFileData::New(sizeMapFile);
1519 MEDCoupling::MEDFileFields* tmpFields = tmpMfd->getFields();
1520 MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeFieldMultiTS> fts( tmpFields->getFieldWithName(fieldName) );
1521 MEDCoupling::MCAuto<MEDCoupling::MEDFileFieldMultiTS> fts1 = MEDCoupling::DynamicCastSafe<MEDCoupling::MEDFileAnyTypeFieldMultiTS,MEDCoupling::MEDFileFieldMultiTS>(fts);
1522 MEDCoupling::MCAuto<MEDCoupling::MEDFileAnyTypeField1TS> f = fts1->getTimeStep(timeStep, rank);
1523 MEDCoupling::MCAuto<MEDCoupling::MEDFileFieldMultiTS> tmFts = MEDCoupling::MEDFileFieldMultiTS::New();
1524 tmFts->pushBackTimeStep(f);
1526 MEDCoupling::MCAuto<MEDCoupling::MEDFileFields> tmp_fields = MEDCoupling::MEDFileFields::New();
1527 tmp_fields->pushField(tmFts);
1529 tmpMfd->setFields( tmp_fields );
1530 MEDCoupling::MeshFormatWriter tmpWriter;
1531 tmpWriter.setMeshFileName(meshFormatsizeMapFile);
1532 tmpWriter.setFieldFileNames( fieldFileNames);
1533 tmpWriter.setMEDFileDS(tmpMfd);
1537 MgAdapt::Status MgAdapt::addMessage(const std::string& msg,
1538 const bool isFatal/*=false*/)
1541 _errorMessages.clear(); // warnings are useless if a fatal error encounters
1543 _errorMessages.push_back( msg );
1547 std::cout << msg << std::endl;
1549 return ( _status = isFatal ? MgAdapt::DRS_FAIL : MgAdapt::DRS_WARN_SKIP_ELEM );
1552 void MgAdapt::updateTimeStepRank()
1557 if (myUseNoTimeStep)
1561 setRankTimeStep((int)tmst, (int)arank);
1563 else if (myUseLastTimeStep)
1565 std::string fieldFile = useBackgroundMap ? sizeMapFile : medFileIn;
1566 getTimeStepInfos(fieldFile, tmst, arank, fieldName);
1567 setRankTimeStep((int)tmst, (int)arank);