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:
+101
@@ -0,0 +1,101 @@
|
||||
// Stilark for enok-energirapporten. Kopieres til utdatakatalogen og kan tilpasses fritt.
|
||||
|
||||
#let aksent = rgb("#8c2f1f")
|
||||
#let aksent-lys = rgb("#b9633f")
|
||||
#let moerk = rgb("#1a1a1a")
|
||||
#let mid = rgb("#555555")
|
||||
#let lys = rgb("#f4f1ee")
|
||||
#let kantlinje = rgb("#ddd4cc")
|
||||
|
||||
#let font-heading = ("Libertinus Serif", "DejaVu Serif", "Noto Serif")
|
||||
#let font-body = ("Libertinus Serif", "DejaVu Serif", "Noto Serif")
|
||||
#let font-tall = ("DejaVu Sans Mono", "Liberation Mono")
|
||||
|
||||
#let oppsett(tittel: "", undertittel: "", bunntekst: "", doc) = {
|
||||
set page(
|
||||
paper: "a4",
|
||||
margin: (top: 2.4cm, bottom: 2.4cm, left: 2.2cm, right: 2.2cm),
|
||||
header: context {
|
||||
if counter(page).get().first() > 1 {
|
||||
grid(
|
||||
columns: (1fr, auto),
|
||||
align: (left + horizon, right + horizon),
|
||||
text(font: font-heading, size: 8pt, fill: mid)[#tittel],
|
||||
text(font: font-body, size: 8pt, fill: mid)[#counter(page).display()],
|
||||
)
|
||||
line(length: 100%, stroke: 0.4pt + kantlinje)
|
||||
}
|
||||
},
|
||||
footer: context {
|
||||
if counter(page).get().first() > 1 and bunntekst != "" {
|
||||
line(length: 100%, stroke: 0.4pt + kantlinje)
|
||||
v(3pt)
|
||||
text(font: font-body, size: 7.5pt, fill: mid)[#bunntekst]
|
||||
}
|
||||
},
|
||||
)
|
||||
set text(font: font-body, size: 10pt, fill: moerk, lang: "nb")
|
||||
set par(justify: true, leading: 0.62em)
|
||||
show heading: it => {
|
||||
set text(font: font-heading, fill: aksent)
|
||||
block(above: 1.2em, below: 0.6em, it)
|
||||
}
|
||||
show heading.where(level: 1): it => {
|
||||
set text(size: 15pt, weight: "bold")
|
||||
block(above: 1.6em, below: 0.7em)[
|
||||
#it.body
|
||||
#v(-0.45em)
|
||||
#line(length: 100%, stroke: 1pt + aksent)
|
||||
]
|
||||
}
|
||||
show heading.where(level: 2): set text(size: 11.5pt, weight: "bold")
|
||||
set table(stroke: none, inset: (x: 6pt, y: 4pt))
|
||||
show table.cell.where(y: 0): set text(weight: "bold", size: 9pt)
|
||||
doc
|
||||
}
|
||||
|
||||
// Tabell med stripete rader og linje under overskriften.
|
||||
#let tabell(kolonner: (), overskrift: (), rader: (), justering: none, sum-rader: ()) = {
|
||||
let j = if justering == none { kolonner.map(_ => right) } else { justering }
|
||||
block(breakable: true, table(
|
||||
columns: kolonner,
|
||||
align: (x, y) => if y == 0 { center + bottom } else { j.at(x) + horizon },
|
||||
fill: (x, y) => if y == 0 { lys }
|
||||
else if sum-rader.contains(y - 1) { rgb("#efe9e4") }
|
||||
else if calc.rem(y, 2) == 0 { rgb("#fbfaf9") } else { white },
|
||||
stroke: (x, y) => (
|
||||
bottom: if y == 0 { 0.8pt + aksent } else { 0.3pt + kantlinje },
|
||||
),
|
||||
..overskrift.map(h => [#h]),
|
||||
..rader.flatten(),
|
||||
))
|
||||
}
|
||||
|
||||
// Stor karakterrute på forsiden.
|
||||
#let karakterrute(bokstav, verdi, farge) = {
|
||||
box(
|
||||
fill: farge,
|
||||
radius: 6pt,
|
||||
inset: (x: 16pt, y: 12pt),
|
||||
stack(
|
||||
spacing: 3pt,
|
||||
align(center, text(size: 46pt, weight: "bold", fill: white)[#bokstav]),
|
||||
align(center, text(size: 9pt, fill: white)[#verdi kWh/(m²·år)]),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
#let faktaboks(innhold) = block(
|
||||
fill: lys,
|
||||
radius: 4pt,
|
||||
inset: 9pt,
|
||||
width: 100%,
|
||||
stroke: 0.4pt + kantlinje,
|
||||
innhold,
|
||||
)
|
||||
|
||||
#let merknad(innhold) = block(
|
||||
inset: (left: 9pt),
|
||||
stroke: (left: 2pt + aksent-lys),
|
||||
text(size: 9pt)[#innhold],
|
||||
)
|
||||
Reference in New Issue
Block a user