Files
enok/src/rapport/csv_ut.rs
T
blandClaude Opus 5 0964cacba3 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
2026-09-14 18:03:00 +02:00

97 lines
2.7 KiB
Rust

//! CSV-utskrift: timeserie for hele året og månedssummer.
use crate::kjor::Resultat;
use crate::Result;
use std::path::Path;
pub fn timeserie(r: &Resultat, sti: &Path) -> Result<()> {
let mut w = csv::Writer::from_path(sti)?;
w.write_record([
"time",
"maaned",
"t_ute_C",
"t_inne_C",
"t_operativ_C",
"sol_horisontal_W_per_m2",
"soltilskudd_W",
"internlast_W",
"romoppvarming_W",
"ventilasjonsvarme_W",
"varmtvann_W",
"romkjoling_W",
"ventilasjonskjoling_W",
"vifter_W",
"pumper_W",
"belysning_W",
"utstyr_W",
"solceller_W",
])?;
let sol = r.solceller.as_ref().map(|p| p.serie.as_slice());
let ts = &r.timeserie;
for t in 0..crate::TIMER {
let f = |v: f64| format!("{v:.1}");
w.write_record([
t.to_string(),
crate::MAANEDER[crate::maaned_for_time(t)].to_string(),
format!("{:.2}", ts.t_ute[t]),
format!("{:.2}", ts.t_inne[t]),
format!("{:.2}", ts.t_operativ[t]),
f(ts.sol_horisontal[t]),
f(ts.soltilskudd[t]),
f(ts.internlast[t]),
f(ts.romoppvarming[t]),
f(ts.ventilasjonsvarme[t]),
f(ts.varmtvann[t]),
f(ts.romkjoling[t]),
f(ts.ventilasjonskjoling[t]),
f(ts.vifter[t]),
f(ts.pumper[t]),
f(ts.belysning[t]),
f(ts.utstyr[t]),
f(sol.map(|s| s[t]).unwrap_or(0.0)),
])?;
}
w.flush()?;
Ok(())
}
pub fn maanedsverdier(r: &Resultat, sti: &Path) -> Result<()> {
let m = r.sammendrag().maanedsverdier;
let mut w = csv::Writer::from_path(sti)?;
w.write_record([
"maaned",
"utetemperatur_C",
"romoppvarming_kWh",
"ventilasjonsvarme_kWh",
"varmtvann_kWh",
"kjoling_kWh",
"vifter_pumper_kWh",
"belysning_kWh",
"utstyr_kWh",
"sum_kWh",
])?;
for i in 0..12 {
let sum = m.romoppvarming[i]
+ m.ventilasjonsvarme[i]
+ m.varmtvann[i]
+ m.kjoling[i]
+ m.vifter_pumper[i]
+ m.belysning[i]
+ m.utstyr[i];
w.write_record([
m.maaned[i].to_string(),
format!("{:.1}", m.utetemperatur[i]),
format!("{:.0}", m.romoppvarming[i]),
format!("{:.0}", m.ventilasjonsvarme[i]),
format!("{:.0}", m.varmtvann[i]),
format!("{:.0}", m.kjoling[i]),
format!("{:.0}", m.vifter_pumper[i]),
format!("{:.0}", m.belysning[i]),
format!("{:.0}", m.utstyr[i]),
format!("{sum:.0}"),
])?;
}
w.flush()?;
Ok(())
}