Skip to main content

Paquete instalable para EnerHabitat

Project description

EnerHabitat

PyPI version Python versions License: MIT

EnerHabitat is a Python package for the thermal simulation of opaque constructive systems (walls and roofs) driven by EPW weather data. It solves the one-dimensional, time-dependent heat conduction equation across multi-layer systems and produces hourly indoor temperatures and air-conditioning energy demands for an average day of a chosen month.

Contents

Overview

EnerHabitat models the heat transfer through opaque constructive systems without windows, ventilation or infiltration. Each layer of the system is described by a material name and three thermal properties:

  • thermal conductivity k (W/m·K)
  • density rho (kg/m³)
  • specific heat c (J/kg·K) — written c_p in the heat equation below

These three names (k, rho, c) are the exact keys expected in materials.ini; they are case-sensitive and Greek letters are not accepted.

Given an EPW file and a constructive system, EnerHabitat computes:

Symbol Description
Ta Outdoor ambient temperature
Tsa Sun-air temperature
Ti Indoor temperature
Tn Adaptive comfort (neutral) temperature
Ig Global horizontal irradiance
Ib Direct normal irradiance
Id Diffuse horizontal irradiance
Is Solar irradiance on the tilted surface

Theoretical background

EnerHabitat solves the 1-D, time-dependent heat conduction equation across the constructive system:

              ∂T          ∂²T
    ρ   c_p   ──  =  k   ────
              ∂t          ∂x²

The exterior boundary condition uses the sun-air temperature, which combines convection, short-wave solar gain and long-wave radiative losses:

    T_sa = T_o + (I_s   a) / h_o + RF

where:

  • T_o — outdoor ambient temperature
  • I_s — solar irradiance incident on the surface
  • a — external solar absorptance
  • h_o — outdoor convective heat transfer coefficient
  • RF — long-wave radiative loss factor (°C). EnerHabitat uses RF = -3.9 °C for horizontal surfaces (tilt = 0, e.g. a roof, where the surface sees the cold sky) and RF = 0 °C for vertical walls (tilt = 90).

The equation is discretised with finite control volumes and solved with the TDMA (Tri-Diagonal Matrix Algorithm). The simulation runs over an average day of a selected month — built from the EPW — and is iterated until a periodic (oscillatory) steady state is reached.

Two solution modes are available:

  • Free-runningsolve(): no air conditioning is applied; the indoor temperature follows the dynamics of the constructive system.
  • Air-conditionedsolveAC(): the indoor temperature is held at a comfort setpoint derived from the Humphreys & Nicol adaptive comfort model combined with Morillón's comfort-zone amplitude proposal. EnerHabitat then applies the cooling or heating needed at every time step to keep Ti at that setpoint, and reports the resulting cooling_energy and heating_energy demands.

Installation

pip install enerhabitat

With uv (we love it and warmly encourage its use — it is fast, reproducible, and our recommended way to install EnerHabitat):

uv add enerhabitat

EnerHabitat requires Python ≥ 3.10.

Recommended folder structure

materials.ini is required — EnerHabitat ships with no default materials, so you must provide this file (see Materials for its format).

project/
├── main.py
├── materials.ini      # Material properties (REQUIRED — user-provided)
└── epw/
    ├── ...
    └── example.epw

Key concepts

  • Location reads an EPW file and computes the average day with meanDay().
  • System combines a Location and a list of layers and computes Tsa(), solve() and solveAC().
  • config is a global instance whose attributes (materials file, discretisation, convection coefficients, time step) affect every subsequent computation.

Quickstart

EnerHabitat does not ship with pre-loaded materials. Before running anything, create a materials.ini file (see Materials) in your working directory or point eh.config.file to its location.

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
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
ti = wall.solve()

Workflow

To simulate a wall (or roof) you need to:

  1. Geolocate it — pass an EPW file to Location.
  2. Orient it — set azimuth (and tilt if needed).
  3. Define its color — set absortance.
  4. Define its layers — set layers from outside to inside.
  5. Choose the period — call location.meanDay(month, year).
  6. Compute Tsa(), then choose one solver:
    • solve()without air conditioning (free-running): the indoor temperature Ti evolves freely with the dynamics of the constructive system.
    • solveAC()with air conditioning: the indoor temperature is held at a comfort setpoint and the cooling/heating energy required is reported.

