Skip to main content

Thermal simulation of opaque constructive systems (walls and roofs) from EPW data — 1D and 2D

Project description

EnerHabitat

PyPI version Python versions License: MIT Documentation

EnerHabitat is a Python package for the thermal simulation of opaque constructive systems (walls and roofs) driven by EPW weather data. It solves the time-dependent heat conduction equation across multi-layer systems — in 1D for homogeneous layers (System) and in 2D for units that are heterogeneous across their width, such as concrete hollow-block walls and joist-and-block (vigueta y bovedilla) roofs (System2D) — and produces indoor temperatures and air-conditioning energy demands for an average day of a chosen month.

📖 Documentation

Full documentation lives at https://ener-habitat.github.io/EnerHabitat/:

Overview

EnerHabitat models the heat transfer through opaque constructive systems without windows, ventilation, infiltration or internal heat gains. Each layer is described by a material name and three properties: thermal conductivity k (W/(m·K)), density rho (kg/m³) and specific heat c (J/(kg·K)) — supplied by a user materials.ini file (no defaults are bundled).

Given an EPW file and a constructive system, EnerHabitat computes the outdoor (Ta), sun–air (Tsa), indoor (Ti) and neutrality (Tn) temperatures, the solar irradiances (Ig GHI, Ib DNI, Id DHI and the plane-of-array Is) and the energy demands over the average day of the selected month.

Theoretical background (summary)

The temperature field in each layer obeys the 1D time-dependent heat conduction equation,

$$ \rho, c_p, \frac{\partial T}{\partial t} = k, \frac{\partial^2 T}{\partial x^2}, $$

with flux continuity at layer joints. At the outdoor surface the boundary condition uses the sun–air temperature, which lumps convection, absorbed solar radiation and the long-wave sky exchange:

$$ T_{sa} = T_a + \frac{a, I_s}{h_o} - RF, $$

with a the solar absorptance, $I_s$ the irradiance on the tilted surface (computed with pvlib) and $RF$ decreasing linearly from 3.9 °C at tilt = 0 (roof) to 0 at tilt = 90 (wall). At the indoor surface the system exchanges heat with the indoor air, and two solution modes exist:

  • Free-runningsolve(): the indoor air is a lumped thermal mass whose temperature Ti evolves freely; the daily energy delivered to it is reported as energy_transfer.
  • Air-conditionedsolveAC(): Ti is held at the neutrality temperature of the adaptive comfort model of Humphreys & Nicol, $T_n = 0.54,\overline{T_a} + 13.5$ °C, and the required cooling_energy and heating_energy are reported. (The average-day data also includes the comfort-zone half-width DeltaTn, after Morillón, for comfort analyses.)

For 2D systems, System2D solves the same problem on the unit's cross-section, adding the cavity physics: radiation between the cavity walls (solved as a radiosity enclosure) and temperature-dependent Nusselt convection with a lumped cavity-air node.

The equations are discretised with implicit finite control volumes and solved with the TDMA; the average day is iterated until the solution is periodic. Full derivations, boundary conditions, convergence criteria and the validation record are in the theory pages.

Installation

pip install enerhabitat

With uv:

uv add enerhabitat

EnerHabitat requires Python ≥ 3.10. The section inspector plots are an optional extra: pip install enerhabitat[viz].

Quickstart

EnerHabitat ships no materials: create a materials.ini in your working directory (or point eh.config.file to one) before running anything. A minimal file for this example:

[Adobe]
k   = 0.58    # W/(m·K)
rho = 1500    # kg/m³
c   = 1480    # J/(kg·K)
import enerhabitat as eh

# 1) Materials file (required — no defaults are bundled)
eh.config.file = "./materials.ini"

# 2) Location from an EPW file
loc = eh.Location("./epw/example.epw")

# 3) Define the constructive system
wall = eh.System(location=loc)
wall.azimuth = 90                    # east-facing
wall.absortance = 0.3
wall.layers = [("Adobe", 0.20)]      # outside → inside

# 4) Average day and solar inputs
loc.meanDay(month=5, year=2025)
wall.Tsa()

# 5) Solve (free-running); Tsa() and solve() share the same time grid,
#    so results concatenate directly.
ti = wall.solve()
print(wall.energy_transfer)          # J/(m²·day)

For a wall with air conditioning, call wall.solveAC() and read wall.cooling_energy / wall.heating_energy.

2D systems

System2D is used like System (see the API page for the differences); its layers list contains exactly one 2D element — a HollowBlock (walls, tilt = 90) or a Slab (joist-and-block roofs, tilt = 0). The materials named below (Concreto, Mortero, Yeso) must also be defined in your materials.ini (see the full example set):

