Building Energy Management System (BEMS) implementations for the Honda R&D Europe facility in Offenbach am Main, Germany, built using the cosimos framework.
This repository supports the research of the PhD thesis Machine Learning Augmented Model Predictive Control for Building Energy Management Systems.
The Honda facility in Offenbach am Main is a medium-sized corporate building (constructed between 1990 and 1992) with a footprint of approximately 13,000 m². It houses:
- Offices (ground and upper floors)
- Workshops
- Server rooms (O4 & CIS)
- Emission laboratory
- Reception area
For this thesis, we consider the following energy systems and thermal zoning:
- Electricity Supply: Four medium-to-low-voltage transformers operating in two parallel pairs.
- Heating:
- Gas-fired boiler: 1,500 kW thermal capacity
- Combined Heat and Power (CHP): 199 kW electrical / ~294 kW thermal capacity
- Cooling: Three water chillers with a combined capacity of 1,550 kW.
- Solar PV: Six panel groups (varied orientation and slope) totaling 749 kWp, installed on the roof and parking-canopy.
- Energy Storage: A 98 kWh second-life battery (from repurposed EV cells).
- EV Charging: Multiple charging stations for associate vehicles (not modeled in this thesis).
The central HVAC system serves nine distinct thermal zones (see Figure 3.1):
- Emission Laboratory (Zone 1)
- Workshops (Zone 2)
- Ground-Floor Offices (Zone 3)
- Upper-Floor Offices (Zone 4)
- Ground-Floor Design Studio (Zone 5)
- Upper-Floor Design Studio (Zone 6)
- Reception (Zone 7)
- Server Room O4 (Zone 8)
- Server Room CIS (Zone 9)
To get going, first checkout the cosimos simulation framework repository
Configure the path to the cosimos framework in pyproject.toml
If you are using uv (which you should), then simply run uv sync.
The dependencies in pyproject.toml reflect the state which is guaranteed to reproduce the PhD results.
They are not strict. from other experiments, python 3.12 works just fine, as do newer versions of cvxpy and gurobipy
the only issue that I did encounter was with more recent versions of xgboost, when loading stored regressors.
I simply pickled the xgboost regressors, which is kinda a big no no, since compatibility between versions is not guaranteed. instead, xgboost has its own API for this, which I did not use, same for torch/lightning. in retrospect, not the smartest move.
Before being able to run any MPC simulations, make sure you either have a valid Gurobi license (and have set it up by setting the GRB_LICENSE_FILE environment variable to point to a valid license file).
Alternatively you can update cvxpy to at least 1.6, which provides the QP solver Clarabel, which is pretty solid. If you don't want to set the solver manually in each simulation, update EMSConfig and set the default value of the solver attribute to "Clarabel" or cp.CLARABEL, i.e.
class EMSConfig:
... a billion fields ...
solver: str = cp.CLARABEL # line 111You need to be on Windows to run the digital twin simulations, as the FMUs have only been compiled for Windows. All other scripts and simulations (which aren't that many though) do not require any special licenses and can be run on any OS. The FMUs are not included, see the note down below in the Models section.
All controllers live under src/bems/controllers/.
- Full System Controllers (
full.py)- NoNegotiationHierarchicalController
Hierarchical OCP split into:- Aggregator (
aggregator.py): Aggregates thermal zones (2 zones, full building, server zones), models thermo-electric coupling, and computes energy budgets & temperature setpoints. - Distributor (
distributor.py): Receives budgets/setpoints, distributes them to best match control objectives.
- Aggregator (
- HierarchicalController
Adds negotiation:- Aggregator proposes budget & setpoint.
- Distributor computes extra budget needed + expected performance loss (EPL).
- Aggregator accepts a portion (0 ≤ p(k) ≤ 1) of extra budget.
- Distributor finalizes distribution.
Note: EPL is approximated to avoid re-solving the OCP.
- ExactEPLHierarchicalController
Similar to above but computes EPL exactly by running the distributor twice (with/without extra budget) and comparing thermal performance. Implemented for testing only.
- NoNegotiationHierarchicalController
- MonolithicController
Monolithic MPC model of all 9 thermal zones + thermo-electric coupling. Serves as baseline in journal paper and main controller in conference work & thesis Ch. 7. - RBCController
Rule-based control:- Deadbeat proportional for non-server zones (1–7) with thermal limits.
- Deadband + deadbeat for server zones (8, 9).
- Splits heating demand between CHP and boiler.
- Peak shaving logic.
- SimpleRBCController
Simplified deadband proportional control for heating/cooling with the same heat-split and peak-shaving rules asRBCController.
Note: All MPC controllers use their own
OptimizationModel(src/bems/helpers/interface.py), encapsulating state-space models. Partial controllers inaggregator.pyanddistributor.pywere prototypes only.
There are plenty of models to evaluate the BEMS approaches (i.e. controllers). there are simple linear (state-space) models for general testing of controller feasbility, and full fledged digital twin models for actually deriving research results.
Linear full facility model (src/bems/models/full.py)
Contains the full state-space model of the facility with all 9 thermal zones and all electrical components considered for the PhD research. This model is used as internal_model for the all controllers, to calculate the state predicted by the controller. The residual errors which are a key element in the thesis are then calculated as the difference between this expected state and the actual state realized by the digital twin model (see below). This could have been implemented differently, but that's what it is now.
Reduced Aggregator/Distributor models for testing (aggregator.py and distributor.py)
State space models used for testing the stand-alone aggregator and distributor controllers/OCPs. They were not used for producing research results.
Digital Twin Models (src/bems/models/digital_twin/)
Models crucial for the PhD research - detailed digital twin models of the facility, originally implemented in SimulationX.
- Interface:
model.pyexposesDigitalTwinModel→ wraps FMUs. - FMUs (
model/): FMU binaries.
FMUs binaries are not included in this repository due to proprietary licenses. To request access, contact
tobias.rodemann@honda-ri.de
Core of the thesis: augmenting MPC with residual-error estimation.
- Controllers include an
epsilonparameter for predicted residuals, supplied via aDataSource. - OnlineCompensator instances call ML models to estimate residuals across the horizon. these are added as (additive) disturbances in the OCP. This significantly improves control performance.
- The general residual estimation framework is quite general. Only the
OnlineCompensatorand training data-prep utilities are building specific and can be adapted/replaced by analogous structures for new buildings quite easily.
Frameworks for fitting Physically Consistent Neural Networks (PCNNs) and purely linear models:
- PCNNs combine linear system blocks with MLPs for residuals. This approach was adopted (and adapted a lot) from Di Natale et al. 2023, "Towards scalable physically consistent neural networks: An application to data-driven multi-zone thermal building models".
- Also supports purely classical numerical optimization without residual models.
The main publication resulting from this code is the PhD Thesis:
Machine Learning Augmented Model Predictive Control for Building Energy Management Systems
@PhdThesis{engel2025machine,
author = {Jens Engel},
school = {Technical University Darmstadt},
title = {Machine Learning Augmented Model Predictive Control for Building Energy Management Systems},
year = {2025},
month = jun,
doi = {https://doi.org/10.26083/tuprints-00030032},
language = {en},
}
Apart from that, there are the following publications:
@InProceedings{engel2024evaluating,
author = {Jens Engel and Thomas Schmitt and Tobias Rodemann and J\"{u}rgen Adamy},
booktitle = {2024 IEEE PES Innovative Smart Grid Technologies Europe (ISGT Europe)},
title = {Evaluating the Impact of Data Availability on Machine Learning-augmented {MPC} for a Building Energy Management System},
year = {2024},
doi = {10.1109/ISGTEUROPE62998.2024.10863763}
}
@Article{engel2024hierarchical,
author = {Jens Engel and Thomas Schmitt and Tobias Rodemann and J\"{u}rgen Adamy},
journal = {Applied Energy},
title = {Hierarchical {MPC} for Building Energy Management: Incorporating Data-Driven Error Compensation and Mitigating Information Asymmetry},
year = {2024},
doi = {https://doi.org/10.1016/j.apenergy.2024.123780},
}
The data used for simulation was retrieved from a monitoring setup at the facility. A curated version of the entire monitoring data, which extends beyond what was used here, can be found here: Dryad: A real-world energy management data set from a smart company building for optimization and machine learning
There is also a paper outlining the data curation and monitoring setup: Scientific Data: A Real-World Energy Management Dataset from a Smart Company Building for Optimization and Machine Learning
A more detailed explanation of what's in each directory can be found below.
.
├── data/ # Simulation data & profile-generation scripts
│ ├── profiles/ # Input profiles (load, PV, weather) from scenarios
│ └── scenarios/ # FMU scenario definitions for co-simulation
├── simulations/ # All simulation workflows
│ ├── common/ # Shared utilities (KPI calc, plotting, benchmarking)
│ ├── digital_twin/ # Controller vs. digital-twin FMU simulations
│ ├── model_fitting/ # Benchmark fitted models + residual estimation
│ └── retraining/ # Periodic retraining simulation workflows
├── src/ # Primary code packages
│ ├── bems/ # BEMS controllers, models & helpers
│ ├── error_compensation/ # Residual-estimation framework & interfaces
│ └── model_fitting/ # Framework for numerical and PCNN model fitting
└── playground/pcnn/ # PCNN fitting experiments for thesis chapter 7- data:
contains any non-code data used for simulations, and scripts to produce simulation profiles from SimulationX simulation profiles
- profiles:
simulation profiles used as data sources for simulations. calendar year data of electrical building load, available PV data, ambient temperature, server electrical loads. Derived from
scenariosusing create_profile_from_scenario.py*_new_fmu.csvare associated with theMPC_FMU_corrected_240909andMPC_FMU_corrected_240924FMU versions. behavior of hvac toggle times changed, requiring updatedP_demseries (= electrical consumption of building) in profiles
- scenarios:
These scenario files used by FMUs for simulation, the
cosimoscontrollers use the derivedprofiles. Data is based on non-corrected data published in
- profiles:
simulation profiles used as data sources for simulations. calendar year data of electrical building load, available PV data, ambient temperature, server electrical loads. Derived from
- simulations:
contains all (and more) simulation scripts to perform all simulations needed to create results for analysis scripts.
- common: scripts and functions used commonly by other simulation scripts, like KPI calculation, plotting, but also scripts for performing benchmarking or periodic retraining simulations (= retraining)
- benchmarking:
simulations to evaluate the rapid EMS benchmarking PoC (see
git:EnergyManagement/code/ems-benchmarking) - digital_twin:
simulations running controllers against digital twin FMUs. used for general development and hierarchical MPC journal paper. Journal scripts:
- year_2021_hierarchical_no_neg.py: Hierarchical MPC without negotiation
- year_2021_hierarchical_no_neg_comp.py: Hierarchical MPC without negotiation but with residual estimations
- year_2021_hierarchical_comp.py: Hierarchical MPC with negotiation and residual estimation
- year_2021_monolithic_comp_equiv_hierarchical.py: Monolithic implementation equivalent to hierarchical MPC (in terms of cost functions) with residual estimation
- model_fitting: simulations for benchmarking fitted models (classic and PCNN) + residual estimation vs. classic augmented models. used for creating result for Ch. 7 in thesis, in conjunction with fitting scripts in pcnn
- no_errors: simulation scripts to run controllers against simplified state space models that agree with internal models of MPC controllers
- retraining: simulations for periodic retraining, i.e. the data availability conference paper mentioned above
- static_errors: tests for checking how controllers act, if recorded model errors are added as additive disturbance to perfect model. plausibility simulations at the beginning of developing the bems-cosimos version of the whole EMS, if you will.
- src:
contains actual implementations in 3 packages
- bems: BEMS implementations (controllers, models, benchmarking models, helper scripts for various things)
- error_compensation:
Framework for error compensation/residual estimations. Not fully independent of actual BEMS implementation.
OnlineCompensatorhas hard coded feature names aligned with data.pyprepare_training_data, and depends onEMSConfig.- compensator_library.py: library of frequently used compensator definitions, i.e. which ML model should be combined with which features and settings. Can be made into actual compensators by training them using training.py
- models.py: Definitions of different ML models
- interfaces.py:
Interface definitions for dealing with compensators, e.g.
OnlineCompensatorto turn a trainedBaseCompensatorinto a data source that can be used in acosimossimulation. - error_compensation.py: legacy implementation from CCTA 2023 conference paper, needed for initial migration from old codebase into new code base. Do not use.
- model_fitting: Framework for fitting models using optimal fit, i.e. numerical constrained fitting using IPOPT, or via PCNNs.
- playground/pcnn:
contains code for a lot of things for Ch 7 of the Thesis
- fit_cooling_efficiency.py: Fits a simplified dynamic curve for the cooling efficiency eps_c = f(ambient temperature theta_air) = max(eps_c_0, m * theta_air + c)
- fit_pcnn.py: Fits a PCNN for a given set of initial parameters for the linear system part and a choice of features for the PCNN’s MLP part
- fit_pcnn_on_bad_initial.py: Fits a PCNN on a very rough guestimate for the initial parameters of the linear system part
- fit_pcnn_on_guestimated_initial.py: Fits a PCNN on a more sophisticated guestimate for the initial parameters of the linear system part
- least_squares_fit_exact.py: Fits a linear system description using constrained nonlinear optimization
- train_regressor_on_fit_residuals.py:
Script used to train residual estimators for a set of given linear system parameters. The residuals are calculated by taking the trajectories realized by a
SimpleRBCControllerin digital twin simulation, and then for each time step, calculating the difference between what consecutive step the linear model would have predicted given the current state and the actually realized step. Thus, this is an entirely offline fitting process and can be performed for any (linear) model.
The code itself is licensed under the MIT license (see LICENSE). However, the hierarchical control scheme with negotiation between the layers is subject to the patents
J. Engel and T. Schmitt, "Hierarchical EMS with mitigation of information asymmetry", European pat. EP24158081.0
and
J. Engel and T. Schmitt, ”Energy management system and method with mitigation of information asymmetry“, US Patent App. 19/053,417
Therefore, restrictions apply.