Both solve() and solveAC() return pandas DataFrames indexed by time of day.

Examples

Two-layer system without air conditioning

import enerhabitat as eh
import pandas as pd

epw_file = "epw/MEX_CAM_Campeche-Ignacio.766961_TMYx.epw"

wall = eh.System(eh.Location(epw_file))
wall.azimuth = 90
wall.absortance = 0.3
wall.layers = [("Mortero", 0.025), ("Ladrillo", 0.10)]
wall.location.meanDay(month=5, year=2025)
wall.Tsa()

# Free-running solution
data = wall.solve()

# Attach Tsa to the result. Note that Tsa is a function of color, tilt,
# orientation, month and location, so it must be recomputed whenever any of
# those inputs change.
data = pd.concat([data, wall.Tsa().asfreq("10min")], axis=1)

Two-layer system with air conditioning

import enerhabitat as eh
import pandas as pd

epw_file = "epw/MEX_CAM_Campeche-Ignacio.766961_TMYx.epw"

wall = eh.System(eh.Location(epw_file))
wall.azimuth = 90
wall.absortance = 0.3
wall.layers = [("Mortero", 0.025), ("Ladrillo", 0.10)]
wall.location.meanDay(month=5, year=2025)
wall.Tsa()

# Air-conditioned solution: setpoint at the upper comfort bound
data = wall.solveAC()
data = pd.concat([data, wall.Tsa().asfreq("10min")], axis=1)

# Cooling and heating energy demands, in J/(m²·day) over one average day
print(wall.cooling_energy, wall.heating_energy)

API reference

import enerhabitat as eh

Location

loc = eh.Location("./epw/example.epw")

Attributes

The EPW path is stored in file. The following are read-only and recovered from the EPW header — change file to update them:

  • citystr, city from the EPW header
  • latitudefloat, degrees
  • longitudefloat, degrees
  • altitudefloat, metres
  • timezonepytz.timezone
loc.file = "./epw/other.epw"

Methods

  • meanDay(month, year) — average-day DataFrame (Ta, Ig, Ib, Id, Tn)
  • copy() — returns a copy of the instance
  • info() — prints instance attributes
  • flag()dict with metadata of the last meanDay() call
loc.meanDay(month=6, year=2020).info()
loc.info()
print(loc.flag()["date"])

System

loc = eh.Location("./epw/example.epw")
wall = eh.System(location=loc)

Attributes

  • location — associated Location

  • tiltfloat, degrees from horizontal (0 = roof, 90 = vertical wall)

  • azimuthfloat, surface azimuth in degrees (pvlib convention, clockwise from north):

    Direction Azimuth
    North 0
    East 90
    South 180
    West 270
  • absortancefloat in [0, 1]

  • layerslist[tuple[str, float]] of (material, thickness_m), ordered from outside to inside

wall.location = loc_2
wall.tilt = 0
wall.azimuth = 45
wall.absortance = 0.3

wall.layers = [("Adobe", 0.10), ("Acero", 0.05), ("Ladrillo", 0.02)]

wall.add_layer("Mortero", 0.20)   # appended at the inside
wall.remove_layer(2)              # removes layer at index 2

Read-only result attributes (all expressed in J/(m²·day) — energy per unit surface area, accumulated over one converged average day):

  • energy_transfer — total energy transferred to the indoor side from solve()
  • heating_energy — heating demand from solveAC()
  • cooling_energy — cooling demand from solveAC()

Units: hi · Δt · ΔT with hi in W/(m²·K), Δt in seconds and ΔT in K yields J/m², and the loop accumulates these contributions over the 24 h of the average day, so the reported value is J/(m²·day). Divide by 3600 to get Wh/(m²·day) or by 3.6e6 to get kWh/(m²·day).

Methods

  • Tsa() — sun-air temperature and Is from Location.meanDay()
  • solve() — indoor temperature Ti (free-running)
  • solveAC() — cooling and heating energy with constant indoor setpoint
  • copy() — returns a copy of the instance
  • info() — prints attributes
  • flag() — reports whether the cached value was recomputed