block = eh.HollowBlock(
    material   = "Concreto",
    emissivity = 0.9,
    geometry   = {"web": 0.02, "block_width": 0.16,
                  "cover_top": 0.02, "cavity": 0.08, "cover_bottom": 0.02},
)

wall = eh.System2D(eh.Location("./epw/example.epw"))
wall.tilt = 90
wall.azimuth = 90
wall.absortance = 0.6
wall.layers = [("Mortero", 0.02), block, ("Yeso", 0.01)]
wall.location.meanDay(month=5, year=2025)
wall.Tsa()
ti = wall.solve()

⏱ A 2D solve at the default mesh (80×160) takes ~10–20 minutes (the 1D ones take seconds). For a quick smoke test, reduce the mesh first — e.g. eh.config2d.nx, eh.config2d.ny = 24, 60 — and check wall.converged.

All the examples — the full 1D/2D × free-running/AC matrix, the joist-and-block roof, and the to-scale section inspector — are in the Usage page.

API at a glance

Object Purpose Key methods / attributes
Location Reads an EPW file, builds the average day meanDay(month, year)
System 1D multilayer wall/roof layers, Tsa(), solve(), solveAC(), energy_transfer, cooling_energy, heating_energy, days, converged
System2D 2D heterogeneous wall/roof mirror of System (see the API page for the differences), plus preview(), section_report(), solve_dataframe, Tfield
HollowBlock / Slab The 2D element inside System2D.layers material(s), fill_type (Fill.AIR/Fill.SOLID), geometry
config Global parameters file, La, Nx, ho, hi, dt (fixed)
config2d 2D mesh & convergence nx, ny, tol_inner, tol_day, max_days, max_inner

Defaults for ho (13) and hi (8.1 W/(m²·K)) are the NOM-008/020-ENER values (hi is the vertical-surface value, applied to all orientations); dt is fixed at 10 s (see why). Full reference: API page.

Dependencies

Direct dependencies: numba and pvlib (numpy, pandas and pytz come with them). Optional: matplotlib via enerhabitat[viz].

How to cite

If you use EnerHabitat in academic work, please cite the reference paper:

Barrios, G., Casas, J.M., Huelsz, G., Rojas, J. (2016). Ener-Habitat: An online numerical tool to evaluate the thermal performance of homogeneous and non-homogeneous envelope walls/roofs. Solar Energy 131, 296–304. https://doi.org/10.1016/j.solener.2015.12.017

@article{Barrios2016,
  author  = {Barrios, G. and Casas, J.M. and Huelsz, G. and Rojas, J.},
  title   = {Ener-Habitat: An online numerical tool to evaluate the thermal
             performance of homogeneous and non-homogeneous envelope walls/roofs},
  journal = {Solar Energy},
  volume  = {131},
  pages   = {296--304},
  year    = {2016},
  doi     = {10.1016/j.solener.2015.12.017}
}

The repository also ships a CITATION.cff (GitHub's Cite this repository button) covering the software itself.

Authors

Developed at the Instituto de Energías Renovables, UNAM.

Source code: https://github.com/Ener-Habitat/EnerHabitat · Issues: https://github.com/Ener-Habitat/EnerHabitat/issues

License

Released under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

enerhabitat-0.3.0.tar.gz (4.9 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

enerhabitat-0.3.0-py3-none-any.whl (49.8 kB view details)

Uploaded Python 3

File details

Details for the file enerhabitat-0.3.0.tar.gz.

File metadata

  • Download URL: enerhabitat-0.3.0.tar.gz
  • Upload date:
  • Size: 4.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for enerhabitat-0.3.0.tar.gz
Algorithm Hash digest
SHA256 8ccb63f22822ee6a2a93b0c232374d7f1fd9ff2a82fc795591a8e36485781a3c
MD5 bbae4b624aff096eea09f58984aa524b
BLAKE2b-256 f5a65f49cc79b1691a2e29c4fce50e822af82bbb7c589eb72d952b8b284efa7c

See more details on using hashes here.

File details

Details for the file enerhabitat-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: enerhabitat-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 49.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for enerhabitat-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a80e82da09f9a0a95899a7645b9d8c69214cf590c38998076e45c27a19e635c3
MD5 fc6bc078d26131848fb3df4a698f3b99
BLAKE2b-256 c5f3a7f2bb38e4078d6cb2c219b2eecb4242e6009ac4517efa5daba0ab25e750

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page