yaml

Other than Tessif, Calliope does usually read the model from yaml files. Examples of these are stored in the calliope folder inside the tessif examples data folder. Additionally any model created with tessif and transformed to calliope will be stored as yaml in the calliope folder inside the tessif write folder.

For deeper information on how to build, run and analyse an energy system model using calliope refer to the documentation of calliope.

Minimum working example

Note

Original yaml data can be found in tessif/examples/data/calliope/mwe/ as well as its subfolders.

Original Data yaml Files

mwe/model.yaml

import:  # Import files (path relative to model file)

- model_config/locations.yaml  # models technologies

- model_config/techs.yaml  # models locations

# Model configuration: all settings that affect the built model
model:

  name: Minimum_Working_Example

  calliope_version: 0.6.6-post1

  timeseries_data_path: timeseries_data

  subset_time:
  - '1990-07-13 00:00:00'
  - '1990-07-13 03:00:00'

group_constraints:

  systemwide_emission_cap:
    cost_max:
      emissions:

run:

  solver: cbc

  cyclic_storage: false

  objective_options.cost_class:
    monetary: 1

mwe/model_config/techs.yaml

# calliope defaults are $ and kW, but since there is no conversion
# any unit can be chosen as long as it is used consistent.
# So defaults here are, just like in tessif, usually € and MW
techs:

  electricity_Demand:
    essentials:
      name: Demand
      parent: demand
      carrier: electricity
    constraints:
      energy_con: true
      resource_unit: energy
      resource: file=electricity_Demand.csv:electricity_Demand
      force_resource: true

  Gas Station:
    essentials:
      name: Gas Station
      parent: supply
      carrier_out: fuel
    constraints:
      resource: .inf
      energy_ramping: true

  Generator:
    essentials:
      name: Generator
      parent: conversion
      carrier_in: fuel
      carrier_out: electricity
    constraints:
      energy_eff: 0.42
      energy_ramping: true
    costs:
      monetary:
        om_con: 0
        om_prod: 2

  Battery:
    essentials:
      name: Battery
      parent: storage
      carrier: electricity
    constraints:
      storage_cap_max: 20
      energy_cap_min: 20
      energy_cap_max: 20
      energy_ramping: true
      storage_cap_min: 20
      storage_initial: 0.5
    costs:
      monetary:
        om_prod: 0.1

  fuel transmission:
    essentials:
      name: fuel transmission
      parent: transmission
      carrier: fuel
    constraints:
      one_way: true

  electricity transmission:
    essentials:
      name: electricity transmission
      parent: transmission
      carrier: electricity
    constraints:
      one_way: true

mwe/model_config/locations.yaml

locations:

  Pipeline:
    coordinates:
      lat: 0.0
      lon: 0.0

  Powerline:
    coordinates:
      lat: 0.0
      lon: 0.0

  electricity_Demand location:
    coordinates:
      lat: 0.0
      lon: 0.0
    techs:
      electricity_Demand:

  Gas Station location:
    coordinates:
      lat: 0.0
      lon: 0.0
    techs:
      Gas Station:

  Generator location:
    coordinates:
      lat: 0.0
      lon: 0.0
    techs:
      Generator:

  Battery location:
    coordinates:
      lat: 0.0
      lon: 0.0
    techs:
      Battery:

links:

  Gas Station location,Pipeline:
    techs:
      fuel transmission:
        constraints:
          one_way: true

  Pipeline,Generator location:
    techs:
      fuel transmission:
        constraints:
          one_way: true

  Battery location,Powerline:
    techs:
      electricity transmission:
        constraints:
          one_way: false

  Generator location,Powerline:
    techs:
      electricity transmission:
        constraints:
          one_way: true

  Powerline,electricity_Demand location:
    techs:
      electricity transmission:
        constraints:
          one_way: true

