Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add capability to support steam boilers (1st gen district systems) #624

Draft
wants to merge 31 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
df9b347
add `cop_heat_pump_cooling` to required 5G ets params
vtnate Mar 5, 2024
30c7b6e
change how we specify which type of district system to consider
vtnate Mar 5, 2024
5189d3f
put all time_series sys-param template data into one file
vtnate Mar 5, 2024
fdcf41f
remove now-outdated microgrid sys-param template
vtnate Mar 5, 2024
9d71467
update cli to use new paradigm for specifying district type
vtnate Mar 5, 2024
389d50c
update tests to use new system type designation
vtnate Mar 5, 2024
09fe233
Merge branch 'develop' into enhance-5th-gen
vtnate Mar 5, 2024
4332082
improve comment in sys-param.py
vtnate Mar 6, 2024
1e54cef
add steam boiler parameters to schema
vtnate Mar 6, 2024
b758d9e
new steam boiler template for 1G districts
vtnate Mar 11, 2024
1a34187
wip: central steam plant characteristics
vtnate Mar 11, 2024
9cc4249
Merge branch 'develop' into ged-steam-boiler
vtnate Mar 15, 2024
e17a167
real path for boiler_efficiency in SteamBoiler template
vtnate Mar 15, 2024
6792301
new code to read SteamBoiler template
vtnate Mar 15, 2024
4f84949
add another property in steam boiler schema
vtnate Mar 15, 2024
2d36ae6
test file & sys-param data for steam boiler
vtnate Mar 15, 2024
4b4f9d0
couplings for steam boiler - this should be reviewed!
vtnate Mar 15, 2024
13a054d
Merge branch 'develop' into ged-steam-boiler
vtnate Mar 19, 2024
18ac742
new geojson method to retrieve any feature by id
vtnate Apr 16, 2024
91b6b2f
Merge branch 'develop' into ged-steam-boiler
vtnate Apr 30, 2024
2b0d687
skip district steam tests until we build that functionality
vtnate Apr 30, 2024
e1be79b
test for steam example
vtnate May 3, 2024
da213ce
steam sys-params
vtnate May 3, 2024
a642d86
update schema with one more steam object
vtnate May 3, 2024
2038afb
WIP: code and template for steam example
vtnate May 3, 2024
9afe09c
rename steam template
vtnate May 3, 2024
df4fe0b
simulation test for steam example
vtnate May 3, 2024
fb39fa9
templatized steam level 1 example model
vtnate May 3, 2024
453371e
point to correct part of sys-params for steam-example
vtnate May 3, 2024
475cae3
skip separately building a steam model during testing
vtnate May 6, 2024
afea51f
Merge branch 'develop' into ged-steam-boiler
vtnate Aug 26, 2024
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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// No components for pipe and steam plant
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
connect({{ coupling.plant.id }}.port_a,{{ coupling.network.id }}.port_bDisRet)
annotation ({{ diagram.line.heating_plant.port_a.two_pipe.port_b_dis_ret }});
connect({{ coupling.network.id }}.dp,{{ coupling.plant.id }}.dpMea)
annotation ({{ diagram.line.two_pipe.dp.heating_plant.dp_mea }});
connect({{ coupling.plant.id }}.port_b,{{ coupling.network.id }}.port_aDisSup)
annotation ({{ diagram.line.heating_plant.port_b.two_pipe.port_a_dis_sup }});
connect(mPum_flow_{{ coupling.id }}.y,{{ coupling.plant.id }}.on)
annotation ({{ diagram.line.m_pum_flow.y.heating_plant.on }});
connect(TDisSetHeaWat_{{ coupling.id }}.y,{{ coupling.plant.id }}.THeaSet)
annotation ({{ diagram.line.t_dis_set_hea_wat.y.heating_plant.t_hea_set }});
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# :copyright (c) URBANopt, Alliance for Sustainable Energy, LLC, and other contributors.
# See also https://github.com/urbanopt/geojson-modelica-translator/blob/develop/LICENSE.md

from pathlib import Path

from modelica_builder.package_parser import PackageParser

from geojson_modelica_translator.model_connectors.plants.plant_base import PlantBase
from geojson_modelica_translator.utils import simple_uuid


class SteamPlant(PlantBase):
model_name = "SteamBoiler"

def __init__(self, system_parameters):
super().__init__(system_parameters)
self.id = "steBoi" + simple_uuid()

def to_modelica(self, scaffold):
"""
Create timeSeries models based on the data in the buildings and geojsons

:param scaffold: Scaffold object, Scaffold of the entire directory of the project.
"""

