1use crate::{
5 der_mach_to_f_mcpt0, der_normal_mach2, der_normal_p02_p01, mach_to_a_ac, mach_to_f_mcpt,
6 mach_to_pm_angle, normal_mach2, normal_p02_p01,
7};
8use eqsolver::single_variable::{FDNewton, Newton};
9use num::Float;
10
11pub fn mach_from_pm_angle<F: Float>(pm_angle: F, gamma: F) -> F {
30 let f = |m| mach_to_pm_angle(m, gamma) - pm_angle;
31 let x0 = F::from(2.).unwrap();
32 match FDNewton::new(f).solve(x0) {
33 Ok(x) => x,
34 Err(_) => F::nan(),
35 }
36}
37
38pub fn mach_from_mach_angle<F: Float>(mach_angle: F) -> F {
49 (F::one()) / mach_angle.sin()
51}
52
53pub fn mach_from_t_t0<F: Float>(t_t0: F, gamma: F) -> F {
65 let two = F::from(2.0).unwrap();
66 (two / (gamma - F::one()) * (F::one() / t_t0 - F::one())).sqrt()
67}
68
69pub fn mach_from_t0_t<F: Float>(t0_t: F, gamma: F) -> F {
72 let two = F::from(2.0).unwrap();
73 (two / (gamma - F::one()) * (t0_t - F::one())).sqrt()
74}
75
76pub fn mach_from_p_p0<F: Float>(p_p0: F, gamma: F) -> F {
88 let two = F::from(2.0).unwrap();
89 (two / (gamma - F::one()) * (p_p0.powf((F::one() - gamma) / gamma) - F::one())).sqrt()
90}
91
92pub fn mach_from_p0_p<F: Float>(p0_p: F, gamma: F) -> F {
93 let two = F::from(2.0).unwrap();
94 (two / (gamma - F::one()) * (p0_p.powf((gamma - F::one()) / gamma) - F::one())).sqrt()
95}
96
97pub fn mach_from_rho_rho0<F: Float>(rho_rho0: F, gamma: F) -> F {
109 let two = F::from(2.0).unwrap();
110 (two / (gamma - F::one()) * (rho_rho0.powf(F::one() - gamma) - F::one())).sqrt()
111}
112
113pub fn mach_from_rho0_rho<F: Float>(rho0_rho: F, gamma: F) -> F {
114 let two = F::from(2.0).unwrap();
115 (two / (gamma - F::one()) * (rho0_rho.powf(gamma - F::one()) - F::one())).sqrt()
116}
117
118pub fn mach_from_v_cpt0<F: Float>(v_cpt0: F, gamma: F) -> F {
119 let half = F::from(0.5).unwrap();
120 (F::one() / (gamma - F::one()) * v_cpt0.powi(2) / (F::one() - half * v_cpt0.powi(2))).sqrt()
121}
122
123pub fn mach_from_f_mcpt0<F: Float>(f_mcpt0: F, gamma: F, supersonic: bool) -> F {
124 let f = |m| mach_to_f_mcpt(m, gamma) - f_mcpt0;
125 let df = |m| der_mach_to_f_mcpt0(m, gamma) - f_mcpt0;
126 let x0 = match supersonic {
127 true => F::from(1.5).unwrap(),
128 false => F::from(0.5).unwrap(),
129 };
130 match Newton::new(f, df).with_itermax(100).solve(x0) {
131 Ok(x) => x,
132 Err(_) => F::nan(),
133 }
134}
135
136pub fn mach_from_mcpt0_ap0<F: Float>(mcpt0_ap0: F, gamma: F, supersonic: bool) -> F {
137 let half = F::from(0.5).unwrap();
138 let gm1 = gamma - F::one();
139 let gp1 = gamma + F::one();
140 let gm1_2 = gm1 * half;
141 let gp1_2 = gp1 * half;
142 let m_gp1_gm1_2 = gp1 / gm1 * -half;
143 let g_sq_gm1 = gamma / gm1.sqrt();
144 let fcrit = g_sq_gm1 * (F::one() + gm1_2).powf(m_gp1_gm1_2);
145 if mcpt0_ap0 > fcrit {
146 return F::nan();
147 }
148 let mut m_try: F;
149 if supersonic {
150 m_try = F::from(1.5).unwrap();
151 } else {
152 m_try = half;
153 }
154 let mut k = 0;
155 let mut err = F::infinity();
156 let tol = F::from(1e-6).unwrap();
157 while err > tol && k < 100 {
158 k = k + 1;
159 let to_t = F::one() + gm1_2 * m_try.powi(2);
161 let f = g_sq_gm1 * m_try * to_t.powf(m_gp1_gm1_2);
162 let df = f * (F::one() - gp1_2 * m_try.powi(2) / to_t) / m_try;
163 let m_new = m_try - (f - mcpt0_ap0) / df;
164 err = (m_new - m_try).abs();
165 m_try = m_new;
166 }
167 let mach: F;
168 if err < tol {
169 mach = m_try;
170 } else {
171 mach = F::nan();
172 }
173 mach
174}
175
176pub fn mach_from_mcpt0_ap<F: Float>(mcpt0_ap: F, gamma: F) -> F {
177 let half = F::from(0.5).unwrap();
178 let gm1 = gamma - F::one();
179 let gm1_2 = gm1 * half;
180 let g_sq_gm1 = gamma / gm1.sqrt();
181 let tol = F::from(1e-6).unwrap();
182 let mut m_try = F::from(0.5).unwrap();
183 let mut err = F::infinity();
184 let mut i: i32 = 0;
185 while err > tol && i < 100 {
186 i = i + 1;
187 let to_t = F::one() + gm1_2 * m_try.powi(2);
189 let f = g_sq_gm1 * m_try * to_t.sqrt();
190 let df = g_sq_gm1 * (to_t.powi(2) - gm1_2 * m_try.powi(2) / to_t.sqrt());
191 let m_new = m_try - (f - mcpt0_ap) / df;
192 err = (m_new - m_try).abs();
193 m_try = m_new;
194 }
195 let mach: F;
196 if err < tol {
197 mach = m_try;
198 } else {
199 mach = F::nan();
200 }
201 mach
202}
203
204pub fn mach_from_a_ac<F: Float>(a_ac: F, gamma: F, supersonic: bool) -> F {
226 if a_ac.is_one() {
227 return F::one();
228 }
229 let mut m_max: F;
230 let mut m_min: F;
231 if supersonic {
232 m_max = F::max_value();
233 m_min = F::one();
234 } else {
235 m_max = F::one();
236 m_min = F::zero();
237 }
238 let mut m_try = (m_max + m_min) / F::from(2.).unwrap();
239 let mut val: F;
240 let mut i: usize = 0;
241 let max_iter: usize = 10000;
242 while i < max_iter {
243 val = mach_to_a_ac(m_try, gamma);
244 if val == a_ac {
245 return m_try;
246 } else if val < a_ac {
247 if supersonic {
248 m_min = m_try;
249 } else {
250 m_max = m_try;
251 }
252 } else if val > a_ac {
253 if supersonic {
254 m_max = m_try;
255 } else {
256 m_min = m_try;
257 }
258 }
259 m_try = (m_max + m_min) / F::from(2.).unwrap();
260 i += 1;
261 }
262 return m_try;
263}
264
265pub fn mach_from_normal_mach2<F: Float>(mach2: F, gamma: F) -> F {
266 if mach2 > F::one() {
267 return F::nan();
268 }
269 let f = |m| normal_mach2(m, gamma) - mach2;
270 let df = |m| der_normal_mach2(m, gamma) - mach2;
271 let x0 = F::from(0.5).unwrap();
272 match Newton::new(f, df).with_itermax(100).solve(x0) {
273 Ok(x) => x,
274 Err(_) => F::nan(),
275 }
276}
277
278pub fn mach_from_normal_p02_p01<F: Float>(p02_p01: F, gamma: F) -> F {
279 let f = |m| normal_p02_p01(m, gamma) - p02_p01;
280 let df = |m| der_normal_p02_p01(m, gamma) - p02_p01;
281 let x0 = F::from(1.5).unwrap();
282 match Newton::new(f, df).with_itermax(100).solve(x0) {
283 Ok(x) => x,
284 Err(_) => F::nan(),
285 }
286}