Use Case

  1. Read the energy system model and optimize it

    >>> from tessif.frused.paths import example_dir
    >>> import pprint
    >>> import calliope
    >>> calliope.set_log_verbosity('ERROR', include_solver_output=False)
    >>> es = calliope.Model(f'{example_dir}/data/calliope/mwe/model.yaml')
    >>> es.run()
    
  2. Print out the objective value

    >>> # See the set production costs
    >>> print(f'Objective: {es.results.objective_function_value}')
    Objective: 61.0
    
  3. Use Tessif post processing

    >>> from tessif.transform.es2mapping.cllp import LoadResultier
    >>> loads = LoadResultier(es)
    >>> print(loads.node_load['Powerline'])
    Powerline            Battery  Generator  Battery  Demand
    1990-07-13 00:00:00    -10.0       -0.0      0.0    10.0
    1990-07-13 01:00:00     -0.0      -10.0      0.0    10.0
    1990-07-13 02:00:00     -0.0      -10.0      0.0    10.0
    1990-07-13 03:00:00     -0.0      -10.0      0.0    10.0
    
    >>> from tessif.transform.es2mapping.cllp import IntegratedGlobalResultier
    >>> global_res = IntegratedGlobalResultier(es)
    >>> pprint.pprint(global_res.global_results)
    {'capex (ppcd)': 0.0,
     'costs (sim)': 61.0,
     'emissions (sim)': 0.0,
     'opex (ppcd)': 61.0}
    

Fully parameterized working example

Note

Original yaml data can be found in tessif/examples/data/calliope/fpwe/ as well as its subfolders.

Original Data – yaml Files

fpwe/model.yaml

#  this file is called for building the model with calliope

import:  # calling the needed yaml files with path relative to this file

- model_config/locations.yaml

- model_config/techs.yaml

model:

  name: Fully_Parameterized_Working_Example

  calliope_version: 0.6.6-post1  # optional but useful if this is going to be used in future for other calliope versions and problems occure

  timeseries_data_path: timeseries_data  # folder name, where the .csv files are; relative to this yaml file

  subset_time:  # optional, but useful e.g. for testing to set timeframe to 3 steps, when csv actually are 8760
  - '1990-07-13 00:00:00'
  - '1990-07-13 02:00:00'

group_constraints:  # optional

  systemwide_emission_cap:
    cost_max:
      emissions:

run:

  solver: cbc  # default solver in calliope

  cyclic_storage: false  # all storages are either cyclic or none is

  objective_options.cost_class:  # only monetary are objective to minimize, no emission cost
    monetary: 1

fpwe/model_config/techs.yaml

# This example is build to be like Tessif fpwe and describe the most common
# used calliope components with most important parameters a little bit.
#
# For more information see also
# https://calliope.readthedocs.io/en/stable/user/config_defaults.html#group-constraints
# as well as
# in installed packages in calliope - config - defaults.yaml

techs:

# Demand
  electricity_Demand:  # this name cant be 'demand' cause demand is already a 'parent' name ! (same for other preset parents)

    essentials:
      name: Demand.Germany.Power.electricity.demand  # This way tessif uid is stored in calliope. name.region.sector.carrier.node_type
      color: '#cc0033'  # colors can be set for native calliope visualization
      parent: demand   # parent gives some presets like energy production is false and consumption is true. Custom parents can be defined as tech_group
      carrier: electricity

    constraints:
      energy_con: true
      resource_unit: energy
      resource: file=electricity_Demand.csv:electricity_Demand  # Resource can either be like Tessif's accumulated amount or give an upper bound as timeseries. Timeseries give in " file=file_name.csv:column_name " style. Negative signs for demands are needed.
      force_resource: true  # can force to use full resource rather than making it optional. Preset on demands is true while sources are false

    costs:
      monetary:
        om_con: 0  # Costs to produce 1 unit of carrier output.
      emissions:
        om_con: 0  # Emissions are handled like costs. They can be (if wanted) included in solver objective to minimize. In tessif they are not included.


# Supply
  Gas Station:

    essentials:
      name: Gas Station.Germany.Power.Gas.source
      color: '#FF7700'
      parent: supply
      carrier_out: fuel

    constraints:
      energy_prod: true
      resource: .inf
      resource_unit: energy
      energy_cap_min: 100.0  # The tessif installed capacity will be called here since calliope does not have installed capacities. Except if installed is infinite
      energy_cap_max: 100.0
      energy_cap_min_use: 0.0
      energy_eff: 1  # sources do have an efficiency in calliope.
      energy_ramping: true  # Energy ramping as a fraction of capacity or true which is same as 1. Important cause default is false which equals 0

    costs:
      monetary:
        om_prod: 10
      emissions:
        om_prod: 3

  Solar Panel:

    essentials:
      name: Solar Panel.Germany.Power.electricity.Renewable
      color: '#FF7700'
      parent: supply
      carrier_out: electricity

    constraints:
      energy_prod: true
      resource: file=Solar Panel.csv:Solar Panel
      resource_unit: energy_per_cap
      energy_cap_min: 20.0
      energy_cap_max: 20.0
      energy_eff: 1
      energy_ramping: true
      force_resource: true

    costs:
      monetary:
        om_prod: 0
      emissions:
        om_prod: 0

