Composants d’une CTA (hors batteries)

Cette page documente les composants unitaires d’une Centrale de Traitement d’Air (CTA) fournis par le paquet AHU, à l’exclusion des batteries chaudes/froides (voir le sous-paquet AHU.Coil). Chaque composant est une classe Object qui échange l’air via des ports AirPort et expose une méthode calculate() remplissant un DataFrame self.df de résultats.

Le connecteur AirPort

Tous les composants communiquent via des objets AHU.AirPort.AirPort. Un AirPort porte l’état d’un flux d’air humide :

Attribut

Signification

Unité

F

Débit massique d’air humide

kg/s

F_dry

Débit massique d’air sec

kg/s

P

Pression (défaut 101325)

Pa

h

Enthalpie spécifique

kJ/kg air sec

w

Humidité absolue

g H₂O / kg air sec

Les propriétés T (°C), RH (%) et Pv_sat (Pa) sont calculées à la demande à partir de h, w et P (propriétés Python en lecture seule) :

  • T = air_humide.Air_T_db(h, w) ;

  • Pv_sat = air_humide.Air_Pv_sat(T) ;

  • RH = air_humide.Air_RH(Pv_sat, w, P).

La méthode update_properties() force le recalcul (invalide le cache _T / _RH / _Pv_sat). Elle est appelée par chaque composant après mise à jour de son port de sortie.

Air neuf — FreshAir

Rôle. Point d’entrée d’air (air neuf, air repris, air extrait…). Convertit un couple température / humidité relative (et éventuellement un débit volumique) en état psychrométrique complet sur le port de sortie.

Connecteurs. Inlet (AirPort), Outlet (AirPort). La sortie est une recopie de l’entrée une fois l’état calculé.

Équations (module AHU.FreshAir.FreshAir). Si T et RH sont fournis :

\[P_{v,sat} = \mathrm{Air\_Pv\_sat}(T) \qquad w = \mathrm{Air\_w}(P_{v,sat}, RH, P) \qquad h = \mathrm{Air\_h}(T, w)\]

Conversion optionnelle d’un débit volumique en débit massique :

\[F = \frac{F_{m3h}\;\rho_{hum}(T, RH, P)}{3600}\quad[\mathrm{kg/s}]\]

Débit d’air sec :

\[F_{dry} = \frac{F}{1 + w/1000}\]

Paramètres (__init__) :

Attribut

Description

Unité

Défaut

id

Identifiant

1

T

Température d’entrée

°C

None

RH

Humidité relative d’entrée

%

None

F

Débit massique air humide

kg/s

None

F_m3h

Débit volumique air humide

m³/h

None

P

Pression

Pa

101325

Exemple.

from AHU.FreshAir.FreshAir import Object as FreshAir

fa = FreshAir()
fa.T = -5.0
fa.RH = 80.0
fa.F_m3h = 10000
fa.calculate()
print(fa.Outlet.T, fa.Outlet.w, fa.Outlet.h, fa.Outlet.F)

Mélange air neuf / air repris — AirMix

Rôle. Mélange adiabatique de deux flux d’air humide (typiquement air neuf + air repris). Le mélange se fait par bilan sur l’air sec.

Connecteurs. Inlet1, Inlet2 (AirPort), Outlet (AirPort).

Équations (module AHU.FreshAir.AirMix). Débits d’air sec de chaque flux :

\[\dot m_{dry,i} = \frac{F_i}{1 + w_i/1000}\]

Humidité absolue et enthalpie du mélange (moyennes pondérées par le débit d’air sec) :

\[w_{out} = \frac{w_1\,\dot m_{dry,1} + w_2\,\dot m_{dry,2}} {\dot m_{dry,1} + \dot m_{dry,2}} \qquad h_{out} = \frac{h_1\,\dot m_{dry,1} + h_2\,\dot m_{dry,2}} {\dot m_{dry,1} + \dot m_{dry,2}}\]

Débit d’air humide et pression :

\[F_{out} = F_1 + F_2 \qquad P_{out} = \min(P_1, P_2)\]

Si un seul flux est renseigné, la sortie reprend cet unique flux.

Paramètres. Aucun paramètre de réglage : Inlet1, Inlet2, Outlet, id (défaut 1). Les débits d’air sec F_dry1 / F_dry2 sont déduits.

Exemple.

from AHU.FreshAir.AirMix import Object as AirMix
from AHU.FreshAir.FreshAir import Object as FreshAir

