Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
cc7f4e8
Wrote basic code infrastructure.
Jaimepatt Feb 4, 2026
cadf89f
Created test and wrote esdl parsin routine. Equations need to be fixed.
Jaimepatt Feb 4, 2026
b7a2c1d
Fixed some esdl implementation errors. Remaining issue with conservat…
Jaimepatt Feb 4, 2026
d49c6d0
Implementation finished. Still need to document, format, lint etc.
Jaimepatt Feb 4, 2026
4d52db2
Wrote missing tests, some documentation.
Jaimepatt Feb 5, 2026
c7354b3
Minor fixes. Need to document, format and lint to complete PR submiss…
Jaimepatt Feb 5, 2026
6d1c63b
Implemented comments from the PR.
Jaimepatt Feb 26, 2026
291f69b
Refactored and modified tests for geothermal source assets.
Jaimepatt Feb 26, 2026
75df94d
Fixed comments from the PR.
Jaimepatt Mar 2, 2026
6e97d91
Merged main.
Jaimepatt Mar 2, 2026
cf80ec6
Changed default COP value for geothermal source.
Jaimepatt Mar 2, 2026
2a16387
Formatting.
Jaimepatt Mar 2, 2026
0d45e48
Linting.
Jaimepatt Mar 2, 2026
0169bed
Fixed mistake.
Jaimepatt Mar 2, 2026
dd80124
Linting.
Jaimepatt Mar 2, 2026
f3a482b
Fixed formatting.
Jaimepatt Mar 2, 2026
e2112be
Implemented comments from PR.
Jaimepatt Mar 12, 2026
e815dbc
Fixed test.
Jaimepatt Mar 12, 2026
2ff0dfb
Modified behavior for cases where no cop is provided. Added a test fo…
Jaimepatt Mar 12, 2026
a7d4645
Merged main.
Jaimepatt Mar 12, 2026
a25ff01
Linting, formatting.
Jaimepatt Mar 12, 2026
855c876
Formatting.
Jaimepatt Mar 12, 2026
17d778e
Merge branch 'main' into 421-geothermal-asset-e-consumption
FJanssen-TNO Mar 12, 2026
7b7c45a
PR comments.
Jaimepatt Mar 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/mesido/esdl/asset_to_component_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -900,6 +900,7 @@ def _get_connected_i_nominal_and_max(self, asset: Asset) -> Tuple[float, float]:
or asset.asset_type == "Electrolyzer"
or asset.asset_type == "ElectricBoiler"
or asset.asset_type == "HeatPump"
or asset.asset_type == "GeothermalSource"
):
for port in asset.in_ports:
if isinstance(port.carrier, esdl.ElectricityCommodity):
Expand Down
21 changes: 19 additions & 2 deletions src/mesido/esdl/esdl_heat_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
GasSubstation,
GasTankStorage,
GeothermalSource,
GeothermalSourceElec,
HeatBuffer,
HeatDemand,
HeatExchanger,
Expand Down Expand Up @@ -1450,8 +1451,24 @@ def convert_heat_source(self, asset: Asset) -> Tuple[Type[HeatSource], MODIFIERS
f"{asset.asset_type} '{asset.name}' has no desired flow rate specified. "
f"'{asset.name}' will not be actuated in a constant manner"
)