# Conversion
  Generator:

    essentials:
      name: Generator.Germany.Power.electricity.transformer
      color: '#99ccff'
      parent: conversion
      carrier_in: fuel
      carrier_out: electricity

    constraints:
      energy_con: true
      energy_prod: true
      energy_cap_min: 15.0
      energy_cap_max: 15.0
      energy_cap_min_use: 0.0
      energy_eff: 0.42
      energy_ramping: true

    costs:
      monetary:
        om_con: 0
        om_prod: 10
      emissions:
        om_con: 0
        om_prod: 10

# Storage
  Battery:

    essentials:
      name: Battery.Germany.Power.electricity.storage
      color: '#ffcc00'
      parent: storage
      carrier: electricity

    constraints:
      energy_con: true
      energy_prod: true
      storage_cap_max: 10
      energy_cap_min: 10
      energy_cap_max: 10  # Energy flow capacity maximum for charge as well as discharge.
      energy_cap_min_use: 0.0
      energy_eff: 1.0  # this efficiency is taken into account on charge as well as discharge
      energy_ramping: true
      storage_cap_min: 10
      storage_initial: 0.9  # 9/10 units is in storage when starting the optimization.
      storage_loss: 0.1  # each timestep 1/10 units of storage state of charge get lost. No standing loss from timestep -1 (initial) to 0 
      energy_cap_per_storage_cap_min: 0
      energy_cap_per_storage_cap_max: 1

    costs:
      monetary:
        om_prod: 0
      emissions:
        om_prod: 0

# transmissions to connect the technologies which will all be located in different locations
  fuel transmission:

    essentials:
      name: fuel transmission
      color: '#8465A9'
      parent: transmission
      carrier: fuel

    constraints:
      energy_eff: 1
      one_way: true

  electricity transmission:

    essentials:
      name: electricity transmission
      color: '#8465A9'
      parent: transmission
      carrier: electricity

    constraints:
      energy_eff: 1
      one_way: true

fpwe/model_config/locations.yaml

locations:

  Pipeline:
    coordinates:
      lat: 42.0  # different locations can have same coordinates
      lon: 42.0  # different locations can have same coordinates

  Powerline:
    coordinates:
      lat: 42.0
      lon: 42.0

  electricity_Demand location:
    coordinates:
      lat: 42.0
      lon: 42.0
    techs:  # calling all technologies that are acting in this location.
      electricity_Demand:

  Gas Station location:
    coordinates:
      lat: 42.0
      lon: 42.0
    techs:
      Gas Station:

  Solar Panel location:
    coordinates:
      lat: 42.0
      lon: 42.0
    techs:
      Solar Panel:

  Generator location:
    coordinates:
      lat: 42.0
      lon: 42.0
    techs:
      Generator:

  Battery location:
    coordinates:
      lat: 42.0
      lon: 42.0
    techs:
      Battery:

links:

  Gas Station location,Pipeline:
    techs:
      fuel transmission:
        constraints:
          one_way: true

  Pipeline,Generator location:
    techs:
      fuel transmission:
        constraints:
          one_way: true

  Battery location,Powerline:
    techs:
      electricity transmission:
        constraints:
          one_way: false

  Generator location,Powerline:
    techs:
      electricity transmission:
        constraints:
          one_way: true

  Solar Panel location,Powerline:
    techs:
      electricity transmission:
        constraints:
          one_way: true

  Powerline,electricity_Demand location:
    techs:
      electricity transmission:
        constraints:
          one_way: true


# a small example like this doesnt need multiple locations
# connected via transmission lines. 
# And all techs could be stored in one location instead

# But keep in mind for tessif post processing different nodes are needed,
# and each location is acting like a node.