neuf = FreshAir(); neuf.T = -5; neuf.RH = 80; neuf.F_m3h = 3000; neuf.calculate()
repris = FreshAir(); repris.T = 20; repris.RH = 45; repris.F_m3h = 7000; repris.calculate()

mx = AirMix()
mx.Inlet1 = neuf.Outlet
mx.Inlet2 = repris.Outlet
mx.calculate()
print(mx.Outlet.T, mx.Outlet.w, mx.Outlet.F)

Récupérateur à plaques — HeatRecovery.Heat_plate_exchanger

Rôle. Échangeur air/air à plaques (récupération sensible). L’air neuf (flux 1) est préchauffé/rafraîchi par l’air extrait (flux 2) sans transfert d’humidité côté air neuf ; la condensation éventuelle est traitée côté air extrait.

Connecteurs. Inlet1 / Outlet1 (air neuf), Inlet2 / Outlet2 (air extrait). Tous des AirPort.

Équations (module AHU.HeatRecovery.Heat_plate_exchanger). Débit d’air sec limitant :

\[\dot m_{dry,min} = \min(F_{dry,1},\,F_{dry,2})\]

Régime hivernal (Inlet2.T Inlet1.T et Inlet1.T T_target) — avec plafonnement de l’efficacité pour ne pas dépasser la consigne T_target :

\[\eta_{cible} = 100\,\frac{F_{dry,1}\,(T_{target} - T_{1i})} {\dot m_{dry,min}\,(T_{2i} - T_{1i})} \qquad \eta_T \leftarrow \max\!\big(\min(\eta_T, \eta_{cible}),\,0\big)\]

Température de sortie de l’air neuf (l’humidité absolue reste constante, \(w_{1o} = w_{1i}\)) :

\[T_{1o} = T_{1i} + \frac{\dot m_{dry,min}\,(\eta_T/100)\,(T_{2i} - T_{1i})}{F_{dry,1}} \qquad h_{1o} = \mathrm{Air\_h}(T_{1o}, w_{1i})\]

Chaleur récupérée et efficacité enthalpique :

\[\dot Q = (h_{1o} - h_{1i})\,F_{dry,1} \qquad \eta_h = 100\,\frac{F_{dry,1}\,(h_{1o} - h_{1i})} {\dot m_{dry,min}\,(h_{2i} - h_{1i})}\]

Enthalpie de sortie de l’air extrait (bilan de chaleur) et gestion de la condensation par comparaison des températures de rosée :

\[h_{2o} = h_{2i} - \frac{\dot Q}{F_{dry,2}}\]
\[T_{dp,dry} = \mathrm{Air\_T\_dp}(w_{2i}) \qquad T_{dp,wet} = \mathrm{Air\_T\_dp}(h_{2o})\]

Si \(T_{dp,wet} \le T_{dp,dry}\) → condensation : \(w_{2o} = \mathrm{Air\_w}(h_{2o}, RH{=}100)\) ; sinon \(w_{2o} = w_{2i}\).

Régime estival (Inlet2.T < Inlet1.T) : l’air neuf est refroidi, \(T_{1o} = T_{1i} - \dot m_{dry,min}\,(\eta_T/100)\,(T_{1i} - T_{2i})/F_{dry,1}\), sans condensation modélisée (\(w_{2o} = w_{2i}\)). Entre les deux (Inlet1.T > T_target) : aucun échange. Les débits d’air sec sont conservés.

Paramètres (__init__) :

Attribut

Description

Unité

Défaut

id

Identifiant

2

T_efficiency

Efficacité en température de l’échangeur

%

80

T_target

Consigne de température de l’air neuf préchauffé (plafonne l’échange)

°C

16

h_efficiency

Efficacité enthalpique (calculée)

%

None

T_efficiency_target

Efficacité maxi admissible pour tenir T_target (calculée)

%

None

Exemple.

from AHU.HeatRecovery.Heat_plate_exchanger import Object as PlateExchanger
from AHU.FreshAir.FreshAir import Object as FreshAir

neuf = FreshAir(); neuf.T = -5; neuf.RH = 80; neuf.F_m3h = 10000; neuf.calculate()
extrait = FreshAir(); extrait.T = 22; extrait.RH = 50; extrait.F_m3h = 10000; extrait.calculate()