wall.Tsa().info()

ti = wall.solve()
energy = wall.energy_transfer

wall.solveAC()
c_energy = wall.cooling_energy
h_energy = wall.heating_energy

Note: Tsa depends on absortance (color), tilt, azimuth (orientation), meanDay (month) and Location. It must be recomputed whenever any of these inputs change. Attach it to a result DataFrame with data = pd.concat([data, wall.Tsa().asfreq("10min")], axis=1).

Config (global)

config is a global singleton that stores parameters shared by every Location and System. Changing it affects all subsequent computations.

Attributes (defaults shown; all are writable)

Attribute Default Description
file "materials.ini" Path to the .ini file with material properties
La 2.5 m Length of the fictional indoor space
Nx 200 Number of control volumes used to discretise the system
ho 13 W/(m²·K) Outdoor convective heat transfer coefficient
hi 8.6 W/(m²·K) Indoor convective heat transfer coefficient
dt 600 s Time step

The default values for ho and hi are those prescribed by the Mexican energy efficiency standards NOM-020-ENER and NOM-008-ENER for the thermal envelope of buildings — both norms specify the same coefficients. They can be overridden at any time:

eh.config.file = "./materials.ini"

# Inspect current values
eh.config.ho      # 13.0
eh.config.hi      # 8.6

# Other configuration parameters
eh.config.La = 2.0
eh.config.Nx = 300
eh.config.dt = 60

# Override the NOM-prescribed coefficients (NOM defaults are not enforced)
eh.config.ho = 12
eh.config.hi = 8.3

# Restore all defaults at any time (the NOM values for ho/hi included)
eh.config.reset()

config.materials is a read-only dict keyed by material name:

adobe = eh.config.materials["Adobe"]
adobe.k     # W/m·K
adobe.rho   # kg/m³
adobe.c     # J/kg·K

Methods

  • info() — prints current config values
  • to_dict() — returns parameters as a dict
  • reset() — restores default values
  • materials_list() — list of material names defined in file
  • materials_dict() — dict of material properties

Materials

EnerHabitat does not bundle any default materials. You must supply a materials.ini file — by default the package looks for materials.ini in the current working directory; otherwise set eh.config.file to the path you want to use.

Material properties are declared in an .ini file, with the material name as the section header and k, rho and c as keys:

[concrete]
k   = 1.35   # Thermal conductivity, W/m·K
rho = 1800   # Density, kg/m³
c   = 1000   # Specific heat, J/kg·K

[adobe]
k   = 0.58
rho = 1500
c   = 1480

Point config.file to a different file when you need to switch material sets:

eh.config.file = "./config/new_materials.ini"

If config.file points at a missing file, EnerHabitat will report Error: <path> not found and materials will be empty — System.solve() will fail because the layer materials cannot be resolved.

Dependencies

Direct dependencies (declared in pyproject.toml):

Pulled in transitively and used internally:

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.1.9.tar.gz (66.0 kB view details)

Uploaded Source

Built Distribution

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

enerhabitat-0.1.9-py3-none-any.whl (19.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: enerhabitat-0.1.9.tar.gz
  • Upload date:
  • Size: 66.0 kB
  • 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.1.9.tar.gz
Algorithm Hash digest
SHA256 5b10cf196cc15d1202a6cd76d8299e7ff469f5cbd339019839b21a17c5ed1d58
MD5 2a1b5277a3190cc92ddfae2de61d643d
BLAKE2b-256 086b605233e3a416b4dd0271783a0ee8e978b035759c6ef74f1d2f79f6048b05

See more details on using hashes here.

File details

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

File metadata

  • Download URL: enerhabitat-0.1.9-py3-none-any.whl
  • Upload date:
  • Size: 19.0 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.1.9-py3-none-any.whl
Algorithm Hash digest
SHA256 df06a92a697a7876f267945ae6183483ee44831197e047a18485194167dd35f0
MD5 cc95ad2d87d8f742f5050548c0799880
BLAKE2b-256 5c51485315663347ae1a4340cf9a370a6ef10838c3df08a79385472e74649172

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