2026-09-14 18:03:00 +02:00
|
|
|
|
//! Inndatamodell for en bygning (`bygning.toml`). Alt en energirådgiver kan variere ligger her;
|
|
|
|
|
|
//! det som utelates hentes fra normerte verdier for kategorien og merkes i rapporten.
|
|
|
|
|
|
|
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
|
use std::path::PathBuf;
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
|
|
pub enum Kategori {
|
|
|
|
|
|
Smaahus,
|
|
|
|
|
|
Boligblokk,
|
|
|
|
|
|
Barnehage,
|
|
|
|
|
|
Kontorbygg,
|
|
|
|
|
|
Skolebygg,
|
|
|
|
|
|
Universitet,
|
|
|
|
|
|
Sykehus,
|
|
|
|
|
|
Sykehjem,
|
|
|
|
|
|
Hotell,
|
|
|
|
|
|
Idrettsbygg,
|
|
|
|
|
|
Forretningsbygg,
|
|
|
|
|
|
Kulturbygg,
|
|
|
|
|
|
Industribygg,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Kategori {
|
|
|
|
|
|
pub fn nokkel(&self) -> &'static str {
|
|
|
|
|
|
match self {
|
|
|
|
|
|
Kategori::Smaahus => "smaahus",
|
|
|
|
|
|
Kategori::Boligblokk => "boligblokk",
|
|
|
|
|
|
Kategori::Barnehage => "barnehage",
|
|
|
|
|
|
Kategori::Kontorbygg => "kontorbygg",
|
|
|
|
|
|
Kategori::Skolebygg => "skolebygg",
|
|
|
|
|
|
Kategori::Universitet => "universitet",
|
|
|
|
|
|
Kategori::Sykehus => "sykehus",
|
|
|
|
|
|
Kategori::Sykehjem => "sykehjem",
|
|
|
|
|
|
Kategori::Hotell => "hotell",
|
|
|
|
|
|
Kategori::Idrettsbygg => "idrettsbygg",
|
|
|
|
|
|
Kategori::Forretningsbygg => "forretningsbygg",
|
|
|
|
|
|
Kategori::Kulturbygg => "kulturbygg",
|
|
|
|
|
|
Kategori::Industribygg => "industribygg",
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
pub fn er_bolig(&self) -> bool {
|
|
|
|
|
|
matches!(self, Kategori::Smaahus | Kategori::Boligblokk)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
|
|
|
|
|
#[serde(deny_unknown_fields)]
|
|
|
|
|
|
pub struct Bygning {
|
|
|
|
|
|
pub bygning: BygningInfo,
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub klima: Klima,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
|
|
|
|
|
pub flate: Vec<Flate>,
|
2026-09-14 19:16:18 +02:00
|
|
|
|
/// Uoppvarmede soner, typisk kjeller eller loft, med egen temperaturberegning.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
|
|
|
|
|
pub sone: Vec<Sone>,
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub grunn: Grunn,
|
2026-09-14 18:03:00 +02:00
|
|
|
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
|
|
|
|
|
pub vindu: Vec<Vindu>,
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub kuldebroer: Kuldebroer,
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub infiltrasjon: Infiltrasjon,
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub ventilasjon: Ventilasjon,
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub tappevann: Tappevann,
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub oppvarming: Oppvarming,
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub distribusjon: Distribusjon,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub solcelle: Option<Solcelle>,
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub kjoling: Kjoling,
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub lufting: Lufting,
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub drift: Drift,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
|
|
|
|
|
pub scenario: Vec<Scenario>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
|
|
|
|
|
pub struct BygningInfo {
|
|
|
|
|
|
pub navn: String,
|
|
|
|
|
|
pub kategori: Kategori,
|
|
|
|
|
|
pub byggeaar: i32,
|
|
|
|
|
|
/// Oppvarmet del av bruksareal, m².
|
|
|
|
|
|
pub oppvarmet_bra: f64,
|
|
|
|
|
|
/// Oppvarmet luftvolum, m³. Utelatt: 2,4 m × BRA.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub oppvarmet_volum: Option<f64>,
|
|
|
|
|
|
#[serde(default = "en")]
|
|
|
|
|
|
pub antall_boenheter: u32,
|
|
|
|
|
|
/// Samlet oppvarmet BRA for hele bygningen når én boenhet i flerbolighus merkes.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub bygningens_oppvarmede_bra: Option<f64>,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub adresse: Option<String>,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub gnr_bnr: Option<String>,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub beskrivelse: Option<String>,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub energiraadgiver: Option<String>,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub oppdragsgiver: Option<String>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn en() -> u32 {
|
|
|
|
|
|
1
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug, Default)]
|
|
|
|
|
|
pub struct Klima {
|
|
|
|
|
|
/// Kommune for lokalt klima (TMY-fil fra Zenodo 14779899). Utelatt: bare Oslo.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub kommune: Option<String>,
|
|
|
|
|
|
/// Egen EPW-fil for lokalt klima (overstyrer kommune).
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub epw: Option<PathBuf>,
|
|
|
|
|
|
/// Referanseklima for energimerket. Standard «Oslo».
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub referanse: Option<String>,
|
|
|
|
|
|
/// Bakkerefleksjon (albedo) for solstråling. Standard 0,2.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub albedo: Option<f64>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Copy, Debug, PartialEq, Eq)]
|
|
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
|
|
pub enum FlateType {
|
|
|
|
|
|
Vegg,
|
|
|
|
|
|
Tak,
|
|
|
|
|
|
Gulv,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Copy, Debug, PartialEq, Eq, Default)]
|
|
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
|
|
pub enum Mot {
|
|
|
|
|
|
#[default]
|
|
|
|
|
|
Ute,
|
|
|
|
|
|
Grunn,
|
|
|
|
|
|
Uoppvarmet,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Copy, Debug, PartialEq, Eq)]
|
|
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
|
|
pub enum Masseklasse {
|
|
|
|
|
|
SvaertLett,
|
|
|
|
|
|
Lett,
|
|
|
|
|
|
Middels,
|
|
|
|
|
|
Tung,
|
|
|
|
|
|
SvaertTung,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Masseklasse {
|
|
|
|
|
|
/// Arealspesifikk varmekapasitet κ_m, J/(m²K) (ISO 52016-1 Tabell B.14).
|
|
|
|
|
|
pub fn kappa(&self) -> f64 {
|
|
|
|
|
|
match self {
|
|
|
|
|
|
Masseklasse::SvaertLett => 50_000.0,
|
|
|
|
|
|
Masseklasse::Lett => 75_000.0,
|
|
|
|
|
|
Masseklasse::Middels => 110_000.0,
|
|
|
|
|
|
Masseklasse::Tung => 175_000.0,
|
|
|
|
|
|
Masseklasse::SvaertTung => 250_000.0,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Hvor massen sitter i konstruksjonen (ISO 52016-1 klasse I/E/IE/D/M).
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Copy, Debug, PartialEq, Eq, Default)]
|
|
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
|
|
pub enum Masseplassering {
|
|
|
|
|
|
Innvendig,
|
|
|
|
|
|
Utvendig,
|
|
|
|
|
|
Begge,
|
|
|
|
|
|
#[default]
|
|
|
|
|
|
Fordelt,
|
|
|
|
|
|
Midt,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
|
|
|
|
|
pub struct Lag {
|
|
|
|
|
|
pub materiale: String,
|
|
|
|
|
|
pub tykkelse: f64,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
|
|
|
|
|
pub struct Flate {
|
|
|
|
|
|
pub navn: String,
|
|
|
|
|
|
#[serde(rename = "type")]
|
|
|
|
|
|
pub typ: FlateType,
|
|
|
|
|
|
pub areal: f64,
|
|
|
|
|
|
/// Himmelretning flatens utside vender mot, grader fra nord med klokka (0 N, 90 Ø, 180 S, 270 V).
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub orientering: f64,
|
|
|
|
|
|
/// Helning fra horisontalplanet: 90 = vertikal vegg, 0 = flatt tak. Utelatt: 90 for vegg, 0 for tak/gulv.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub helning: Option<f64>,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub u_verdi: Option<f64>,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub lag: Option<Vec<Lag>>,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub masseklasse: Option<Masseklasse>,
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub masseplassering: Masseplassering,
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub mot: Mot,
|
|
|
|
|
|
/// Temperaturfaktor b for uoppvarmet rom. Utelatt: 0,5 (loft/kjeller), jf. NS-EN ISO 13789.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub b_faktor: Option<f64>,
|
|
|
|
|
|
/// Solabsorptans for utvendig overflate. Utelatt: 0,6.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub absorptans: Option<f64>,
|
2026-09-14 19:16:18 +02:00
|
|
|
|
/// Gulv mot grunn: eksponert omkrets, m. Brukes i den karakteristiske dimensjonen B′.
|
2026-09-14 18:03:00 +02:00
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub omkrets: Option<f64>,
|
2026-09-14 19:16:18 +02:00
|
|
|
|
/// Dybde under terreng, m. For gulv: gulvets dybde. For kjellervegg: veggens nedgravde høyde.
|
2026-09-14 18:03:00 +02:00
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub dybde: Option<f64>,
|
2026-09-14 19:16:18 +02:00
|
|
|
|
/// Kjellervegg: høyden som står over terreng, m. Den delen regnes som vanlig yttervegg,
|
|
|
|
|
|
/// og arealet deles mellom over og under terreng i forhold til høydene.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub over_terreng: Option<f64>,
|
|
|
|
|
|
/// Navnet på den uoppvarmede sonen flaten vender mot, når `mot = "uoppvarmet"`.
|
|
|
|
|
|
/// Uten dette brukes temperaturfaktoren `b_faktor` i stedet.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub sone: Option<String>,
|
2026-09-14 18:03:00 +02:00
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub kommentar: Option<String>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Copy, Debug, PartialEq, Eq, Default)]
|
|
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
|
|
pub enum SolskjermingType {
|
|
|
|
|
|
#[default]
|
|
|
|
|
|
Ingen,
|
|
|
|
|
|
Manuell,
|
|
|
|
|
|
Automatisk,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
|
|
|
|
|
pub struct Solskjerming {
|
|
|
|
|
|
#[serde(rename = "type")]
|
|
|
|
|
|
pub typ: SolskjermingType,
|
|
|
|
|
|
/// Gjennomslipp når skjermingen er i bruk (0–1). Utelatt: 0,8 manuell, 0,4 automatisk.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub faktor: Option<f64>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
|
|
|
|
|
pub struct Vindu {
|
|
|
|
|
|
pub navn: String,
|
|
|
|
|
|
/// Areal inkl. karm, m².
|
|
|
|
|
|
pub areal: f64,
|
|
|
|
|
|
#[serde(default = "en_f64")]
|
|
|
|
|
|
pub antall: f64,
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub orientering: f64,
|
|
|
|
|
|
#[serde(default = "nitti")]
|
|
|
|
|
|
pub helning: f64,
|
|
|
|
|
|
pub u_verdi: f64,
|
|
|
|
|
|
/// Solfaktor for glasset (g-verdi). Utelatt: 0,75 for 2-lags, 0,5 for 3-lags energiglass.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub g_verdi: Option<f64>,
|
|
|
|
|
|
/// Karm- og rammeandel av arealet. Utelatt: 0,2.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub karmandel: Option<f64>,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub solskjerming: Option<Solskjerming>,
|
|
|
|
|
|
/// Horisontavskjerming i grader (terreng, nabobygg). Utelatt: 0.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub horisont: Option<f64>,
|
|
|
|
|
|
/// Er dette en dør (regnes uten solinnstråling)?
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub dor: bool,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub kommentar: Option<String>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn en_f64() -> f64 {
|
|
|
|
|
|
1.0
|
|
|
|
|
|
}
|
|
|
|
|
|
fn nitti() -> f64 {
|
|
|
|
|
|
90.0
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-14 19:16:18 +02:00
|
|
|
|
/// Grunnforhold for beregning etter NS-EN ISO 13370.
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug, Default)]
|
|
|
|
|
|
pub struct Grunn {
|
|
|
|
|
|
/// Varmeledningsevne for jorda, W/(m·K). Utelatt: 2,0 (leire eller silt).
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub ledningsevne: Option<f64>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// En uoppvarmet sone, typisk kjeller, loft eller garasje.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Sonen har ingen egen oppvarming, men får varme fra den oppvarmede delen gjennom
|
|
|
|
|
|
/// etasjeskilleren og fra varmerør og bereder som står der. Temperaturen regnes ut time for
|
|
|
|
|
|
/// time av varmebalansen etter NS-EN ISO 13789, slik at et varmt rørnett i kjelleren både
|
|
|
|
|
|
/// teller som tap fra varmeanlegget og som varme som holder etasjeskilleren varm.
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
|
|
|
|
|
pub struct Sone {
|
|
|
|
|
|
pub navn: String,
|
|
|
|
|
|
/// Luftvolum, m³. Brukes til ventilasjonstapet fra sonen.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub volum: Option<f64>,
|
|
|
|
|
|
/// Luftvekslinger per time mot det fri. Utelatt: 0,3 for en kjeller.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub luftveksling: Option<f64>,
|
|
|
|
|
|
/// Sonens egne flater mot det fri og mot grunnen.
|
|
|
|
|
|
#[serde(default, rename = "flate", skip_serializing_if = "Vec::is_empty")]
|
|
|
|
|
|
pub flater: Vec<Flate>,
|
|
|
|
|
|
/// Andel av varmeanleggets distribusjonstap som avgis i denne sonen. Utelatt: 1,0 når
|
|
|
|
|
|
/// bygningen har vannbåren varme og sonen er den eneste uoppvarmede.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub andel_distribusjonstap: Option<f64>,
|
|
|
|
|
|
/// Andel av tappevannsanleggets tap som avgis her.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub andel_tappevannstap: Option<f64>,
|
|
|
|
|
|
/// Fast varmetilskudd i sonen, W. For eksempel kappetap fra en kjel.
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub fast_effekt: f64,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub kommentar: Option<String>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-14 18:03:00 +02:00
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug, Default)]
|
|
|
|
|
|
pub struct Kuldebroer {
|
|
|
|
|
|
/// Normalisert kuldebroverdi, W/(m²K) av oppvarmet BRA. Utelatt: verdi etter byggeår.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub normalisert: Option<f64>,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
|
|
|
|
|
pub liste: Vec<Kuldebro>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
|
|
|
|
|
pub struct Kuldebro {
|
|
|
|
|
|
pub navn: String,
|
|
|
|
|
|
pub psi: f64,
|
|
|
|
|
|
pub lengde: f64,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Copy, Debug, PartialEq, Eq, Default)]
|
|
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
|
|
pub enum Skjerming {
|
|
|
|
|
|
Skjermet,
|
|
|
|
|
|
#[default]
|
|
|
|
|
|
Moderat,
|
|
|
|
|
|
Utsatt,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug, Default)]
|
|
|
|
|
|
pub struct Infiltrasjon {
|
|
|
|
|
|
/// Lekkasjetall ved 50 Pa, 1/h. Utelatt: verdi etter byggeår.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub n50: Option<f64>,
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub skjerming: Skjerming,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub maalt_dato: Option<String>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Copy, Debug, PartialEq, Eq, Default)]
|
|
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
|
|
pub enum VentilasjonType {
|
|
|
|
|
|
#[default]
|
|
|
|
|
|
Naturlig,
|
|
|
|
|
|
Avtrekk,
|
|
|
|
|
|
Balansert,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug, Default)]
|
|
|
|
|
|
pub struct Ventilasjon {
|
|
|
|
|
|
#[serde(rename = "type", default)]
|
|
|
|
|
|
pub typ: VentilasjonType,
|
|
|
|
|
|
/// Gjennomsnittlig luftmengde i driftstiden, m³/(h·m²). Utelatt: normert.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub luftmengde: Option<f64>,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub luftmengde_natt: Option<f64>,
|
|
|
|
|
|
/// Temperaturvirkningsgrad varmegjenvinner (0–1). Bare balansert. Utelatt: normert.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub gjenvinning: Option<f64>,
|
|
|
|
|
|
/// Spesifikk vifteeffekt, kW/(m³/s). Utelatt: normert (balansert) / 0,6 (avtrekk).
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub sfp: Option<f64>,
|
|
|
|
|
|
/// Har anlegget varmebatteri som ettervarmer tilluften?
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub varmebatteri: Option<bool>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Copy, Debug, PartialEq, Eq, Default)]
|
|
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
|
|
pub enum TappevannSystem {
|
|
|
|
|
|
#[default]
|
|
|
|
|
|
Aapent,
|
|
|
|
|
|
Sirkulasjon,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug, Default)]
|
|
|
|
|
|
pub struct Tappevann {
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub system: TappevannSystem,
|
|
|
|
|
|
/// Netto energibehov, kWh/(m²·år). Utelatt: normert.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub energibehov: Option<f64>,
|
|
|
|
|
|
/// Tap i bereder og rør som andel av netto behov. Utelatt: 0,25 åpent, 0,45 sirkulasjon.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub tap_andel: Option<f64>,
|
|
|
|
|
|
/// Andel av tapet som avgis i oppvarmet sone (uregulerbart varmetilskudd). Utelatt: 0,8 / 0,5.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub tap_i_oppvarmet_sone: Option<f64>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
|
|
pub enum VarmekildeType {
|
|
|
|
|
|
DirekteEl,
|
|
|
|
|
|
ElKjel,
|
|
|
|
|
|
LuftLuftVp,
|
|
|
|
|
|
LuftVannVp,
|
|
|
|
|
|
VaeskeVannVp,
|
|
|
|
|
|
AvtrekkVp,
|
|
|
|
|
|
Vedovn,
|
|
|
|
|
|
Pellets,
|
|
|
|
|
|
Olje,
|
|
|
|
|
|
Gass,
|
|
|
|
|
|
Fjernvarme,
|
|
|
|
|
|
Solfanger,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl VarmekildeType {
|
|
|
|
|
|
pub fn nokkel(&self) -> &'static str {
|
|
|
|
|
|
match self {
|
|
|
|
|
|
VarmekildeType::DirekteEl => "direkte_el",
|
|
|
|
|
|
VarmekildeType::ElKjel => "el_kjel",
|
|
|
|
|
|
VarmekildeType::LuftLuftVp => "luft_luft_vp",
|
|
|
|
|
|
VarmekildeType::LuftVannVp => "luft_vann_vp",
|
|
|
|
|
|
VarmekildeType::VaeskeVannVp => "vaeske_vann_vp",
|
|
|
|
|
|
VarmekildeType::AvtrekkVp => "avtrekk_vp",
|
|
|
|
|
|
VarmekildeType::Vedovn => "vedovn",
|
|
|
|
|
|
VarmekildeType::Pellets => "pellets",
|
|
|
|
|
|
VarmekildeType::Olje => "olje",
|
|
|
|
|
|
VarmekildeType::Gass => "gass",
|
|
|
|
|
|
VarmekildeType::Fjernvarme => "fjernvarme",
|
|
|
|
|
|
VarmekildeType::Solfanger => "solfanger",
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
pub fn beskrivelse(&self) -> &'static str {
|
|
|
|
|
|
match self {
|
|
|
|
|
|
VarmekildeType::DirekteEl => "Direkte elektrisk (panelovner, varmekabler)",
|
|
|
|
|
|
VarmekildeType::ElKjel => "Elektrokjel, vannbåren varme",
|
|
|
|
|
|
VarmekildeType::LuftLuftVp => "Varmepumpe luft–luft",
|
|
|
|
|
|
VarmekildeType::LuftVannVp => "Varmepumpe luft–vann",
|
|
|
|
|
|
VarmekildeType::VaeskeVannVp => "Varmepumpe væske–vann (berg/jord/sjø)",
|
|
|
|
|
|
VarmekildeType::AvtrekkVp => "Avtrekksvarmepumpe",
|
|
|
|
|
|
VarmekildeType::Vedovn => "Vedovn",
|
|
|
|
|
|
VarmekildeType::Pellets => "Pelletskamin/-kjel",
|
|
|
|
|
|
VarmekildeType::Olje => "Oljekjel",
|
|
|
|
|
|
VarmekildeType::Gass => "Gasskjel",
|
|
|
|
|
|
VarmekildeType::Fjernvarme => "Fjernvarme",
|
|
|
|
|
|
VarmekildeType::Solfanger => "Solfanger",
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
pub fn er_varmepumpe(&self) -> bool {
|
|
|
|
|
|
matches!(
|
|
|
|
|
|
self,
|
|
|
|
|
|
VarmekildeType::LuftLuftVp
|
|
|
|
|
|
| VarmekildeType::LuftVannVp
|
|
|
|
|
|
| VarmekildeType::VaeskeVannVp
|
|
|
|
|
|
| VarmekildeType::AvtrekkVp
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
/// Kan kilden levere til vannbåren distribusjon (ventilasjonsvarme, tappevann)?
|
|
|
|
|
|
pub fn vannbaaren(&self) -> bool {
|
|
|
|
|
|
!matches!(
|
|
|
|
|
|
self,
|
|
|
|
|
|
VarmekildeType::DirekteEl | VarmekildeType::LuftLuftVp | VarmekildeType::Vedovn
|
|
|
|
|
|
)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
|
|
|
|
|
pub struct Varmekilde {
|
|
|
|
|
|
#[serde(rename = "type")]
|
|
|
|
|
|
pub typ: VarmekildeType,
|
|
|
|
|
|
/// Andel av romoppvarmingsbehovet kilden dekker (0–1).
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub andel_rom: f64,
|
|
|
|
|
|
/// Andel av ventilasjonsvarme. Utelatt: som andel_rom for vannbårne kilder, ellers 0.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub andel_ventilasjon: Option<f64>,
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub andel_tappevann: f64,
|
|
|
|
|
|
/// Årsvarmefaktor (SPF) for varmepumper eller virkningsgrad for kjeler. Utelatt: tabellverdi.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub spf: Option<f64>,
|
|
|
|
|
|
/// Turtemperatur °C for vannbårne varmepumper (35/45/55).
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub turtemperatur: Option<f64>,
|
|
|
|
|
|
/// Vedovn: lukket ildsted med lavt partikkelutslipp (gir vektingsfaktor 0,45).
|
|
|
|
|
|
#[serde(default = "sann")]
|
|
|
|
|
|
pub lukket: bool,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub kommentar: Option<String>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn sann() -> bool {
|
|
|
|
|
|
true
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug, Default)]
|
|
|
|
|
|
pub struct Oppvarming {
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
|
|
|
|
|
pub kilde: Vec<Varmekilde>,
|
|
|
|
|
|
/// Maks varmeeffekt installert, W (begrenser innetemperatur ved underdekning). Utelatt: ubegrenset.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub maks_effekt: Option<f64>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Copy, Debug, PartialEq, Eq, Default)]
|
|
|
|
|
|
#[serde(rename_all = "snake_case")]
|
|
|
|
|
|
pub enum DistribusjonType {
|
|
|
|
|
|
#[default]
|
|
|
|
|
|
Punkt,
|
|
|
|
|
|
Radiator,
|
|
|
|
|
|
Gulvvarme,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug, Default)]
|
|
|
|
|
|
pub struct Distribusjon {
|
|
|
|
|
|
#[serde(rename = "type", default)]
|
|
|
|
|
|
pub typ: DistribusjonType,
|
|
|
|
|
|
/// Distribusjonstap som andel av avgitt romvarme. Utelatt: 0 punkt, 0,03 radiator, 0,05 gulvvarme.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub tap_andel: Option<f64>,
|
|
|
|
|
|
/// Andel av tapet som går til uoppvarmet areal (rør i kjeller/loft). Utelatt: 0,2.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub roer_uoppvarmet: Option<f64>,
|
|
|
|
|
|
/// Pumpeeffekt, W/m² i driftstid. Utelatt: normert for vannbåren, 0 for punkt.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub pumpe_effekt: Option<f64>,
|
|
|
|
|
|
/// Turtemperatur °C i vannbårent anlegg (60 radiator, 35 gulvvarme). Brukes for SPF-oppslag.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub turtemperatur: Option<f64>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
|
|
|
|
|
pub struct Solcelle {
|
|
|
|
|
|
/// Modulareal, m².
|
|
|
|
|
|
pub areal: f64,
|
|
|
|
|
|
#[serde(default = "tjue_prosent")]
|
|
|
|
|
|
pub virkningsgrad: f64,
|
|
|
|
|
|
#[serde(default = "sor")]
|
|
|
|
|
|
pub orientering: f64,
|
|
|
|
|
|
#[serde(default = "tretti")]
|
|
|
|
|
|
pub helning: f64,
|
|
|
|
|
|
/// Ytelsesfaktor (inverter, kabler, snø, smuss). Utelatt: 0,8.
|
|
|
|
|
|
#[serde(default = "aatti_prosent")]
|
|
|
|
|
|
pub ytelsesfaktor: f64,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn tjue_prosent() -> f64 {
|
|
|
|
|
|
0.20
|
|
|
|
|
|
}
|
|
|
|
|
|
fn sor() -> f64 {
|
|
|
|
|
|
180.0
|
|
|
|
|
|
}
|
|
|
|
|
|
fn tretti() -> f64 {
|
|
|
|
|
|
30.0
|
|
|
|
|
|
}
|
|
|
|
|
|
fn aatti_prosent() -> f64 {
|
|
|
|
|
|
0.8
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
|
|
|
|
|
pub struct Kjoling {
|
|
|
|
|
|
#[serde(default = "sann")]
|
|
|
|
|
|
pub ingen: bool,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub settpunkt: Option<f64>,
|
|
|
|
|
|
/// Årskuldefaktor (SEER). Utelatt: 3,0.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub spf: Option<f64>,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub maks_effekt: Option<f64>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl Default for Kjoling {
|
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
|
Self {
|
|
|
|
|
|
ingen: true,
|
|
|
|
|
|
settpunkt: None,
|
|
|
|
|
|
spf: None,
|
|
|
|
|
|
maks_effekt: None,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Vinduslufting: økt luftmengde når rommene blir for varme.
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Bygninger uten kjøleanlegg luftes gjennom vinduer når det blir for varmt. Uten denne
|
|
|
|
|
|
/// modellen vil en tett bygning med store vindusflater få urealistisk høye innetemperaturer
|
|
|
|
|
|
/// om våren og høsten, og lagret solvarme vil kunstig redusere oppvarmingsbehovet.
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug, Default)]
|
|
|
|
|
|
pub struct Lufting {
|
|
|
|
|
|
/// Slår av vinduslufting. Standard er lufting for bygninger uten kjøleanlegg.
|
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
|
pub ingen: bool,
|
|
|
|
|
|
/// Operativ temperatur der luftingen starter, °C. Utelatt: 24.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub settpunkt: Option<f64>,
|
|
|
|
|
|
/// Største luftmengde ved vinduslufting, m³/(h·m²) oppvarmet BRA. Utelatt: 8.
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub maks_luftmengde: Option<f64>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug, Default)]
|
|
|
|
|
|
pub struct Drift {
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub settpunkt_oppvarming: Option<f64>,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub nattsenking: Option<f64>,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub belysning_effekt: Option<f64>,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub utstyr_effekt: Option<f64>,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub personer_varmetilskudd: Option<f64>,
|
|
|
|
|
|
/// Effektiv innvendig varmekapasitet for luft og inventar, J/(m²K). Utelatt: 10 000 (ISO 52016-1).
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub innvendig_varmekapasitet: Option<f64>,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
|
|
|
|
|
pub struct Scenario {
|
|
|
|
|
|
pub navn: String,
|
|
|
|
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
|
|
|
|
pub beskrivelse: Option<String>,
|
|
|
|
|
|
/// Delvis bygningsbeskrivelse som flettes inn: tabeller flettes rekursivt, tabellarrayer
|
|
|
|
|
|
/// (flate, vindu, oppvarming.kilde …) matches på `navn`/`type`, skalarer erstattes.
|
|
|
|
|
|
/// `slett = true` fjerner et element.
|
|
|
|
|
|
pub endringer: toml::Value,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-09-14 21:20:34 +02:00
|
|
|
|
pub mod kontroll;
|
2026-09-14 18:03:00 +02:00
|
|
|
|
pub mod lost;
|