hx = PlateExchanger()
hx.T_efficiency = 75
hx.Inlet1 = neuf.Outlet
hx.Inlet2 = extrait.Outlet
hx.calculate()
print(hx.Outlet1.T, hx.heat_transfer, hx.h_efficiency)

Récupérateur à roue — HeatRecovery.Thermal_wheel_exchanger

Rôle. Roue thermique (échangeur rotatif). Contrairement à la plaque, la roue transfère chaleur et humidité (échange enthalpique total). Le module distingue transfert total (heat_transfer1/2), transfert sensible (sensible_heat_transfer1/2) et transfert d’eau (delta_mw1/2).

Connecteurs. Inlet1 / Outlet1 (air neuf), Inlet2 / Outlet2 (air extrait). Tous des AirPort.

Équations (module AHU.HeatRecovery.Thermal_wheel_exchanger). Le plafonnement d’efficacité et \(\dot m_{dry,min}\) sont identiques à la plaque. En régime hivernal, l’efficacité s’applique à l”enthalpie :

\[T_{1o} = T_{1i} + \frac{\dot m_{dry,min}\,(\eta_T/100)\,(T_{2i} - T_{1i})}{F_{dry,1}}\]
\[h_{1o} = h_{1i} + \frac{\dot m_{dry,min}\,(\eta_T/100)\,(h_{2i} - h_{1i})}{F_{dry,1}} \qquad w_{1o} = \mathrm{Air\_w}(h_{1o}, T_{1o})\]

Transferts total et sensible du flux air neuf :

\[\dot Q_1 = (h_{1o} - h_{1i})\,F_{dry,1} \qquad \dot Q_{s,1} = \big(\mathrm{Air\_h}(w_{1i}, T_{1o}) - h_{1i}\big)\,F_{dry,1}\]

Côté air extrait, bilan miroir (\(\dot Q_2 = -\dot Q_1\)) et transfert d’humidité :

\[h_{2o} = h_{2i} + \frac{\dot Q_2}{F_{dry,2}} \qquad \Delta \dot m_{w,1} = F_{dry,1}\,(w_{1o} - w_{1i}) \;,\quad \Delta \dot m_{w,2} = -\Delta \dot m_{w,1}\]
\[w_{2o} = w_{2i} + \frac{\Delta \dot m_{w,2}}{F_{dry,2}} \qquad T_{2o} = \mathrm{Air\_T\_db}(w_{2o}, h_{2o})\]

Efficacité enthalpique : \(\eta_h = 100\,F_{dry,1}(h_{1o}-h_{1i}) / [\dot m_{dry,min}(h_{2i}-h_{1i})]\). Le régime estival est symétrique (air neuf refroidi) ; entre les deux, pas d’échange.

Paramètres (__init__) : identiques à la plaque (id défaut 2, T_efficiency défaut 80 %, T_target défaut 16 °C), plus les grandeurs calculées heat_transfer1/2, sensible_heat_transfer1/2, delta_mw1/2 (g H₂O/s), T1o / T2o.

Exemple.

from AHU.HeatRecovery.Thermal_wheel_exchanger import Object as ThermalWheel
from AHU.FreshAir.FreshAir import Object as FreshAir

neuf = FreshAir(); neuf.T = -5; neuf.RH = 80; neuf.F_m3h = 10000; neuf.calculate()
extrait = FreshAir(); extrait.T = 22; extrait.RH = 50; extrait.F_m3h = 10000; extrait.calculate()

wheel = ThermalWheel()
wheel.T_efficiency = 75
wheel.Inlet1 = neuf.Outlet
wheel.Inlet2 = extrait.Outlet
wheel.calculate()
print(wheel.Outlet1.T, wheel.Outlet1.w, wheel.delta_mw1)

Humidificateur — Humidification.Humidifier

Rôle. Porte l’humidité absolue de l’air à une consigne wo_target. Deux technologies : humidification adiabatique (à eau, enthalpie conservée) ou à vapeur (apport d’enthalpie). L’état de sortie est résolu numériquement (scipy.optimize.fsolve).

Connecteurs. Inlet, Outlet (AirPort).

Équations (module AHU.Humidification.Humidifier). L’humidification n’a lieu que si wo_target > wi (sinon l’air traverse sans changement, F_water = 0, Q_th = 0).

Adiabatique — enthalpie conservée (\(h_o = h_i\)). Le système résolu fixe \((P_{v,sat}, T_o, RH_o)\) par :

