//! 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 = ts.romoppvarming[TIMER / 2..].to_vec(); let snitt = siste.iter().sum::() / 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::() + ts.internlast.iter().sum::(); // 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}" ); }