import dependencies
import copy
import numpy as np
from IPython.display import display, HTML
from hvac.heat_loss_calc import BuildingElement, BuildingCompositeElement, BuildingPart, Space
from hvac.components import Radiator, ControlValve, ControlValveMotor
from hvac.process import Room, OutsideTemperature, DeadTime
from hvac.controller import OnOffController, DataLogger, OutdoorResetController
from nummath import graphing
In deze Jupyter Notebook wordt een computerprogramma gedemonstreerd waarmee de temperatuurregeling in verwarmingsbedrijf van een fictieve ruimte dynamisch wordt gesimuleerd. De ruimte wordt verwarmd d.m.v. een radiator. De regelaar is een aan/uit-regelaar waarmee het volumedebiet (Vw) verwarmingswater, dat naar de radiator stroomt, wordt gecorrigeerd afhankelijk van de gemeten ruimtetemperatuur (Tr). Het corrigerend orgaan is een regelklep in het radiatorcircuit. Naast de aan/uit-regelaar kan er ook nog een wateraanvoertemperatuuregelaar (stookregelaar) worden toegepast die de aanvoertemperatuur van het verwarmingswater (Twe) naar de radiator regelt afhankelijk van de gemeten buitentemperatuur (To). De wateraanvoertemperatuurregelaar kan ingrijpen op de brander van de verwarmingsketel of op een mengklep aan het begin van de radiatorcircuits.
De regelkring kan in een blokschema schematisch worden voorgesteld. De drie hoofdblokken in het schema zijn: de regelaar, de regelklep (het "corrigerend orgaan") en het proces. De regelaar krijgt via meting informatie over de momentane waarde van de procesgrootheid, in casu de (lucht)temperatuur in de ruimte (Tr). Op basis van de deviatie tussen de gemeten en de gewenste waarde van de procesgrootheid (e) bepaalt de regelaar het regelcommando (hier: ofwel "aan" of 100%, ofwel "uit" of 0%). Het regelcommando (OUT) wordt aan de regelklep toegevoerd en stemt overeen met de klepstand (h) die de regelklep moet innemen (hier: ofwel volledig open, ofwel volledig dicht). Daarmee wordt het volumedebiet verwarmingswater (Vw) gewijzigd dat naar de radiator in de ruimte stroomt. De warmteafgifte van een radiator (Qe) wordt immers o.a. beĆÆnvloed door het volumedebiet van het verwarmingswater dat door de radiator stroomt; de twee andere invloedsfactoren zijn de aanvoertemperatuur van het verwarmingswater (Twe) en de ruimtetemperatuur (Tr).
Onder paragraaf 1 wordt de opmaak van het procesmodel in het computerprogramma beschreven. Het proces omvat de radiator en de ruimte waarin de radiator zich bevindt. Voor de computersimulatie moet de ruimte door een wiskundig model worden voorgesteld. In casu is een sterk vereenvoudigd model toegepast. Een ruimte wordt voorgesteld door een lineair thermisch netwerk samengesteld uit twee temperatuurknopen (een 2de orde systeem), nl. het luchtvolume van de ruimte en de bouwschil die de ruimte omhult. In deze demonstratie is bovendien gemakshalve een homogene bouwschil verondersteld, die slechts uit Ć©Ć©n bouwdeel bestaat. Vandaar de vermelding hierboven dat het om een fictieve ruimte gaat.
In paragraaf 2 wordt het model van de regelklep beschreven. De regeklep bestaat in feite uit twee te onderscheiden onderdelen: de regeklepmotor en de eigenlijke tweewegregelklep.
In paragraaf 3 wordt het model van de aan/uit-regelaar en de wateraanvoertemperatuurregelaar beschreven. Noteer dat de wateraanvoertemperatuurregelaar hier ook geĆÆdealiseerd is voorgesteld: de aanpassing van de wateraanvoertemperatuur volgt via de regelaarkarakteristiek (stookcurve) ogenblikkelijk de verandering van de buitentemperatuur. In realiteit vergt de aanpassing van de wateraanvoertemperatuur volgend op een verandering van de buitentemperatuur tijd.
In paragraaf 4 wordt een datalogger aangemaakt. In realiteit zal deze niet in de regelkring voorkomen. Het betreft een "helper-object" van het computerprogramma dat zal dienen om de ogenblikkelijke parameterwaarden van de gesimuleerde regelkring op te slaan, zodat na het doorlopen van de simulatieberekeningen, de parameterwaarden in een grafiek langs de tijdsas kunnen uitgezet worden.
In paragraaf 5 wordt de volledige regelkring in het programma geconfigureerd, waarna de simulatieberekeningen van de regelkring worden uitgevoerd (par. 5.5).
In paragraaf 6 worden, nadat de simulatieberekeningen zijn voltooid, de berekeningsresultaten in drie grafieken voorgesteld (grafiek 1: verloop temperaturen in de tijd, grafiek 2: warmteafgifte van de radiator in de loop van de tijd en grafiek 3: regelcommando + klepstand in de loop van de tijd).
Hieronder wordt de samenstelling van een buitenmuur gedefinieerd. Deze buitenmuur is samengesteld uit:
Buitenblad
brick_ext = BuildingElement(
A=188.0e-3 * 65.0e-3, # oppervlakte van 1 baksteen
t=88.0e-3, # dikte van 1 baksteen
k=0.91, # warmtegeleidingscoƫfficiƫnt van de baksteen
rho=1500.0, # massadichtheid van de baksteen
cm=840.0 # specifieke warmtecapaciteit van de baksteen
)
joint_ext = BuildingElement(
# oppervlakte van de cementvoeg rond 1 baksteen (1 langse voeg + 1 kopse voeg)
A=12.0e-3 * (188.0e-3 + 12.0e-3) + 12.0e-3 * 65.0e-3,
t=88.0e-3,
k=1.5,
rho=1800.0,
cm=840.0
)
# De baksteen en omringende cementvoeg vormen gecombineerd het buitenblad van de buitenmuur.
leaf_ext = BuildingCompositeElement(brick_ext, joint_ext)
leaf_ext.num_of_layers = 4
Luchtspouw
air_cavity = BuildingElement(
t=20.0e-3,
r=0.085, # specifieke warmteweerstand van de luchtspouw
rho=1.205, # massadichtheid lucht
cm=1005.0 # specifieke warmtecapaciteit van lucht
)
air_cavity.num_of_layers = 1
Isolatielaag
insulation = BuildingElement(
t=60.0e-3,
k=0.041,
rho=25.0,
cm=840.0,
corr_r=-0.1 # correctiefactor voor de plaatsing van de isolatie
)
insulation.num_of_layers = 3
Binnenblad
brick_int = BuildingElement(
A=288.0e-3 * 138.0e-3,
t=138.0e-3,
k=0.32,
rho=1100.0,
cm=840.0
)
joint_int = BuildingElement(
A=12.0e-3 * (288.0e-3 + 12.0e-3) + 12.0e-3 * 138.0e-3,
t=138.0e-3,
k=1.0,
rho=1900.0,
cm=840.0
)
leaf_int = BuildingCompositeElement(brick_int, joint_int)
leaf_int.num_of_layers = 6
Pleisterlaag
stucco = BuildingElement(
t=10.0e-3,
k=0.57,
rho=1300.0,
cm=840.0
)
stucco.num_of_layers = 1
Compleet samengestelde buitenmuur
wall = BuildingPart(leaf_ext, air_cavity, insulation, leaf_int, stucco, r_conv_in=0.13, r_conv_out=0.04)
wall.calculate_effective_capacity()
Noot
r_conv_in
is de specifieke convectieweerstand aan de binnenzijde (geklimatiseerde zijde) van het bouwdeel, r_conv_out
is de specifieke convectieweerstand aan de buitenzijde van het bouwdeel.
Voor de eenvoud zullen we aannemen dat de ruimte wordt omgeven door een homogene bouwschil (alle bouwdelen die de ruimte omgeven zijn identiek samengesteld). Uiteraard is dit geen realistisch gegeven. Deuren, ramen, plafond, vloer kunnen op analoge wijze worden gedefinieerd zoals de muur hierboven onder par. 1.1.
De binnenafmetingen van de ruimte zijn:
De bouwschil is 30 cm dik.
De ruimte heeft 4 muren, een vloer en plafond:
walls = [copy.deepcopy(wall) for _ in range(4)]
floor = copy.deepcopy(wall)
ceiling = copy.deepcopy(wall)
De voor- en achtermuur en de twee zijmuren hebben dezelfde afmetingen. We bepalen de binnen- en buitenoppervlakte van de muren met de opgegeven afmetingen.
# front and back wall have indices 0 and 1
for i in range(2):
walls[i].set_areas(
A_inside=6.0 * 2.7,
A_outside=(6.0 + 2 * 0.3) * 2.7
)
# the two side walls have indices 2 and 3
for i in range(2, 4):
walls[i].set_areas(
A_inside=4.0 * 2.7,
A_outside=(4.0 + 2 * 0.3) * 2.7
)
Binnen- en buitenoppervlakte van de vloer:
floor.set_areas(
A_inside=6.0 * 4.0,
A_outside=(6.0 + 2 * 0.3) * (4.0 + 2 * 0.3)
)
Binnen- en buitenoppervlakte van het plafond:
ceiling.set_areas(
A_inside=6.0 * 4.0,
A_outside=(6.0 + 2 * 0.3) * (4.0 + 2 * 0.3)
)
De ruimte kan nu gedefinieerd worden:
room = Space()
room.set_dimensions(length=6.0, width=4.0, height=2.7)
room.set_building_parts(*walls, ceiling, floor)
De ontwerptemperaturen aan de binnen- en buitenzijde van de bouwdelen en binnenin en buiten de ruimte worden vastgelegd. De temperatuur aan de buitenzijde van een bouwdeel is niet noodzakelijk gelijk aan de buitentemperatuur (de temperatuur van de buitenomgeving). Een ruimte kan grenzen aan een aanpalende ruimte waarvan de binnentemperatuur dan gelijk is aan de temperatuur aan de buitenzijde van het beschouwde bouwdeel. Het warmteverlies van de ruimte wordt berekend door achtereenvolgens het warmteverlies door elk bouwdeel die de ruimte omgeeft te berekenen en deze warmteverliezen dan op te tellen. Om de thermische weerstand van de omhullende bouwschil van de ruimte te berekenen wordt het temperatuurverschil tussen de binnentemperatuur van de ruimte en de buitentemperatuur gedeeld door het totaal warmteverlies van de ruimte. Bijgevolg, het is alsof we de afzonderlijke ruimte naar de buitenomgeving brengen, maar ervoor zorgen dat het totale warmteverlies van de ruimte daarbij ongewijzigd blijft. De berekende thermische weerstand van de ruimte is m.a.w. gerefereerd aan de temperatuur van de buitenomgeving.
T_in_des = 22.0 # Ā°C
T_out_des = -10.0 # Ā°C
for bp in room.building_parts:
bp.set_temperatures(T_inside=T_in_des, T_outside=T_out_des)
room.set_temperatures(T_inside=T_in_des, T_outside=T_out_des)
Nu de ruimte volledig is geconfigureerd, kan het warmteverlies berekend worden. Tevens worden de globale transmissieweerstand van de bouwschil, de statische en effectieve thermische capaciteit van de bouwschil en de statische thermische capaciteit van het luchtvolume in de ruimte berekend. Het onderscheid tussen de statische en effectieve thermische capaciteit van de bouwschil is essentieel. In werkelijkheid zullen in de bouwschil temperatuurgradiƫnten in alle richtingen voorkomen. Om de bouwschil realistisch te modelleren, dienen in principe alle verschillende bouwdelen die de bouwschil samenstellen, door complexe, intergeconnecteerde thermische netwerken worden voorgesteld. In ons vereenvoudigd wiskundig model wordt de bouwschil echter maar door ƩƩn temperatuurknoop voorgesteld. Zou men daaraan de statische thermische capaciteit koppelen, dan zou dit betekenen dat verondersteld wordt dat de bouwschil slechts ƩƩn uniforme temperatuur bezit (m.a.w. uniform wordt opgewarmd of afgekoeld). De toepassing van de effectieve capaciteit laat toe om de bouwschil bij benadering toch als ƩƩn temperatuurknoop te blijven opvatten. De effectieve capaciteit van een bouwdeel wordt bepaald door een multiknopig lineair thermisch netwerk van het bouwdeel uit te rekenen en vervolgens een evenwaardig of equivalent ƩƩnknopig model te bepalen dat voor dezelfde amplitude van de buitentemperatuur dezelfde amplitude van de warmtestroom aan de binnenzijde van het bouwdeel oplevert als in het multiknopig lineair thermisch netwerk. De bepaling van de effectieve thermische capaciteit wordt gedemonstreerd in de Jupyter Notebook Effectieve thermische capaciteit van een buitenmuur.
room.calculate()
heat_loss_calculation = room.get_results()
display(HTML(
"<ul>"
f"<li>Warmteverlies door transmissie onder ontwerpcondities = <b>{heat_loss_calculation['Q_tr']:.3f}</b> W</li>"
f"<li>Thermische weerstand van de bouwschil = <b>{heat_loss_calculation['R_tr']:.3f}</b> K/W</li>"
f"<li>Thermische capacititeit van het luchtvolume in de ruimte = <b>{heat_loss_calculation['C_ra']:.3e}</b> J/K</li>"
f"<li>Statische thermische capaciteit van de bouwschil = <b>{heat_loss_calculation['C_bm_stat']:.3e}</b> J/K</li>"
f"<li>Effectieve thermische capaciteit van de bouwschil = <b>{heat_loss_calculation['C_bm_eff']:.3e}</b> J/K</li>"
"</ul>"
))
Nadat de warmteverliesberekening is voltooid (paragrafen 1.1 t.e.m. 1.4), kennen we de thermische karakteristieken van de ruimte die we nu kunnen gebruiken om de temperatuurregeling van de ruimte te simuleren. De ruimte, inclusief de radiator(en) in de ruimte, vormen het regelproces. Het regelproces wordt door een afzonderlijk object van de klasse Room
gemodelleerd (en is niet te verwarren met het object van de klasse Space
die uitsluitend voor de warmteverliesberekening en de bepaling van de thermische karakteristieken van een ruimte dient).
Eerst zullen we een radiator selecteren om in de ruimte te plaatsen.
Selectie van de radiator
We kiezen een radiator die onder nominale condities een warmtevermogen afgeeft die in de lijn ligt van het berekende warmteverlies.
radiator = Radiator(
Qe_nom=1886.0, # nominaal warmtevermogen [W]
Twe_nom=75.0, # nom. wateraanvoertemperatuur [Ā°C]
Twl_nom=65.0, # nom. waterretourtemperatuur [Ā°C]
Tr_nom=20.0, # nom. ruimtetemperatuur [Ā°C]
n=1.3279 # radiatorexponent
)
Keuze wateraanvoertemperatuur en berekening van het vereist volumedebiet verwarmingswater door de radiatoren onder ontwerpcondities
We houden de opgegeven, nominale wateraanvoertemperatuur aan. De gewenste ruimtetemperatuur werd reeds vastgelegd in de warmteverliesberekening van de ruimte (zie par. 1.3). Het warmteverlies onder ontwerpcondities is eveneens berekend (zie par. 1.4).
# vereist volumedebiet verwarmingswater onder ontwerpcondities [m^3/s]
Vw_max = radiator.calc_Vw(
Qe=heat_loss_calculation['Q_tr'],
Twe=radiator.nominal_specs['Twe'], # wateraanvoertemperatuur naar de radiator [Ā°C]
Tr=T_in_des
)
display(HTML(f"Maximum volumedebiet verwarmingswater (volumedebiet onder ontwerpcondities) = <b>{Vw_max * 1000.0 * 60.0:.3f}</b> L/min"))
Alle informatie om het ruimtemodel aan te maken en te initialiseren is nu voorhanden. We dienen alleen nog een tijdstap in te stellen waarmee de numerieke berekeningen zullen uitgevoerd worden.
Tijdstap van de simulatieberekeningen
dt = 60.0 # seconden
Ruimtemodel
Voor de thermische massa C_bm
van de bouwschil maken we gebruik van de effectieve thermische capaciteit.
room = Room(
R_tr=heat_loss_calculation['R_tr'],
C_ra=heat_loss_calculation['C_ra'],
C_bm=heat_loss_calculation['C_bm_eff'],
dt=dt,
radiator=radiator
)
De regelklep omvat de regelklepmotor en de eigenlijke regelklep. De regelklepmotor ontvangt van de regelaar een regelcommando dat inhoudt naar welke klepstand de klepmotor de klepsteel van de regelklep moet bewegen. Het regelcommando kan een waarde zijn tussen 0% en 100% (klep volledig dicht c.q. klep volledig open).
Regelklepmotor
De regelklepmotor wordt gekenmerkt door de snelheid waarmee de klepmotor de klepsteel doet bewegen. De snelheid wordt uitgedrukt in procenten van de klepsteelweg per seconde. Bv. 5% / seconde betekent dat de klepsteel in Ć©Ć©n seconde 5% van de totale weg aflegt. De berekeningen worden in tijdstapjes uitgevoerd. De maximale weg die de klepsteel kan afleggen in Ć©Ć©n tijdstap dt
wordt bepaald door het produkt van de ingestelde snelheid en de grootte van de tijdstap. Indien de gevraagde klepverplaatsing in een tijdstap groter is dan de maximale weg, wordt de klepverplaatsing begrensd tot deze waarde. Dit impliceert dat de klepstand die de regelklep inneemt in een tijdstap niet per se zal overeenstemmen met de klepstand die de regelaar vraagt.
valve_motor = ControlValveMotor(travel_speed=0.5, dt=dt)
Regelklep
De regelklep is standaard van het equiprocentuele type. De regelklep ontvangt de gevraagde kleppositie van de klepmotor. M.b.v. de klepautoriteit a
en het regelbereik R
van de geĆÆnstalleerde regeklep kan de effectieve klepkarakteristiek van de regelklep worden berekend. Daaruit volgt voor een gegeven kleppositie (in procenten) een zeker volumedebiet uitgedrukt in procenten van het volumedebiet dat de regelklep in volledig geopende stand zal doorlaten. Om de absolute waarde van dit volumedebiet te kunnen bepalen bij een zekere kleppositie, moet het programma weten welke het maximaal volumedebiet Vmax
zal zijn dat doorgelaten wordt wanneer de klep volledig openstaat. Dit maximumdebiet werd hierboven bepaald in par. 1.5.
control_valve = ControlValve(
a=0.5, # klepautoriteit van de geĆÆnstalleerde regelklep
R=150.0, # inherent regelbereik van de regelklep
V_max=Vw_max, # maximum debiet dat de regelklep in volledig geopende stand doorlaat
) # (= vereist volumedebiet onder ontwerpcondities) [m^3/s]
We zullen de temperatuur in de ruimte regelen met een aan/uit-regelaar. De parameters van een aan/uit-regelaar zijn:
SP
, d.i. de gewenste ruimtetemperatuur waarnaar de regelaar de ruimtetemperatuur moet regelen (in casu de ontwerp-binnentemperatuur)HL_offset
die de bovenste limiet van de schakeldifferentie vastlegt t.o.v. het setpunt waarbinnen de regelaar met aan- en uitschakelen de ruimtetemperatuur regelt.LL_offset
die de onderste limiet van de schakeldifferentie vastlegt t.o.v. het setpunt.PV_range
waartussen de regelaar de procesgrootheid (temperatuur) kan meten.dt
van de regelaar (in seconden); d.i het tijdsverloop tussen 2 opeenvolgende metingen (in casu is de bemonsteringstijd gelijk aan de tijdstap van de simulatieberekeningen).ctrl_dir
van de regelaar: direct werkend (1) of indirect werkend (-1)on_off_controller = OnOffController(
SP=T_in_des,
HL_offset=1.0,
LL_offset=-1.0,
PV_range=(-100.0, 100.0),
dt=dt,
ctrl_dir=-1
)
Een wateraanvoertemperatuurregelaar regelt de wateraanvoertemperatuur naar de radiator i.f.v. de buitentemperatuur (outdoor reset control). Met de ingestelde regelkarakteristiek (reset line) bepaalt de regelaar de wateraanvoertemperatuur die hoort bij de gemeten buitentemperatuur. De regelkarakteristiek is een rechte met 2 coƫfficiƫnten: T_we = c0 + c1 * T_out
. De 2 coƫfficiƫnten kunnen, ofwel extern berekend worden en rechtstreeks aan de OutdoorResetController
worden doorgegeven, ofwel door de OutdoorResetController
worden berekend (met de functie calc_reset_line
). Om de regelkarakteristiek te kunnen berekenen, moeten volgende parameters ingegeven worden:
Radiator
-object)outdoor_reset_controller = OutdoorResetController()
outdoor_reset_controller.calc_reset_line(
Q_load_des=heat_loss_calculation['Q_tr'],
T_out_des=T_out_des,
T_we_des=room.radiator.nominal_specs['Twe'],
T_in_des=T_in_des,
radiator=radiator
)
c0, c1 = outdoor_reset_controller.get_coefficients()
display(HTML(
f"Vergelijking van de regelaarkarakteristiek: <code>T_we = <b>{c0:.3f}</b> + <b>{c1:.3f}</b> * T_out</code>"
))
graph = outdoor_reset_controller.plot_reset_line(fig_size=[8, 8], dpi=96)
graph.show_graph()
De datalogger is een object die de waarden van de diverse parameters in de regelkring zal opslaan tijdens het doorlopen van de regellus. Volgende parameters zullen op elk discreet tijdstip worden gelogd:
data_logger = DataLogger('T_out', 'T_we', 'out', 'h', 'V_w', 'T_in', 'T_bm', 'Q_e')
Nadat de regellus voltooid is, kunnen via de datalogger de resultaten worden bekeken (zie par. 6).
We stellen een tijdsas op die 1 etmaal (24 h) omspant. De tijdsafstand tussen 2 opeenvolgende tijdstippen is de tijdstap dt
.
time_axis = np.arange(0.0, 24 * 3600.0 + dt, dt)
We maken een temperatuurprofiel aan van de buitentemperatuur. De buitentemperatuur zal sinusvormig variƫren rond een gemiddelde waarde avg
, met een amplitude van ampl
en een periode van period
.
T_out = OutsideTemperature(avg=0.0, ampl=5.0, period=24 * 3600.0, profile='sine')
Het berekeningsalgoritme heeft (omwille van de numerieke benadering van de eerste afgeleide) van de ruimtetemperatuur en de bouwschiltemperatuur twee voorafgaande beginwaarden nodig (d.w.z. op de tijdstippen t = -2.dt en t = -1.dt).
room.initial_values(T_r_ini=[T_out.avg] * 2, T_bm_ini=[T_out.avg] * 2)
Er kan wat tijd overgaan alvorens een verandering van de ruimtetemperatuur door de regelaar wordt gemeten. Een 'dode tijd' of looptijd is in het programma geĆÆmplementeerd als een FIFO-buffer. De lengte van de buffer bepaalt het aantal tijdstappen dat het duurt voordat de op het tijdstip t gemeten ruimtetemperatuur wordt doorgegeven aan de regelaar.
m_delay = DeadTime(2, T_out.avg) # 2: de lengte van de FIFO-buffer (2 tijdstappen), T_out.avg = initiƫle waarden in de buffer
De regelkring wordt opgestart met de initiƫle waarde van de ruimtetemperatuur op het tijdstip t = -1.dt die aan de regelaar wordt toegevoerd. De regelaar bepaalt het regelcommando (in procenten). Dit regelcommando stemt overeen met de gevraagde kleppositie van de regelklep en wordt toegevoerd aan de klepmotor. De klepmotor drijft de regelklep aan. De bereikte klepstand bepaalt het volumedebiet dat de regelklep doorlaat tussen de tijdstippen t en t+dt. Op basis van dit volumedebiet, de wateraanvoertemperatuur en de buitentemperatuur wordt de nieuwe ruimtetemperatuur op het tijdstip t+dt berekend (alsook de bouwschiltemperatuur en de warmteafgifte van de radiator). Deze nieuwe waarde wordt dan vooraan in de meetvertraging (FIFO-buffer) gestopt en de laatste waarde in de FIFO-buffer wordt aan de regelaar toegevoerd. De regllus wordt dan herhaald tot het einde van de tijdas is bereikt.
We zullen de regellus (for-lus) een aantal keer doorlopen (num_cycles
). In de laatste cyclus (num_cycles
= 1) voeren we op 6h een setpointverlaging in op de regelaar en op 12h zetten we het setpoint terug op de ontwerp-binnentemperatuur. In de laatste cyclus schrijven we de parameters van de regelkring naar de datalogger.
De variabele outdoor_reset
wordt aangewend om al dan niet een variabele wateraanvoertemperatuur i.f.v. de buitentemperatuur te gebruiken. Indien True
zal de wateraanvoertemperatuurregelaar (cf. par. 3.2) de wateraanvoertemperatuur bepalen. Indien False
wordt de wateraanvoertemperatuur op een constante waarde gehouden.
outdoor_reset = True # True: outdoor reset control is actief, False: wateraanvoertemperatuur is constant en gelijk aan ontwerpwaarde
num_cycles = 4
while num_cycles > 0:
# initialisatie van de regelkring met de ingestelde initiƫle waarde of de laatste waarde uit de vorige cyclus
T_in = room.T_r[-1]
# regellus
for t in time_axis:
if num_cycles == 1:
if t == 6 * 3600.0:
on_off_controller.set_point(T_in_des - 3.0)
if t == 12 * 3600.0:
on_off_controller.set_point(T_in_des)
# regelcommando tussen t en t+dt
out = on_off_controller(t, T_in)
# klepstand tussen t en t+dt
h = valve_motor(out)
# volumedebiet tussen t en t+dt
V_w = control_valve(h)
# buitentemperatuur tussen t en t+dt
T_out_ = T_out(t)
if outdoor_reset is True:
# wateraanvoertemperatuur wordt door temperatuurregelaar berekend
T_we = outdoor_reset_controller(T_out_)
else:
# wateraanvoertemperatuur blijft constant
T_we = room.radiator.nominal_specs['Twe']
# ruimtetemperatuur, bouwschiltemperatuur en warmteafgifte in de ruimte op tijdstip t+dt
T_in, T_bm, Q_e = room(V_w, T_we, T_out_)
# ruimtetemperatuur op het tijdstip t + dt dat de regelaar meet (t.g.v. meetvertraging)
T_in = m_delay(T_in)
if num_cycles == 1:
data_logger.log(t / 3600.0, T_out=T_out_, T_we=T_we, out=out, h=h, V_w=V_w * 6.0e4, T_in=T_in, T_bm=T_bm, Q_e=Q_e)
num_cycles -= 1
De gelogde data wordt aan de datalogger opgevraagd. Daarmee worden 3 grafieken aangemaakt:
data = data_logger.get_data()
graph = graphing.MultiGraph(row_num=3, col_num=1, fig_size=[10.0, 15.0], dpi=96)
graph[1].add_data_set('T_out', data['t'], data['T_out'])
graph[1].add_data_set('T_bm', data['t'], data['T_bm'])
graph[1].add_data_set('T_in', data['t'], data['T_in'])
graph[1].add_data_set('T_we', data['t'], data['T_we'])
graph[1].add_legend()
graph[1].set_axis_titles('time (h)', 'T_out, T_bm, T_in, T_we (Ā°C)')
graph[1].scale_x_axis(data.iloc[0, 0], data.iloc[-1, 0], 2.0)
graph[1].scale_y_axis(-10.0, 80.0, 5.0)
graph[1].turn_grid_on()
graph[1].draw_graph()
graph[2].add_data_set('Qe', data['t'], data['Q_e'])
graph[2].set_axis_titles('time (h)', 'Q_e (W)')
graph[2].scale_x_axis(data.iloc[0, 0], data.iloc[-1, 0], 2.0)
graph[2].turn_grid_on()
graph[2].draw_graph()
graph[3].add_data_set('out', data['t'], data['out'])
graph[3].add_data_set('h', data['t'], data['h'])
graph[3].add_legend()
graph[3].set_axis_titles('time (h)', 'out, h (%)')
graph[3].scale_x_axis(data.iloc[0, 0], data.iloc[-1, 0], 2.0)
graph[3].turn_grid_on()
graph[3].draw_graph()
graph.show_graph()
Via onderstaande link-knop kan men een webapplicatie opstarten waarmee men met de regelkring interactief kan experimenteren. Het kan wel een paar minuten duren alvorens de webapplicatie volledig is opgestart (de applicatie draait op een publieke server mybinder.org). Op de webpagina die zal verschijnen, selecteer "on_off_control". Er zal dan een volgende webpagina openen. Klik daar op "on_off_control.ipynb". De eigenlijke webapplicatie zal nu opstarten. Het kan even duren voordat de gebruikersinterface volledig zichtbaar wordt. Het programma berekent namelijk eerst een simulatie met standaard waarden. Uiteindelijk zal een invulformulier op het scherm verschijnen. Door parameterwaarden te wijzigen, bv. de gemiddelde buitentemperatuur of de coƫfficiƫnten van de wateraanvoertemperatuurregelkarakteristiek (outdoor reset line) kan men nagaan welk effect dit zal hebben op het gedrag van de regelkring. Men kan ook de radiator, het ruimtemodel, de regelparameters van de aan/uit-regelaar, etc. veranderen. Wanneer op de 'submit'-knop wordt gedrukt, wordt de simulatie gemaakt en de resultaten afgebeeld in grafieken zoals hierboven.