Energiberegning etter NS 3031:2025 med timesmetode og energirapport
enok leser en bygningsbeskrivelse i TOML, henter typisk klimaår for kommunen, simulerer 8760 timer etter NS-EN ISO 52016-1 og skriver energirapport, CSV og JSON. Motor - Femnodemodell for opake bygningsdeler, tonodemodell for vinduer, luftnode og strålingsnode per sone, implisitt løsning per time med egen tett LU-løser. - Varme- og kjølebehov ved eksakt interpolasjon mellom to løsninger, siden systemet er lineært. Vinduslufting for bygninger uten kjøleanlegg. - Solberegning etter ISO 52010-1, kontrollert mot pvlib med avvik under 1 prosent. Beregningsgang - Beregningspunktene A til E: netto, brutto, tilført, levert per energibærer og vektet levert energi, med solceller, klimakorrigering og effektbehov. - Energikarakter etter Enovas skala fra 1.1.2026, med arealkorreksjon. Inndata - TOML med scenarier for tiltak, og import fra IFC, gbXML og regneark. - Normerte verdier, karakterskala, vektingsfaktorer og klimadata i data/, som kan overstyres med --data. Kontroll - Stasjonært varmetap mot U·A·ΔT innenfor 2 prosent, energibalansen innenfor 2 prosent, varmetapsbudsjettet for TEK17-referansebygget identisk med publisert tabell. Kjent avvik i romoppvarming mot Simien 8 er dokumentert i README. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015GeH3y8fwTaTudaD88P57o
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
//! Ventilasjon og infiltrasjon.
|
||||
|
||||
use crate::modell::lost::Lost;
|
||||
use crate::modell::{Skjerming, VentilasjonType};
|
||||
|
||||
/// Infiltrasjonsluftmengde, m³/h, etter NS-EN 15242 slik NS 3031 anvender den:
|
||||
///
|
||||
/// `n_inf = n50 · e / (1 + (f/e) · ((q_til − q_fra) / (V · n50))²)`
|
||||
///
|
||||
/// `e` er skjermingskoeffisienten og `f` en anleggskoeffisient. Ved balansert ventilasjon
|
||||
/// faller ubalanseleddet bort, og infiltrasjonen blir `n50 · e`.
|
||||
pub fn infiltrasjonsluftmengde(l: &Lost) -> f64 {
|
||||
let e = match l.skjerming {
|
||||
Skjerming::Skjermet => 0.03,
|
||||
Skjerming::Moderat => 0.07,
|
||||
Skjerming::Utsatt => 0.10,
|
||||
};
|
||||
let f = 15.0;
|
||||
let v = l.volum;
|
||||
let q_snitt = l.ventilasjon.luftmengde * l.bra;
|
||||
let (q_til, q_fra) = match l.ventilasjon.typ {
|
||||
VentilasjonType::Balansert => (q_snitt, q_snitt),
|
||||
VentilasjonType::Avtrekk => (0.0, q_snitt),
|
||||
VentilasjonType::Naturlig => (0.0, 0.0),
|
||||
};
|
||||
let ubalanse = (q_til - q_fra).abs();
|
||||
let nevner = if l.n50 * v > 1e-9 {
|
||||
1.0 + (f / e) * (ubalanse / (v * l.n50)).powi(2)
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
let n_inf = l.n50 * e / nevner;
|
||||
n_inf * v
|
||||
}
|
||||
|
||||
/// Ventilasjonsluftmengde for en klokketime, m³/h.
|
||||
pub fn luftmengde(l: &Lost, klokketime: usize) -> f64 {
|
||||
let spesifikk = if l.ventilasjon.driftstid.aktiv(klokketime) {
|
||||
l.ventilasjon.luftmengde
|
||||
} else {
|
||||
l.ventilasjon.luftmengde_natt
|
||||
};
|
||||
spesifikk * l.bra
|
||||
}
|
||||
|
||||
/// Tilluftstemperatur etter varmegjenvinner (uten ettervarming), °C.
|
||||
pub fn tilluftstemperatur(l: &Lost, t_ute: f64, t_avtrekk: f64) -> f64 {
|
||||
match l.ventilasjon.typ {
|
||||
VentilasjonType::Balansert => t_ute + l.ventilasjon.gjenvinning * (t_avtrekk - t_ute),
|
||||
_ => t_ute,
|
||||
}
|
||||
}
|
||||
|
||||
/// Vifteeffekt for en klokketime, W.
|
||||
pub fn vifteeffekt(l: &Lost, klokketime: usize) -> f64 {
|
||||
if matches!(l.ventilasjon.typ, VentilasjonType::Naturlig) {
|
||||
return 0.0;
|
||||
}
|
||||
let q = luftmengde(l, klokketime) / 3600.0; // m³/s
|
||||
l.ventilasjon.sfp * 1000.0 * q
|
||||
}
|
||||
Reference in New Issue
Block a user