\[P_{v,sat} = \mathrm{Air\_Pv\_sat}(T_o) \;,\quad w_{target} = \mathrm{Air\_w}(P_{v,sat}, RH_o, 101325) \;,\quad h_i = \mathrm{Air\_h}(T_o, w_{target})\]

Vapeur — apport d’enthalpie de la vapeur injectée (variable supplémentaire \(h_o\)) :

\[h_o - h_i = \frac{w_{target} - w_i}{1000}\,h_{vap} \qquad h_{vap} = C_{pv}\,T_{vap} + L_{lv} \approx 2676\ \mathrm{kJ/kg}\]

Dans les deux cas, débit d’air sec, consommation d’eau et puissance thermique :

\[\dot m_{dry} = \frac{F}{1 + w_i/1000} \qquad \dot m_{water} = \dot m_{dry}\,\frac{w_{target} - w_i}{1000}\ [\mathrm{kg/s}]\]
\[\dot Q_{th} = (h_o - h_i)\,\dot m_{dry}\]

Le port de sortie prend \(w_{out} = w_{target}\), \(P_{out} = P_{in} - \Delta P\), \(h_{out} = h_o\).

Paramètres (__init__) :

Attribut

Description

Unité

Défaut

HumidType

"adiabatique" ou "vapeur"

"adiabatique"

wo_target

Humidité absolue de consigne

g/kg air sec

10

RH_out_target

Humidité relative de consigne

%

60

P_drop

Perte de charge

Pa

0

Llv

Chaleur latente de vaporisation

kJ/kg

2500.8

T_vap

Température vapeur injectée

°C

100

Cpv

Chaleur massique vapeur

kJ/kg·K

1.8262

Exemple.

from AHU.Humidification.Humidifier import Object as Humidifier
from AHU.FreshAir.FreshAir import Object as FreshAir

amont = FreshAir(); amont.T = 18; amont.RH = 20; amont.F_m3h = 10000; amont.calculate()

hmd = Humidifier()
hmd.HumidType = "adiabatique"
hmd.wo_target = 8
hmd.Inlet = amont.Outlet
hmd.calculate()
print(hmd.Outlet.T, hmd.Outlet.RH, hmd.F_water, hmd.Q_th)

Capteur d’air — Sensor.AirSensor

Rôle. Capteur passif (observateur) qui lit un AirPort sans modifier son état et restitue une grandeur choisie parmi dix types de mesure. Utile pour instrumenter n’importe quel point de la CTA.

Connecteurs. Inlet (AirPort observé, non modifié). calculate() retourne self.value (la grandeur sélectionnée) et renseigne self.df.

Types de mesure (attribut measurement_type) : Température (°C), Humidité absolue (g/kg air sec), Humidité relative (%), Débit air humide (kg/s), Débit air humide kg/h (kg/h), Débit air sec (kg air sec/s), Débit volumique (m³/h), Débit normal (Nm³/h), Enthalpie (kJ/kg air sec), Pression (bar).

Équations (module AHU.Sensor.AirSensor). Le port doit être complet (w, h, F, P non nuls, sinon ValueError). Masses volumiques humide et normale :

\[\rho = \mathrm{Air\_rho\_hum}(T, RH, P) \qquad \rho_N = \mathrm{Air\_rho\_hum}(T_N, RH_N, P_N)\]

Débits dérivés :

\[\dot m_{dry} = \frac{F}{1 + w/1000} \qquad \dot V = \frac{F}{\rho}\,3600\ [\mathrm{m^3/h}] \qquad \dot V_N = \frac{F}{\rho_N}\,3600\ [\mathrm{Nm^3/h}]\]

Les autres mesures sont des recopies directes du port : \(T\), \(w\), \(RH\), \(F\) (kg/s et ×3600 en kg/h), \(h\), \(P/10^5\) (bar).

Paramètres (__init__) :

Attribut

Description

Unité

Défaut

measurement_type

Grandeur à restituer

"Température"

Timestamp

Horodatage (reporté dans df)

None

normal_temperature_degC

Température des conditions normales

°C

0.0

normal_relative_humidity_percent

Humidité relative des conditions normales

%

0.0

normal_pressure_Pa

Pression des conditions normales

Pa

101325.0

Exemple.

from AHU.Sensor.AirSensor import Object as AirSensor
from AHU.FreshAir.FreshAir import Object as FreshAir