Use Case

  1. Read the energy system model and optimize it

    >>> from tessif.frused.paths import example_dir
    >>> import pprint
    >>> import calliope
    >>> calliope.set_log_verbosity('ERROR', include_solver_output=False)
    >>> es = calliope.Model(f'{example_dir}/data/calliope/fpwe/model.yaml')
    >>> es.run()
    
  2. Print out the objective value

    >>> # See the set production costs
    >>> print(f'Objective: {es.results.objective_function_value}')
    Objective: 104.809524
    
  3. Use Tessif post processing

    >>> from tessif.transform.es2mapping.cllp import LoadResultier
    >>> loads = LoadResultier(es)
    >>> print(loads.node_load['Powerline'])
    Powerline            Battery  Generator  Solar Panel  Battery  Demand
    1990-07-13 00:00:00     -0.0       -0.0        -12.0      1.0    11.0
    1990-07-13 01:00:00     -8.0       -0.0         -3.0      0.0    11.0
    1990-07-13 02:00:00     -0.9       -3.1         -7.0      0.0    11.0
    
    >>> from tessif.transform.es2mapping.cllp import IntegratedGlobalResultier
    >>> global_res = IntegratedGlobalResultier(es)
    >>> pprint.pprint(global_res.global_results)
    {'capex (ppcd)': 0.0,
     'costs (sim)': 105.0,
     'emissions (sim)': 53.0,
     'opex (ppcd)': 105.0}
    

CHP expansion example

Note

Original yaml data can be found in tessif/examples/data/calliope/chp_expansion/ as well as its subfolders.

This energy system model was created to further inspect the parameter definitions of CHPs when they are expandable. It can be optimized using calliope and then be inspected using either the usual calliope commands as well as the tessif post processing.

Original Data – yaml Files

chp_expansion/model.yaml

# CHP expansion example to further inspect the treatment of
# parameters like energy_cap as it is not trivial whether it 
# refers to in or output

import:

- model_config/techs.yaml

- model_config/locations.yaml

model:

  name: CHP_Example

  calliope_version: 0.6.6-post1

  timeseries_data_path: timeseries_data

  subset_time:
  - '1990-07-13 00:00:00'
  - '1990-07-13 03:00:00'

group_constraints:

  systemwide_emission_cap:
    cost_max:
      emissions:

run:

  solver: cbc

  cyclic_storage: false

  objective_options.cost_class:
    monetary: 1

chp_expansion/model_config/techs.yaml

techs:

  Power Demand:
    essentials:
      name: Power Demand.None.None.None.None
      parent: demand
      carrier: electricity
    constraints:
      energy_con: true
      resource_unit: energy
      resource: file=Power Demand.csv:Power Demand
      force_resource: true
    costs:
      monetary:
        om_con: 0.0
      emissions:
        om_con: 0.0

  Heat Demand:
    essentials:
      name: Heat Demand.None.None.None.None
      parent: demand
      carrier: heat
    constraints:
      energy_con: true
      resource_unit: energy
      resource: file=Heat Demand.csv:Heat Demand
      force_resource: true
    costs:
      monetary:
        om_con: 0.0
      emissions:
        om_con: 0.0

  Gas Source:
    essentials:
      name: Gas Source.None.None.None.None
      parent: supply
      carrier_out: gas
    constraints:
      energy_prod: true
      resource: inf
      resource_unit: energy
      energy_cap_min: 0
      energy_cap_max: .inf
      energy_cap_min_use: 0
      energy_eff: 1
      energy_ramping: true
    costs:
      monetary:
        om_prod: 0.0
      emissions:
        om_prod: 0.0

  Backup Power:
    essentials:
      name: Backup Power.None.None.None.None
      parent: supply
      carrier_out: electricity
    constraints:
      energy_prod: true
      resource: inf
      resource_unit: energy
      energy_cap_min: 0
      energy_cap_max: .inf
      energy_cap_min_use: 0
      energy_eff: 1
      energy_ramping: true
    costs:
      monetary:
        om_prod: 1000
      emissions:
        om_prod: 0.0

  Backup Heat:
    essentials:
      name: Backup Heat.None.None.None.None
      parent: supply
      carrier_out: heat
    constraints:
      energy_prod: true
      resource: inf
      resource_unit: energy
      energy_cap_min: 0
      energy_cap_max: .inf
      energy_cap_min_use: 0
      energy_eff: 1
      energy_ramping: true
    costs:
      monetary:
        om_prod: 1000
      emissions:
        om_prod: 0.0

  CHP:
    essentials:
      name: CHP.None.None.None.None
      parent: conversion_plus
      carrier_in: gas
      carrier_out: electricity
      primary_carrier_out: electricity
      carrier_out_2: heat
    constraints:
      energy_con: true
      energy_prod: true
      carrier_ratios.carrier_out_2.heat: 0.8
      energy_eff: 0.5
      energy_cap_max: 8
      energy_cap_min: 0
      energy_ramping: true
      lifetime: 0.00045662100456621003
    costs:
      monetary:
        om_prod: 1
        energy_cap: 1
        interest_rate: 0
      emissions:
        om_prod: 1

  gas transmission:
    essentials:
      name: gas transmission
      parent: transmission
      carrier: gas
    constraints:
      energy_eff: 1
      one_way: true

  electricity transmission:
    essentials:
      name: electricity transmission
      parent: transmission
      carrier: electricity
    constraints:
      energy_eff: 1
      one_way: true

  heat transmission:
    essentials:
      name: heat transmission
      parent: transmission
      carrier: heat
    constraints:
      energy_eff: 1
      one_way: true

