Create SiModIn models¶
To create your own SiModIn model, create a new python file and import the SimModel base class:
from simodin import SimModel
class your_simodin_model_class(SimModel):
def __init__(self, name):
super().__init__(name)
# Your model specific initializations here
def init_model(self):
# Code to initialize your simulation model
def calculate_model(self):
# Code to run your simulation model
def define_flows(self):
# Code to define the flows for your model
In this example, replace your_simodin_model_class with the desired name
for your model class. Implement the init_model, calculate_model,
and define_flows methods with the specific logic for your simulation model.
The setup of a model will be demonstrated on the Gas turbine example from
Tespy documentation.
The full code is available here.
Import dependencies:¶
from simodin import interface as link
from simodin import tespy
from tespy.networks import Network
from tespy.components import (
DiabaticCombustionChamber, Turbine, Source, Sink, Compressor,
Generator, PowerBus, PowerSink
)
from tespy.connections import Connection, Ref, PowerConnection
Define class attributes:¶
Reference can be passed to the model by using the class attribute reference.
A bibtex like dictionary with reference informations can be passed here.
Aditionally, needed parameter can be defined here with default values in the parameter list.
An allowed parameter range can be defined by the min and max attributes.
class tespy_model(link.SimModel):
reference= {
'type': 'misc',
'key': 'tespy_gas_turbine',
'author' :'Francesco Witte',
'title' : 'Gas Turbine',
'url': 'https://tespy.readthedocs.io/en/main/basic_tutorials/gas_turbine.html'
}
parameter=[
link.parameter(name='heat_output',
default= 100*self.model.units.ureg.MJ,
),
link.parameter(name='lifetime_turbine',
default=80000*self.model.units.ureg.hour, #lifetime in hours
min =40000*self.model.units.ureg.hour,
max = 160000*self.model.units.ureg.hour
)
]
Implementation of the concrete methods:¶
init_model:
This method contain the code to initialize your simulation model,
such as setting up parameters or loading data. In this example the Tespy
network is build here. The key word argument heat_output is used
as model parameter to define the heat output at the combustion chamber.
def init_model(self, **params):
self.model = Network()
self.model.units.set_defaults(temperature='degC', pressure='bar', enthalpy='kJ / kg')
self.model.units.ureg.define('m3 = meter**3')
cp = Compressor("Compressor")
cc = DiabaticCombustionChamber("combustion chamber")
tu = Turbine("turbine")
air = Source("air source")
fuel = Source("fuel source")
fg = Sink("flue gas sink")
c1 = Connection(air, "out1", cp, "in1", label="1")
c2 = Connection(cp, "out1", cc, "in1", label="2")
c3 = Connection(cc, "out1", tu, "in1", label="3")
c4 = Connection(tu, "out1", fg, "in1", label="4")
c5 = Connection(fuel, "out1", cc, "in2", label="5")
cc.set_attr(pr=1, eta=1, lamb=1.5, ti=self.params['heat_output'])
c5.set_attr(p=1, T=25, fluid={"CO2": 0.04, "CH4": 0.96, "H2": 0})
self.model.add_conns(c1, c2, c3, c4, c5)
generator = Generator("generator")
grid = PowerSink("grid")
shaft = PowerBus("shaft", num_in=1, num_out=2)
e1 = PowerConnection(tu, "power", shaft, "power_in1", label="e1")
e2 = PowerConnection(shaft, "power_out1", cp, "power", label="e2")
e3 = PowerConnection(shaft, "power_out2", generator, "power_in", label="e3")
e4 = PowerConnection(generator, "power_out", grid, "power", label="e4")
self.model.add_conns(e1, e2, e3, e4)
generator.set_attr(eta=0.98)
cp.set_attr(eta_s=0.85, pr=15)
tu.set_attr(eta_s=0.90)
c1.set_attr(
p=1, T=25,
fluid={"Ar": 0.0129, "N2": 0.7553, "CO2": 0.0004, "O2": 0.2314}
)
#c3.set_attr(m=30)
c4.set_attr(p=Ref(c1, 1, 0))
calculate_model:
This method contain the code to run your simulation model, performing the necessary calculations or simulations.
In this example it contains the solve() method of the tespy network.
def calculate_model(self):
self.model.solve("design")
# unset the value, set Referenced value instead
self.model.get_conn('5').set_attr(p=None)
self.model.get_conn('5').set_attr(p=Ref(self.model.get_conn('2'), 1.05, 0))
self.model.solve("design")
define_flows:
This method should define the flows of your model which needs to be considered in
the LCA calculation. Those flows can be linked to brightway25 datasets in the
concrete modelInterface class. SiModIn extractors can be used for specific
software to extract typical flows automatically. This is be done for example for tespy
models by using the class simodin.extractors.tespy.extract_technosphere_flows.
For conducting LCA calculations, minimum one functional unit must be defined and exact one reference flow by the set_flow_attr method:
def define_flows(self):
#get all technosphere flows:
technosphere=tespy.extract_technosphere_flows(self)
'''
Add a flow for the fuel source and convert it to a volume,
as most generic datasets are not using flows as reference value:
'''
technosphere['fuel source'].amount = lambda: (self.model.get_conn('5').v._val
* self.model.units.ureg.hour
).to('meter**3')
# remove not needed flows:
del technosphere['flue gas sink']
#set functional unit and reference flow:
technosphere['grid'].functional = True
technosphere['grid'].reference = True
self.technosphere = technosphere
# add biosphere flows:
biosphere={}
biosphere['flue gas sink']=link.biosphere_edge(
name='flue gas sink',
source= self,
target= None,
amount=lambda: (self.model.get_conn('4').m._val*self.model.get_conn('4').fluid.val['CO2']
* self.model.units.ureg.hour
).to('kg'),
)
self.biosphere= biosphere
'''
Add a technosphere flow representing the impact of the equipment.
This can be done by the setter method:
'''
self.add_flow(link.technosphere_edge(
name = 'turbine equipment',
source = None,
target = self,
amount= lambda: (self.model.get_conn('e3').E._val *
self.model.units.ureg.hour /self.params['lifetime_turbine']
),
description= (
'Impact of the turbine equipment. Link a dataset with the' +
'production of a turbine with a suitable power as functional unit')
))
Note
Currently, the amount property of technosphere flows must be callable.
Lambda functions can be used for that.
Apply the model¶
After defining your model class, you can instantiate and use it in your application as shown in the “Use SiModIn models” tutorial.