Code_TYMPAN  4.4.0
Industrial site acoustic simulation
TYChemin9613Solver2024.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 
17 
19  const OSpectreOctave& Agr_r,
20  const OSpectreOctave& Agr_m, double hs,
21  double hr, double dp) const
22 {
23  OSpectreOctave Agr9613 = TYChemin9613Solver::calcTotalGroundAttenuation(Agr_s, Agr_r, Agr_m, hs, hr, dp);
24  double Kgeo = (dp * dp + (hs - hr) * (hs - hr)) / (dp * dp + (hs + hr) * (hs + hr));
25  OSpectreOctave s = Agr9613 * (-1.0);
26  s = s.div(10.0);
27  s = s.exp(std::log(10));
28  s = (s + (-1.0)) * Kgeo + 1.0;
29  s = s.log() * (-10.0);
30 
31  return s;
32 }
33 
35  const OPoint3D& O,
36  double d_SO, double d_OR,
37  double a, double h,
38  const OVector3D& n) const
39 {
40  // first we need to set a convention to the normal of the surface:
41  // (1) it is a normal of a vertical plane (vertical component = 0)
42  // (2) it is normalized
43  // (3) from O, it points towards S and R
44  OVector3D nCopy{n}; // a copy is necessary because coordinates cannot be retrieved for a const OVector3D
45  const double nx = nCopy.getCoords()[0];
46  const double ny = nCopy.getCoords()[1];
47  OVector3D nConventional{nx, ny, 0.}; // condition (1)
48  nConventional.normalize(); // condition (2)
49  const OVector3D OSvec{O, Oprev};
50  if (OSvec.scalar(nConventional) < 0.) // condition (3)
51  {
52  nConventional.invert();
53  }
54 
55  // to compute cos(beta_a) and cos(beta_h), we need to perform 2D geometry in two planes:
56  // - a horizontal plane passing by O --> cos(beta_a)
57  // - a vertical plane passing by O --> cos(beta_h)
58  // for that, we define normalized tangential vectors of the reflecting surface
59  // - tHorizontal
60  // - tVertical
61  const OVector3D tVertical{0., 0., 1.};
62  OVector3D tHorizontal = tVertical.cross(nConventional);
63  tHorizontal.normalize();
64 
65  // cos(beta_a)
66  const double OSvecHorizontalT = OSvec.scalar(tHorizontal);
67  const double OSvecN = OSvec.scalar(nConventional);
68  const OVector3D OSvecHorizontal = tHorizontal * OSvecHorizontalT + nConventional * OSvecN;
69  const double dSOHorizontal = OSvecHorizontal.norme();
70  const double cos_beta_a = OSvecN / dSOHorizontal;
71 
72  // cos(beta_h)
73  const double OSvecVerticalT = OSvec.scalar(tVertical);
74  const OVector3D OSvecVertical = tVertical * OSvecVerticalT + nConventional * OSvecN;
75  const double dSOVertical = OSvecVertical.norme();
76  const double cos_beta_h = OSvecN / dSOVertical;
77 
78  // l_eff (Eq. 27)
79  const double l_eff = std::min(a * cos_beta_a, h * cos_beta_h);
80 
81  // f_threshold (Eq. 26 multiplied by c)
82  const double c_9613_2 = 340.0; // TODO: to factorize by using somehow the constant defined in
83  // TYAcousticModel::computeWaveLength
84  const double fThreshold = c_9613_2 * (2. / (l_eff * l_eff)) * (d_SO * d_OR) / (d_SO + d_OR);
85 
86  // filter spectrum
87  OSpectreOctave filter{0.};
89  for (unsigned int i = 0; i < frequencies.size(); i++)
90  {
91  if (frequencies[i] > fThreshold)
92  {
93  filter.getTabValReel()[i] = 1.;
94  }
95  }
96 
97  return filter;
98 }
99 
101  const OPoint3D& P, const OPoint3D& M, double r,
102  const OVector3D& axis)
103 {
104  // in 9613-2:2024 standard, geometric computation have to be performed "on a plane perpendicular to the
105  // cylinder-axis"
106 
107  assert(r > 0.);
108 
109  // build an orthonormal basis of a plane orthogonal to axis
110  OVector3D u1, u2;
111  if (abs(axis._x) < EPSILON_13 && abs(axis._y) < EPSILON_13)
112  {
113  // axis is colinear to (0, 0, 1)
114  // in this case, we get directly an orthonormal basis using e1 and e2
115  u1 = OVector3D{1., 0., 0.};
116  u2 = OVector3D{0., 1., 0.};
117  }
118  else
119  {
120  // axis is not colinear to (0, 0, 1)
121  // in this case, we have to build an orthonormal basis:
122  // - define a candidate u1_prime, non-colinear with axis
123  // - build u1, orthogonal to axis using the Gram-Schmidt process
124  // - build u2 using cross product
125  // - normalize u1 and u2
126  const OVector3D u1_prime{0., 0., 1.};
127  const OVector3D u1_non_normalized{u1_prime - axis * (u1_prime.scalar(axis) / axis.scalar(axis))};
128  const OVector3D u2_non_normalized{u1_non_normalized.cross(axis)};
129  u1 = u1_non_normalized * (1. / u1_non_normalized.norme());
130  u2 = u2_non_normalized * (1. / u2_non_normalized.norme());
131  }
132 
133  // project S, R, P and M in this basis with origin (0, 0, 0)
134  const OPoint3D S2D = projectOnPlane(S, u1, u2);
135  const OPoint3D R2D = projectOnPlane(R, u1, u2);
136  const OPoint3D P2D = projectOnPlane(P, u1, u2);
137  const OPoint3D M2D = projectOnPlane(M, u1, u2);
138 
139  // compute intermediate variables dS, dR, d, and k
140  const double dS{S2D.dist2DFrom(P2D)};
141  const double dR{R2D.dist2DFrom(P2D)};
142  // d is the norm of a vector v fulfilling these properties:
143  // v . SP = 0
144  // MP + v = mu SP
145  // thus:
146  // v = mu SP - MP, with mu = MP . SP / SP^2
147  const OVector3D MP{M2D, P2D};
148  const OVector3D SP{S2D, P2D};
149  const OVector3D v{SP * (MP.scalar(SP) / (dS * dS)) - MP};
150  const double d{v.norme()};
151  const double k{d / r};
152 
153  assert(k <= 1.);
154 
155  // compute Acurv using Eq. 30 of 9613-2:2024 standard
156  const double Acurv = 10. * log10(1. + 2 * dS * dR / r / (dS + dR) / sqrt(1. - k * k));
157 
158  OSpectreOctave AcurvSpectrum{Acurv};
160 }
161 
163 {
164  return OPoint3D{u1.scalar(P), u2.scalar(P), 0.};
165 }
#define EPSILON_13
Definition: 3d.h:41
NxReal s
Definition: NxVec3.cpp:317
#define min(a, b)
Representation of one of the most optimal path between source and receptor: S—>R Specific derivation ...
void getCoords(double coords[3])
Gets the coordinates as an array of double.
Definition: 3d.cpp:90
double _y
y coordinate of OCoord3D
Definition: 3d.h:283
double _x
x coordinate of OCoord3D
Definition: 3d.h:282
The 3D point class.
Definition: 3d.h:487
double dist2DFrom(const OPoint3D &pt) const
Computes the distance from this point to another in 2D plan.
Definition: 3d.cpp:376
static OTabFreq getTabFreqExact()
Definition: spectre.cpp:1590
The 3D vector class.
Definition: 3d.h:298
double norme() const
Computes the length of this vector.
Definition: 3d.cpp:215
void normalize()
Normalizes this vector.
Definition: 3d.cpp:225
double scalar(const OVector3D &vector) const
Performs the scalar product between this object and another vector.
Definition: 3d.cpp:210
OVector3D cross(const OVector3D &vector) const
Cross product.
Definition: 3d.cpp:196
OSpectreOctave calcTotalGroundAttenuation(const OSpectreOctave &Agr_s, const OSpectreOctave &Agr_r, const OSpectreOctave &Agr_m, double hs, double hr, double dp) const override
Compute total ground attenuation Agr from region ground attenuations and geometric configuration.
void calcCylinderReflectionAttenuation(const OPoint3D &S, const OPoint3D &R, const OPoint3D &P, const OPoint3D &M, double r, const OVector3D &axis) override
Compute attenuation when a reflection occur on a cylinder Implements Eq. 30 of 9613-2:2024 standard.
OSpectreOctave calcMinimalExtensionConditionOneReflection(const OPoint3D &Oprev, const OPoint3D &O, double d_SO, double d_OR, double a, double h, const OVector3D &n) const override
Evaluate minimal extension condition for a specular reflection on a flat surface in function of the w...
OPoint3D projectOnPlane(const OPoint3D &P, const OVector3D &u1, const OVector3D &u2)
Project a point P on the plane spanned by (u1, u2) from (0, 0, 0)
void setAttenuation(const TYTypeAttenuation &type, const OSpectreOctave &att)
Set the atmospheric attenuation.
virtual OSpectreOctave calcTotalGroundAttenuation(const OSpectreOctave &Agr_s, const OSpectreOctave &Agr_r, const OSpectreOctave &Agr_m, double hs, double hr, double dp) const
Compute total ground attenuation Agr from region ground attenuations and geometric configuration.
std::vector< double > OTabFreq
Frequencies collection.
Definition: spectre.h:60