#[inline]
pub fn sapm_cell_temperature(poa_global: f64, temp_air: f64, wind_speed: f64, a: f64, b: f64, delta_t: f64, irrad_ref: f64) -> (f64, f64) {
if poa_global <= 0.0 {
return (temp_air, temp_air);
}
let temp_module = temp_air + poa_global * (a + b * wind_speed).exp();
let temp_cell = temp_module + (poa_global / irrad_ref) * delta_t;
(temp_cell, temp_module)
}
#[inline]
pub fn pvsyst_cell_temperature(poa_global: f64, temp_air: f64, wind_speed: f64, u_c: f64, u_v: f64, module_efficiency: f64, alpha_absorption: f64) -> f64 {
if poa_global <= 0.0 {
return temp_air;
}
let h_total = (u_c + u_v * wind_speed).max(0.01);
temp_air + (alpha_absorption * poa_global * (1.0 - module_efficiency)) / h_total
}
#[inline]
pub fn faiman(poa_global: f64, temp_air: f64, wind_speed: f64, u0: f64, u1: f64) -> f64 {
if poa_global <= 0.0 {
return temp_air;
}
let h_total = (u0 + u1 * wind_speed).max(0.01);
temp_air + poa_global / h_total
}
#[inline]
pub fn fuentes(poa_global: f64, temp_air: f64, wind_speed: f64, inoct: f64) -> f64 {
if poa_global <= 0.0 { return temp_air; }
let h = 1.2 + 0.8 * wind_speed; temp_air + poa_global * (inoct - 20.0) / (800.0 * h)
}
#[inline]
pub fn ross(poa_global: f64, temp_air: f64, inoct: f64) -> f64 {
if poa_global <= 0.0 {
return temp_air;
}
let k = (inoct - 20.0) / 800.0;
temp_air + k * poa_global
}
#[inline]
pub fn sapm_module(poa_global: f64, temp_air: f64, wind_speed: f64, a: f64, b: f64) -> f64 {
poa_global * (a + b * wind_speed).exp() + temp_air
}
#[inline]
pub fn sapm_module_default(poa_global: f64, temp_air: f64, wind_speed: f64) -> f64 {
sapm_module(poa_global, temp_air, wind_speed, -3.56, -0.0750)
}
#[inline]
pub fn sapm_cell_from_module(module_temperature: f64, poa_global: f64, delta_t: f64, irrad_ref: f64) -> f64 {
module_temperature + poa_global / irrad_ref * delta_t
}
#[inline]
pub fn sapm_cell_from_module_default(module_temperature: f64, poa_global: f64) -> f64 {
sapm_cell_from_module(module_temperature, poa_global, 3.0, 1000.0)
}
fn adj_for_mounting_standoff(x: f64) -> f64 {
if x <= 0.0 {
0.0
} else if x < 0.5 {
18.0
} else if x < 1.5 {
11.0
} else if x < 2.5 {
6.0
} else if x <= 3.5 {
2.0
} else {
0.0
}
}
#[allow(clippy::too_many_arguments)]
#[inline]
pub fn noct_sam(
poa_global: f64,
temp_air: f64,
wind_speed: f64,
noct: f64,
module_efficiency: f64,
transmittance_absorptance: f64,
array_height: u32,
mount_standoff: f64,
) -> f64 {
let wind_adj = match array_height {
1 => 0.51 * wind_speed,
2 => 0.61 * wind_speed,
_ => 0.51 * wind_speed, };
let noct_adj = noct + adj_for_mounting_standoff(mount_standoff);
let tau_alpha = transmittance_absorptance;
let cell_temp_init = poa_global / 800.0 * (noct_adj - 20.0);
let heat_loss = 1.0 - module_efficiency / tau_alpha;
let wind_loss = 9.5 / (5.7 + 3.8 * wind_adj);
temp_air + cell_temp_init * heat_loss * wind_loss
}
#[inline]
pub fn noct_sam_default(
poa_global: f64,
temp_air: f64,
wind_speed: f64,
noct: f64,
module_efficiency: f64,
) -> f64 {
noct_sam(poa_global, temp_air, wind_speed, noct, module_efficiency, 0.9, 1, 4.0)
}
#[inline]
pub fn generic_linear(
poa_global: f64,
temp_air: f64,
wind_speed: f64,
u_c: f64,
u_v: f64,
module_efficiency: f64,
absorptance: f64,
) -> f64 {
let heat_input = poa_global * (absorptance - module_efficiency);
let total_loss_factor = u_c + u_v * wind_speed;
temp_air + heat_input / total_loss_factor
}
#[inline]
pub fn generic_linear_default(poa_global: f64, temp_air: f64, wind_speed: f64) -> f64 {
generic_linear(poa_global, temp_air, wind_speed, 29.0, 0.0, 0.15, 0.9)
}