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 =
102  fileInfo.path().replace("\\", "/") + "/" + fileInfo.completeBaseName() + "." + "ply";
103 
104  if (!init_tmp_file(problemfile, keep_tmp_files) || !init_tmp_file(resultfile, keep_tmp_files))
105  {
106  logger.error(
107  "Creation de fichier temporaire impossible. Veuillez verifier l'espace disque disponible.");
108  return false;
109  }
110  // Serialize current project
111  try
112  {
113  tympan::save_project(problemfile.fileName().toUtf8().data(), pProject);
114  }
115  catch (const tympan::invalid_data& exc)
116  {
117  std::ostringstream msg;
118  msg << boost::diagnostic_information(exc);
119  logger.error("Could not export current project. Computation won't be done");
120  logger.debug(msg.str().c_str());
121  return false;
122  }
123  if (keep_tmp_files)
124  {
125  logger.debug("Le calcul va s'executer en mode debug.\nLes fichiers temporaires ne seront pas "
126  "supprimes une fois le calcul termine.\nProjet courant non calcule: %s. Projet avec les "
127  "resultats du calcul: %s.",
128  problemfile.fileName().toStdString().c_str(),
129  resultfile.fileName().toStdString().c_str());
130  }
131 
132  // Call python script "solve_tympan_project.py" with: the name of the file
133  // containing the problem, the name of the file where to record
134  // the result and the directory containing the solver plugin to use
135  // to solve the acoustic problem
136  QStringList args;
137  QString absolute_plugins_path(QCoreApplication::applicationDirPath());
138  absolute_plugins_path.append("/");
139  absolute_plugins_path.append(PLUGINS_PATH);
140  QString absolute_pyscript_path(QCoreApplication::applicationDirPath());
141  absolute_pyscript_path.append("/");
142  absolute_pyscript_path.append(SOLVE_PYSCRIPT);
143  args << absolute_pyscript_path << problemfile.fileName() << resultfile.fileName() << meshFilePath
144  << absolute_plugins_path;
145 
146  // Altimetry parameters
147 
148  QString parameters = pCalcul->solverParams;
149  QRegularExpression altimetry_size_criterion_reg("(MeshElementSizeMax\\s?=\\s?)([0-9]+.[0-9]*)");
150  QRegularExpression altimetry_refine_mesh_reg("(RefineMesh\\s?=\\s?)(True|False)");
151  QRegularExpression altimetry_use_volumes_landtakes_reg("(UseVolumesLandtake\\s?=\\s?)(True|False)");
152  QRegularExpressionMatch match_size = altimetry_size_criterion_reg.match(parameters);
153  QRegularExpressionMatch match_refi = altimetry_refine_mesh_reg.match(parameters);
154  QRegularExpressionMatch match_land = altimetry_use_volumes_landtakes_reg.match(parameters);
155 
156  bool altiIsOK = oldSite->getAltimetry()->isUpToDate();
157 
158  if (match_size.hasMatch() && match_refi.hasMatch() && match_land.hasMatch())
159  {
160  QString altimetry_size_criterion = match_size.captured(2);
161  QString altimetry_refine_mesh = match_refi.captured(2);
162  QString altimetry_use_volumes_landtakes = match_land.captured(2);
163  QString altimetry_update = (altiIsOK) ? QString("False") : QString("True");
164 
165  args << altimetry_size_criterion << altimetry_refine_mesh << altimetry_use_volumes_landtakes
166  << altimetry_update;
167  }
168  logger.info(TR("id_msg_go_calcul"));
169 
170  if (!python_gui(args))
171  {
172  return false;
173  }
174  // Then read the result to update the internal model
175  LPTYProjet result;
176  try
177  {
178  // Before loading result project, set current working directory of the application to working
179  // directory to ensure correct loading of topographic file.
181  result = tympan::load_project(resultfile.fileName().toUtf8().data());
182  }
183  catch (const tympan::invalid_data& exc)
184  {
185  std::ostringstream msg;
186  msg << boost::diagnostic_information(exc);
187  logger.error("Could not import computed project. No results available.");
188  logger.debug(msg.str().c_str());
189  QMessageBox msgBox;
190  msgBox.setText("Le fichier de resultats n'a pas pu etre lu.");
191  msgBox.exec();
192  return false;
193  }
194  // Update the current project with the results of the current acoustic
195  // problem
196  pProject = result.getRealPointer();
197  pCalcul = pProject->getCurrentCalcul();
198  getTYApp()->setCurProjet(result);
199  getTYMainWnd()->getProjetFrame()->setProjet(pProject);
200  // Update site altimetry with the mesh retrieved from the ply file
201  LPTYSiteNode pSite = pProject->getSite();
202  std::deque<OPoint3D> points;
203  std::deque<OTriangle> triangles;
204  std::deque<LPTYSol> materials;
205  pSite->readMesh(points, triangles, materials, meshFilePath);
206  pSite->setMeshFilePath(meshFilePath);
207  pSite->getAltimetry()->plugBackTriangulation(points, triangles, materials);
208  // If altimetry was already up to date, it is loaded from .ply
209  if (!altiIsOK)
210  {
211  // One global altimetry update for all the sites
212  pSite->updateAltimetrie(meshFilePath);
213  }
214  pSite->getAltimetry()->setIsUpToDate(true);
215  pSite->updateAltiInfra();
216  pSite->updateAcoustique();
217  pProject->updateAltiRecepteurs();
218  // Update graphics
219  pCalcul->getParent()->updateGraphicTree();
220  pCalcul->updateGraphicTree();
221 
222  // Update modeler frames after computation
224 
225  // Clean at best old project, site and calcul by removing references on them
226  oldCalcul->setSite(NULL);
227  oldSite->setProjet(NULL);
228  oldProjet->remAllCalcul();
229  oldProjet->remAllMaillage();
230  oldProjet->remAllPointControl();
231  oldProjet->unsetSite();
232 
233  getTYMainWnd()->updateModelers(false, false);
235  // Update projet frame
237  // Reset ActionManager
238  // TODO Reset ActionManager for all modelers
239  if (getTYMainWnd()->getCurrentModeler())
241  // Computation achieved with success
242  logger.info(TR("id_msg_calcul_done"));
243  return true;
244 }
245 
247 {
248  if (!pRootSite)
249  {
250  return;
251  }
252 
253  TYApplication::setOverrideCursor(Qt::WaitCursor);
254 
255  writeOutputMsg(TR("id_msg_calculalti"));
256 
257  QFileInfo fileInfo(getTYApp()->getCurrentFileName());
258  QString resultMeshFilePath =
259  fileInfo.path().replace("\\", "/") + "/" + fileInfo.completeBaseName() + "." + "ply";
261  pRootSite->updateAltimetrie(resultMeshFilePath);
262  // Check altimetry update went well before using it
263  if (pRootSite->getAltimetry()->containsData())
264  {
265  // This method uses the altimetry above-computed to update the infrastructure
266  // as well as the receptors and sources and recurses on the current site and
267  // all its subsites
268  pRootSite->update();
269  LPTYProjet pProjet = pRootSite->getProjet();
270  if (pProjet)
271  {
272  writeOutputMsg(TR("id_msg_updatealtimaillages"));
273  pProjet->updateAltiRecepteurs();
274  }
275  pRootSite->getAltimetry()->setIsUpToDate(true);
277  }
278 
279  pRootSite->updateGraphicTree();
280  TYApplication::restoreOverrideCursor();
281 }
282 
284 {
285  bool ret = true;
286  TYCalcul* pCalcul = NULL;
287  TYProjet* pProjet = getTYApp()->getCurProjet().getRealPointer();
288  if (pProjet)
289  {
290  pCalcul = pProjet->getCurrentCalcul();
291  }
292  else
293  {
294  return true;
295  }
296 
297  if (pCalcul)
298  {
299  ret = true;
301 
302  /*// Question
303  int del = QMessageBox::Yes;
304  if (pCalcul->getIsAcousticModified())
305  {
306  del = QMessageBox::warning(getTYMainWnd(), getTYMainWnd()->windowTitle(),
307  TR("id_msg_del_resultat"), QMessageBox::Yes, QMessageBox::No);
308  }
309  if (del == QMessageBox::Yes)
310  {
311  // Ok pour effacer les resultats (uniquement si c'est un resultat calcule);
312  if (pCalcul->getState() == TYCalcul::Actif)
313  {
314  // Reset du resultat
315  pCalcul->getResultat()->purge();
316  for (unsigned int i=0 ; i<pProjet->getPointsControl().size() ; i++)
317  {
318  pProjet->getPointsControl()[i]->purge(pCalcul);
319  }
320 
321  pCalcul->setIsAcousticModified(false); // La calcul est a jour
322  }
323 
324  ret = true;
325  }
326  else
327  {
328  ret = false;
329  }*/
330  }
331 
332  return ret;
333 }
334 
336 {
337  bool ret = false;
338  TYSiteNode* pSite = dynamic_cast<TYSiteNode*>(pElement);
339  if (pSite != nullptr)
340  {
341  pSite->updateAcoustique();
342  }
343  LPTYAcousticVolumeNode pAccVolNode = dynamic_cast<TYAcousticVolumeNode*>(pElement);
344  if (pAccVolNode._pObj != nullptr)
345  {
346  TYMessageManager::get()->info(TR("id_msg_go_updateacoustic"));
347 
348  TYApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
349 
350  // Calcul acoustique
351  ret = pAccVolNode->updateAcoustic();
352 
353  if (ret)
354  {
355  TYMessageManager::get()->info(TR("id_msg_updateacoustic_done"));
356  }
357  else
358  {
359  TYMessageManager::get()->info(TR("id_msg_updateacoustic_failed"));
360  }
361 
362  // MaJ graphique
363  pAccVolNode->getGraphicObject()->update(true);
364  getTYMainWnd()->updateModelers(false, false);
365 
366  TYApplication::restoreOverrideCursor();
367  }
368  else
369  {
370  LPTYAcousticLine pLine = dynamic_cast<TYAcousticLine*>(pElement);
371  if (pLine._pObj != nullptr)
372  {
373  TYMessageManager::get()->info(TR("id_msg_go_updateacoustic"));
374 
375  TYApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
376 
377  // Calcul acoustique
378  ret = pLine->updateAcoustic();
379 
380  if (ret)
381  {
382  TYMessageManager::get()->info(TR("id_msg_updateacoustic_done"));
383  }
384  else
385  {
386  TYMessageManager::get()->info(TR("id_msg_updateacoustic_failed"));
387  }
388 
389  // MaJ graphique
390  pLine->getGraphicObject()->update(true);
391  getTYMainWnd()->updateModelers(false, false);
392 
393  TYApplication::restoreOverrideCursor();
394  }
395  }
396 
397  return ret;
398 }
void writeOutputMsg(QString msg)
Affiche un message dans la fenetre de sortie.
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 containsData()
Definition: TYAltimetrie.h:251
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.
void launchAltiComputation(LPTYSiteNode pRootSite)
Execute altimetry computation.
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:706
static void setIsSavedOk(const bool &toSave)
Definition: TYElement.h:914
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:507
bool updateAltiRecepteurs()
Definition: TYProjet.cpp:653
bool remAllMaillage()
Suppression de tous les maillages.
Definition: TYProjet.cpp:919
LPTYSiteNode getSite()
Get du site.
Definition: TYProjet.h:169
void unsetSite()
Supprime la liaison avec le site.
Definition: TYProjet.cpp:576
LPTYCalcul getCurrentCalcul()
Set/Get du pointeur du Calcul courant.
Definition: TYProjet.h:426
void remAllCalcul()
Suppression de tous les elements.
Definition: TYProjet.cpp:571
void setProjet(const LPTYProjet pProjet)
Definition: TYSiteNode.cpp:560
LPTYAltimetrie getAltimetry() const
bool readMesh(std::deque< OPoint3D > &points, std::deque< OTriangle > &triangles, std::deque< LPTYSol > &materials, const QString &meshFilePath)
Definition: TYSiteNode.cpp:733
TYProjet * getProjet()
Accesseurs.
Definition: TYSiteNode.h:106
virtual void updateAcoustique(const bool &force=false)
void setMeshFilePath(const QString &path)
Definition: TYSiteNode.cpp:64
void update(const bool &force=false)
virtual bool updateAltimetrie(QString resultMeshFilePath)
Definition: TYSiteNode.cpp:628
virtual void updateAltiInfra()
Definition: TYSiteNode.cpp:838
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.