template_data = {
"nominal_values": {
"boiler_efficiency": self.system_parameters.get_param(
"$.district_system.first_generation.central_steam_plant_parameters.boiler_efficiency"
)
}
}

plant_template = self.template_env.get_template("SteamBoiler.mot")
self.run_template(
template=plant_template,
save_file_name=Path(scaffold.plants_path.files_dir) / "SteamBoiler.mo",
project_name=scaffold.project_name,
data=template_data,
)

self.copy_required_mo_files(
dest_folder=scaffold.plants_path.files_dir, within=f"{scaffold.project_name}.Plants"
)

package = PackageParser(scaffold.project_path)
if "Plants" not in package.order:
package.add_model("Plants")
package.save()

package_models = ["SteamBoiler"] + [Path(mo).stem for mo in self.required_mo_files]
plants_package = PackageParser(scaffold.plants_path.files_dir)
if plants_package.order_data is None:
plants_package = PackageParser.new_from_template(
path=scaffold.plants_path.files_dir, name="Plants", order=package_models, within=scaffold.project_name
)
else:
for model_name in package_models:
plants_package.add_model(model_name)
plants_package.save()

def get_modelica_type(self, scaffold):
return "Plants.SteamBoiler"
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
within {{ project_name }}.Plants;
model SteamBoiler
// "Single steam boiler model for GMT level 1 testing in district heating application"
// Central heating plant
parameter Real boiler_efficiency[:]={{ data["nominal_values"]["boiler_efficiency"] }}
"Coefficients for boiler efficiency curve";
// Steam properties
parameter Modelica.Units.SI.AbsolutePressure pSat_GMT={{data["Saturatation pressure"]}}
"Saturation pressure, high pressure";
parameter Modelica.Units.SI.AbsolutePressure pLow_GMT={{data["Reduced pressure"]}}
"Reduced pressure, after PRV";
parameter Modelica.Units.SI.Temperature TSat_GMT=MediumSte.saturationTemperature(
pSat_GMT)
"Saturation temperature, at high pressure";
// Building
parameter Integer N_GMT={{data["number_of_loads"]}}
"Number of buildings";
// Distribution Network
parameter Modelica.Units.SI.PressureDifference dp_nominal_GMT={{data["condensate_pressure_drop_nominal"]}}
"Pressure drop of distribution at nominal mass flow rate";
extends Buildings.Experimental.DHC.Examples.Steam.SingleBoiler(
// Central heating plant
pla(
boi(
a=boiler_efficiency
"Boiler efficiency")),
pSat=pSat_GMT,
pLow=pLow_GMT,
TSat=TSat_GMT,
QBui_flow_nominal=QBui_flow_nominal_GMT,
N=N_GMT,
dp_nominal=dp_nominal_GMT);
annotation (
Icon(
coordinateSystem(
preserveAspectRatio=false)),
Diagram(
coordinateSystem(
preserveAspectRatio=false)),
experiment(
StopTime=86400,
Tolerance=1e-06),
Documentation(
info="<html>
<p>This model validates the steam boiler in district heating system template model implemented in
<a href=\"Buildings.Experimental.DHC.Examples.Steam.SingleBoiler.mo\">
Buildings.Experimental.DHC.Examples.Steam.SingleBoiler.mot</a>.
</p>
</html>",
revisions="<html>
<ul>
<li>

February 01, 2024 by Zhanwei He:<br/>
First implementation.
</li>
</ul>
</html>"));
end SteamBoiler;
135 changes: 135 additions & 0 deletions geojson_modelica_translator/modelica/GMT_Lib/DHC/Steam.mot
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
within;
model Steam "Example model for a complete steam district heating system with a
central plant that contains a single boiler"
extends Modelica.Icons.Example;

package MediumSte = Buildings.Media.Steam (p_default=400000,
T_default=273.15+143.61,
h_default=2738100)
"Steam medium";
package MediumWat =
Buildings.Media.Specialized.Water.TemperatureDependentDensity (
p_default=101325,
T_default=100+273.15,
h_default=2738100)
"Water medium";

parameter Modelica.Units.SI.AbsolutePressure pSat={{ data["steam_pressure_setpoint"] }}
"Saturation pressure, high pressure";
parameter Modelica.Units.SI.AbsolutePressure pLow={{ data["reduced_pressure_setpoint"] }}
"Reduced pressure, after PRV";
parameter Modelica.Units.SI.Temperature TSat=
MediumSte.saturationTemperature(pSat)
"Saturation temperature, at high pressure";

parameter Integer N = 3 "Number of buildings";
parameter Modelica.Units.SI.MassFlowRate mDis_flow_nominal=sum(bld.m_flow_nominal)*1.2
"Nominal mass flow rate of entire district";
parameter Modelica.Units.SI.HeatFlowRate QDis_flow_nominal=QBui_flow_nominal*N
"Nominal heat flow rate of entire district";
parameter Modelica.Units.SI.HeatFlowRate QBui_flow_nominal=20000
"Nominal heat flow rate of each building";
parameter Modelica.Units.SI.PressureDifference dpPip={{ data["condensate_pressure_drop_nominal"] }}
"Pressure drop in the condensate return pipe";

parameter Buildings.Fluid.Movers.Data.Generic perPumFW(
pressure(V_flow=(mDis_flow_nominal/1000)*{0,1,2},
dp=(pSat-101325)*{2,1,0}))
"Performance data for feedwater pump at the plant";

parameter Modelica.Units.SI.PressureDifference dp_nominal=6000
"Pressure drop of distribution at nominal mass flow rate";

Buildings.Experimental.DHC.Loads.Steam.BuildingTimeSeriesAtETS bld[N](
redeclare final package MediumSte = MediumSte,
redeclare final package MediumWat = MediumWat,
each have_prv=true,
each dp_nominal=dpPip/2,
each final pSte_nominal=pSat,
each final Q_flow_nominal=QBui_flow_nominal,
each pLow_nominal=pLow,
each energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
each tableOnFile=false,
each QHeaLoa=
[0,0.8; 2,1; 10,1; 12,0.5; 20,0.5; 24,0.8]*[1,0;0,QBui_flow_nominal],
each smoothness=Modelica.Blocks.Types.Smoothness.MonotoneContinuousDerivative1,
each timeScale(displayUnit="s") = 3600,
each show_T=true)
"Buildings"
{% raw %}annotation (Placement(transformation(extent={{60,20},{40,40}})));
Buildings.Experimental.DHC.Networks.Steam.DistributionCondensatePipe dis(
redeclare final package MediumSup = MediumSte,
redeclare final package MediumRet = MediumWat,
final dp_nominal=dp_nominal,
final nCon=N,
final mDis_flow_nominal=mDis_flow_nominal,
final mCon_flow_nominal=bld.m_flow_nominal)
"Distribution network"
annotation (Placement(transformation(extent={{0,-20},{40,0}})));
Buildings.Experimental.DHC.Plants.Steam.SingleBoiler pla(
redeclare final package Medium = MediumWat,
redeclare final package MediumHea_b = MediumSte,
final m_flow_nominal=mDis_flow_nominal,
final pSteSet=pSat,
final Q_flow_nominal=QDis_flow_nominal,
final per=perPumFW,
energyDynamics=Modelica.Fluid.Types.Dynamics.FixedInitial,
kBoi=600,
TiBoi(displayUnit="min") = 120,
kPum=200,
TiPum=1000)
"Plant"
annotation (Placement(transformation(extent={{-50,20},{-30,40}})));
equation
connect(dis.ports_bCon, bld.port_a)
annotation (Line(points={{8,0},{8,30},{40,30}}, color={0,127,255}));
connect(bld.port_b, dis.ports_aCon)
annotation (Line(points={{40,24},{32,24},{32,0}}, color={0,127,255}));
connect(pla.port_bSerHea, dis.port_aDisSup)
annotation (Line(points={{-30,30},{-20,30},{-20,-10},{0,-10}},
color={0,127,255}));
connect(dis.port_bDisRet, pla.port_aSerHea) annotation (Line(points={{0,-16},{
-60,-16},{-60,30},{-50,30}}, color={0,127,255}));
annotation (Icon(coordinateSystem(preserveAspectRatio=false)), Diagram(
coordinateSystem(preserveAspectRatio=false)),
__Dymola_Commands(file=
"modelica://Buildings/Resources/Scripts/Dymola/Experimental/DHC/Examples/Steam/SingleBoiler.mos"
"Simulate and plot"),
experiment(
StopTime=86400,
Tolerance=1e-06),
Documentation(revisions="<html>
<ul>
<li>
September 15, 2023, by Kathryn Hinkelman:<br/>
Added publication references.
</li>
<li>
March 3, 2022 by Kathryn Hinkelman:<br/>
First implementation.
</li>
</ul>
</html>", info="<html>
<p>
This example model demonstrates a complete system simulation for
steam district heating systems. The central plant features a single boiler.
For the distribution network, pressure losses on the condensate return
pipes are included, while the steam pipes are assumed to be lossless.
</p>
<h4>References </h4>
<p>
Kathryn Hinkelman, Saranya Anbarasu, Michael Wetter, Antoine Gautier, Wangda Zuo. 2022.
&ldquo;A Fast and Accurate Modeling Approach for Water and Steam
Thermodynamics with Practical Applications in District Heating System Simulation,&rdquo;
<i>Energy</i>, 254(A), pp. 124227.
<a href=\"https://doi.org/10.1016/j.energy.2022.124227\">10.1016/j.energy.2022.124227</a>
</p>
<p>
Kathryn Hinkelman, Saranya Anbarasu, Michael Wetter, Antoine Gautier, Baptiste Ravache, Wangda Zuo 2022.
&ldquo;Towards Open-Source Modelica Models For Steam-Based District Heating Systems.&rdquo;
<i>Proc. of the 1st International Workshop On Open Source Modelling And Simulation Of
Energy Systems (OSMSES 2022)</i>, Aachen, German, April 4-5, 2022.
<a href=\"https://doi.org/10.1109/OSMSES54027.2022.9769121\">10.1109/OSMSES54027.2022.9769121</a>
</p>
</html>"));
end Steam;{% endraw %}
25 changes: 25 additions & 0 deletions geojson_modelica_translator/modelica/GMT_Lib/DHC/steam_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import logging
from pathlib import Path

from geojson_modelica_translator.modelica.simple_gmt_base import SimpleGMTBase

logger = logging.getLogger(__name__)


class Steam(SimpleGMTBase):
def __init__(self, system_parameters):
self.system_parameters = system_parameters
self.template_dir = Path(__file__).parent
super().__init__(self.system_parameters, self.template_dir)

def build_from_template(self, output_dir: Path):
steam_params = self.system_parameters.get_param(
"$.district_system.first_generation.central_steam_plant_parameters"
)
# render template to final modelica file
self.to_modelica(
output_dir=output_dir,
model_name="Steam",
param_data=steam_params,
)
# If the sys-param file is missing an entry, it will show up as a jinja2.exceptions.UndefinedError
57 changes: 55 additions & 2 deletions geojson_modelica_translator/system_parameters/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
"description": "Parameters associated with district systems.",
"type": "object",
"oneOf": [
{
"$ref": "#/definitions/first_generation_def"
},
{
"$ref": "#/definitions/fourth_generation_def"
},
Expand Down Expand Up @@ -910,6 +913,32 @@
}
}
},
"central_steam_plant_parameters": {
"description": "Central steam heating plant.",
"type": "object",
"properties": {
"boiler_efficiency": {
"description": "Boiler efficiency (fraction)",
"type": "number",
"default": 0.7
},
"steam_pressure_setpoint": {
"description": "The saturation pressure, high pressure setpoint. (Pa)",
"type": "number",
"default": 500000
},
"reduced_pressure_setpoint": {
"description": "The reduced pressure, after the PRV. (Pa)",
"type": "number",
"default": 200000
},
"condensate_pressure_drop_nominal": {
"description": "Nominal pressure drop along the condensate return pipe. (Pa)",
"type": "number",
"default": 6000
}
}
},
"ghe_parameters": {
"description": "Parameters associated with Ground Heat Exchangers.",
"type": "object",
Expand Down Expand Up @@ -1227,6 +1256,30 @@
}
}
},
"first_generation_def": {
"properties": {
"first_generation": {
"properties": {
"central_steam_plant_parameters": {
"$ref": "#/definitions/central_steam_plant_parameters"
},
"central_pump_parameters": {
"description": "Parameters for central pump",
"type": "object",
"properties": {
"pump_design_head": {
"description": "Central pump nominal pressure (Pa)",
"type": "number"
}
}
}
}
}
},
"required": [
"first_generation"
]
},
"fourth_generation_def": {
"properties": {
"fourth_generation": {
Expand Down Expand Up @@ -1256,7 +1309,7 @@
"type": "object",
"properties": {
"pump_design_head": {
"description": "Measured in Pa",
"description": "Central pump nominal pressure (Pa)",
"type": "number"
}
}
Expand Down Expand Up @@ -1291,7 +1344,7 @@
"type": "object",
"properties": {
"pump_design_head": {
"description": "Measured in Pa.",
"description": "Central pump nominal pressure (Pa)",
"type": "number"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -926,7 +926,7 @@ def csv_to_sys_param(
if "5G_ghe" in district_type:
self.process_ghe_inputs(scenario_dir)
elif "4G" in district_type or "steam" in district_type:
# remove fifth generation district system type if it exists in template and ghe is not true
# remove fifth generation district system type if it's not appropriate
with suppress(KeyError):
del self.param_template["district_system"]["fifth_generation"]

Expand Down
Loading
Loading