Code_TYMPAN  4.4.0
Industrial site acoustic simulation
TYCalculManager.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) <2012-2024> <EDF-DTG> <FRANCE>
3  * This file is part of Code_TYMPAN (R).
4  * Code_TYMPAN (R) is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * Code_TYMPAN (R) 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.
11  * See the GNU General Public License for more details.
12  * You should have received a copy of the GNU General Public License along
13  * with Code_TYMPAN (R). If not, see <https://www.gnu.org/licenses/>.
14  */
15 
22 #include <qcursor.h>
23 #include <qmessagebox.h>
24 #include <QTemporaryFile>
25 
26 #include "Tympan/core/config.h"
27 #include "Tympan/core/chrono.h"
28 #include "Tympan/core/defines.h"
32 #include "Tympan/gui/app/os.h"
40 #include "TYCalculManager.h"
41 
42 #define TR(id) OLocalizator::getString("TYCalculManager", (id))
43 
44 // using namespace tympan;
45 
47 {
48  _pCurrentCalcul = NULL;
49 }
50 
52 {
53  _pCurrentCalcul = NULL;
54 }
55 
57 {
58  _pCurrentCalcul = pCalcul;
59 }
60 
62 {
63  return launch(_pCurrentCalcul);
64 }
65 
67 {
68  if (!pCalcul)
69  {
70  return false;
71  }
72 
73  if (pCalcul->getState() == TYCalcul::Locked)
74  {
75  OMessageManager::get()->info("+++ UN RESULTAT MESURE NE PEUX FAIRE L'OBJET D'UN CALCUL +++");
76  return true; // Si le calcul est bloque, il ne peut etre execute
77  }
78  // Keep track of old objects in order to clean them at best
79  // Issue #226
80  LPTYProjet oldProjet = pCalcul->getProjet();
81  LPTYSiteNode oldSite = oldProjet->getSite();
82  LPTYCalcul oldCalcul = oldProjet->getCurrentCalcul();
83 
84  TYProjet* pProject = pCalcul->getProjet();
85 
86  // Clear "calcul" result data before computing (avoid problems when removing some elements)
87  pCalcul->clearResult();
88 
90 
91  // Is the debug option "TYMPAN_DEBUG=keep_tmp_files" enabled?
92  bool keep_tmp_files = must_keep_tmp_files();
93  // Temporary XML files to give the current acoustic problem to the python
94  // script and get the results
95  QTemporaryFile problemfile;
96  problemfile.setFileTemplate(QDir::tempPath() + QString("/XXXXXX.xml"));
97  QTemporaryFile resultfile;
98  resultfile.setFileTemplate(QDir::tempPath() + QString("/XXXXXX.xml"));
99 
100  QFileInfo fileInfo(getTYApp()->getCurrentFileName());
101  QString meshFilePath = fileInfo.path().replace("\\", "/") + "/" + fileInfo.baseName() + "." + "ply";
102 
103  if (!init_tmp_file(problemfile, keep_tmp_files) || !init_tmp_file(resultfile, keep_tmp_files))
104  {
105  logger.error(
106  "Creation de fichier temporaire impossible. Veuillez verifier l'espace disque disponible.");
107  return false;
108  }
109  // Serialize current project
110  try
111  {
112  tympan::save_project(problemfile.fileName().toUtf8().data(), pProject);
113  }
114  catch (const tympan::invalid_data& exc)
115  {
116  std::ostringstream msg;
117  msg << boost::diagnostic_information(exc);
118  logger.error("Could not export current project. Computation won't be done");
119  logger.debug(msg.str().c_str());
120  return false;
121  }
122  if (keep_tmp_files)
123  {
124  logger.debug("Le calcul va s'executer en mode debug.\nLes fichiers temporaires ne seront pas "
125  "supprimes une fois le calcul termine.\nProjet courant non calcule: %s. Projet avec les "
126  "resultats du calcul: %s. Mesh de l'altimetrie au format ply: %s",
127  problemfile.fileName().toStdString().c_str(),
128  resultfile.fileName().toStdString().c_str());
129  }
130 
131  // Call python script "solve_tympan_project.py" with: the name of the file
132  // containing the problem, the name of the file where to record
133  // the result and the directory containing the solver plugin to use
134  // to solve the acoustic problem
135  QStringList args;
136  QString absolute_plugins_path(QCoreApplication::applicationDirPath());
137  absolute_plugins_path.append("/");
138  absolute_plugins_path.append(PLUGINS_PATH);
139  QString absolute_pyscript_path(QCoreApplication::applicationDirPath());
140  absolute_pyscript_path.append("/");
141  absolute_pyscript_path.append(SOLVE_PYSCRIPT);
142  args << absolute_pyscript_path << problemfile.fileName() << resultfile.fileName() << meshFilePath
143  << absolute_plugins_path;
144 
145  // Altimetry parameters
146 
147  QString parameters = pCalcul->solverParams;
148  QRegularExpression altimetry_size_criterion_reg("(MeshElementSizeMax\\s?=\\s?)([0-9]+.[0-9]*)");
149  QRegularExpression altimetry_refine_mesh_reg("(RefineMesh\\s?=\\s?)(True|False)");
150  QRegularExpression altimetry_use_volumes_landtakes_reg("(UseVolumesLandtake\\s?=\\s?)(True|False)");
151  QRegularExpressionMatch match_size = altimetry_size_criterion_reg.match(parameters);
152  QRegularExpressionMatch match_refi = altimetry_refine_mesh_reg.match(parameters);
153  QRegularExpressionMatch match_land = altimetry_use_volumes_landtakes_reg.match(parameters);
154 
155  bool altiIsOK = oldSite->getAltimetry()->isUpToDate();
156 
157  if (match_size.hasMatch() && match_refi.hasMatch() && match_land.hasMatch())
158  {
159  QString altimetry_size_criterion = match_size.captured(2);
160  QString altimetry_refine_mesh = match_refi.captured(2);
161  QString altimetry_use_volumes_landtakes = match_land.captured(2);
162  QString altimetry_update = (altiIsOK) ? QString("False") : QString("True");
163 
164  args << altimetry_size_criterion << altimetry_refine_mesh << altimetry_use_volumes_landtakes
165  << altimetry_update;
166  }
167  logger.info(TR("id_msg_go_calcul"));
168 
169  if (!python_gui(args))
170  {
171  return false;
172  }
173  // Then read the result to update the internal model
174  LPTYProjet result;
175  try
176  {
177  // Before loading result project, set current working directory of the application to working
178  // directory to ensure correct loading of topographic file.
180  result = tympan::load_project(resultfile.fileName().toUtf8().data());
181  }
182  catch (const tympan::invalid_data& exc)
183  {
184  std::ostringstream msg;
185  msg << boost::diagnostic_information(exc);
186  logger.error("Could not import computed project. No results available.");
187  logger.debug(msg.str().c_str());
188  QMessageBox msgBox;
189  msgBox.setText("Le fichier de resultats n'a pas pu etre lu.");
190  msgBox.exec();
191  return false;
192  }
193  // Update the current project with the results of the current acoustic
194  // problem
195  pProject = result.getRealPointer();
196  pCalcul = pProject->getCurrentCalcul();
197  getTYApp()->setCurProjet(result);
198  getTYMainWnd()->getProjetFrame()->setProjet(pProject);
199  // Update site altimetry with the mesh retrieved from the ply file
200  LPTYSiteNode pSite = pProject->getSite();
201  std::deque<OPoint3D> points;
202  std::deque<OTriangle> triangles;
203  std::deque<LPTYSol> materials;
204  pSite->readMesh(points, triangles, materials, meshFilePath);
205  pSite->setMeshFilePath(meshFilePath);
206  pSite->getAltimetry()->plugBackTriangulation(points, triangles, materials);
207  // If altimetry was already up to date, it is loaded from .ply
208  if (!altiIsOK)
209  {
210  // One global altimetry update for all the sites
211  pSite->updateAltimetrie(meshFilePath);
212  }
213  pSite->getAltimetry()->setIsUpToDate(true);
214  pSite->updateAltiInfra();
215  pSite->updateAcoustique();
216  pProject->updateAltiRecepteurs();
217  // Update graphics
218  pCalcul->getParent()->updateGraphicTree();
219  pCalcul->updateGraphicTree();
220 
221  // Update modeler frames after computation
223 
224  // Clean at best old project, site and calcul by removing references on them
225  oldCalcul->setSite(NULL);
226  oldSite->setProjet(NULL);
227  oldProjet->remAllCalcul();
228  oldProjet->remAllMaillage();
229  oldProjet->remAllPointControl();
230  oldProjet->unsetSite();
231 
232  getTYMainWnd()->updateModelers(false, false);
234  // Update projet frame
236  // Reset ActionManager
237  // TODO Reset ActionManager for all modelers
238  if (getTYMainWnd()->getCurrentModeler())
240  // Computation achieved with success
241  logger.info(TR("id_msg_calcul_done"));
242  return true;
243 }
244 
246 {
247  bool ret = true;
248  TYCalcul* pCalcul = NULL;
249  TYProjet* pProjet = getTYApp()->getCurProjet().getRealPointer();
250  if (pProjet)
251  {
252  pCalcul = pProjet->getCurrentCalcul();
253  }
254  else
255  {
256  return true;
257  }
258 
259  if (pCalcul)
260  {
261  ret = true;
263 
264  /*// Question
265  int del = QMessageBox::Yes;
266  if (pCalcul->getIsAcousticModified())
267  {
268  del = QMessageBox::warning(getTYMainWnd(), getTYMainWnd()->windowTitle(),
269  TR("id_msg_del_resultat"), QMessageBox::Yes, QMessageBox::No);
270  }
271  if (del == QMessageBox::Yes)
272  {
273  // Ok pour effacer les resultats (uniquement si c'est un resultat calcule);
274  if (pCalcul->getState() == TYCalcul::Actif)
275  {
276  // Reset du resultat
277  pCalcul->getResultat()->purge();
278  for (unsigned int i=0 ; i<pProjet->getPointsControl().size() ; i++)
279  {
280  pProjet->getPointsControl()[i]->purge(pCalcul);
281  }
282 
283  pCalcul->setIsAcousticModified(false); // La calcul est a jour
284  }
285 
286  ret = true;
287  }
288  else
289  {
290  ret = false;
291  }*/
292  }
293 
294  return ret;
295 }
296 
298 {
299  bool ret = false;
300  TYSiteNode* pSite = dynamic_cast<TYSiteNode*>(pElement);
301  if (pSite != nullptr)
302  {
303  pSite->updateAcoustique();
304  }
305  LPTYAcousticVolumeNode pAccVolNode = dynamic_cast<TYAcousticVolumeNode*>(pElement);
306  if (pAccVolNode._pObj != nullptr)
307  {
308  TYMessageManager::get()->info(TR("id_msg_go_updateacoustic"));
309 
310  TYApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
311 
312  // Calcul acoustique
313  ret = pAccVolNode->updateAcoustic();
314 
315  if (ret)
316  {
317  TYMessageManager::get()->info(TR("id_msg_updateacoustic_done"));
318  }
319  else
320  {
321  TYMessageManager::get()->info(TR("id_msg_updateacoustic_failed"));
322  }
323 
324  // MaJ graphique
325  pAccVolNode->getGraphicObject()->update(true);
326  getTYMainWnd()->updateModelers(false, false);
327 
328  TYApplication::restoreOverrideCursor();
329  }
330  else
331  {
332  LPTYAcousticLine pLine = dynamic_cast<TYAcousticLine*>(pElement);
333  if (pLine._pObj != nullptr)
334  {
335  TYMessageManager::get()->info(TR("id_msg_go_updateacoustic"));
336 
337  TYApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
338 
339  // Calcul acoustique
340  ret = pLine->updateAcoustic();
341 
342  if (ret)
343  {
344  TYMessageManager::get()->info(TR("id_msg_updateacoustic_done"));
345  }
346  else
347  {
348  TYMessageManager::get()->info(TR("id_msg_updateacoustic_failed"));
349  }
350 
351  // MaJ graphique
352  pLine->getGraphicObject()->update(true);
353  getTYMainWnd()->updateModelers(false, false);
354 
355  TYApplication::restoreOverrideCursor();
356  }
357  }
358 
359  return ret;
360 }
TYApplication * getTYApp()
Retourne le pointeur sur l'application.
TYMainWindow * getTYMainWnd()
Retourne le pointeur sur la fenetre principale.
pour l'application Tympan (fichier header)
#define TR(id)
Gestionnaire des calculs acoustiques. Il fait l'interface entre l'IHM et le gestionnaire de donnees p...
Fenetre principale de l'application Tympan (fichier header)
utilitaire pour la gestion des messages dans Tympan (fichier header)
Classe generique pour une fenetre de modeleur (fichier header)
Frame pour la gestion de projet (fichier header)
Frame pour la gestion de site (fichier header)
Classe Modeler specialisee pour l'edition des sites (fichier header)
virtual void debug(const char *message,...)
Definition: logging.cpp:151
virtual void error(const char *message,...)
Definition: logging.cpp:127
static OMessageManager * get()
Definition: logging.cpp:108
virtual void info(const char *message,...)
Definition: logging.cpp:143
T * getRealPointer()
Definition: smartptr.h:291
T * _pObj
The real pointer, must derived IRefCount.
Definition: smartptr.h:307
virtual bool updateAcoustic(const bool &force=false)
void reset()
Reinitialise l'historique.
bool isUpToDate() const
Definition: TYAltimetrie.h:176
void plugBackTriangulation(const std::deque< OPoint3D > &points, std::deque< OTriangle > &triangles, const std::deque< LPTYSol > &materials)
plug back triangulation providfed by the TYTopographie
void setIsUpToDate(bool isUpToDate)
static void setCurrentQtDir()
Indique Ã&#160; Qt le chemin du répertoire courant.
LPTYProjet getCurProjet()
Set/Get du projet courant.
void setCurProjet(LPTYProjet pProjet)
Set/Get du projet courant.
virtual ~TYCalculManager()
Destructeur.
bool launchCurrent()
Execute le calcul courant.
bool updateAcoustic(TYElement *pElement)
Appelle la methode de calcul acoustique du volume node passe.
bool askForResetResultat()
Previent l'utilisateur que le resultat va etre efface, si celui-ci est valide.
bool launch(LPTYCalcul pCalcul)
Execute un calcul.
LPTYCalcul _pCurrentCalcul
Le Calcul courant.
void setCurrent(LPTYCalcul pCalcul)
Set du Calcul et Projet courant.
TYCalculManager()
Constructeur par defaut.
Calculation program.
Definition: TYCalcul.h:50
void clearResult()
Definition: TYCalcul.cpp:845
int getState()
Get calculation state.
Definition: TYCalcul.h:416
void setSite(LPTYSiteNode pSite)
Definition of the site on which the calculation will be done.
Definition: TYCalcul.cpp:868
@ Locked
Definition: TYCalcul.h:62
QString solverParams
Definition: TYCalcul.h:482
TYProjet * getProjet()
Definition: TYCalcul.cpp:67
TYElement * getParent() const
Definition: TYElement.h:697
static void setIsSavedOk(const bool &toSave)
Definition: TYElement.h:905
void updateModelersAfterComputation(LPTYProjet &result)
TYProjetFrame * getProjetFrame()
Definition: TYMainWindow.h:73
void updateModelers(bool clipping=true, bool axesAndGrid=true, bool displayList=true)
TYModelerFrame * getCurrentModeler()
Definition: TYMainWindow.h:68
TYActionManager * getActionManager()
void setCalculDone(bool state)
void setProjet(LPTYProjet pProjet)
classe de definition d'un projet.
Definition: TYProjet.h:45
bool remAllPointControl()
Definition: TYProjet.cpp:486
bool updateAltiRecepteurs()
Definition: TYProjet.cpp:632
bool remAllMaillage()
Suppression de tous les maillages.
Definition: TYProjet.cpp:898
LPTYSiteNode getSite()
Get du site.
Definition: TYProjet.h:169
void unsetSite()
Supprime la liaison avec le site.
Definition: TYProjet.cpp:555
LPTYCalcul getCurrentCalcul()
Set/Get du pointeur du Calcul courant.
Definition: TYProjet.h:426
void remAllCalcul()
Suppression de tous les elements.
Definition: TYProjet.cpp:550
void setProjet(const LPTYProjet pProjet)
Definition: TYSiteNode.cpp:557
LPTYAltimetrie getAltimetry() const
bool readMesh(std::deque< OPoint3D > &points, std::deque< OTriangle > &triangles, std::deque< LPTYSol > &materials, const QString &meshFilePath)
Definition: TYSiteNode.cpp:731
virtual void updateAcoustique(const bool &force=false)
void setMeshFilePath(const QString &path)
Definition: TYSiteNode.cpp:64
virtual bool updateAltimetrie(QString resultMeshFilePath)
Definition: TYSiteNode.cpp:625
virtual void updateAltiInfra()
Definition: TYSiteNode.cpp:781
void save_project(const char *filename, const LPTYProjet &project)
save a project into an XML file
LPTYProjet load_project(const char *filename)
load an XML project file
bool python_gui(QStringList args)
Launch a Python-driven computation with a GUI progress dialog.
Definition: os.cpp:45
Utilities for interactions between the GUI and the operating system (headers).
The base exception class for errors due to invalid data.
Definition: exceptions.h:75
bool must_keep_tmp_files()
Tell whether temporary files should be preserved (debug mode).
bool init_tmp_file(QTemporaryFile &tmp_file, bool keep_file)
Create and initialize a QTemporaryFile according to the current policy.
Utilities to interact with Python subprocesses from the Tympan application.
Utilities to load a project and a solver.