Code_TYMPAN  4.4.0
Industrial site acoustic simulation
TYTrajetDefaultSolver.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 
18 
20  : TYTrajet(asrc_, arcpt_)
21 {
22 }
23 
25 {
26  reset();
27 }
28 
30 {
31  _chemins.clear();
32  _cheminsDirect.clear();
33 }
34 
36 {
37  if (this != &other)
38  {
39  TYTrajet::operator=(other);
40  _chemins = other._chemins;
41  _sLP = other._sLP;
42  }
43  return *this;
44 }
45 
47 {
48  if (this != &other)
49  {
50  if (TYTrajet::operator!=(other))
51  {
52  return false;
53  }
54  if (_chemins != other._chemins)
55  {
56  return false;
57  }
58  if (_sLP != other._sLP)
59  {
60  return false;
61  };
62  // if (asrc != other.asrc) { return false; };
63  // if (arcpt != other.arcpt) ;
64  }
65 
66  return true;
67 }
68 
70 {
71  return !operator==(other);
72 }
73 
75 {
76  _chemins.push_back(chemin);
77 }
78 
80 {
81  _cheminsDirect.push_back(chemin);
82 }
83 
85 {
87  OSpectreComplex sTemp;
88  int firstReflex = -1;
89  unsigned int indiceDebutEffetEcran = 0;
90  unsigned int i = 0;
91 
92  // On calcule l'attenuation sur le trajet direct (sauf chemins reflechis).
93  for (i = 0; i < this->_chemins.size(); i++)
94  {
95  // Si un ecran est present, on ne traite pas les reflexions (dans un premier temp ...)
96  if ((_chemins[0].getType() == TYTypeChemin::CHEMIN_ECRAN) &&
97  (_chemins[i].getType() == TYTypeChemin::CHEMIN_REFLEX))
98  {
99  firstReflex = i;
100  break;
101  }
102  sTemp = _chemins[i].getAttenuation();
103  s = s.sum(sTemp.mult(sTemp)); // somme des carres des modules
104  }
105 
106  // Dans le cas d'un ecran, on compare l'attenuation obtenue a celle du trajet direct
107  // pour eviter les effets d'amplification (plus de bruit avec l'ecran que sans ecran ...)
108  if (_chemins[0].getType() == TYTypeChemin::CHEMIN_ECRAN)
109  {
111 
112  for (i = 0; i < _cheminsDirect.size(); i++)
113  {
114  sTemp = _cheminsDirect[i].getAttenuation();
115  attDirect = attDirect.sum(sTemp.mult(sTemp));
116  }
117 
118  // On regarde l'attenuation globale obtenue pour chaque frequence,
119  // on la compare a celle obtenue sur le trajet sans ecran,
120  // si elle est superieure a 1 alors on prend la valeur obtenue pour le trajet sans ecran
121  for (i = 0; i < s.getNbValues(); i++)
122  {
123  if (s.getTabValReel()[i] < attDirect.getTabValReel()[i])
124  {
125  indiceDebutEffetEcran = i; // On prend note de l'indice
126  break; // Si l'ecran commence a attenuer plus que le trajet direct, il faut sortir de la
127  // boucle
128  }
129  } //*/
130 
131  if (firstReflex != -1) // S'il y a une reflexion sur un ecran
132  {
133  // On rajoute la contribution des chemins reflechis
134  // 1. Aux chemins normaux et aux chemins directs
135  for (i = firstReflex; i < _chemins.size(); i++)
136  {
137  sTemp = _chemins[i].getAttenuation().mult(_chemins[i].getAttenuation());
138  s = s.sum(sTemp);
139  attDirect = attDirect.sum(sTemp);
140  }
141 
142  // On remplace la contribution du trajet direct pour toutes les frequences ou cela est necessaire
143  for (i = 0; i < indiceDebutEffetEcran; i++)
144  {
145  s.getTabValReel()[i] = attDirect.getTabValReel()[i];
146  }
147  }
148  }
149  build_tab_rays();
150  _chemins.clear(); // On efface le tableau des chemins pour (essayer de) gagner de la place en memoire
151  _cheminsDirect.clear();
152  return s;
153 }
154 
156 {
157  unsigned int i = 0, j = 0;
158  int firstReflex = -1;
159  unsigned int indiceDebutEffetEcran = 0;
160  bool ecranFound = false;
161 
162  if (_chemins.size())
163  {
164  ecranFound = (_chemins[0].getType() == TYTypeChemin::CHEMIN_ECRAN);
165  }
166 
167  // On recupere prealablement l'ensemble des attenuations et les longueurs des chemins
168  std::vector<OSpectreComplex> tabSpectreAtt;
169  std::vector<OSpectreComplex> tabSpectreAttDirect;
170  std::vector<double> tabLongueur;
171  std::vector<double> tabLongueurDirect;
172 
173  for (i = 0; i < _chemins.size(); i++)
174  {
175  tabSpectreAtt.push_back(_chemins[i].getAttenuation());
176  tabLongueur.push_back(_chemins[i].getLongueur());
177  }
178 
179  // On calcule la somme des carres des modules et la somme des produits croises
180 
181  OSpectre sCarreModule = OSpectre::getEmptyLinSpectre();
182  OSpectre sProduitCroise = OSpectre::getEmptyLinSpectre();
183  OSpectre sTemp;
184 
185  for (i = 0; i < _chemins.size(); i++)
186  {
187 
188  // Si un ecran est present, on ne traite pas les reflexions (dans un premier temp ...)
189  if (ecranFound && (_chemins[i].getType() == TYTypeChemin::CHEMIN_REFLEX))
190  {
191  firstReflex = i;
192  break;
193  }
194  // on fait la somme du carre des modules
195  sCarreModule = sCarreModule.sum(tabSpectreAtt[i].mult(tabSpectreAtt[i]));
196 
197  // on calcule les produits croises avec les autres chemins
198  for (j = i + 1; j < _chemins.size(); j++)
199  {
200  // On procedera aux produits croise avec les chemins reflechis plus loin ...
201  if (ecranFound && (_chemins[j].getType() == TYTypeChemin::CHEMIN_REFLEX))
202  {
203  continue;
204  }
205 
206  sTemp = tabSpectreAtt[i].mult(tabSpectreAtt[j].mult(2.0));
207  sTemp = sTemp.mult(
208  correctTiers(tabSpectreAtt[i], tabSpectreAtt[j], atmos, tabLongueur[i], tabLongueur[j]));
209  sProduitCroise = sProduitCroise.sum(sTemp);
210  }
211  }
212 
213  OSpectre s = sCarreModule.sum(sProduitCroise); //.abs() ;
214 
215  // Dans le cas d'un ecran, on compare l'attenuation obtenue a celle du trajet direct
216  // pour eviter les effets d'amplification (plus de bruit avec l'ecran que sans ecran ...)
217 
218  if (ecranFound) // On comparera au carre des modules des trajets directs
219  {
220  // On calcule l'attenuation sur le trajet direct
221  OSpectre sCarreModuleDirect = OSpectre::getEmptyLinSpectre();
222  OSpectre sProduitCroiseDirect = OSpectre::getEmptyLinSpectre();
223 
224  for (i = 0; i < _cheminsDirect.size(); i++)
225  {
226  tabSpectreAttDirect.push_back(_cheminsDirect[i].getAttenuation());
227  tabLongueurDirect.push_back(_cheminsDirect[i].getLongueur());
228  }
229 
230  for (i = 0; i < _cheminsDirect.size(); i++)
231  {
232  // on fait la somme du carre des modules
233  sCarreModuleDirect = sCarreModuleDirect.sum(tabSpectreAttDirect[i].mult(tabSpectreAttDirect[i]));
234 
235  // on calcule les produits croises avec les autres chemins
236  for (j = i + 1; j < _cheminsDirect.size(); j++)
237  {
238  sTemp = tabSpectreAttDirect[i].mult(tabSpectreAttDirect[j].mult(2.0));
239  sTemp = sTemp.mult(correctTiers(tabSpectreAttDirect[i], tabSpectreAttDirect[j], atmos,
240  tabLongueurDirect[i], tabLongueurDirect[j]));
241  sProduitCroiseDirect = sProduitCroiseDirect.sum(sTemp);
242  }
243  }
244 
245  OSpectre attDirect = sCarreModuleDirect.sum(sProduitCroiseDirect); //.abs() ;
246 
247  // On compare l'attenuation sur le trajet "normal" en energetique a
248  // l'attenuation sur le trajet direct en energetique.
249  // Si elle est superieure, alors on prend l'attenuation sur le trajet direct
250 
251  for (j = 0; j < s.getNbValues(); j++)
252  {
253  if (s.getTabValReel()[j] < attDirect.getTabValReel()[j])
254  {
255  indiceDebutEffetEcran = j; // On prend note de l'indice
256  break; // Si l'ecran commence a attenuer plus que le trajet direct, il faut sortir de la
257  // boucle
258  }
259  }
260 
261  if (firstReflex != -1) // S'il y a une reflexion sur un ecran
262  {
263  // On rajoute la contribution des chemins reflechis:
264  // 1. aux chemins "normaux"
265  for (i = firstReflex; i < _chemins.size(); i++)
266  {
267  sCarreModule = sCarreModule.sum(tabSpectreAtt[i].mult(tabSpectreAtt[i]));
268 
269  // on calcule les produits croises avec les autres chemins
270  for (j = 0; j < _chemins.size(); j++)
271  {
272  if (j == i)
273  {
274  continue;
275  } // pas avec lui meme
276 
277  sTemp = tabSpectreAtt[i].mult(tabSpectreAtt[j].mult(2.0));
278  sTemp = sTemp.mult(correctTiers(tabSpectreAtt[i], tabSpectreAtt[j], atmos, tabLongueur[i],
279  tabLongueur[j]));
280  sProduitCroise = sProduitCroise.sum(sTemp);
281  }
282  }
283 
284  s = sCarreModule.sum(sProduitCroise);
285 
286  // // 2. au chemins "direct"
287  for (i = firstReflex; i < _chemins.size(); i++)
288  {
289  sCarreModuleDirect = sCarreModuleDirect.sum(tabSpectreAtt[i].mult(tabSpectreAtt[i]));
290 
291  // Produit croise avec les chemins directs
292  for (j = 0; j < _cheminsDirect.size(); j++)
293  {
294  sTemp = tabSpectreAtt[i].mult(tabSpectreAttDirect[j].mult(2.0));
295  sTemp = sTemp.mult(correctTiers(tabSpectreAtt[i], tabSpectreAttDirect[j], atmos,
296  tabLongueur[i], tabLongueurDirect[j]));
297  sProduitCroiseDirect = sProduitCroiseDirect.sum(sTemp);
298  }
299  // Produit croise avec les autres chemins reflechis
300  for (j = i + 1; j < _chemins.size(); j++)
301  {
302  sTemp = tabSpectreAtt[i].mult(tabSpectreAtt[j].mult(2.0));
303  sTemp = sTemp.mult(correctTiers(tabSpectreAtt[i], tabSpectreAtt[j], atmos, tabLongueur[i],
304  tabLongueur[j]));
305  sProduitCroiseDirect = sProduitCroiseDirect.sum(sTemp);
306  }
307  }
308 
309  attDirect = sCarreModuleDirect.sum(sProduitCroiseDirect); //.abs();
310  }
311 
312  // On remplace la contribution du trajet direct pour toutes les frequences ou cela est necessaire
313  for (i = 0; i < indiceDebutEffetEcran; i++)
314  {
315  s.getTabValReel()[i] = attDirect.getTabValReel()[i];
316  }
317  }
318  build_tab_rays();
319  _chemins.clear(); // On efface le tableau des chemins pour (essayer de) gagner de la place en memoire
320  _cheminsDirect.clear();
321 
322  return s;
323 }
324 
326  const AtmosphericConditions& atmos, const double& ri,
327  const double& rj) const
328 {
329  const double dp6 = pow(2, (1.0 / 6.0));
330  const double invdp6 = 1.0 / dp6;
331  const double dfSur2f = (dp6 - invdp6) / 2.0; // df/2f
332  OSpectre cosTemp;
333  OSpectre s;
334 
335  OSpectre sTemp = atmos.get_k().mult(ri - rj); // k(ri-rj)
336 
337  if (ri == rj)
338  {
339  s = (si.getPhase().subst(sj.getPhase()).subst(sTemp)).cos(); // cos(EPS_i - EPS_j)
340  }
341  else
342  {
343 
344  s = si.getPhase().subst(sj.getPhase()); // thetaI - thetaJ
345 
346  double df = sqrt(1 + dfSur2f * dfSur2f);
347  cosTemp = sTemp.mult(df); // k(ri-rj) * sqrt(1 + (df/2f)²)
348  cosTemp = cosTemp.sum(s); // k(ri-rj) * sqrt(1 + (df/2f)²) + (thetaI - thetaJ)
349  cosTemp = cosTemp.subst(sTemp); // k(ri-rj)*sqrt(1 + (df/2f)²) + EPS_i - EPS_j
350  cosTemp = cosTemp.cos(); // cos(k(ri-rj)*sqrt(1 + (df/2f)²) + EPS_i - EPS_j)
351 
352  sTemp = sTemp.mult(dfSur2f); // k(ri-rj)*df/2f
353 
354  s = sTemp.sin(); // sin(k(ri-rj)*df/2f)
355  s = s.div(sTemp); // sin(k(ri-rj)*df/2f) / (k(ri-rj)*df/2f)
356  s = s.mult(cosTemp); // sin(k(ri-rj)*df/2f) / (k(ri-rj)*df/2f) * cos(k(ri-rj)*sqrt(1 + (df/2f)²) +
357  // EPS_i - EPS_j)
358  }
359 
360  return s;
361 }
362 
364 {
365  _tabRays.clear();
366  for (size_t i = 0; i < _chemins.size(); i++)
367  {
368  _tabRays.push_back(_chemins[i].get_ray(_ptR));
369  }
370 }
NxReal s
Definition: NxVec3.cpp:317
Class for the definition of atmospheric conditions.
const OSpectre & get_k() const
Get the wave number spectrum.
OSpectreAbstract & sum(const OSpectreAbstract &spectre) const
Arithmetic sum of two spectrums in one-third Octave.
Definition: spectre.cpp:224
OSpectreAbstract & subst(const OSpectreAbstract &spectre) const
Arithmetic subtraction of two spectrums in one-third Octave.
Definition: spectre.cpp:321
OSpectreAbstract & sin() const
Compute the sin of this spectrum.
Definition: spectre.cpp:469
OSpectreAbstract & cos() const
Compute the cos of this spectrum.
Definition: spectre.cpp:483
OSpectreAbstract & mult(const OSpectreAbstract &spectre) const
Multiplication of two spectrums.
Definition: spectre.cpp:248
OSpectre getPhase() const
Definition: spectre.cpp:1379
static OSpectre getEmptyLinSpectre(const double &valInit=1.0E-20)
Create a physical quantity spectrum.
Definition: spectre.cpp:1129
double * getTabValReel() override
Definition: spectre.h:357
Representation of one of the most optimal path between source and receptor: S—>R. The class TYChemin ...
This class TYTrajet (journey) links a couple Source-Receptor and a collection of paths,...
TYTrajetDefaultSolver(tympan::AcousticSource &asrc_, tympan::AcousticReceptor &arcpt_)
Constructor.
bool operator!=(const TYTrajetDefaultSolver &other) const
Operator !=.
void reset() override
Reset method.
OSpectre correctTiers(const OSpectreComplex &si, const OSpectreComplex &sj, const AtmosphericConditions &atmos, const double &ri, const double &rj) const
TYTabCheminDefaultSolver _chemins
Paths collection.
void addChemin(const TYCheminDefaultSolver &chemin)
Add a new path.
OSpectre getPInterference(const AtmosphericConditions &atmos)
Compute the quadratic pressure on the journey.
TYTrajetDefaultSolver & operator=(const TYTrajetDefaultSolver &other)
Operator =.
virtual ~TYTrajetDefaultSolver()
Destructor.
bool operator==(const TYTrajetDefaultSolver &other) const
Operator ==.
void addCheminDirect(const TYCheminDefaultSolver &chemin)
Add a new path to the array of direct paths.
OSpectre getPEnergetique(const AtmosphericConditions &atmos)
Compute the acoustic pressure (phase modulation) on the journey.
TYTabCheminDefaultSolver _cheminsDirect
Direct paths collection (without obstacles)
This class TYTrajet (journey) links a couple Source-Receptor and a collection of paths,...
Definition: TYTrajet.h:33
OPoint3D _ptR
Receptor point definition in the site frame.
Definition: TYTrajet.h:139
std::vector< acoustic_path * > _tabRays
Vector of rays equivalent to chemin.
Definition: TYTrajet.h:145
TYTrajet & operator=(const TYTrajet &other)
Operator =.
Definition: TYTrajet.cpp:43
Describes an acoustic receptor.
Definition: entities.hpp:403
Describes an acoustic source.
Definition: entities.hpp:381
This file provides class for solver configuration.