openBES 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
openbes-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,55 @@
1
+ Metadata-Version: 2.4
2
+ Name: openBES
3
+ Version: 0.1.0
4
+ Summary: Python implementation of the Open Building Energy Simulation (OpenBES) tool.
5
+ Requires-Python: >=3.11
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: pandas
8
+ Requires-Dist: pvlib
9
+ Requires-Dist: numba
10
+ Provides-Extra: dev
11
+ Requires-Dist: line_profiler; extra == "dev"
12
+
13
+ # OpenBES-py
14
+
15
+ [![Unittest](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/unittest.yml/badge.svg)](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/unittest.yml)
16
+ [![ASHRAE 140 Suite](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/test_cases.yml/badge.svg)](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/test_cases.yml)
17
+ [![.github/workflows/package_test.yml](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/package_test.yml/badge.svg)](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/package_test.yml)
18
+
19
+ OpenBES-py is an open-source building energy simulation tool written in Python. It is designed to provide transparent, reproducible, and extensible energy modeling for buildings, supporting research, education, and practical analysis.
20
+
21
+ ## Features
22
+
23
+ - **Modular simulation engine**: Each energy category is implemented as a separate module for clarity and extensibility.
24
+ - **Comprehensive test suite**: All core modules are covered by unit and integration tests.
25
+ - **Standardized test cases**: Planned integration with ASHRAE Standard 140 test cases (see `cases_ashrae_std140_...` directory).
26
+ - **Modern dependency management**: Uses [UV](https://github.com/astral-sh/uv) for fast, reliable Python environment setup (`uv.lock` included).
27
+
28
+ ## Current Status
29
+
30
+ The Python code reproduces the Excel spreadsheet simulation results for the Holywell House specification to at least 6 decimal places.
31
+
32
+ The next step is to validate the Python code against ASHRAE Standard 140 test cases.
33
+
34
+ ## Installation
35
+
36
+ 1. Install [UV](https://github.com/astral-sh/uv) if you do not have it: `pip install uv`
37
+
38
+ 2. Set up a virtual environment (recommended): `uv venv`
39
+
40
+ 3. Install dependencies: `uv sync`
41
+
42
+ 4. Run tests to verify installation: `uv run python -m unittest discover -s tests`
43
+
44
+ ## License
45
+
46
+ The license for this project is under consideration.
47
+
48
+ ## Credits
49
+
50
+ We use Pandas for data manipulation and NumPy for numerical calculations.
51
+
52
+ We use PVLib.iotools for reading EPW (energy plus weather) files.
53
+
54
+ Jensen, A., Anderson, K., Holmgren, W., Mikofski, M., Hansen, C., Boeman, L., Loonen, R. “pvlib iotools — Open-source Python functions for seamless access to solar irradiance data.” Solar Energy, 266, 112092, (2023). DOI: 10.1016/j.solener.2023.112092.
55
+
@@ -0,0 +1,43 @@
1
+ # OpenBES-py
2
+
3
+ [![Unittest](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/unittest.yml/badge.svg)](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/unittest.yml)
4
+ [![ASHRAE 140 Suite](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/test_cases.yml/badge.svg)](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/test_cases.yml)
5
+ [![.github/workflows/package_test.yml](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/package_test.yml/badge.svg)](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/package_test.yml)
6
+
7
+ OpenBES-py is an open-source building energy simulation tool written in Python. It is designed to provide transparent, reproducible, and extensible energy modeling for buildings, supporting research, education, and practical analysis.
8
+
9
+ ## Features
10
+
11
+ - **Modular simulation engine**: Each energy category is implemented as a separate module for clarity and extensibility.
12
+ - **Comprehensive test suite**: All core modules are covered by unit and integration tests.
13
+ - **Standardized test cases**: Planned integration with ASHRAE Standard 140 test cases (see `cases_ashrae_std140_...` directory).
14
+ - **Modern dependency management**: Uses [UV](https://github.com/astral-sh/uv) for fast, reliable Python environment setup (`uv.lock` included).
15
+
16
+ ## Current Status
17
+
18
+ The Python code reproduces the Excel spreadsheet simulation results for the Holywell House specification to at least 6 decimal places.
19
+
20
+ The next step is to validate the Python code against ASHRAE Standard 140 test cases.
21
+
22
+ ## Installation
23
+
24
+ 1. Install [UV](https://github.com/astral-sh/uv) if you do not have it: `pip install uv`
25
+
26
+ 2. Set up a virtual environment (recommended): `uv venv`
27
+
28
+ 3. Install dependencies: `uv sync`
29
+
30
+ 4. Run tests to verify installation: `uv run python -m unittest discover -s tests`
31
+
32
+ ## License
33
+
34
+ The license for this project is under consideration.
35
+
36
+ ## Credits
37
+
38
+ We use Pandas for data manipulation and NumPy for numerical calculations.
39
+
40
+ We use PVLib.iotools for reading EPW (energy plus weather) files.
41
+
42
+ Jensen, A., Anderson, K., Holmgren, W., Mikofski, M., Hansen, C., Boeman, L., Loonen, R. “pvlib iotools — Open-source Python functions for seamless access to solar irradiance data.” Solar Energy, 266, 112092, (2023). DOI: 10.1016/j.solener.2023.112092.
43
+
@@ -0,0 +1,24 @@
1
+ [project]
2
+ name = "openBES"
3
+ version = "0.1.0"
4
+ description = "Python implementation of the Open Building Energy Simulation (OpenBES) tool."
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ dependencies = [
8
+ "pandas",
9
+ "pvlib",
10
+ "numba",
11
+ ]
12
+
13
+ [project.optional-dependencies]
14
+ dev = [
15
+ "line_profiler",
16
+ ]
17
+
18
+ [tool.setuptools.packages.find]
19
+ where = ["src"]
20
+ include = ["openbes*"]
21
+
22
+ [build-system]
23
+ requires = ["setuptools>=61", "wheel", "build"]
24
+ build-backend = "setuptools.build_meta"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,55 @@
1
+ Metadata-Version: 2.4
2
+ Name: openBES
3
+ Version: 0.1.0
4
+ Summary: Python implementation of the Open Building Energy Simulation (OpenBES) tool.
5
+ Requires-Python: >=3.11
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: pandas
8
+ Requires-Dist: pvlib
9
+ Requires-Dist: numba
10
+ Provides-Extra: dev
11
+ Requires-Dist: line_profiler; extra == "dev"
12
+
13
+ # OpenBES-py
14
+
15
+ [![Unittest](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/unittest.yml/badge.svg)](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/unittest.yml)
16
+ [![ASHRAE 140 Suite](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/test_cases.yml/badge.svg)](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/test_cases.yml)
17
+ [![.github/workflows/package_test.yml](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/package_test.yml/badge.svg)](https://github.com/OxfordRSE/OpenBES-py/actions/workflows/package_test.yml)
18
+
19
+ OpenBES-py is an open-source building energy simulation tool written in Python. It is designed to provide transparent, reproducible, and extensible energy modeling for buildings, supporting research, education, and practical analysis.
20
+
21
+ ## Features
22
+
23
+ - **Modular simulation engine**: Each energy category is implemented as a separate module for clarity and extensibility.
24
+ - **Comprehensive test suite**: All core modules are covered by unit and integration tests.
25
+ - **Standardized test cases**: Planned integration with ASHRAE Standard 140 test cases (see `cases_ashrae_std140_...` directory).
26
+ - **Modern dependency management**: Uses [UV](https://github.com/astral-sh/uv) for fast, reliable Python environment setup (`uv.lock` included).
27
+
28
+ ## Current Status
29
+
30
+ The Python code reproduces the Excel spreadsheet simulation results for the Holywell House specification to at least 6 decimal places.
31
+
32
+ The next step is to validate the Python code against ASHRAE Standard 140 test cases.
33
+
34
+ ## Installation
35
+
36
+ 1. Install [UV](https://github.com/astral-sh/uv) if you do not have it: `pip install uv`
37
+
38
+ 2. Set up a virtual environment (recommended): `uv venv`
39
+
40
+ 3. Install dependencies: `uv sync`
41
+
42
+ 4. Run tests to verify installation: `uv run python -m unittest discover -s tests`
43
+
44
+ ## License
45
+
46
+ The license for this project is under consideration.
47
+
48
+ ## Credits
49
+
50
+ We use Pandas for data manipulation and NumPy for numerical calculations.
51
+
52
+ We use PVLib.iotools for reading EPW (energy plus weather) files.
53
+
54
+ Jensen, A., Anderson, K., Holmgren, W., Mikofski, M., Hansen, C., Boeman, L., Loonen, R. “pvlib iotools — Open-source Python functions for seamless access to solar irradiance data.” Solar Energy, 266, 112092, (2023). DOI: 10.1016/j.solener.2023.112092.
55
+
@@ -0,0 +1,23 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/openBES.egg-info/PKG-INFO
4
+ src/openBES.egg-info/SOURCES.txt
5
+ src/openBES.egg-info/dependency_links.txt
6
+ src/openBES.egg-info/requires.txt
7
+ src/openBES.egg-info/top_level.txt
8
+ src/openbes/__init__.py
9
+ src/openbes/simulations/__init__.py
10
+ src/openbes/simulations/base.py
11
+ src/openbes/simulations/building_energy.py
12
+ src/openbes/simulations/climate.py
13
+ src/openbes/simulations/cooling.py
14
+ src/openbes/simulations/geometry.py
15
+ src/openbes/simulations/heating.py
16
+ src/openbes/simulations/hot_water.py
17
+ src/openbes/simulations/lighting.py
18
+ src/openbes/simulations/occupancy.py
19
+ src/openbes/simulations/solar_irradiation.py
20
+ src/openbes/simulations/ventilation.py
21
+ src/openbes/types/__init__.py
22
+ src/openbes/types/dataclasses.py
23
+ src/openbes/types/enums.py
@@ -0,0 +1,6 @@
1
+ pandas
2
+ pvlib
3
+ numba
4
+
5
+ [dev]
6
+ line_profiler
@@ -0,0 +1 @@
1
+ openbes
@@ -0,0 +1,2 @@
1
+ from .simulations.building_energy import BuildingEnergySimulation
2
+ from .types import OpenBESSpecification
File without changes
@@ -0,0 +1,91 @@
1
+ from pandas import DataFrame
2
+
3
+ from ..types import OpenBESSpecification, ENERGY_SOURCES
4
+
5
+
6
+ def month_for_day(day_number_in_year: int) -> int:
7
+ """Calculate the month for a given day number in the year.
8
+ Args:
9
+ day_number_in_year (int): The day number in the year (1-365).
10
+ Returns:
11
+ int: The corresponding month (1-12).
12
+ """
13
+ if day_number_in_year <= 31:
14
+ return 1
15
+ elif day_number_in_year <= 59:
16
+ return 2
17
+ elif day_number_in_year <= 90:
18
+ return 3
19
+ elif day_number_in_year <= 120:
20
+ return 4
21
+ elif day_number_in_year <= 151:
22
+ return 5
23
+ elif day_number_in_year <= 181:
24
+ return 6
25
+ elif day_number_in_year <= 212:
26
+ return 7
27
+ elif day_number_in_year <= 243:
28
+ return 8
29
+ elif day_number_in_year <= 273:
30
+ return 9
31
+ elif day_number_in_year <= 304:
32
+ return 10
33
+ elif day_number_in_year <= 334:
34
+ return 11
35
+ else:
36
+ return 12
37
+
38
+
39
+ # Blank DataFrame of each hour with month info, indexed by day of the year
40
+ HOURS_DF = DataFrame([
41
+ {
42
+ 'month': month_for_day(d),
43
+ 'day': d,
44
+ 'hour': h,
45
+ 'is_daytime': 8 <= h <= 22
46
+ } for d in range(1, 366) for h in range(1, 25)
47
+ ]).set_index(['month', 'day', 'hour'])
48
+
49
+
50
+ class HourlySimulation:
51
+ """
52
+ Base class for hourly simulations.
53
+
54
+ Each instance is initialized with an OpenBESSpecification and contains an _hours property
55
+ that holds a DataFrame representing each hour of the year.
56
+
57
+ Properties will typically add columns to the _hours DataFrame as needed for various calculations,
58
+ and usually return that DataFrame or specific columns from it.
59
+ """
60
+
61
+ spec: OpenBESSpecification
62
+ _hours: DataFrame
63
+
64
+ def __init__(self, spec: OpenBESSpecification):
65
+ self.spec = spec
66
+ self._hours = HOURS_DF.copy()
67
+
68
+
69
+ class EnergyUseSimulation(HourlySimulation):
70
+ """
71
+ Base class for hourly energy use simulations.
72
+
73
+ Child classes should override the energy_use property to return a DataFrame representing
74
+ the energy use in kW for each hour of the year, with a column for each of the ENERGY_SOURCES.
75
+
76
+ The _energy_use property is initialized as a DataFrame of NaNs with the same index as _hours
77
+ and columns for each ENERGY_SOURCES. self.energy_use should populate this DataFrame appropriately.
78
+ """
79
+ def __init__(self, spec: OpenBESSpecification):
80
+ super().__init__(spec)
81
+ self._energy_use = DataFrame(index=self._hours.index, columns=list(ENERGY_SOURCES)).astype(float)
82
+
83
+ @property
84
+ def energy_use(self) -> DataFrame:
85
+ """DataFrame of energy use in kW for each hour of the year, with a column for each ENERGY_SOURCES.
86
+ """
87
+ raise NotImplementedError("Child classes must implement the energy_use property.")
88
+
89
+ @property
90
+ def annual_energy_use(self) -> DataFrame:
91
+ return self.energy_use.sum().sum()
@@ -0,0 +1,102 @@
1
+ import logging
2
+ from typing import Dict
3
+
4
+ from pandas import DataFrame
5
+
6
+ from .base import EnergyUseSimulation
7
+ from .climate import ClimateSimulation
8
+ from .cooling import CoolingSimulation
9
+ from .geometry import BuildingGeometry
10
+ from .heating import HeatingSimulation
11
+ from .hot_water import HotWaterSimulation
12
+ from .lighting import LightingSimulation
13
+ from .occupancy import OccupationSimulation
14
+ from .ventilation import VentilationSimulation
15
+ from ..types import (
16
+ OpenBESSpecification,
17
+ ENERGY_USE_CATEGORIES,
18
+ ENERGY_SOURCES,
19
+ )
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+ class BuildingEnergySimulation(EnergyUseSimulation):
24
+ """
25
+ A building energy simulation takes a building specification and model parameters and produces a report
26
+ on the energy use of the building.
27
+ """
28
+
29
+ def __init__(
30
+ self,
31
+ spec: OpenBESSpecification,
32
+ hot_water: HotWaterSimulation = None,
33
+ geometry: BuildingGeometry = None,
34
+ occupancy: OccupationSimulation = None,
35
+ lighting: LightingSimulation = None,
36
+ ventilation: VentilationSimulation = None,
37
+ climate: ClimateSimulation = None,
38
+ cooling: CoolingSimulation = None,
39
+ heating: HeatingSimulation = None,
40
+ ):
41
+ super().__init__(spec)
42
+ self._standby_energy_use = self._energy_use.copy()
43
+ self._standby_energy_use[ENERGY_SOURCES.Electricity] = (spec.building_standby_load * 12) / len(self._energy_use)
44
+ self._other_energy_use = self._energy_use.copy()
45
+ self._other_energy_use[ENERGY_SOURCES.Electricity] = (spec.other_electricity_usage * 12) / len(self._energy_use)
46
+ self._other_energy_use[ENERGY_SOURCES.Natural_gas] = (spec.other_gas_usage * 12) / len(self._energy_use)
47
+ self.hot_water = hot_water or HotWaterSimulation(self.spec)
48
+ self.geometry = geometry or BuildingGeometry(self.spec)
49
+ self.occupancy = occupancy or OccupationSimulation(self.spec, geometry=self.geometry)
50
+ self.lighting = lighting or LightingSimulation(self.spec, occupancy=self.occupancy)
51
+ self.ventilation = ventilation or VentilationSimulation(
52
+ self.spec,
53
+ occupancy=self.occupancy,
54
+ geometry=self.geometry
55
+ )
56
+ self.climate = climate or ClimateSimulation(
57
+ spec,
58
+ geometry=self.geometry,
59
+ occupancy=self.occupancy,
60
+ lighting=self.lighting,
61
+ ventilation=self.ventilation,
62
+ )
63
+ self.cooling = cooling or CoolingSimulation(
64
+ spec,
65
+ geometry=self.geometry,
66
+ occupancy=self.occupancy,
67
+ lighting=self.lighting,
68
+ ventilation=self.ventilation,
69
+ climate=self.climate,
70
+ )
71
+ self.heating = heating or HeatingSimulation(
72
+ spec,
73
+ geometry=self.geometry,
74
+ occupancy=self.occupancy,
75
+ lighting=self.lighting,
76
+ ventilation=self.ventilation,
77
+ climate=self.climate,
78
+ )
79
+
80
+ @property
81
+ def energy_use_by_category(self) -> Dict[ENERGY_USE_CATEGORIES, DataFrame]:
82
+ """Heating energy use in kWh for each hour of the year for each ENERGY_SOURCE for each ENERGY_USE_CATEGORY.
83
+ """
84
+ return {
85
+ ENERGY_USE_CATEGORIES.Others: self._other_energy_use,
86
+ ENERGY_USE_CATEGORIES.Building_standby: self._standby_energy_use,
87
+ ENERGY_USE_CATEGORIES.Lighting: self.lighting.energy_use,
88
+ ENERGY_USE_CATEGORIES.Hot_water: self.hot_water.energy_use,
89
+ ENERGY_USE_CATEGORIES.Ventilation: self.ventilation.energy_use,
90
+ ENERGY_USE_CATEGORIES.Cooling: self.cooling.energy_use,
91
+ ENERGY_USE_CATEGORIES.Heating: self.heating.energy_use,
92
+ }
93
+
94
+ @property
95
+ def energy_use(self) -> DataFrame:
96
+ """Total energy use in kWh for each hour of the year for each ENERGY_SOURCE.
97
+ """
98
+ if self._energy_use.isna().any().any():
99
+ self._energy_use.fillna(0, inplace=True)
100
+ for category_use in self.energy_use_by_category.values():
101
+ self._energy_use = self._energy_use.add(category_use, fill_value=0.0)
102
+ return self._energy_use