return GeothermalSource, modifiers
modifiers["elec_power_nominal"] = max_supply
modifiers["cop"] = asset.attributes["COP"] if asset.attributes["COP"] else 0.0
if len(asset.in_ports) == 2:
for port in asset.in_ports:
if isinstance(port.carrier, esdl.ElectricityCommodity):
min_voltage = port.carrier.voltage
i_max, i_nom = self._get_connected_i_nominal_and_max(asset)
modifiers.update(
min_voltage=min_voltage,
ElectricityIn=dict(
Power=dict(min=0.0, max=max_supply, nominal=max_supply / 2.0),
I=dict(min=0.0, max=i_max, nominal=i_nom),
V=dict(min=min_voltage, nominal=min_voltage),
),
)
return GeothermalSourceElec, modifiers
else:
return GeothermalSource, modifiers
elif asset.asset_type == "HeatPump":
modifiers["cop"] = asset.attributes["COP"]
return AirWaterHeatPump, modifiers
Expand Down
13 changes: 8 additions & 5 deletions src/mesido/esdl/esdl_model_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def __set_primary_secondary_heat_ports():
f"milp(4) and electricity (1) ports"
)
elif (
asset.asset_type == "HeatPump"
(asset.asset_type == "HeatPump")
and len(asset.out_ports) == 1
and len(asset.in_ports) in [1, 2]
):
Expand All @@ -201,11 +201,12 @@ def __set_primary_secondary_heat_ports():
)
else:
raise Exception(
f"{asset.name} has incorrect number of in/out ports. HeatPumps are allows "
f"to have 1 in and 1 out port for air-water HP, 2 in ports and 2 out ports "
f"when modelling a water-water HP, or 3 in ports and 2 out ports when the "
f"electricity connection of the water-water HP is modelled."
f"{asset.name} has incorrect number of in/out ports. HeatPumps allow "
f"to have 1 in and 1 out port for air-water HP, 2 in ports and 2 out "
f"ports when modelling a water-water HP, or 3 in ports and 2 out ports "
f"when the electricity connection of the water-water HP is modelled."
)

elif (
asset.asset_type == "GasHeater"
and len(asset.out_ports) == 1
Expand All @@ -226,6 +227,7 @@ def __set_primary_secondary_heat_ports():
)
elif (
asset.asset_type == "ElectricBoiler"
or asset.asset_type == "GeothermalSource"
and len(asset.out_ports) == 1
and len(asset.in_ports) == 2
):
Expand Down Expand Up @@ -258,6 +260,7 @@ def __set_primary_secondary_heat_ports():
raise Exception(
f"{asset.name} must have one inport for electricity and one outport for gas"
)

