test / test (push) Successful in 1m19s
Netto energibehov skal ikke avhenge av varmeanlegget, men enok lot systemtapet fra tappevann og varmedistribusjon telle som varmetilskudd i rommene. Det er riktig etter ISO 52000-1 og NS 3031:2025 for et bygg som skal beskrive faktisk energibruk, men ikke for energirammene, som er netto tall. «drift.systemtap_som_tilskudd» styrer det nå, og referansebyggene settes opp uten. Snittavviket mot de publiserte verdiene går fra 27,9 til 26,4 prosent. Samtidig er det dokumentert hva avviket kommer av. Beregningen er kontrollert mot en uavhengig bin-beregning rett av klimafilen: under de samme forutsetningene gir enok 49,5 mot bin-beregningens 51,5 kWh/(m²·år). Varmetapet er altså riktig, og avviket ligger i varmetilskuddene, som er målt hver for seg i README. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015GeH3y8fwTaTudaD88P57o
93 lines
3.5 KiB
Rust
93 lines
3.5 KiB
Rust
//! Kontroll mot de publiserte referansebyggene for energirammene i TEK17.
|
|
//!
|
|
//! Multiconsult for DiBK, «Grunnlag og forutsetninger for beregnede energirammer»
|
|
//! (128298-RIEn-NOT-001, 13. november 2015), gir geometri (tabell 1), komponentverdier
|
|
//! (tabell 2) og beregnet netto energibehov (tabell 3) for tretten bygningskategorier,
|
|
//! beregnet med Simien etter NS 3031:2014. Modellene er gjengitt i `eksempler/referansebygg/`.
|
|
//!
|
|
//! Dette er den eneste kontrollen der hele beregningen kan sammenlignes med et publisert
|
|
//! resultat for flere bygningskategorier. Testen låser dagens avvik, slik at det blir synlig
|
|
//! både når motoren nærmer seg de publiserte tallene og når noe gjør avviket større.
|
|
//!
|
|
//! Kjør `cargo test --release referansebygg_2015 -- --nocapture` for hele tabellen.
|
|
|
|
use enok::data::Datakilde;
|
|
use enok::{inndata, kjor};
|
|
use std::path::Path;
|
|
|
|
/// Fil, publisert netto energibehov, og enoks verdi slik den er i dag, kWh/(m²·år).
|
|
const BYGG: [(&str, f64, f64); 7] = [
|
|
("smaahus", 107.5, 87.7),
|
|
("boligblokk", 91.8, 79.7),
|
|
("barnehage", 132.0, 81.1),
|
|
("kontorbygg", 115.3, 93.9),
|
|
("skolebygg", 106.8, 73.6),
|
|
("idrettsbygg", 144.3, 111.1),
|
|
("kulturbygg", 128.0, 74.2),
|
|
];
|
|
|
|
fn netto(navn: &str) -> f64 {
|
|
let sti = format!("eksempler/referansebygg/{navn}.toml");
|
|
let b = inndata::les_bygning(Path::new(&sti)).unwrap();
|
|
let r = kjor::kjor(&b, &Datakilde::default()).unwrap();
|
|
r.budsjett.netto_spesifikk(r.lost.bra)
|
|
}
|
|
|
|
/// Verdiene skal ikke endre seg uten at noen har ment det.
|
|
#[test]
|
|
fn referansebyggene_gir_de_samme_tallene() {
|
|
println!(
|
|
"\n {:14}{:>10}{:>12}{:>9}",
|
|
"bygg", "enok", "publisert", "avvik"
|
|
);
|
|
let mut avvik = Vec::new();
|
|
for (navn, publisert, laast) in BYGG {
|
|
let n = netto(navn);
|
|
println!(
|
|
" {navn:14}{n:10.1}{publisert:12.1}{:8.1} %",
|
|
100.0 * (n - publisert) / publisert
|
|
);
|
|
avvik.push(100.0 * (n - publisert) / publisert);
|
|
assert!(
|
|
(n - laast).abs() < 1.0,
|
|
"{navn}: {n:.1} kWh/(m²·år), låst verdi {laast:.1}"
|
|
);
|
|
}
|
|
let snitt = avvik.iter().sum::<f64>() / avvik.len() as f64;
|
|
println!(" {:14}{:>10}{:>12}{snitt:8.1} %\n", "snitt", "", "");
|
|
}
|
|
|
|
/// Varmetapstallet for småhuset skal treffe den publiserte verdien for TEK17-nivå.
|
|
///
|
|
/// Geometri og U-verdier er dermed riktig gjengitt, og avviket i netto energibehov ligger i
|
|
/// den dynamiske beregningen, ikke i inndataene.
|
|
#[test]
|
|
fn varmetapstallet_for_smaahuset_stemmer() {
|
|
let b = inndata::les_bygning(Path::new("eksempler/referansebygg/smaahus.toml")).unwrap();
|
|
let r = kjor::kjor(&b, &Datakilde::default()).unwrap();
|
|
let publisert = 0.69;
|
|
assert!(
|
|
(r.varmetap.totalt - publisert).abs() < 0.03,
|
|
"varmetapstall {:.2}, publisert {publisert:.2}",
|
|
r.varmetap.totalt
|
|
);
|
|
}
|
|
|
|
/// De faste postene følger av normerte verdier og skal stemme uavhengig av motoren.
|
|
#[test]
|
|
fn faste_poster_i_referansebyggene() {
|
|
let post = |r: &kjor::Resultat, nr: &str| {
|
|
r.budsjett
|
|
.poster
|
|
.iter()
|
|
.find(|p| p.nr == nr)
|
|
.map(|p| p.netto / r.lost.bra)
|
|
.unwrap_or(0.0)
|
|
};
|
|
let b = inndata::les_bygning(Path::new("eksempler/referansebygg/smaahus.toml")).unwrap();
|
|
let r = kjor::kjor(&b, &Datakilde::default()).unwrap();
|
|
assert!((post(&r, "2") - 25.1).abs() < 0.2, "varmtvann");
|
|
assert!((post(&r, "5") - 11.4).abs() < 0.2, "belysning");
|
|
assert!((post(&r, "6") - 17.5).abs() < 0.2, "teknisk utstyr");
|
|
}
|