Multiconsults notat for DiBK gir geometri, komponentverdier og beregnet netto energibehov for bygningskategoriene bak energirammene i TEK17. Sju av dem, de vi har normerte verdier for, er gjengitt i eksempler/referansebygg/ og regnes om igjen av en ny test. Resultatet er at enok regner gjennomgående for lavt, fra 15 til 43 prosent, i snitt 28. Varmetapstallet for småhuset treffer publisert verdi, og de faste postene stemmer nøyaktig, så avviket ligger i den dynamiske delen. README beskriver hva som er kontrollert, hva avviket trolig kommer av, og hva tallene kan brukes til inntil videre. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015GeH3y8fwTaTudaD88P57o
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
//! 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, 85.3),
|
||||
("boligblokk", 91.8, 77.6),
|
||||
("barnehage", 132.0, 80.1),
|
||||
("kontorbygg", 115.3, 93.5),
|
||||
("skolebygg", 106.8, 72.8),
|
||||
("idrettsbygg", 144.3, 106.7),
|
||||
("kulturbygg", 128.0, 73.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");
|
||||
}
|
||||
Reference in New Issue
Block a user