Files
enok/tests/motor.rs
T

175 lines
5.2 KiB
Rust
Raw Normal View History

//! Kontroll av beregningsmotoren mot analytiske sammenhenger og mot publiserte eksempler.
use enok::data::Datakilde;
use enok::klima::Vaerdata;
use enok::modell::lost::{Lost, Regulering};
use enok::modell::Bygning;
use enok::motor::{iso52016::Systemtilskudd, simuler, Timeserie, Varmetapsbudsjett};
use enok::TIMER;
/// Bygger et kunstig værdatasett med konstant utetemperatur og uten sol.
fn stille_vaer(t_ute: f64) -> Vaerdata {
Vaerdata {
sted: "Prøve".into(),
land: "NOR".into(),
bredde: 60.0,
lengde: 10.0,
tidssone: 1.0,
hoyde: 0.0,
t_ute: vec![t_ute; TIMER],
rf: vec![50.0; TIMER],
ghi: vec![0.0; TIMER],
dni: vec![0.0; TIMER],
dhi: vec![0.0; TIMER],
// Himmeltemperatur lik utetemperatur, slik at langbølget utstråling ikke spiller inn.
ir_himmel: vec![5.67e-8 * (t_ute + 273.15f64).powi(4); TIMER],
vind: vec![0.0; TIMER],
}
}
const ENKEL: &str = r#"
[bygning]
navn = "Kassen"
kategori = "smaahus"
byggeaar = 2020
oppvarmet_bra = 100.0
oppvarmet_volum = 240.0
[[flate]]
navn = "Vegger"
type = "vegg"
areal = 120.0
u_verdi = 0.20
masseklasse = "middels"
[[flate]]
navn = "Tak"
type = "tak"
areal = 100.0
u_verdi = 0.15
masseklasse = "middels"
[[flate]]
navn = "Gulv"
type = "gulv"
areal = 100.0
u_verdi = 0.15
masseklasse = "tung"
[kuldebroer]
normalisert = 0.0
[infiltrasjon]
n50 = 0.0
[ventilasjon]
type = "naturlig"
luftmengde = 0.0
luftmengde_natt = 0.0
[drift]
nattsenking = 21.0
[[oppvarming.kilde]]
type = "direkte_el"
andel_rom = 1.0
andel_ventilasjon = 1.0
andel_tappevann = 1.0
"#;
/// Uten varmetilskudd, sol, ventilasjon og infiltrasjon skal effektbehovet i stasjonær
/// tilstand være varmetapskoeffisienten ganger temperaturdifferansen.
///
/// Overgangsmotstanden R_si = 0,13 m²K/W som U-verdien bygger på, gjelder mot operativ
/// temperatur. Nodemodellen skiller luft- og strålingstemperatur, så sammenligningen gjøres
/// med regulering på operativ temperatur.
#[test]
fn stasjonaert_varmetap_stemmer_med_varmetapstallet() {
let b: Bygning = toml::from_str(ENKEL).unwrap();
let kilde = Datakilde::default();
let mut l = Lost::fra(&b, &kilde).unwrap();
// Slå av alle interne laster og bruk lufttemperatur som reguleringsstørrelse.
l.laster.belysning = [0.0; 24];
l.laster.utstyr_effekt = [0.0; 24];
l.laster.utstyr_varme = [0.0; 24];
l.laster.personer = [0.0; 24];
l.laster.varmtvann = [0.0; 24];
l.laster.pumper = [0.0; 24];
l.regulering = Regulering::Operativ;
let t_ute = 1.0;
let v = stille_vaer(t_ute);
let ts = simuler(&l, &v, Systemtilskudd::default()).unwrap();
let budsjett = Varmetapsbudsjett::beregn(&l);
// Gulvet står mot det fri i denne prøven, så hele transmisjonstapet er mot utetemperaturen.
let h = budsjett.transmisjon_w_per_k;
let forventet = h * (l.settpunkt_oppvarming - t_ute);
// Se bort fra innkjøringen: bruk siste halvdel av året.
let siste: Vec<f64> = ts.romoppvarming[TIMER / 2..].to_vec();
let snitt = siste.iter().sum::<f64>() / siste.len() as f64;
let avvik = (snitt - forventet).abs() / forventet;
assert!(
avvik < 0.02,
"stasjonært varmetap avviker {:.2} %: beregnet {snitt:.1} W, forventet {forventet:.1} W",
avvik * 100.0
);
}
/// Energibalansen skal gå opp: tilført varme og varmetilskudd skal være lik varmetapet.
#[test]
fn aarlig_energibalanse_gaar_opp() {
let b: Bygning = toml::from_str(ENKEL).unwrap();
let kilde = Datakilde::default();
let l = Lost::fra(&b, &kilde).unwrap();
let v = stille_vaer(1.0);
let ts = simuler(&l, &v, Systemtilskudd::default()).unwrap();
let budsjett = Varmetapsbudsjett::beregn(&l);
let tilfort: f64 = ts.romoppvarming.iter().sum::<f64>() + ts.internlast.iter().sum::<f64>();
// Varmetapet regnet av de simulerte operative temperaturene, som U-verdiene gjelder mot.
let tap: f64 = ts
.t_operativ
.iter()
.map(|t| budsjett.transmisjon_w_per_k * (t - 1.0))
.sum();
let avvik = (tilfort - tap).abs() / tap;
assert!(
avvik < 0.02,
"energibalansen avviker {:.2} %",
avvik * 100.0
);
}
/// Dobbelt så stort temperaturfall skal gi dobbelt så stort varmebehov i en lineær modell.
#[test]
fn varmebehovet_er_lineaert_i_temperaturdifferansen() {
let b: Bygning = toml::from_str(ENKEL).unwrap();
let kilde = Datakilde::default();
let mut l = Lost::fra(&b, &kilde).unwrap();
l.laster.belysning = [0.0; 24];
l.laster.utstyr_effekt = [0.0; 24];
l.laster.utstyr_varme = [0.0; 24];
l.laster.personer = [0.0; 24];
l.laster.varmtvann = [0.0; 24];
l.laster.pumper = [0.0; 24];
l.regulering = Regulering::Operativ;
let en = Timeserie::sum_kwh(
&simuler(&l, &stille_vaer(11.0), Systemtilskudd::default())
.unwrap()
.romoppvarming,
);
let to = Timeserie::sum_kwh(
&simuler(&l, &stille_vaer(1.0), Systemtilskudd::default())
.unwrap()
.romoppvarming,
);
let forhold = to / en;
assert!(
(forhold - 2.0).abs() < 0.01,
"forholdet skulle vært 2,0, men ble {forhold:.3}"
);
}