Stationäre hydraulisch-thermische Berechnung von HVAC-Hydraulikschaltungen (Heizung/Kühlung) als generisches 1D-Netzwerk. Inkompressibles Fluid mit konstanten Stoffwerten (ρ, μ, cp); SIMPLE-artiger Druckkorrektur-Solver plus sequentiell gelöste Energiegleichung — mit zwei grafischen Schema-Editoren (Hydraulik und Lüftung/VKA) inklusive integriertem Solver: Rechnen direkt im GUI, Ergebnisse per Mouse-Over in der Zeichnung.
Maschinenlesbare Strangschemas für KI-Agenten: Strangschemas sind für KI-Agenten bislang schwer zugänglich, weil ihre Vision-Fähigkeiten für das zuverlässige Interpretieren von Anlagenschemata nicht ausreichen. Dieses Tool löst das Eingabeproblem konstruktiv: Das Schema wird im Editor gezeichnet und liegt damit von Anfang an maschinenlesbar als YAML vor — die Zeichnung ist das Modell, es gibt keinen Interpretationsschritt. Über den integrierten Solver (▶ Rechnen) wird die Eingabe per Human in the Loop geprüft (Volumenströme, Drücke, Temperaturen direkt im Schema), bevor ein KI-Agent das validierte YAML für Analyse- und Optimierungsstudien übernimmt. Das Paket dient zugleich der Entwicklung von Benchmark-Tests für KI-Agenten in der technischen Gebäudeausrüstung.
git clone https://github.com/AI4Buildings/HVAC-Hydronic-Network-Solver.git
cd HVAC-Hydronic-Network-Solver
pip install -e ".[dev]"
pytest # 1287 Tests (analytische Referenzen + Validierung gegen Musterlösungen)editor server # startet beide Editoren: http://127.0.0.1:8091/Die Startseite verlinkt den Hydraulikschema-Editor (/hydraulik) und den
Lüftungsschema-Editor (/lueftung); gerechnet wird direkt im GUI
(lokaler Endpunkt, nur 127.0.0.1). editor serve, kurz editor oder das
ältere hydraulik serve tun dasselbe; --port/--no-open optional.
Daneben gibt es das CLI hydraulik (run = YAML/JSON rechnen, export --json =
geprüftes Modell als kanonisches JSON, schema = JSON Schema des
Eingabeformats, editor = statische HTML-Datei erzeugen, serve).
hydraulik run examples/04_heatpump_separator.yamloder in Python:
import hydraulik as h
net = h.Network(fluid=h.water_at(45))
net.add(h.HeatPump("wp1", mode="target_t_out", t_out_set_C=45, q_max_kW=12, q_nom_m3h=1.4))
net.add(h.Pump("pu1", mode="constant_flow", q_m3h=1.4))
net.add(h.Radiator("hk1", q_nom_kW=7.5, t_sup_nom_C=45, t_ret_nom_C=40, t_room_C=21))
net.connect("wp1.out", "pu1.in")
net.connect("pu1.out", "hk1.in")
net.connect("hk1.out", "wp1.in")
result = net.solve()
print(result.report())
print(result["hk1"].q_dot_kW) # Wärmestrom ins Wasser [kW]editor server # Editor MIT Rechen-Endpunkt (empfohlen)
hydraulik editor --out hydraulik_editor.html # nur Zeichnen (statische Datei)Workflow: Schaltung zeichnen → ▶ Rechnen direkt im GUI (lokaler Endpunkt POST /solve, nur 127.0.0.1) → Ergebnisse erscheinen in der Zeichnung: Wertezeile unter jeder Komponente (V̇, T ein→aus) und Mouse-Over-Tooltips (Komponenten: V̇, Δp, T, Q̇, v; Leitungen/Ports: Knotendruck in kPa(ü) und Temperatur) → prüfen, korrigieren, neu rechnen (jede Änderung verwirft die Ergebnisse automatisch) → YAML als Datei exportieren → Analyse-/Optimierungsstudien mit dem Solver skripten (z.B. durch einen Coding-Agenten — der das Anlagenschema dann nicht mehr aus Abbildungen interpretieren muss, sondern das validierte YAML erhält).
Eigenständige HTML-Datei (kein Server, keine Internetverbindung): Komponenten
aus der Palette platzieren; jede gezogene Linie ist eine
Verbindungsleitung (conduit): standardmäßig ideal, per Inspector
wahlweise C-Wert, Auslegungspunkt (dp + q) oder Rohrmodell (length +
d_inner …, inkl. Wärmeverlust) — mit eigenem Namen (sichtbar bei
Selektion), ts-Label und eigenen Ergebniswerten im Hover (V̇, Δp, T, v).
Leitungsführung mit Knickpunkten (Doppelklick auf Leitung setzt eine
Umlenkung, Griffe ziehen, Doppelklick auf Griff entfernt; ohne Knick
automatisch gerade bzw. abgewinkelt), Vorlagen für Standardschaltungen
(Palette-Register „Vorlagen“: mitgeliefert sind die sieben Grundschaltungen
Beimischschaltung einfach/doppelt/doppelt-differenzdruckarm, Drossel-,
Umlenk- sowie Einspritzschaltung mit Durchgangs- bzw. Dreiwegeventil;
eigene Vorlagen: Bereich auswählen → „Als Vorlage speichern" → per Klick
platzieren und Parameter anpassen; im Browser gespeichert, als JSON-Datei
export-/importierbar zum Teilen), Mehrfachauswahl
(Auswahlrechteck aufziehen oder Shift+Klick) mit gemeinsamem Verschieben und
Kopieren/Einfügen ganzer Teilschaltungen (Strg+C/V/D — interne Leitungen
werden mitkopiert, Namen automatisch hochgezählt), Undo/Redo
(Strg+Z / Strg+Shift+Z oder ↶/↷), Zoom (Strg+Mausrad an der
Cursorposition oder −/+/1:1-Buttons, 25–300 %, Zeichenfläche wächst automatisch mit),
Drehen in 90°-Schritten (Taste r —
Ports rotieren mit), Parameter im Inspector (mit Einheitenwahl und
Bereichsanzeige), Leitungsfarben Heizung (VL rot / RL blau) und Kälte
(VL hellgrün / RL dunkelgrün), ts-Labels, Live-Prüfliste (unverbundene
Ports, fehlende Pflichtparameter, Wertebereiche; klicken wählt die
betroffene Komponente aus). Export erzeugt direkt
rechenbares YAML inkl. layout:-Block (Zeichnungskoordinaten) für den
Re-Import — die Zeichnung ist damit das Modell, es gibt keinen
Interpretationsschritt. Editor und Solver lesen YAML identisch (YAML 1.2,
siehe unten): Unter editor server importiert der Server-Parser jede
YAML-Form samt Loader-Hinweisen in der Statuszeile; die statische HTML-Datei
nutzt einen lokalen YAML-1.2-Parser (Block- und Flow-Stil) mit derselben
Semantik, der Anker, Tags und Block-Skalare mit Meldung ablehnt statt sie
anders zu lesen. Ein Import ohne components-Abschnitt wird abgelehnt (die
Zeichnung bleibt stehen); settings und der Fluidname einer Datei bleiben
über Import/Export erhalten und gelten beim Rechnen. Zahlenfelder nehmen
Dezimalpunkt oder -komma. Der Server antwortet nur auf Anfragen an
127.0.0.1/localhost vom eigenen Ursprung und begrenzt den Anfragekörper auf
5 MB. Palette, Ports und Formulare werden aus der
Komponenten-Registry generiert (Single Source of Truth): Nach neuen
Komponenten einfach den Editor neu erzeugen.
fluid: {preset: water, t_C: 45} # oder {rho: 998, mu: 1.0e-3, cp: 4180}
settings: {max_iter: 400} # optional (siehe SolverSettings)
# uniqueness_starts: 16 – Eindeutigkeitsprüfung bei
# Idelchik-T-Stücken (0 = aus)
components:
wp1: {type: heat_pump, mode: target_t_out, t_out_set_C: 45, q_max_kW: 12, q_nom_m3h: 1.4}
pu1: {type: pump, mode: constant_flow, q_m3h: 1.4}
hk1: {type: radiator, q_nom_kW: 7.5, t_sup_nom_C: 45, t_ret_nom_C: 40, t_room_C: 21}
connections: # 'komponente.port'; ≥3 Einträge = Verzweigung
- [wp1.out, pu1.in]
- [pu1.out, hk1.in]
- [hk1.out, wp1.in]Regeln:
- Einheiten über Suffixe:
dp_kPa/dp_Pa/dp_bar,q_m3h/q_l_s/q_m3s,t_..._C,..._kW/..._W,length_m/..._mm,kvs_m3h,ua_W_K,u_linear_W_mK,k_W_m2K,m_dot_air_kg_s. Intern strikt SI. - Jeder Port muss in mindestens einer Verbindung vorkommen. Ein Port in mehreren Verbindungen (oder ≥3 Ports je Eintrag) bildet eine ideale Mischstelle (Verzweigung).
- Validierungsfehler werden gesammelt als nummerierte Liste gemeldet
(mit Korrekturvorschlägen), sodass eine Datei in einem Durchgang korrigierbar ist:
hydraulik run/export, der Editor-Server undhydraulik.load_checked()fassen Parameter-,settings- und Verbindungsfehler in EINER Liste zusammen.
Solver, CLI, Server und beide Editoren lesen Dateien nach dem YAML 1.2
Core Schema (eine zentrale Ladefunktion hydraulik.load_document, im
Editor yaml_core.js mit identischer Semantik — per Paritätstest abgesichert):
| Schreibweise | gelesen als |
|---|---|
1.4e0, 14e-1, 1e3, 5e-7, .5 |
Zahl |
08, 010 |
Ganzzahl 8 bzw. 10 (keine Oktalzahl; Oktal 0o17, Hex 0x1F) |
true/false (auch True, TRUE) |
Wahrheitswert |
yes, no, on, off, y, n |
Zeichenkette (YAML 1.1 las sie als Wahrheitswert) |
null, ~, leer |
null |
1_000, 0b101, 2026-10-05, 12:30 |
Zeichenkette |
.inf, .nan |
gelesen, vom Loader aber abgelehnt (nur endliche Zahlen) |
- Schlüssel sind immer Zeichenketten im Originaltext:
no:,off:odertrue:sind gültige Komponentennamen. - Komponentennamen dürfen Punkte enthalten (
"HK 1.OG",TS1.1): eine Portreferenz wird am letzten Punkt getrennt ("HK 1.OG.in"→ KomponenteHK 1.OG, Portin); Portnamen enthalten nie einen Punkt. - Doppelte Schlüssel sind ein Fehler (mit Zeilennummer). Anker/Aliase
(
&name/*name) sind erlaubt, solange sie nicht rekursiv sind; YAML-1.1-Merge-Schlüssel<<und Tags wie!!binary/!!timestampnicht. - Grenzen der Eingabe (jeweils mit eigener Fehlermeldung): höchstens
200 000 Werte je Dokument (Aliase aufgelöst gezählt), keine rohen
Steuerzeichen (in doppelten Anführungszeichen als
\uXXXXschreiben), eine%YAML-Direktive nur in Version 1.2. Leerraum ist nur Leerzeichen und Tabulator — ein geschütztes Leerzeichen gehört zum Wert. - Bool-Parameter (z.B.
closedam Kugelhahn) nur mittrue/false—yes/nomeldet der Loader mit dem Hinweis „bitte true/false verwenden". - Ganzzahl-Parameter akzeptieren auch
2.0bzw.1e3(wie JSON Schema).
Quoting-Regeln (für von Hand oder per LLM geschriebene Dateien):
- Labels quoten:
ts: "08", BEMS-Felderid: "…". Ungequotet liest YAML 1.2ts: 08als Zahl 8 (Label „8");ts: 1.10ist ein Fehler, weil daraus still „1.1" würde. Ganzzahlen (ts: 4) sind erlaubt. - Strings, die wie Zahl, Wahrheitswert oder null aussehen, quoten:
"1e3","true","null". #nach einem Leerzeichen beginnt einen Kommentar — Texte mit#oder:quoten:description: "Kreis #2: Vorlauf".- Der Editor-Export quotet selbsttätig (missverständliche Strings, Namen,
tsimmer) und schreibt Exponentenzahlen stets mit Punkt und Vorzeichen (5.0e-7), sodass auch YAML-1.1-Werkzeuge eine Zahl lesen.
- JSON ist gleichwertig:
hydraulik run schaltung.json,h.load("schaltung.json")..json-Dateien werden strikt gelesen (doppelte Schlüssel,NaN/Infinityund Kommentare sind Fehler). - Kanonisches JSON:
hydraulik export --json schaltung.yaml [--out schaltung.json]prüft das Modell vollständig (Parameter,settings, Einbindung der Ports — bei Fehlern wird nichts geschrieben) und schreibt es mit denselben Schlüsseln (Einheiten-Suffixe bleiben) in stabiler Reihenfolge (oberste Ebene fest, Komponenten in Dateireihenfolge mittypezuerst; Kommentare entfallen). YAML → JSON → identische Lösung ist für alle Beispiele getestet. - JSON Schema:
hydraulik schema [--luft] [--out hydraulik.schema.json]erzeugt ein Schema (Draft 2020-12) ausschließlich aus der Komponenten-Registry — alle Typen mit allen Suffix-Schlüsseln, Pflichtparametern, „genau eine Einheit" (z.B.dp_kPaODERdp_Pa), Wertebereichen in der Einheit des Schlüssels, Auswahllisten (enum), reservierten Feldern (ts,bems,description,pipes,layout) und Port-Referenzenkomponente.port. Nutzbar für Autovervollständigung im Editor (VS Code, YAML-Erweiterung: erste Zeile# yaml-language-server: $schema=hydraulik.schema.json) und als Vorgabe für LLM-Ausgaben. Was ein Schema nicht ausdrücken kann (Existenz der Ports, Portanzahl, Betriebsart ↔ Parameter, endliche Zahlen), prüft weiterhin der Loader — im Schema perdescriptiongekennzeichnet.
Zweites GUI unter editor server → http://127.0.0.1:8091/lueftung (Hydraulik: /hydraulik; die Startseite / verlinkt beide):
Lüftungsanlagen als zwei Ketten zeichnen (Zuluft: AUL → … → ZUL oben,
Abluft: ABL → … → FOL unten; die WRG verbindet beide Stränge) und mit dem
integrierten VKA-Rechenkern (energieoptimale Regelung, aus dem Skill
vka-effizienz-en16798) rechnen. Komponenten: WRG (Sorptions-/Enthalpie-/
Kondensationsrotor, KVS, Platte), Frostschutz, Vor-/Nachheizer, Kühler,
Befeuchter (Dampf/Sprüh), Ventilatoren (SFP), Umluft, Filter, Schalldämpfer
und Luft-Sensoren (Kombifühler T+rF, T, rF, Δp, p, V̇, Energiezähler,
Stromzähler — als Anzapfungen mit dünner Messleitung an beliebige
Kanal-Anschlüsse, ohne die Stränge zu berühren; alle mit BEMS-Messpunktlisten).
Nach dem Rechnen zeigen Mouseover-Tooltips auf jeder Kanalleitung den
Luftzustand des Abschnitts (ϑ, φ, x, V̇); Fühler zeigen den Zustand an
ihrer Messstelle. Regelungsart an der Zuluft wählbar:
Zustand fest gepinnt, Sollband oder raumgekoppelt mit
Feuchtelast (simulate_room); der Abluft-Volumenstrom wird praxisgerecht an
der Abluft angegeben (leer = balancierte Anlage); der WRG-Auslegungs-
volumenstrom v_nom ist ohne Angabe der Zuluftvolumenstrom. Ventilator-SFP
werden je Strang summiert (P_el mit dem jeweiligen Volumenstrom); aktive
Komponenten gehören in den Zuluftstrang. Ergebnisse (Heiz-/Kühl-/
Befeuchterleistung, WRG-Kennwerte, Zuluftzustand, Ventilatorstrom) erscheinen
im Ergebnispanel, als Tooltip und unter jeder Komponente. Drei Vorlagen
liegen bei: Vollklima mit Sorptionsrotor, KVS-Anlage sowie die reale
Anlage „GEA Vollklima Energetikum" (CAIRplus SX 096.064 IVBV) — fertig
parametriert mit dem Winter-Auslegungsfall aus der Gerätedokumentation und
per Regressionstest gegen die Datenblattwerte abgesichert. Die
Ventilatorposition wird rechnerisch am Stranganfang bilanziert (validierte
Modellkonvention); Rotor-Übertragungsgrade sind physikalisch auf ε ≤ 1
begrenzt (Hinweis bei stark unbalancierten Volumenströmen).
Modellkonventionen der Reihenfolge: Der Vorheizer ist das Register NACH
der WRG (davor gezeichnet wird er abgelehnt; für den Frostschutz der WRG gibt
es die Komponente Frostschutz). Bei Anlagen mit Umluft sitzt der
Zuluftventilator rechnerisch nach der Mischkammer (Außenluft → Mischkammer →
Ventilator → Zuluft): er fördert den vollen Zuluftstrom, seine Wärme geht
vollständig in die Zuluft. Der Kühler hat die Kaltwasser-Vorlauftemperatur
t_kw_C (Standard 6 °C) als tiefsten erreichbaren Taupunkt; verlangt die
Sollfeuchte einen tieferen, entfeuchtet er bis zu dieser Grenze und meldet es.
Die Rückfeuchtzahl des Rotors richtet sich nach dem Feuchtegefälle (Spender
ist der Strom mit der höheren Wasserbeladung).
Plausibilität: Je Zuluftstrang rechnet der Kern genau ein Register je Typ (doppelte Vorheizer/Kühler/Nachheizer/Befeuchter werden abgelehnt); nicht angeschlossene Komponenten werden mit Hinweis übergangen. Eine KVS-Auslegung, die mit dem angegebenen Sole-Volumenstrom nicht möglich ist, wird mit dem nötigen Mindestwert gemeldet. Erreicht die Anlage das Zuluft-Sollband nicht (z.B. Feuchteband ohne Befeuchter), steht das als Hinweis im Ergebnis. Im raumgekoppelten Modus ist die ausgegebene Raumfeuchte immer bilanzkonsistent (Raumfeuchte = Abluftfeuchte); ist das Raumfeuchteband nicht erreichbar, wird der sich einstellende Zustand mit Hinweis ausgegeben.
Das maschinenlesbare Strangschema ist nicht nur Rechenmodell, sondern auch semantische Karte für die Betriebsdatenanalyse eines Building Energy Management Systems (BEMS, z.B. Aedifion). Die Palette-Rubrik SENSOREN (unterste Gruppe im Register „Komponenten“) stellt dafür Temperatur-, Druck-, Differenzdruck-, Volumenstromsensoren und Wärmemengenzähler bereit:
- Rückwirkungsfrei: Fühler zapfen den Messknoten nur an (Messleitung = dünne Linie, reine Knotenverschmelzung, keine Rohrleitung); V̇-Sensor und WMZ sitzen quasi-ideal in der Leitung. Die Hydraulik bleibt unverändert.
- Mitwachsende Zeichenfläche: das Canvas vergrößert sich automatisch, sobald Komponenten oder Knickpunkte an den Rand rücken (immer ~600 px Reserve hinter dem äußersten Element) — beliebig große Strangschemas ohne Einstellungen; beim Löschen schrumpft es auf die Standardgröße zurück.
- Strömungsrichtung im Bild: nach erfolgreicher Rechnung zeigt jede Verbindungsleitung in ihrer Mitte ein schlankes Richtungsdreieck in Linienfarbe (V̇ ≈ 0 oder zu kurze Stücke bleiben pfeilfrei; bei jeder Änderung verschwinden die Pfeile mit dem Ergebnis).
- Messwerte per Mouseover: nach dem Rechnen zeigt der Tooltip die simulierten
Sensorwerte (ϑ, p, Δp, V̇, WMZ zusätzlich Q̇ aus ṁ·cp·Δϑ) samt BEMS-Zuordnung;
im Python-Ergebnis stehen sie unter
result.sensorsbzw.to_dict()["sensors"]. - BEMS-Datenpunkte (generisch): JEDE Komponente trägt eine frei lange
Messpunktliste
bems: [{id, key, description}, …]—idist die abfragbare Datenpunkt-ID,keyder sprechende Alias (z.B.EXP_HP_SEK_T_VL),descriptiondie Semantik. So bildet ein WMZ seine fünf realen Datenpunkte (V̇, Q̇, Q_kum, ϑ_VL, ϑ_RL) ab, ein Speicher mehrere Fühler, ein Stellventil sein Stellsignal, eine Pumpe Cmd + kWh-Zähler. Zusätzlich hat jede Komponente ein freiesdescription-Feld. Im Editor sind die Eingaben in zwei Register getrennt: Fluid-Info (Simulationsparameter) und BEMS-Info (Beschreibung + Messpunkte, „+ Messpunkt hinzufügen"). - Zweck: Ein LLM, das die YAML-Datei liest, erhält damit beides zugleich — die Netzwerktopologie (wo sitzt der Sensor, was liegt stromauf/-ab) und den Schlüssel zu den realen Zeitreihen. Simulation und Messdaten lassen sich so automatisiert verknüpfen (Soll-Ist-Vergleich, Performance-Gap-Analyse).
type |
Ports | Wichtigste Parameter |
|---|---|---|
pipe |
in, out | length_m, d_inner_mm, roughness_mm, zeta, u_linear_W_mK, t_amb_C |
flow_resistance |
in, out | c_Pa_m3h2 (C-Wert, z.B. aus REGuA) oder c_Pa_m3s2 oder Auslegungspunkt dp_kPa + q_m3h; optional a_Pa_m3h (linearer Anteil). Genau eine Widerstandsangabe. Dichteunabhängig (anders als Kv!) |
pump |
in, out | mode: constant_dp|constant_flow, dp_kPa bzw. q_m3h, q_nom_m3h |
control_valve |
in, out | kvs_m3h, opening (0…1), characteristic: equal_percentage|linear |
balancing_valve |
in, out | kvs_m3h, opening (Voreinstellung) |
ball_valve |
in, out | Kugelhahn (Absperrarmatur): Default offen und druckverlustfrei (1 Pa Referenzverlust bei q_nom_m3h, wie link); optional realer kvs_m3h; closed: true = Revisionsfall, sperrt exakt (V̇ = 0) |
temperature_sensor |
port | Temperaturfühler (Messstelle anzapfen, keine Kante): liest ϑ des Knotens |
pressure_sensor |
port | Drucksensor: statischer Überdruck an der Messstelle (p_Knoten − ρw²/2, p_dyn_kPa); optional d_inner_mm |
pressure_diff_sensor |
plus, minus | Differenzdrucksensor: Δp der statischen Drücke p(plus) − p(minus), z.B. über Pumpe/Ventil; optional d_inner_plus_mm/d_inner_minus_mm |
flow_sensor |
in, out | Volumenstromsensor in der Leitung (quasi-ideal, 1 Pa bei q_nom_m3h) |
energy_meter |
in, out, t_ref | Wärmemengenzähler: Durchflussteil in der Leitung + Fühler t_ref in der Gegenleitung; misst V̇, beide ϑ und Q̇ = ṁ·cp·(ϑ_ref − ϑ_Leitung) (Einbau im RL → Q̇ > 0 = Kreisabgabe); die 5 realen Datenpunkte als bems-Einträge |
check_valve |
in, out | Rückschlagklappe: kvs_m3h (Durchlassrichtung in→out); sperrt rückwärts (Restleckage kvs/1000, über block_factor einstellbar) |
mixing_valve_3way |
a, b, ab | kvs_m3h, opening (A-Pfad), characteristic (A–AB, Default gleichprozentig), characteristic_b (B–AB, Default linear) |
radiator |
in, out | q_nom_kW, t_sup_nom_C, t_ret_nom_C, t_room_C, n, q_prescribed_kW; Hydraulik: kv_m3h ODER c_Pa_m3h2 (Default 10 kPa bei Nennstrom) |
floor_heating |
in, out | area_m2, k_W_m2K, t_room_C; Hydraulik: length_m (+ d_inner_mm, Rohrmodell) ODER c_Pa_m3h2 |
heating_coil / cooling_coil |
in, out | ε-NTU mit Teillast-UA nach Gl. 4.2 (ua_ref_W_K, n Default 0.4, Referenzen q_w_ref_m3h/m_dot_air_ref_kg_s; ohne Referenzen UA konstant); m_dot_air_kg_s, t_air_in_C, arrangement; ODER feste Leistung q_prescribed_kW (dann kein UA nötig); Hydraulik: kv_m3h ODER c_Pa_m3h2. Kühlregister zusätzlich Greybox MIT Kondensation: ua_star_wet_kg_s + rh_air_in (0…1) → Q̇ = max(trocken, nass), Kondensatrate/Luftaustritt in extras |
heat_pump / chiller |
in, out | mode: prescribed_q|target_t_out, q_dot_kW bzw. t_out_set_C + q_max_kW, dp_nom_kPa, q_nom_m3h |
buffer_storage |
p1…pN | n_ports, ua_W_K, t_amb_C (ideal durchmischt) |
inflow (Zulauf) |
port | t_set_C + ENTWEDER q_m3h (Zulauf-V̇) ODER p_kPa (statischer Überdruck gauge, optional d_inner_mm) |
outflow (Austritt) |
port | ENTWEDER p_kPa (statischer Überdruck gauge; Auslauf ins Freie: 0; optional d_inner_mm) ODER q_m3h (Entnahme-V̇); Austrittstemperatur ist Ergebnis |
ideal_storage |
in, out | t_set_C (Vorlauf fest; Rücklauf und Leistung sind Ergebnis); optional q_m3h (eingeprägter Volumenstrom, Δp ist Ergebnis) und/oder p_out_kPa (Überdruck am Austritt = Druckanker); dp_nom_kPa + q_nom_m3h |
conduit (Verbindungsleitung) |
in, out | universelle Leitung (im Editor als Linie): ohne Angabe ideal; c_Pa_m3h2 ODER dp_kPa+q_m3h ODER Rohrmodell — ein Abschnitt via length_m (+ d_inner_mm, …) ODER beliebig viele Abschnitte in Reihe via pipes: [{length_m, d_inner_mm, roughness_mm, zeta}, …] (im Editor: Abschnittsliste mit +/−); Wärmeverlust u_linear_W_mK/t_amb_C über die Gesamtlänge |
link |
in, out | q_nom_m3h. Widerstandsfreie Verbindung (Δp ≈ 1 Pa), die zwei Knoten thermisch trennt — für Anschlüsse entlang eines Sammlers, damit Zapfstellen nicht stromab eingemischtes Wasser „sehen" |
hydraulic_separator |
prim_in, prim_out, sec_in, sec_out | q_nom_m3h, dp_nom_Pa, ua_W_K |
manifold |
main, s1…sN | n_ports |
tee |
a, b, c | T-Stück 90° (a–b gerader Strang, c Abzweig): Default idealer Knoten; mit d_run_mm + d_branch_mm Druckverlust nach Idelchik (Diagramme 7-10/7-21, ζ = f(V̇-Verhältnis, Flächenverhältnis), Vereinigung UND Trennung automatisch aus der Strömungsrichtung, stetig über die Regimewechsel; im Netz Totaldruckverlust wie bei allen Bauteilen, statische Anschlussdrücke als Ergebnis p_static_port_kPa; zwei Schenkel am selben Punkt werden abgelehnt — direkt verbunden oder nur über widerstandsfreie Verbindungen wie ideale Linien, link, Kugelhahn ohne Kvs, Volumenstromsensor; mehrdeutige Lösungen werden gemeldet) |
open_end |
port | bc: pressure|flow, p_kPa (statisch, optional d_inner_mm) bzw. q_m3h, t_supply_C |
cap |
port | dichtes Endstück (Blindstopfen): V̇ = 0 — zum Verschließen von Anschlüssen bei Teilbereichstests; keine Parameter |
Alle wärmeübertragenden Komponenten akzeptieren q_prescribed_kW
(feste Leistung statt physikalischem Modell; Default im Editor). Das
Kühlregister rechnet wahlweise trocken (ε-NTU) oder als Greybox mit
Kondensation (ua_star_wet_kg_s + Eintrittsfeuchte).
Teilstrecken-Gruppierung: Jede Komponente kann ein Label ts: <nummer>
tragen (YAML wie Python-API). Der Bericht enthält dann eine Teilstrecken-
Tabelle, die je Gruppe die Kette(n) in Strömungsrichtung auswertet: V̇, ΣΔp
sowie p und T an Anfang und Ende jedes Abschnitts (eine klassische TS mit
Vor- + Rücklauf unter einer Nummer zerfällt in zwei Abschnitte). Konsistenz
wird geprüft: uneinheitliche Volumenströme oder Verzweigungen innerhalb einer
Gruppe (= Teilstrecke falsch geschnitten) erzeugen einen Hinweis.
Modellierungsrichtlinie — Teilstrecken-Widerstände aufteilen: C-Werte aus
Handrechnungen enthalten meist Vor- UND Rücklauf. Empfohlen ist die hälftige
Aufteilung (C/2 als eigene flow_resistance je Richtung — die Leitungen sind
in der Praxis parallel und gleich lang verlegt): Für die Kreisvolumenströme
ist das äquivalent zum konzentrierten Wert, liefert aber korrekte Druckniveaus
an allen Knoten, und die Rücklaufäste sind eigene Kanten — die thermische
Mischreihenfolge an Sammlern stimmt dann von selbst. Konzentriert man dagegen
alles in den Vorlauf, verschmelzen widerstandsfreie Rücklaufanschlüsse zu
EINEM Mischknoten (Zapfstellen „sehen" stromab eingemischtes Wasser); dann
Knoten mit link trennen. Beispiel: examples/07_twe_heizkreisverteiler.py.
Ventile: opening: 0 (bzw. die Endlagen des 3-Wege-Ventils) sperrt
exakt — die Kante wird zur Randbedingung V̇ = 0, der abgesperrte
Netzteil erhält automatisch einen Referenzdruck. Im Regelbereich
(0 < opening < 1) begrenzt das Stellverhältnis (rangeability) den
kleinsten Kv auf Kvs/R.
- Pumpen: konstante Druckdifferenz (
constant_dp) oder konstanter Volumenstrom (constant_flow, Druckerhöhung ist dann Ergebnis). - Offene Rohrenden (
open_end): Druck ODER Volumenstrom vorgebbar, plus Zulauftemperatur. - Alle Drücke sind Überdrücke (gauge). Bei inkompressiblem Fluid ohne
Verdampfung/Kondensation ist nur das Druckniveau relativ zur Atmosphäre
relevant; Randbedingungen und Ergebnisse sind einheitlich als Überdruck zu
lesen (Auslauf ins Freie:
p_kPa: 0). - Druckbegriff – statisch vs. total. Alle Bauteile rechnen ihren
Druckabfall als Totaldruckverlust; die Knotendrücke im Ergebnis sind
daher Totaldrücke. Was man misst bzw. vorgibt, ist dagegen der
statische Überdruck: p_statisch = p_Knoten − ρw²/2.
- Druckrandbedingungen (
inflow/outflow/open_endmitp_kPa) sind der statische Überdruck am Anschluss. Sitzt der Rand am Ende genau einer Leitung mit bekanntem Querschnitt (Rohr, Verbindungsleitung im Rohrmodell, Idelchik-T-Stück) oder istd_inner_mmangegeben, liegt der Netzknoten um ρw²/2 darüber (Übergangskante<name>:dynim Ergebnis). An einem Knotenpunkt mehrerer Bauteile ist die Geschwindigkeit am Rand nicht definiert; dort gilt der Wert als Knotendruck (mit Hinweis), ebenso ohne bekannten Querschnitt (Behälter, ideale Verbindung). - Drucksensoren zeigen den statischen Überdruck an der Messstelle,
p_dyn_kPaist der abgezogene dynamische Anteil. w stammt aus dem Querschnitt des Anschlusses, an dem die Messleitung hängt; hat dieser keinen (Pumpe, Ventil, Rand – im Editor der Regelfall, weil Leitungen eigene Verbindungen sind), gilt wie beim Druckrand die einzige Leitung mit bekanntem Querschnitt an der Messstelle; mitd_inner_mmder angegebene Querschnitt. An einem Knotenpunkt mehrerer Leitungen oder ohne bekannten Querschnitt zeigt der Sensor den Knotendruck (dann ohnep_dyn_kPa; der Bericht weist ihn als Knotendruck aus). Differenzdrucksensoren zeigen die statische Differenz; bei gleicher Nennweite beidseits ist sie gleich der Totaldruckdifferenz. - Fühleranschlüsse (Temperatur-/Drucksensoren,
t_refdes Wärmemengenzählers) sind rückwirkungsfrei: sie zählen bei der Frage, ob ein Druckrand am Ende genau einer Leitung sitzt, nicht mit. - Der Druckanker
p_outeines Speichers ist der Behälterdruck; im Behälter ruht das Wasser, statisch = total. - Größenordnung von ρw²/2 bei Wasser: 0,5 kPa bei 1 m/s, 2 kPa bei 2 m/s.
- Druckrandbedingungen (
- Geschlossene Kreise ohne Druckvorgabe erhalten automatisch einen
Referenzdruck (150 kPa(ü) ≈ typischer Anlagenfülldruck, einstellbar über
p_ref) – nur Druckdifferenzen sind dann physikalisch relevant; ein Hinweis erscheint im Bericht. Alternativ verankert eine Quelle mitp_outdas Niveau explizit (wie ein Ausdehnungsgefäß am Erzeuger). - Inflow/Outflow (je ein Anschlusspunkt): Zulauf mit Temperatur +
(V̇ ODER Überdruck); Austritt mit (Überdruck ODER Entnahme-V̇), die
Austrittstemperatur ist Ergebnis — die Randbedingungen offener Systeme.
Speicher (
ideal_storage, Zweitor für geschlossene Kreise): Vorlauftemperatur fest, Rücklauf/Leistung Ergebnis; optional eingeprägter Volumenstrom und/oder Druckankerp_out. - Rein hydraulische Rechnung:
net.solve(thermal=False)überspringt die Energiegleichung — nützlich für Kennlinienstudien und für Fälle ohne stationäre Temperaturlösung (z.B. thermisch isolierter Umlauf mit fest vorgegebener Leistung; wird sonst erkannt und verständlich gemeldet).
- Hydraulik: SIMPLE-artige Druckkorrektur auf dem Netzgraphen. Knoten tragen p und T, Komponenten sind Kanten mit Δp = a·Q + b·Q·|Q| − Δp_Quelle. Der Impulsprädiktor in Newton-Inkrementform und die Druckkorrektur K = A·diag(1/J)·Aᵀ (J = a + 2b|Q|) machen den Schritt bei α = 1 zu einem exakten Newton-Schritt (Schur-Komplement) → typisch 3–6 Iterationen. Robustheit: Churchill-Reibungskorrelation (glatt über alle Re-Bereiche), Widerstands-Floor für Q → 0, Kv-Leckage-Floor für fast geschlossene Ventile, Divergenz-Wächter mit automatischer Relaxationshalbierung, Jacobi-Skalierung. Kompilierzeit-Checks: Druckinsel-Analyse, Bilanz fester Volumenströme.
- Thermik: nach Hydraulik-Konvergenz Upwind-Advektion; Newton-Verfahren auf der Knotenbilanz F(T) = G(T) − T (dünne Jacobi-Matrix, Kantensteigung per Differenzenquotient aus dem Komponentenmodell) mit Levenberg-Marquardt- Vertrauensbereich und Armijo-Liniensuche — lineare Netze in einem Schritt, nichtlineare quadratisch, unabhängig vom Rezirkulationsverhältnis (docs/numerik.md §2). Ideale Mischung an Knoten, UA-Verluste, Heizkörper- Exponentenmodell (Brent-Verfahren), ε-NTU-Register, exponentielle Rohr-/FBH-Modelle. Globale Energiebilanz wird geprüft und im Bericht ausgewiesen. Strömungsumkehr ist zulässig (Upwind folgt dem Vorzeichen). Robustheit: Klemmen (z.B. Erzeuger an q_max) werden über den singulären Unterraum verlassen; thermisch isolierte Umläufe mit fester Leistung (keine stationäre Lösung) werden erkannt und mit Knoten und Abhilfevorschlägen gemeldet; unplausible Austrittstemperaturen (feste Leistung bei Kleinstdurchfluss) erscheinen als Hinweis im Bericht.
| Datei | Inhalt |
|---|---|
examples/01_single_loop.yaml |
WP + Pumpe + Heizkörper (Einzelkreis) |
examples/02_parallel_radiators.yaml |
3 parallele HK-Stränge mit Strangregulierventilen |
examples/03_mixed_floorheating.yaml |
Beimischschaltung (3-Wege-Ventil) für FBH |
examples/04_heatpump_separator.yaml |
WP + hydraulische Weiche + HK-Kreis + FBH-Beimischkreis |
examples/05_umlenk_einspritz.yaml |
Umlenk- + Einspritzschaltung, Teilstrecken als Kvs-Äquivalente |
examples/06_umlenk_einspritz_flow_resistance.yaml |
wie 05, Teilstrecken direkt als C-Werte (REGuA) |
examples/07_twe_heizkreisverteiler.py |
TWE (Durchlaufprinzip) + Verteiler mit Einspritz-Regelgruppen: Auslegung (RG-Ventil, SRVs, Pumpen) + Solver-Verifikation + Abschaltfall; TS-Labels, hälftige Widerstandsaufteilung |
Validierung gegen unabhängige Referenzlösungen (FH-Burgenland-Übungen):
| Datei | Inhalt |
|---|---|
examples/validation_fh_verteiler.py |
Kennlinien-Plots (Ventilhub-Sweeps) zu Bsp 05/06 mit Referenzankern aus den Lösungsplots |
examples/08_ventilautoritaet.py |
Wirkung der Ventilautorität: installierte Kennlinien (linear/gleichprozentig) für a_V = 0.1…0.9 |
examples/09_energetikum_lueftungsregister.yaml + .py |
Reale Anlage (Energetikum-Lüftung): VE/NE-Register als Einspritzschaltung mit Durchgangsventil im Rücklauf, echte Aedifion-BEMS-IDs; Analyse: Datenblatt-Reproduktion, Einregulierung (STAD-Voreinstellung), Ventilautorität |
examples/referenzwerte_fh_verteiler.txt |
alle aus dem Lösungs-PDF extrahierten Referenzwerte (exakt vs. abgelesen) |
tests/test_validation_fh_verteiler.py |
Volllast-Volumenströme < 0.1 %, Ventilautoritäten, Kennlinien-Anker |
python3 examples/run_examples.py # alle YAML-Beispiele mit Bericht
hydraulik run <datei.yaml> --json # maschinenlesbares Ergebnis| Datei | Inhalt |
|---|---|
CLAUDE.md |
Projektleitfaden: Befehle, Struktur, Konventionen |
docs/architektur.md |
Graphmodell, Solver-Verträge, Kompilierung, Parametersystem |
docs/numerik.md |
Herleitung des Solvers (SIMPLE ≡ Newton via Schur-Komplement), Robustheitsmaßnahmen, Thermik, Testabdeckung |
docs/erweitern.md |
Anleitung: neue Komponenten hinzufügen (mit Codegerüst) |
docs/roadmap.md |
Stand, bewusste v1-Grenzen, v2-Ideen, Wiedereinstieg |
docs/solver_pruefung_2026-10.md |
Prüfbericht des Solvers (Befunde, Korrekturen, offene Punkte, Kampagnenwirkung) |
docs/fehlerbehebung_2026-11.md |
Fehleranalyse des ganzen Projekts 2026-11: Befunde, Korrekturen, Nutzerentscheidungen (inkl. Luftseite L13–L19), offene Punkte |
tools/README.md |
Prüfwerkzeuge außerhalb der Testsuite: Zufallsnetz-Kampagne, Eindeutigkeit/Stabilität, Browser-E2E |
git clone https://github.com/AI4Buildings/HVAC-Hydronic-Network-Solver.git hydraulik
cd hydraulik
python3 -m venv .venv && source .venv/bin/activate # Python ≥ 3.10
pip install -e ".[dev]" # optional: ".[dev,e2e]"
pytest # alle Tests grün
editor server # GUIs: http://127.0.0.1:8091/- Node.js: Die Paritätstests JS ↔ Python (
tests/test_editor_paritaet.py) laufen nur, wennnodeinstalliert ist; sonst werden sie übersprungen. - Nicht im Repository: Die Referenzunterlagen (Übungs-PDFs, Idelchik-Scans, GEA-Datenblatt) sind urheberrechtlich geschützt und werden nicht committet. Zum Rechnen und Testen werden sie nicht gebraucht.
- Skill-Kopie: Die Skill-Kopie
vka-effizienz-en16798liegt außerhalb (~/.claude/skills) und ist nicht versioniert. Der Lüftungskern im Repo (src/hydraulik/air/vka/) ist eigenständig und maßgebend. Ob die Skill-Kopie eines Rechners auf dem Stand des Repos ist, zeigtpython3 tools/vka_skill_abgleich.py;… --schreibenerzeugt ihre Kern-Dateien aus dem Repo neu (danach im Skillpython3 validate_vka.py). DieSKILL.mdund die Hilfsskripte des Skills liegen nur dort — auf einem Rechner mit älterem Skill fehlen in derSKILL.mddie Beschreibungen der Korrekturen L13–L19 und der neuen Schlüssel (T_KW,KR_dew_limited). - Stand und offene Punkte: oberster Block in
docs/roadmap.md, Details indocs/fehlerbehebung_2026-11.md(was entschieden ist, was offen ist). - Browsertests (optional):
pip install -e ".[dev,e2e]",python -m playwright install chromium, dann die Skripte intools/e2e/.

