Dimensionnement d’un bassin de rétention — Méthodologie SPW
Ce notebook illustre l’utilisation de la classe MockupSPWXLSX du module wolfhece.mockup_spw_xlsx pour dimensionner un bassin de rétention d’eaux pluviales selon la méthodologie du SPW (Service Public de Wallonie).
Sommaire
Factory ``MockupSPWXLSX.make()` <#10.-Factory-MockupSPWXLSX.make()>`__
1. Imports et initialisations
On importe la classe principale MockupSPWXLSX, le registre d’unités UNITS (basé sur pint) et l’énumération LandUse qui regroupe les types d’occupation du sol avec leurs coefficients de ruissellement.
Note : pour une introduction à
pintet à la manipulation des unités de surface, de débit et de longueur en hydrologie, voir le notebook dédié : pint_unites.ipynb.
[ ]:
from wolfhece import check_version
check_version("2.2.74")
from wolfhece.mockup_spw_xlsx import MockupSPWXLSX, UNITS, LandUse
# Pour l'affichage des graphiques dans le notebook
%matplotlib inline
import matplotlib.pyplot as plt
INFO:root:Version de wolfhece : 2.2.73 ou supérieure est installée.
Rappel des types d’occupation du sol disponibles
Chaque membre de LandUse possède un nom, une description et un coefficient de ruissellement (C) :
[2]:
LandUse.print_summary()
Name Description C [-]
----------------------------------------------------------------------------------------
Forest Forêts et bois 0.05
Grassland Prairies, jardins et zones enherbées 0.15
Fields Champs cultivés, landes et broussailles 0.25
Green Roofs Dalles de gazon et toitures vertes 0.40
Bare Soil Terres battues et toitures vertes 0.50
Drained Paving Pavés à joints écartés et pavés drainants 0.70
Impervious Surfaces Allées pavées, trottoirs pavés et parkings 0.90
Water and Roofs Toitures, routes et plans d'eau 1.00
2. Définition du projet
On crée une instance de MockupSPWXLSX et on configure :
La localité (commune belge, identifiée par son code NIS ou son nom) ;
Les sous-bassins avec leur type d’occupation du sol et leur superficie.
Les superficies peuvent être exprimées en m² (valeur numérique brute) ou en toute autre unité de surface via UNITS (hectare, km², …).
[3]:
m = MockupSPWXLSX()
# Choix de la localité — détermine les courbes IDF de l'IRM
m.set_locality("Liège")
print(f"Localité : {m.locality_name} (NIS {m._locality_nsi})")
Localité : Liège (NIS 62063)
[4]:
# Ajout des sous-bassins
# Chaque appel à add_area(clé, type_occupation, superficie)
m.add_area("parking", LandUse.IMPERVIOUS_SURFACES, 800) # 800 m²
m.add_area("toitures", LandUse.WATER_AND_ROOFS, 350) # 350 m²
m.add_area("trottoirs", LandUse.DRAINED_PAVING, 200) # 200 m²
m.add_area("jardin", LandUse.GRASSLANDS, 0.15 * UNITS.hectare) # 1500 m²
m.add_area("potager", LandUse.CULTIVATED_FIELDS, 300) # 300 m²
m.add_area("boisement", LandUse.FORESTS, 0.2 * UNITS.hectare) # 2000 m²
print(f"Surface totale : {m.total_area.to('m^2'):.0f}")
print(f"Surface pondérée (C·A) : {m.total_area_ponderated.to('m^2'):.1f}")
Surface totale : 5150 meter ** 2
Surface pondérée (C·A) : 1610.0 meter ** 2
3. Paramètres d’infiltration et de rejet
On définit :
Paramètre |
Description |
Unité par défaut |
|---|---|---|
|
Surface d’infiltration du bassin |
m² |
|
Conductivité hydraulique (loi de Darcy) |
m/s |
|
Débit de fuite admissible vers le réseau |
L/s/ha (défaut 5) |
Toutes les grandeurs physiques acceptent des valeurs brutes (interprétées dans l’unité par défaut) ou des pint.Quantity pour une conversion automatique.
[5]:
# Surface d'infiltration : 150 m²
m.infiltration_area = 150 * UNITS.meter**2
# Conductivité hydraulique : 1×10⁻⁵ m/s (on peut aussi écrire en mm/h)
m.infiltration_darcy = 1e-5 * UNITS.meter / UNITS.second
# Équivalent : m.infiltration_darcy = 36 * UNITS.mm / UNITS.hour
# Débit de fuite admissible : 5 L/s/ha
m.admissible_outflow = 5.0 # valeur numérique → L/s/ha par défaut
print(f"Surface infiltration : {m.infiltration_area:.0f}")
print(f"Darcy : {m.infiltration_darcy:.2e}")
print(f" (soit : {m.infiltration_darcy.to('mm/h'):.2f})")
print(f"Débit admissible : {m.admissible_outflow:.1f}")
Surface infiltration : 150 meter ** 2
Darcy : 1.00e-05 meter / second
(soit : 36.00 millimeter / hour)
Débit admissible : 5.0 liter / hectare / second
4. Calcul de la capacité de rétention
La méthode get_retention_capacity() réalise les opérations suivantes :
Récupération du hyétogramme de Chicago pour la période de retour choisie (courbes IDF de l’IRM, localité sélectionnée) ;
Conversion de la pluie brute en apport net via le coefficient de ruissellement pondéré ;
Calcul du débit de fuite (infiltration + rejet réseau) ;
Détermination du volume de rétention nécessaire (cumul des excédents positifs au pas de temps dt = 5 min).
Le résultat est un pint.Quantity en m³. Les propriétés design_rainfall_duration et emptying_time sont également calculées.
[6]:
# Période de retour de 25 ans (valeur par défaut)
volume = m.get_retention_capacity(return_period=25)
print(f"Volume de rétention : {volume:.2f}")
print(f"Durée pluie de projet : {m.design_rainfall_duration.to('hour'):.2f}")
print(f"Temps de vidange : {m.emptying_time.to('hour'):.2f}")
print(f"Volume spécifique : {volume.magnitude / m.total_area.magnitude * 1000:.1f} L/m²")
Volume de rétention : 43.05 meter ** 3
Durée pluie de projet : 1.00 hour
Temps de vidange : 3.60 hour
Volume spécifique : 8.4 L/m²
Calcul pour d’autres périodes de retour
[7]:
for T in [2, 5, 10, 25, 50, 100]:
vol = m.get_retention_capacity(return_period=T)
print(f" T = {T:>3d} ans → V = {vol.to('m^3').magnitude:>8.2f} m³ | "
f"Durée pluie = {m.design_rainfall_duration.to('hour').magnitude:.1f} h | "
f"Vidange = {m.emptying_time.to('hour').magnitude:.1f} h")
T = 2 ans → V = 15.13 m³ | Durée pluie = 0.5 h | Vidange = 1.3 h
T = 5 ans → V = 24.56 m³ | Durée pluie = 0.7 h | Vidange = 2.1 h
T = 10 ans → V = 32.06 m³ | Durée pluie = 0.8 h | Vidange = 2.7 h
T = 25 ans → V = 43.05 m³ | Durée pluie = 1.0 h | Vidange = 3.6 h
T = 50 ans → V = 52.37 m³ | Durée pluie = 1.2 h | Vidange = 4.4 h
T = 100 ans → V = 62.68 m³ | Durée pluie = 1.3 h | Vidange = 5.2 h
5. Rapport de synthèse
La méthode generate_report() produit un rapport texte structuré reprenant l’ensemble des données d’entrée et des résultats.
[8]:
# On recalcule pour T=25 afin d'avoir le rapport correspondant
m.get_retention_capacity(return_period=25)
rapport = m.generate_report()
print(rapport)
======================================================================
STORMWATER RETENTION BASIN — SIZING REPORT (SPW methodology)
======================================================================
Locality : Liège (NSI 62063)
Return period : 25 years
----------------------------------------------------------------------
Key Land use C [-] Area [m²]
----------------------------------------------------------------------
parking Impervious Surfaces 0.90 800.0
toitures Water and Roofs 1.00 350.0
trottoirs Drained Paving 0.70 200.0
jardin Grassland 0.15 1500.0
potager Fields 0.25 300.0
boisement Forest 0.05 2000.0
----------------------------------------------------------------------
Total 0.31 5150.0
Weighted area 1610.0
----------------------------------------------------------------------
Infiltration & outflow parameters
----------------------------------------------------------------------
Infiltration area : 150.0 m²
Darcy velocity : 1.00e-05 m/s (36.00 mm/h)
Security factor : 2.0
Infiltration outflow : 0.7500 L/s
Admissible outflow : 5.00 L/s/ha (2.5750 L/s)
Total outflow : 3.3250 L/s
======================================================================
RESULTS
======================================================================
Retention capacity : 43.05 m³
Design rainfall duration : 1.00 h
Emptying time : 3.60 h
Specific volume : 8.4 L/m²
======================================================================
6. Graphiques
Quatre méthodes de visualisation sont disponibles :
Méthode |
Contenu |
|---|---|
|
Hyétogramme de Chicago (intensité vs temps) |
|
Bilan volumique : débit entrant, sortant et volume stocké |
|
Diagramme circulaire de la répartition des surfaces |
|
Figure composite regroupant les trois graphiques |
Chaque méthode accepte un paramètre ax optionnel pour intégrer le graphique dans une figure personnalisée.
6.1 Hyétogramme de Chicago
[9]:
m.plot_hyetograph(show=False)
plt.show()
6.2 Bilan volumique
Le graphique à double axe montre :
En bleu : le débit net entrant (pluie × C × A) en L/s
En rouge pointillé : le débit de fuite total en L/s
En vert (aire remplie) : le volume cumulé stocké en m³
[10]:
m.plot_volume_balance(show=False)
plt.show()
6.3 Répartition des surfaces par occupation du sol
[11]:
m.plot_land_use(show=False)
plt.show()
6.4 Figure de synthèse
[12]:
fig = m.plot_summary(show=False)
plt.show()
# Pour sauvegarder la figure :
# fig.savefig("rapport_bassin_retention.png", dpi=150, bbox_inches="tight")
7. Export / Import JSON
Le projet peut être sauvegardé au format JSON pour archivage ou rechargement ultérieur. Toutes les grandeurs sont sérialisées en unités SI (m², m/s, L/s/ha).
[13]:
import tempfile, json
from pathlib import Path
# Export
output_dir = Path(tempfile.mkdtemp())
json_path = output_dir / "projet_bassin.json"
m.to_json(json_path)
# Affichage du contenu JSON
with open(json_path) as f:
print(json.dumps(json.load(f), indent=2, ensure_ascii=False))
{
"locality_nsi": 62063,
"reference_area_m2": 0,
"infiltration_area_m2": 150,
"infiltration_darcy_m_per_s": 1e-05,
"infiltration_security_factor": 2.0,
"admissible_outflow_l_per_s_per_ha": 5.0,
"climate_delta_t": 0.0,
"climate_rate": 0.07,
"areas": {
"parking": {
"land_use": "IMPERVIOUS_SURFACES",
"area_m2": 800
},
"toitures": {
"land_use": "WATER_AND_ROOFS",
"area_m2": 350
},
"trottoirs": {
"land_use": "DRAINED_PAVING",
"area_m2": 200
},
"jardin": {
"land_use": "GRASSLANDS",
"area_m2": 1500.0
},
"potager": {
"land_use": "CULTIVATED_FIELDS",
"area_m2": 300
},
"boisement": {
"land_use": "FORESTS",
"area_m2": 2000.0
}
}
}
[14]:
# Rechargement depuis le fichier JSON
m2 = MockupSPWXLSX.from_json(json_path)
# Vérification
print(f"Localité rechargée : {m2.locality_name}")
print(f"Nombre de sous-bassins : {len(m2.areas)}")
print(f"Surface totale : {m2.total_area:.0f}")
# Recalcul sur le projet rechargé
vol2 = m2.get_retention_capacity(return_period=25)
print(f"Volume (rechargé) : {vol2:.2f}")
print(f"Volume (original) : {volume:.2f}")
Localité rechargée : Liège
Nombre de sous-bassins : 6
Surface totale : 5150 meter ** 2
Volume (rechargé) : 43.05 meter ** 3
Volume (original) : 43.05 meter ** 3
8. Analyse de sensibilité
La classe intègre deux méthodes dédiées :
Méthode |
Description |
|---|---|
|
Balaye un paramètre sur une plage de valeurs et renvoie un |
|
Idem + graphique automatique |
Paramètres supportés : "admissible_outflow", "infiltration_darcy", "infiltration_area", "infiltration_security_factor", "return_period".
La valeur originale du paramètre est automatiquement restaurée après le balayage.
[15]:
import numpy as np
# --- 8.1 Influence du débit de fuite admissible ---
ax, df_q = m.plot_sensitivity(
"admissible_outflow",
np.linspace(0, 20, 21), # 0 → 20 L/s/ha
show=False,
)
ax.axvline(5.0, color='red', ls='--', alpha=0.7, label='Réf. (5 L/s/ha)')
ax.legend()
plt.tight_layout(); plt.show()
# Le DataFrame contient toutes les valeurs calculées
df_q.head()
[15]:
| parameter | volume_m3 | duration_h | emptying_h | |
|---|---|---|---|---|
| 0 | 0.0 | 67.286378 | 7.500000 | 24.920881 |
| 1 | 1.0 | 57.532655 | 3.833333 | 12.633433 |
| 2 | 2.0 | 51.933546 | 2.500000 | 8.104486 |
| 3 | 3.0 | 48.120372 | 1.666667 | 5.824301 |
| 4 | 4.0 | 45.299546 | 1.333333 | 4.478010 |
[16]:
# --- 8.2 Influence de la conductivité hydraulique (échelle log) ---
ax, df_k = m.plot_sensitivity(
"infiltration_darcy",
np.logspace(-7, -3, 30), # 1e-7 → 1e-3 m/s
show=False,
)
ax.axvline(1e-5, color='red', ls='--', alpha=0.7, label='Réf. (1e-5 m/s)')
ax.legend()
plt.tight_layout(); plt.show()
[17]:
# --- 8.3 Influence de la période de retour ---
ax, df_t = m.plot_sensitivity(
"return_period",
[2, 5, 10, 25, 50, 100],
show=False,
)
ax.axvline(25, color='red', ls='--', alpha=0.7, label='Réf. (T = 25 ans)')
ax.legend()
plt.tight_layout(); plt.show()
Comparaison multi-paramètres
On peut combiner plusieurs analyses dans une même figure grâce au paramètre ax :
[16]:
fig, axes = plt.subplots(1, 3, figsize=(16, 5))
m.plot_sensitivity("admissible_outflow", np.linspace(0, 20, 21),
ax=axes[0], show=False)
m.plot_sensitivity("infiltration_darcy", np.logspace(-7, -3, 30),
ax=axes[1], show=False)
m.plot_sensitivity("return_period", [2, 5, 10, 25, 50, 100],
ax=axes[2], show=False)
fig.suptitle(f"Analyses de sensibilité — {m.locality_name}", fontweight="bold")
fig.tight_layout()
plt.show()
9. Impact du changement climatique
En Belgique, on admettra qu’un réchauffement climatique entraîne une augmentation des précipitations de 7 % par degré de réchauffement. La classe MockupSPWXLSX intègre ce facteur via deux attributs :
climate_delta_t— écart de température en °C (par défaut 0)climate_factor— facteur multiplicatif appliqué aux pluies : \(f = 1 + 0{,}07 \times \Delta T\)
Ainsi, pour un scénario à +2 °C, le facteur vaut 1,14 : l’intensité de pluie utilisée dans le dimensionnement est majorée de 14 %.
[17]:
# Volume de référence sans changement climatique
vol_ref = m.get_retention_capacity(25)
print(f"Volume de référence (ΔT = 0 °C) : {vol_ref.to('m^3'):.1f}")
# Scénario +2 °C
m.climate_delta_t = 2.0
vol_2deg = m.get_retention_capacity(25)
print(f"Volume scénario +2 °C (facteur {m.climate_factor:.2f}) : {vol_2deg.to('m^3'):.1f}")
print(f"Augmentation : +{(vol_2deg - vol_ref).to('m^3'):.1f}"
f" ({(vol_2deg / vol_ref - 1) * 100:.1f} %)")
# Retour à la situation actuelle
m.climate_delta_t = 0.0
Volume de référence (ΔT = 0 °C) : 43.0 meter ** 3
Volume scénario +2 °C (facteur 1.14) : 51.1 meter ** 3
Augmentation : +8.0 meter ** 3 (18.6 dimensionless %)
Analyse de sensibilité au réchauffement
On peut balayer une plage de ΔT (de 0 à 4 °C) pour visualiser l’impact sur le volume de rétention :
[18]:
import numpy as np
delta_t_values = np.arange(0, 4.5, 0.5) # 0 à 4 °C par pas de 0.5
m.plot_sensitivity("climate_delta_t", delta_t_values)
[18]:
(<Axes: title={'center': 'Sensibilité — climate_delta_t'}, xlabel='Réchauffement climatique ΔT [°C]', ylabel='Volume de rétention [m³]'>,
parameter volume_m3 duration_h emptying_h
0 0.0 43.045739 1.000000 3.596135
1 0.5 45.035887 1.166667 3.762397
2 1.0 47.031086 1.166667 3.929080
3 1.5 49.026285 1.166667 4.095763
4 2.0 51.057803 1.333333 4.265481
5 2.5 53.115367 1.333333 4.437374
6 3.0 55.172931 1.333333 4.609267
7 3.5 57.249762 1.500000 4.782770
8 4.0 59.363952 1.500000 4.959394)
Rapport avec prise en compte du changement climatique
Le rapport de synthèse affiche automatiquement la section « changement climatique » lorsque climate_delta_t est non nul :
[19]:
m.climate_delta_t = 2.0
m.get_retention_capacity(25)
print(m.generate_report())
m.climate_delta_t = 0.0 # reset
======================================================================
STORMWATER RETENTION BASIN — SIZING REPORT (SPW methodology)
======================================================================
Locality : Liège (NSI 62063)
Return period : 25 years
----------------------------------------------------------------------
Key Land use C [-] Area [m²]
----------------------------------------------------------------------
parking Impervious Surfaces 0.90 800.0
toitures Water and Roofs 1.00 350.0
trottoirs Drained Paving 0.70 200.0
jardin Grassland 0.15 1500.0
potager Fields 0.25 300.0
boisement Forest 0.05 2000.0
----------------------------------------------------------------------
Total 0.31 5150.0
Weighted area 1610.0
----------------------------------------------------------------------
Infiltration & outflow parameters
----------------------------------------------------------------------
Infiltration area : 150.0 m²
Darcy velocity : 1.00e-05 m/s (36.00 mm/h)
Security factor : 2.0
Infiltration outflow : 0.7500 L/s
Admissible outflow : 5.00 L/s/ha (2.5750 L/s)
Total outflow : 3.3250 L/s
Climate change ΔT : +2.0 °C
Rainfall increase rate : 7 %/°C
Climate factor : 1.14 (×1.14 on rainfall)
======================================================================
RESULTS
======================================================================
Retention capacity : 51.06 m³
Design rainfall duration : 1.33 h
Emptying time : 4.27 h
Specific volume : 9.9 L/m²
======================================================================
10. Factory MockupSPWXLSX.make()
Les sections précédentes montrent la construction pas à pas d’un projet (localité → sous-bassins → paramètres d’infiltration). Une fois la logique bien comprise, on peut utiliser la factory make() pour tout configurer en un seul appel :
m = MockupSPWXLSX.make(
locality=...,
areas={clé: (LandUse.XXX, superficie), ...},
infiltration_area=...,
infiltration_darcy=...,
admissible_outflow=...,
)
Voici le même projet que celui défini dans les sections 2 et 3, reconstruit en une seule instruction :
[20]:
m_fast = MockupSPWXLSX.make(
locality="Liège",
areas={
"parking": (LandUse.IMPERVIOUS_SURFACES, 800),
"toitures": (LandUse.WATER_AND_ROOFS, 350),
"trottoirs": (LandUse.DRAINED_PAVING, 200),
"jardin": (LandUse.GRASSLANDS, 0.15 * UNITS.hectare),
"potager": (LandUse.CULTIVATED_FIELDS, 300),
"boisement": (LandUse.FORESTS, 0.2 * UNITS.hectare),
},
infiltration_area=150,
infiltration_darcy=1e-5,
admissible_outflow=5.0,
)
# Vérification rapide
vol_fast = m_fast.get_retention_capacity(25)
print(f"Volume (factory) : {vol_fast:.2f}")
print(f"Volume (original) : {volume:.2f}")
print(f"Identiques ? {abs(vol_fast.magnitude - volume.magnitude) < 1e-10}")
Volume (factory) : 43.05 meter ** 3
Volume (original) : 43.05 meter ** 3
Identiques ? True
On peut aussi intégrer directement le scénario climatique dans l’appel :
[21]:
m_climate = MockupSPWXLSX.make(
locality="Namur",
areas={
"parking": (LandUse.IMPERVIOUS_SURFACES, 1200),
"toitures": (LandUse.WATER_AND_ROOFS, 500),
"jardin": (LandUse.GRASSLANDS, 0.3 * UNITS.hectare),
},
infiltration_area=200,
infiltration_darcy=5e-6,
admissible_outflow=5.0,
climate_delta_t=2.0,
)
vol_cc = m_climate.get_retention_capacity(25)
print(f"Localité : {m_climate.locality_name}")
print(f"Facteur climatique : ×{m_climate.climate_factor:.2f}")
print(f"Volume de rétention: {vol_cc:.2f}")
print(f"Durée pluie projet : {m_climate.design_rainfall_duration.to('hour'):.2f}")
print(f"Temps de vidange : {m_climate.emptying_time.to('hour'):.2f}")
Localité : Namur
Facteur climatique : ×1.14
Volume de rétention: 71.85 meter ** 3
Durée pluie projet : 2.17 hour
Temps de vidange : 7.00 hour