Getting started with GemsPy
The GEMS framework consists of an algebraic modelling language, close to mathematical syntax, and a data structure for describing energy systems.
More specifically, three main types of input files can be defined with the GEMS framework:
- Library files: describe abstract component models.
- System files: describe the graph of components that make up a system of interest; refer to model libraries (instantiation of abstract models) and to timeseries files.
- Timeseries files: the data of timeseries.
To get started with the syntax of these files, the reader can find basic examples below. A detailed introduction to the language is available on the GEMS documentation website.
Simple example of a library file
The first category of input files mentioned above comprises libraries of models. A simple library.yml file might look like this:
library:
id: basic
description: Basic library
port-types:
- id: flow
description: A port which transfers power flow
fields:
- id: flow
models:
- id: generator
description: A basic generator model
taxonomy-category: production
parameters:
- id: marginal_cost
time-dependent: false
scenario-dependent: false
- id: p_max
time-dependent: false
scenario-dependent: false
variables:
- id: generation
lower-bound: 0
upper-bound: p_max
ports:
- id: injection_port
type: flow
port-field-definitions:
- port: injection_port
field: flow
definition: generation
objective-contributions:
- id: obj
expression: expec(sum(marginal_cost * generation))
- id: node
description: A basic balancing node model
ports:
- id: injection_port
type: flow
binding-constraints:
- id: balance
expression: sum_connections(injection_port.flow) = 0
- id: load
description: A basic fixed demand model
parameters:
- id: load
time-dependent: true
scenario-dependent: true
ports:
- id: injection_port
type: flow
port-field-definitions:
- port: injection_port
field: flow
definition: -load
Simple example of system file
The second category of input files mentioned above corresponds to system files. A system file describes a practical instance that the user wants to simulate. Such a system.yml file might look like this:
system:
model-libraries: basic
nodes:
- id: N
model: basic.node
components:
- id: G1
model: basic.generator
properties:
- id: technology
value: nuclear
parameters:
- id: marginal_cost
time-dependent: false
scenario-dependent: false
value: 30
- id: p_max
time-dependent: false
scenario-dependent: false
value: 100
- id: G2
model: basic.generator
parameters:
- id: marginal_cost
time-dependent: false
scenario-dependent: false
value: 10
- id: p_max
time-dependent: false
scenario-dependent: false
value: 50
- id: D
model: basic.load
parameters:
- id: load
time-dependent: true
scenario-dependent: true
value: load_data
connections:
- component1: N
port1: injection_port
component2: D
port2: injection_port
- component1: N
port1: injection_port
component2: G1
port2: injection_port
- component1: N
port1: injection_port
component2: G2
port2: injection_port
Example of a timeseries file
Here is an example for the data file ~load_data~ mentioned in the system file above, in the case with 4 timesteps and 2 scenarios.
A data file may have a.txt or .csv extension.
Getting started with GemsPy
Installation
You can directly clone the GitHub repo of the project.
Interpretation and simulation with GemsPy
Here is an example of how to load component and library files, resolve the system, and solve the optimisation problem using the GemsPy package.
Option A — directory-based (recommended)
If your inputs are organised in a study directory (see Reading input files), the simplest way is:
from pathlib import Path
from gems.study.folder import load_study
from gems.session import SimulationSession
from gems.optim_config import load_optim_config
study = load_study(Path("my_study"))
optim_config = load_optim_config(Path("my_study/input/optim-config.yml"))
session = SimulationSession(study=study, optim_config=optim_config)
results = session.run()
Or, in a single call:
Option B — file-by-file (programmatic)
Here is the GemsPy syntax to read a test case described by
- A library of models:
library.yml - A system file:
system.yml - A set of timeseries located in the directory:
series_dir.
from pathlib import Path
from gems.model.parsing import parse_yaml_library
from gems.model.resolve_library import resolve_library
from gems.study.parsing import parse_yaml_components
from gems.study.resolve_components import resolve_system, build_data_base
with open("library.yml") as lib_file:
input_libraries = [parse_yaml_library(lib_file)]
with open("system.yml") as compo_file:
input_system = parse_yaml_components(compo_file)
result_lib = resolve_library(input_libraries)
system = resolve_system(input_system, result_lib)
database = build_data_base(input_system, Path(series_dir))
Building the optimisation problem
from gems.study import Study
from gems.simulation import build_problem, TimeBlock
problem = build_problem(
Study(system, database),
TimeBlock(1, list(range(timespan))),
scenario_ids=list(range(nb_scenarios)),
)