air = FreshAir(); air.T = 20; air.RH = 50; air.F_m3h = 5000; air.calculate()

capteur = AirSensor()
capteur.Inlet = air.Outlet
capteur.measurement_type = "Débit volumique"
debit = capteur.calculate()
print(debit, capteur.unit)   # m³/h

Modèle thermique de bâtiment — Building.BuildingRC

Rôle. Modèle RC à deux nœuds (air intérieur + enveloppe/mur) pour simuler l’évolution de la température d’un local desservi par la CTA. Il ne possède pas de port AirPort : l’action de la CTA est représentée par un débit et une température de soufflage.

Structure RC. Deux capacités thermiques (\(C_{air}\), \(C_{mur}\)) et trois résistances : mur↔extérieur (\(R_{ext,mur}\)), air↔mur (\(R_{int,mur}\)), sol↔air (\(R_{sol,int}\)).

Équations (module AHU.Building.BuildingRC). Résistances (demi-mur de part et d’autre du nœud d’enveloppe) :

\[R_{ext,mur} = \frac{1}{h_{ext}\,A_{env}} + \frac{e_{mur}}{2\,\lambda_{mur}\,A_{env}} \qquad R_{int,mur} = \frac{e_{mur}}{2\,\lambda_{mur}\,A_{env}} + \frac{1}{h_{int}\,A_{env}}\]
\[R_{sol,int} = \frac{1}{h_{sol}\,A_{sol}}\]

Capacités thermiques :

\[C_{air} = \rho_{air}\,c_{p,air}\,V_{int} \qquad C_{mur} = \rho_{mur}\,c_{p,mur}\,A_{env}\,e_{mur}\]

Débit massique de soufflage : \(\dot m_{air} = \dot V_{souff}\,\rho_{air}/3600\). La consigne de soufflage est régulée : \(T_{souff} = T_{froid}\) si \(T_{int} > T_{froid}\), \(T_{chaud}\) si \(T_{int} < T_{chaud}\), sinon \(T_{int}\).

Intégration temporelle (Euler explicite, sous-pas de 30 s maxi) des deux nœuds :

\[\frac{dT_{int}}{dt} = \frac{1}{C_{air}}\Bigg[ \frac{T_{mur} - T_{int}}{R_{int,mur}} + \frac{T_{sol} - T_{int}}{R_{sol,int}} + \dot m_{air}\,c_{p,air}\,(T_{souff} - T_{int}) \Bigg]\]
\[\frac{dT_{mur}}{dt} = \frac{1}{C_{mur}}\Bigg[ \frac{T_{int} - T_{mur}}{R_{int,mur}} + \frac{T_{ext} - T_{mur}}{R_{ext,mur}} \Bigg]\]

Puissances et énergies stockées :

\[\dot Q_{vent} = \dot m_{air}\,c_{p,air}\,(T_{souff} - T_{int}) \qquad \dot Q_{dep} = \frac{T_{ext} - T_{mur}}{R_{ext,mur}} \qquad \dot Q_{sol} = \frac{T_{sol} - T_{int}}{R_{sol,int}}\]
\[E_{air} = (C_{air}\,T_{int} - E_{air,init})\;/\;3.6{\times}10^{6}\ [\mathrm{kWh}]\]

Paramètres (__init__, extrait) :

Attribut

Description

Unité

Défaut

V_int

Volume intérieur

1000

A_env / A_sol

Surface enveloppe / sol

800 / 200

e_mur

Épaisseur mur

m

0.2

lambda_mur

Conductivité thermique mur

W/m·K

1.7

rho_mur / cp_mur

Masse volumique / chaleur massique mur

kg/m³, J/kg·K

2300 / 880

h_ext / h_int / h_sol

Coefficients de convection ext / int / sol

W/m²·K

25 / 7.7 / 5.9

T_ext / T_sol

Température extérieure / sol

°C

5 / 18

debit_soufflage

Débit de soufflage

m³/h

0

T_consigne_chaud / T_consigne_froid

Consignes chauffage / rafraîchissement

°C

19 / 25

Exemple.

from AHU.Building.BuildingRC import Object as BuildingRC

local = BuildingRC()
local.T_ext = -2.0
local.debit_soufflage = 500     # m³/h
local.T_int = 18.0

for _ in range(60):             # 60 pas de 60 s = 1 h
    local.calculate(dt=60)
print(local.T_int, local.Q_total, local.E_mur)