Tutorial 5: Models and Simulations¶
The PV system power demo now has all of the component except the simulation
and the model. The Simulation
class defines
the parameters used to run the simulation. Simulation parameters are settings
that control the simulation. The Model
class
collects all of the model components together. The two classes work closely with
each other because by default the simulation class is set as the command layer
in the model. Commands can be executed from the model by passing the name of the
command to the model command()
method.
Simulation Class¶
The simulation is delegated the responsibility of running the model. It is the
default command layer of the model meaning that commands passed to the model
execute methods in the simulation of the same name. The simulation layer also
stores any simulation or model settings such as the timestep, any thresholds
that limit when calculations are skipped and which data and output fields are
displayed or written while a dynamic simulation is running. A simulation can
have multiple sets of settings, each declared as a class attributes set to an
instance of SimParameter
, but only one set
of settings are stored in the SimRegistry
.
Much more on that later. For now here’s the PV system power simulation example:
from simkit.core.simulations import Simulation, SimParameter
class PVPowerSim(Simulation):
"""
PV Power Demo Simulations
"""
settings = SimParameter(
ID = "Tuscon_SAPM",
path = "~/SimKit_Simulations",
thresholds = None,
interval = [1, "hour"],
sim_length = [0, "hours"],
write_frequency = 0,
write_fields = {
"data": ["latitude", "longitude", "Tamb", "Uwind"],
"outputs": ["monthly_energy", "annual_energy"]
},
display_frequency = 12,
display_fields = {
"data": ["latitude", "longitude", "Tamb", "Uwind"],
"outputs": ["monthly_energy", "annual_energy"]
},
commands = ['start', 'pause']
)
Simulation Attributes¶
The simulation parameter arguments correspond to attributes. If passed as positional arguments, the order is given in the table below, otherwise keyword arguments can be in any order.
Attribute |
Description |
Default |
---|---|---|
ID |
name used to save files |
|
path |
location where files are saved |
|
commands |
list of methods that can be called by model |
|
data |
not used |
|
thresholds |
list of limits when calculations are skipped |
None |
interval |
length of timesteps for dynamic calculations |
1-hour |
sim_length |
length of dynamic simulation |
1-year |
display_frequency |
frequency data displays in console |
1 |
display_fields |
data and output fields displayed in console |
None |
write_frequency |
frequency that outputs written to file |
8760 |
write_fields |
data and outputs written in output file |
None |
Defaults¶
Most of the simulation settings are optional and apply specifically to dynamic
simulations only. If ID is not given then it will be generated from the
simulation class name and the date and time. The ID is used as the name for the
folder where files are written, and as a prefix of the files written. Each file
ends with a number to indicate the order. The default path of the folder where
the files are written from dynamic simulations is ~/SimKit/Simulations
.
The default commands are 'start'
and 'pause'
, but this list is only used
to populate the model commands()
property. The
data attribute is not used. The rest of the defaults are specified in the table.
Write and Display Fields¶
The write and display fields determine what data and outputs are displayed or written to disk during dynamic simulations. They should be set to a dictionary containing two keys:
``{'data': ['list', 'of', 'data'], 'output': ['outputs', 'list']}``
The display and write frequency are in units of the interval, so if using the default values then display is shown every 1 hour and written to disk every 8760 hours.
Warning
Currently for static only simulations, the value for sim_length
should be
changed to [0, 'hour']
and the write fields should be set to at least one
data or outputs item, or the simulation will raise an unhandled exception.
Settings¶
Settings are specified in the model by passing the settings
argument to the
simulation model parameter. If no settings are provided, then the 1st setting is
used. However, more than one simulation class can be listed in the model, each
with it’s own setting, so that’s a workaround if multiple settings are desired.
To indicate which simulation to use, append the simulation, or list of
simulations after the command passed to the model. For example:
m = MyModel()
m.command('start MySimulation') # runs MySimulation
m.command('start') # runs all simulations in the model
m.command('start Sim1 Sim2 Sim3') # starts Sim1, then Sim2, etc.
Model Class¶
The model class lists the user defined outputs, calculations, formulas, data and
simulations that make up a complete model as class attributes named after the
layer they represent. Subclass Model
and list
each layer as an instance of ModelParameter
. Pass
the classes you’ve defined for each layer as a list of sources
and set the
the Meta
class option modelpath
to PROJ_PATH
which is automatically
generated by simkit-quickstart
in your model package. If a class takes an
argument then list that class as a tuple with the class first and the arguments
in a dictionary second. The model already has a map to the classes used to read
each layer, but you can optionally specify the layer
argument.
from pvpower import PROJ_PATH
from simkit.core.models import Model
class NewSAPM(Model):
"""
PV Power Demo model
"""
data = ModelParameter(
layer = 'Data',
sources = [(PVPowerData, {'filename': 'Tuscon.json'})]
)
outputs = ModelParameter(
layer = 'Outputs',
sources = [PVPowerOutputs, PerformanceOutputs, IrradianceOutputs]
)
formulas = ModelParameter(
layer = 'Formulas',
sources = [UtilityFormulas, PerformanceFormulas, IrradianceFormulas]
)
calculations = ModelParameter(
layer = 'Calculations',
sources = [UtilityCalcs, PerformanceCalcs, IrradianceCalcs]
)
simulations = ModelParameter(layer='Simulations', sources=[PVPowerSim])
class Meta:
modelpath = PROJ_PATH # folder containing project, not model
Model Parameter Attributes¶
The only argument that model parameters really need is a list of sources, but if you need to you can also pass others. The order of positional arguments is the same as the table, or you can pass keyword arguments in any order.
Attribute |
Description |
---|---|
layer |
name of the layer class of these parameters, optional |
module |
module that the sources are defined in, optional |
package |
package that the sources’ module is contained in, optional |
path |
path to source package if not on |
sources |
name of classes with each layers parameters |
Passing Arguments¶
Model parameters that take arguments such as the data and simulation layers can
be specified as a tuple. For example, if we want to load a specific set of data
for PVPowerData
, like Tuscon data, then we could declare it in the model.
data = [(PVPowerData, {'filename': 'Tuscon.json'})]
Model Path¶
The modelpath
is an attribute that is used with the folder structure that is
created by simkit-quickstart
. You should set this to the PROJ_PATH
module constant created in your project package by simkit-quickstart
.
It’s confusing since the attribute is model path not project path, but
refers to the path that contains the layer folders created by
simkit-quickstart
. The value of modelpath
is prepended to the name of
the layer to set the relative path to look for files loaded by each
Layer
. For new parameter style models this is
actually only used by the data layer, since the model looks in the project
data folder created by simkit-quickstart
, unless path
is passed as a
sources
argument, then it appends the value of path
to the relative
path. So, still confused? Just set modelpath
to the name of the folder
containing the data folder, which should be PROJ_PATH
if you used
simkit-quickstart
, and you’ll be okay.
Running Model Simulation¶
Finally, let’s simulate the model. First import your model:
>>> from pvpower.sandia_perfmod_newstyle import NewSAPM
Then, instantiate the model:
>>> m = NewSAPM()
You can tell whether or not all of the layers are loaded in the model by checking its state:
>>> m.state # returns 'initialized'
If the model layers: outputs, calculations, formulas, data and simulations are not all initialized, then the state is “uninitialized”.
The simulations commands are listed in the model as m.commands
and tell you
which actions have been delegated to the command layer. In the PV system power
example, data is already loaded and we can now run the simulation of the model
with the start command.
>>> m.command('start')
In cases where data has not been preloaded in the model, the base simulation
class run
method first loads the specified data and then starts the
simulation.
>>> m.command('run', data={'PVPowerData': {'filename': 'data/Tuscon.json'}})
This is equivalent to calling those two commands consecutively. The model data
cannot be reloaded without clearing it from the registry first or you will get a
DuplicateRegItemError
that indicates which
fields exist already.
>>> m.command(
'load', data={'PVPowerData': {'filename': 'data/Tuscon.json'}}
... )
DuplicateRegItemError: Duplicate data can't be registered:
YEARLY
HOURLY
inverter_database
timestamp_count
elevation
Tamb
inverter
surface_azimuth
module
MONTHLY
timestamp_start
longitude
Uwind
module_database
latitude
timezone
The simulation has several properties that can be accessed directly from the object, for example to see if data is already loaded:
>>> m.simulations.objects['PVPowerSim'].is_data_loaded # True
Registries¶
All model parameters are stored in registries, which are a subclass of dictionary. The are collected in the model for easy access. To get an output you can access it by its keyname.
>>> annual_energy = sum(m.registries['outputs']['annual_energy']).to('kWh')
>>> print annual_energy # 258.8441299 kilowatt_hour