elif (
asset.in_ports is None
and isinstance(asset.out_ports[0].carrier, esdl.ElectricityCommodity)
Expand Down
2 changes: 2 additions & 0 deletions src/mesido/pycml/component_library/milp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from .heat.cold_demand import ColdDemand
from .heat.control_valve import ControlValve
from .heat.geothermal_source import GeothermalSource
from .heat.geothermal_source_elec import GeothermalSourceElec
from .heat.heat_buffer import HeatBuffer
from .heat.heat_demand import HeatDemand
from .heat.heat_exchanger import HeatExchanger
Expand Down Expand Up @@ -68,6 +69,7 @@
"GasSubstation",
"GasTankStorage",
"GeothermalSource",
"GeothermalSourceElec",
"HeatExchanger",
"HeatFourPort",
"HeatPipe",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from mesido.pycml import Variable
from mesido.pycml.pycml_mixin import add_variables_documentation_automatically

from numpy import nan
Expand All @@ -9,11 +10,14 @@
class GeothermalSource(HeatSource):
"""
The geothermal source component is used to model geothermal doublets. It is equivilent to a
normal source with the only difference being in the modelling of doublets. The main reason for
this component instead of using just a regular source is that to have the integer behaviour of
increasing the amount of doublets. In the HeatMixin an integer is created _aggregation_count to
model the amount of doublets and the maximum power will scale with this integer instead of
continuous. This will also ensure that the cost will scale with this integer.
normal source with the only difference being the modelling of doublets and power consumption.
The main reason for this component instead of using just a regular source is that to have the
integer behaviour of increasing the amount of doublets. In the HeatMixin an integer is created
_aggregation_count to model the amount of doublets and the maximum power will scale with this
integer instead of continuous. This will also ensure that the cost will scale with this integer.
The power consumption is computed through a COP calculation, directly linked to the heat source
production. COP is set to a default value of 0 in order to ensure power and its associated costs
are only inlcuded in the computations intentionally.

Variables created:
{add_variable_names_for_documentation_here}
Expand All @@ -31,4 +35,13 @@ def __init__(self, name, **modifiers):

self.target_flow_rate = nan
self.single_doublet_power = nan
self.cop = nan
self.elec_power_nominal = nan
self.nr_of_doublets = 1.0

self.add_variable(Variable, "Power_elec", min=0.0, nominal=self.elec_power_nominal)

if self.cop == 0.0:
self.add_equation((self.Power_elec))
else:
self.add_equation(((self.Power_elec * self.cop - self.Heat_source) / self.Heat_nominal))
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from mesido.pycml.component_library.milp.electricity.electricity_base import ElectricityPort
from mesido.pycml.component_library.milp.heat.geothermal_source import GeothermalSource
from mesido.pycml.pycml_mixin import add_variables_documentation_automatically

from numpy import nan


@add_variables_documentation_automatically
class GeothermalSourceElec(GeothermalSource):
"""
The geothermal source electric asset is almost identical to the geothermal source one. The
only difference is that this one includes an electricity in port. The electricity power
calculation that it inherits from the geothermal source asset needs to be satisfied by an
electricity carrier supplied through this new in port.

Variables created:
{add_variable_names_for_documentation_here}

Parameters:
name : The name of the asset. \n
modifiers : Dictionary with asset information.
"""

def __init__(self, name, **modifiers):
super().__init__(
name,
**modifiers,
)

self.component_subtype = "geothermal_source_elec"
self.min_voltage = nan

self.add_variable(ElectricityPort, "ElectricityIn")

self.add_equation(((self.ElectricityIn.Power - self.Power_elec) / self.elec_power_nominal))
57 changes: 57 additions & 0 deletions tests/models/source_pipe_sink/model/sourcesink_with_geo.esdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?xml version='1.0' encoding='UTF-8'?>
<esdl:EnergySystem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:esdl="http://www.tno.nl/esdl" version="11" id="5d539f68-f98e-466b-9ff5-b908a211e0ab_with_return_network_with_return_network" name="sourcesink_withHP_voc" description="" esdlVersion="v2401">
<instance xsi:type="esdl:Instance" name="Untitled instance" id="90e7e098-038e-4462-89fe-a8852c501753">
<area xsi:type="esdl:Area" id="4fd1adc2-5371-4ab7-806a-b40e49d127e9" name="Untitled area">
<asset xsi:type="esdl:HeatingDemand" id="f6d5923d-ba9a-409d-80a0-26f73b2a574b" power="10000000.0" name="demand">
<port xsi:type="esdl:InPort" id="b8849fb5-fe97-48d9-91a8-9abcbf365738" name="In" connectedTo="76679c8a-43ec-4f6d-81c4-9b43e21696cc" carrier="435a0034-fab0-4e7e-9a17-edf8de9a2b11"/>
<port xsi:type="esdl:OutPort" id="eb68d4fe-b361-4e64-9f54-a1e05e5712ee" name="Out" carrier="435a0034-fab0-4e7e-9a17-edf8de9a2b11_ret" connectedTo="0f4bf90b-218d-4d45-a83e-97a8a6a187af"/>
<geometry xsi:type="esdl:Point" lat="52.086586960901776" CRS="WGS84" lon="4.398479461669923"/>
</asset>
<asset xsi:type="esdl:Pipe" outerDiameter="0.45" id="Pipe1" length="1000.0" diameter="DN300" innerDiameter="0.15" name="Pipe1" related="Pipe1_ret">
<dataSource xsi:type="esdl:DataSource" attribution="https://www.logstor.com/media/6506/product-catalogue-uk-202003.pdf" name="Logstor Product Catalogue Version 2020.03"/>
<costInformation xsi:type="esdl:CostInformation" id="a5e06a9f-ad3d-4c95-afcf-28ce7f772ec3">
<investmentCosts xsi:type="esdl:SingleValue" name="Combined investment and installation costs" value="1962.1" id="1e93bdda-8a74-42d5-960d-d64e4dff2025">
<profileQuantityAndUnit xsi:type="esdl:QuantityAndUnitType" description="Costs in EUR/m" id="983f0959-8566-43ce-a380-782d29406ed3" physicalQuantity="COST" perUnit="METRE" unit="EURO"/>
</investmentCosts>
</costInformation>
<port xsi:type="esdl:InPort" id="3b5636b1-7b14-46bd-bb27-c0718350b418" name="In" connectedTo="e6b47a7a-1f59-4f62-8fa4-6d69cc4ce40d" carrier="435a0034-fab0-4e7e-9a17-edf8de9a2b11"/>
<port xsi:type="esdl:OutPort" id="76679c8a-43ec-4f6d-81c4-9b43e21696cc" name="Out" connectedTo="b8849fb5-fe97-48d9-91a8-9abcbf365738" carrier="435a0034-fab0-4e7e-9a17-edf8de9a2b11"/>
<geometry xsi:type="esdl:Line" CRS="WGS84">
<point xsi:type="esdl:Point" lat="52.08646829489945" lon="4.386527538299561"/>
<point xsi:type="esdl:Point" lat="52.086586960901776" lon="4.398479461669923"/>
</geometry>
<material xsi:type="esdl:CompoundMatter" compoundType="LAYERED">
<component xsi:type="esdl:CompoundMatterComponent" layerWidth="0.0056">
<matter xsi:type="esdl:Material" thermalConductivity="52.15" name="steel" id="f4cee538-cc3b-4809-bd66-979f2ce9649b"/>
</component>
<component xsi:type="esdl:CompoundMatterComponent" layerWidth="0.05785">
<matter xsi:type="esdl:Material" thermalConductivity="0.027" name="PUR" id="e4c0350c-cd79-45b4-a45c-6259c750b478"/>
</component>
<component xsi:type="esdl:CompoundMatterComponent" layerWidth="0.0052">
<matter xsi:type="esdl:Material" thermalConductivity="0.4" name="HDPE" id="9a97f588-10fe-4a34-b0f2-277862151763"/>
</component>
</material>
</asset>
<asset xsi:type="esdl:Pipe" outerDiameter="0.45" id="Pipe1_ret" length="1000.0" diameter="DN300" innerDiameter="0.15" name="Pipe1_ret" related="Pipe1">
<port xsi:type="esdl:InPort" id="0f4bf90b-218d-4d45-a83e-97a8a6a187af" name="In_ret" connectedTo="eb68d4fe-b361-4e64-9f54-a1e05e5712ee" carrier="435a0034-fab0-4e7e-9a17-edf8de9a2b11_ret"/>
<port xsi:type="esdl:OutPort" id="0f11bb2d-fb28-4f9d-8992-8d5901f579d7" name="Out_ret" carrier="435a0034-fab0-4e7e-9a17-edf8de9a2b11_ret" connectedTo="142d22a2-bc50-4ba3-8723-2eb16fe385b0"/>
<geometry xsi:type="esdl:Line">
<point xsi:type="esdl:Point" lat="52.086676960991774" CRS="WGS84" lon="4.39796569977892"/>
<point xsi:type="esdl:Point" lat="52.086558294989445" CRS="WGS84" lon="4.386013537838319"/>
</geometry>
</asset>
<asset xsi:type="esdl:GeothermalSource" id="a77bc442-c981-4d26-a308-b65be7224f6f" name="GeothermalSource_a77b" power="10000000.0" COP="4.0">
<geometry xsi:type="esdl:Point" lat="52.08656166975579" lon="4.38586851522473" CRS="WGS84"/>
<port xsi:type="esdl:OutPort" id="e6b47a7a-1f59-4f62-8fa4-6d69cc4ce40d" name="Out" connectedTo="3b5636b1-7b14-46bd-bb27-c0718350b418" carrier="435a0034-fab0-4e7e-9a17-edf8de9a2b11"/>
<port xsi:type="esdl:InPort" id="142d22a2-bc50-4ba3-8723-2eb16fe385b0" name="In" connectedTo="0f11bb2d-fb28-4f9d-8992-8d5901f579d7" carrier="435a0034-fab0-4e7e-9a17-edf8de9a2b11_ret"/>
</asset>
</area>
</instance>
<energySystemInformation xsi:type="esdl:EnergySystemInformation" id="11f4eafa-7fbc-4d82-b346-e893326d2c30">
<carriers xsi:type="esdl:Carriers" id="eafbd8f4-1fde-4bb5-8dce-fdb74a1a1097">
<carrier xsi:type="esdl:HeatCommodity" supplyTemperature="70.0" name="heat" id="435a0034-fab0-4e7e-9a17-edf8de9a2b11"/>
<carrier xsi:type="esdl:HeatCommodity" returnTemperature="40.0" name="heat_ret" id="435a0034-fab0-4e7e-9a17-edf8de9a2b11_ret"/>
<carrier xsi:type="esdl:ElectricityCommodity" voltage="10000.0" name="elec" id="0e237e2a-00d1-4c6c-b966-9c9b8d9657f8"/>
</carriers>
</energySystemInformation>
</esdl:EnergySystem>
Loading
Loading