chp_expansion/model_config/locations.yaml

locations:

  Gas Grid:
    coordinates:
      lat: 0.0
      lon: 0.0

  Powerline:
    coordinates:
      lat: 0.0
      lon: 0.0

  Heat Grid:
    coordinates:
      lat: 0.0
      lon: 0.0

  Power Demand location:
    coordinates:
      lat: 0.0
      lon: 0.0
    techs:
      Power Demand:

  Heat Demand location:
    coordinates:
      lat: 0.0
      lon: 0.0
    techs:
      Heat Demand:

  Gas Source location:
    coordinates:
      lat: 0.0
      lon: 0.0
    techs:
      Gas Source:

  Backup Power location:
    coordinates:
      lat: 0.0
      lon: 0.0
    techs:
      Backup Power:

  Backup Heat location:
    coordinates:
      lat: 0.0
      lon: 0.0
    techs:
      Backup Heat:

  CHP location:
    coordinates:
      lat: 0.0
      lon: 0.0
    techs:
      CHP:

links:

  Gas Source location,Gas Grid:
    techs:
      gas transmission:
        constraints:
          one_way: true

  Gas Grid,CHP location:
    techs:
      gas transmission:
        constraints:
          one_way: true

  CHP location,Powerline:
    techs:
      electricity transmission:
        constraints:
          one_way: true

  Backup Power location,Powerline:
    techs:
      electricity transmission:
        constraints:
          one_way: true

  Powerline,Power Demand location:
    techs:
      electricity transmission:
        constraints:
          one_way: true

  Backup Heat location,Heat Grid:
    techs:
      heat transmission:
        constraints:
          one_way: true

  CHP location,Heat Grid:
    techs:
      heat transmission:
        constraints:
          one_way: true

  Heat Grid,Heat Demand location:
    techs:
      heat transmission:
        constraints:
          one_way: true

Use Case

  1. Read the energy system model and optimize it

    >>> from tessif.frused.paths import example_dir
    >>> import pprint
    >>> import calliope
    >>> calliope.set_log_verbosity('ERROR', include_solver_output=False)
    >>> es = calliope.Model(f'{example_dir}/data/calliope/chp_expansion/model.yaml')
    >>> es.run()
    
  2. Print out the flow result

    >>> # See the set production costs
    >>> print(es.inputs.cost_om_prod.loc[{'loc_techs_om_cost': 'CHP location::CHP'}].loc[{'costs': 'monetary'}].data)
    array(1.)
    
    >>> # See the production result for each CHP carrier
    >>> print(es.get_formatted_array('carrier_prod').loc[{'carriers':'electricity'}].sum('locs').to_pandas().T['CHP'])
    timesteps
    1990-07-13 00:00:00    8.0
    1990-07-13 01:00:00    8.0
    1990-07-13 02:00:00    8.0
    1990-07-13 03:00:00    8.0
    Name: CHP, dtype: float64
    >>> print(es.get_formatted_array('carrier_prod').loc[{'carriers':'heat'}].sum('locs').to_pandas().T['CHP'])
    timesteps
    1990-07-13 00:00:00    6.4
    1990-07-13 01:00:00    6.4
    1990-07-13 02:00:00    6.4
    1990-07-13 03:00:00    6.4
    Name: CHP, dtype: float64
    
    >>> # See the variable costs of the CHP
    >>> print(es.get_formatted_array('cost_var').loc[{'costs':'monetary'}].loc[{'locs':'CHP location'}].sum('techs'))
    Out[64]:
    <xarray.DataArray 'cost_var' (timesteps: 4)>
    array([8., 8., 8., 8.])
    Coordinates:
        costs      <U8 'monetary'
        locs       <U12 'CHP location'
      * timesteps  (timesteps) datetime64[ns] 1990-07-13 ... 1990-07-13T03:00:00
    

So it can be seen that production costs of CHP refer to the primary output.

  1. Print out the capacity

    >>> # See the input expansion costs
    >>> print(es.get_formatted_array('cost_energy_cap').sum('locs').to_pandas().T)
    costs  emissions  monetary
    techs
    CHP          0.0       1.0
    
    >>> # See the expansion cost result
    >>> print(es.get_formatted_array('cost_investment').sum('locs').to_pandas().T)
    costs  emissions  monetary
    techs
    CHP          0.0       8.0
    

With the already known flow maximum it can be seen that the energy capacity costs of CHP refer to the primary output.

  1. Compare to tessif post processing

    >>> from tessif.transform.es2mapping.cllp import FlowResultier
    >>> flow = FlowResultier(es)
    >>> pprint.pprint(flow.edge_net_energy_flow)
    {Edge(source='Backup Heat', target='Heat Grid'): 14.4,
     Edge(source='Backup Power', target='Powerline'): 8.0,
     Edge(source='CHP', target='Heat Grid'): 25.6,
     Edge(source='CHP', target='Powerline'): 32.0,
     Edge(source='Gas Grid', target='CHP'): 64.0,
     Edge(source='Gas Source', target='Gas Grid'): 64.0,
     Edge(source='Heat Grid', target='Heat Demand'): 40.0,
     Edge(source='Powerline', target='Power Demand'): 40.0}
    
    >>> pprint.pprint(flow.edge_specific_flow_costs)
    {Edge(source='Backup Heat', target='Heat Grid'): 1000.0,
     Edge(source='Backup Power', target='Powerline'): 1000.0,
     Edge(source='CHP', target='Heat Grid'): 0,
     Edge(source='CHP', target='Powerline'): 1.0,
     Edge(source='Gas Grid', target='CHP'): 0,
     Edge(source='Gas Source', target='Gas Grid'): 0.0,
     Edge(source='Heat Grid', target='Heat Demand'): 0.0,
     Edge(source='Powerline', target='Power Demand'): 0.0}
    
    >>> from tessif.transform.es2mapping.cllp import CapacityResultier
    >>> cap_res = CapacityResultier(es)
    >>> print(cap_res.node_original_capacity['CHP'])
    Heat Grid    0.0
    Powerline    0.0
    dtype: float64
    >>> print(cap_res.node_installed_capacity['CHP'])
    Heat Grid    6.4
    Powerline    8.0
    dtype: float64
    >>> print(cap_res.node_expansion_costs['CHP'])
    Heat Grid    0.0
    Powerline    1.0
    dtype: float64
    
    >>> from tessif.transform.es2mapping.cllp import LoadResultier
    >>> loads = LoadResultier(es)
    >>> print(loads.node_load['Powerline'])
    Powerline            Backup Power  CHP  Power Demand
    1990-07-13 00:00:00          -2.0 -8.0          10.0
    1990-07-13 01:00:00          -2.0 -8.0          10.0
    1990-07-13 02:00:00          -2.0 -8.0          10.0
    1990-07-13 03:00:00          -2.0 -8.0          10.0
    >>> print(loads.node_load['Heat Grid'])
    Heat Grid            Backup Heat  CHP  Heat Demand
    1990-07-13 00:00:00         -3.6 -6.4         10.0
    1990-07-13 01:00:00         -3.6 -6.4         10.0
    1990-07-13 02:00:00         -3.6 -6.4         10.0
    1990-07-13 03:00:00         -3.6 -6.4         10.0
    
    >>> from tessif.transform.es2mapping.cllp import IntegratedGlobalResultier
    >>> global_res = IntegratedGlobalResultier(es)
    >>> pprint.pprint(global_res.global_results)
    {'capex (ppcd)': 8.0,
     'costs (sim)': 22440.0,
     'emissions (sim)': 32.0,
     'opex (ppcd)': 22432.0}
    
    >>> print(f'Objective: {es.results.objective_function_value}')
    Objective: 22440.0