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 auto-generated docs for custom math examples #508

Closed
wants to merge 33 commits into from
Closed
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
f5cfe90
Move change to correct backend file
brynpickering Oct 6, 2023
4c1abe2
Merge branch 'main' into update-remove-equals-and-scale
brynpickering Oct 24, 2023
e4e8be0
Remove `_equals` and `_scale` params
brynpickering Apr 21, 2023
e2912be
Clean diff by reverting to 4 space YAML indent
brynpickering Apr 25, 2023
1f24195
Minor fixes
brynpickering May 29, 2023
3895141
Add test to increase coverage
brynpickering May 29, 2023
4fa3e6a
Minor docs fix
brynpickering Oct 2, 2023
644edb6
run/model config -> config.init/build/solve
brynpickering Oct 5, 2023
a8db367
Update top-level param config
brynpickering Oct 11, 2023
d73dc96
Minor fixes
brynpickering Oct 24, 2023
34dacd0
Add comments to config options
brynpickering Oct 24, 2023
5fcabf0
Merge branch 'main' into update-top-level-config-params
brynpickering Oct 24, 2023
7549643
Minor fixes
brynpickering Oct 25, 2023
c271b0b
Create `definition_matrix`; new where helper func
brynpickering Oct 6, 2023
b3c985a
Fixes to handle definition_matrix
brynpickering Oct 6, 2023
2b5bf13
Add docstrings
brynpickering Oct 9, 2023
8167a41
Updates to clean up docs
brynpickering Oct 9, 2023
e3b66a1
Create `definition_matrix`; new where helper func
brynpickering Oct 6, 2023
79c07ff
Updates to clean up docs
brynpickering Oct 9, 2023
3f8aa87
Fix clean-up of model data with def matrix
brynpickering Oct 25, 2023
78b3ba8
Remove rogue file
brynpickering Oct 25, 2023
49231e6
Pre-commit run all
brynpickering Oct 25, 2023
c721d2e
Add custom math examples
brynpickering Oct 10, 2023
a27770b
Fix base math
brynpickering Oct 10, 2023
c37aa94
Start adding tests
brynpickering Oct 11, 2023
89d472d
Clean up example math & issues in code; add tests
brynpickering Oct 13, 2023
3903aea
Verbose constraint coords; minor name fixes
brynpickering Oct 25, 2023
dd01765
Track dev requirements in mamba CI cache decision
brynpickering Oct 25, 2023
f5f8696
Merge branch 'main' into feature-custom-math-examples
brynpickering Oct 26, 2023
3537c52
Add helper function test
brynpickering Oct 26, 2023
7ccc4c5
Add auto-generated docs for custom math examples
sjpfenninger Oct 27, 2023
639ca41
Move `# noqa: E402`
sjpfenninger Oct 27, 2023
edeffe9
ruff-organise imports
sjpfenninger Oct 27, 2023
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
2 changes: 1 addition & 1 deletion .github/workflows/commit-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- uses: mamba-org/setup-micromamba@v1
with:
micromamba-version: latest
environment-name: ${{ github.event.repository.name }}-ubuntu-latest-311
environment-name: ${{ github.event.repository.name }}-ubuntu-latest-311-${{ hashFiles('requirements/dev.txt') }}
environment-file: requirements/base.txt
create-args: >-
-f requirements/dev.txt
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pr-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
- uses: mamba-org/setup-micromamba@v1
with:
micromamba-version: latest
environment-name: ${{ github.event.repository.name }}-${{ matrix.os }}-3${{ matrix.py3version }}
environment-name: ${{ github.event.repository.name }}-${{ matrix.os }}-3${{ matrix.py3version }}-${{ hashFiles('requirements/dev.txt') }}
environment-file: requirements/base.txt
create-args: >-
-f requirements/dev.txt
Expand Down
Empty file added doc/_generated/.gitkeep
Empty file.
58 changes: 58 additions & 0 deletions doc/_static/custom_math/annual_energy_balance.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# title: Annual energy balance

# description: |
# Limit or set the total (e.g. annual) outflow of a technology to a specified absolute value.
#
# New technology-level parameters:
#
# * ``annual_flow_max``
# * ``annual_source_max``
#
# New top-level parameters:
#
# * ``annual_flow_max`` (if grouping technologies and/or nodes)
# * ``flow_max_group`` (if grouping technologies and/or nodes)

# ---

constraints:
annual_energy_balance_per_tech_and_node:
description: Limit total technology annual energy production at each possible deployment site.
foreach: [nodes, techs]
where: annual_flow_max
equations:
- expression: "sum(flow_out, over=[carriers, timesteps]) <= annual_flow_max"

annual_energy_balance_global_per_tech:
description: Limit total technology annual energy production across all possible deployment sites.
foreach: [techs]
where: annual_flow_max
equations:
- expression: "sum(flow_out, over=[nodes, carriers, timesteps]) <= annual_flow_max"

annual_energy_balance_global_multi_tech:
description: Limit total combined technology annual energy production across all possible deployment sites.
# To slice a model component with a list of values, we need to use referenced `slices`.
where: annual_flow_max AND flow_max_group
equations:
- expression: "sum(flow_out[techs=$techs], over=[nodes, techs, carriers, timesteps]) <= annual_flow_max"
slices:
techs:
- expression: flow_max_group

annual_energy_balance_total_source_availability:
description: >
Limit total flow into the system from a particular source.
NOTE: this only works for supply_plus technologies.
For `supply` technologies you will need to convert `flow_out` to `flow_in` using `energy_eff` and limit that.
foreach: [techs]
where: source_use AND annual_source_max
equations:
- expression: "sum(source_use, over=[nodes, techs, timesteps]) <= annual_source_max"

annual_energy_balance_total_sink_availability:
description: Limit total flow out of the system into a sink that is not pinned by `sink_equals`.
foreach: [techs]
where: inheritance(demand) AND annual_sink_max
equations:
- expression: "sum(flow_in, over=[nodes, carriers, timesteps]) <= annual_sink_max"
144 changes: 144 additions & 0 deletions doc/_static/custom_math/chp_htp.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# title: CHP plants

# description: |
# Set Combined heat and power (CHP) plant heat to power operational zones.
# There are three types of CHP that can be described by the following constraints:
# 1. CHPs with extraction (condensing) turbines, where some electrical efficiency can be sacrificed by diverting high-temperature steam to provide more heat (following the extraction (cv) line).
# At maximum electrical efficiency, some heat can still be generated from the low-temperature steam output (following the backpressure (cb) line).
# The following figure shows the 2D plane of electricity and heat generation; there is a third dimension not shown here: fuel consumption.
#
# .. code-block:: text
#
# Along the cv line, fuel consumption remains constant.
# ^
# |Electricity
# |
# |----
# | \------- Cv
# | \-------
# | \-------
# | \------
# | --/
# | operating region --/
# | --/
# | --/
# | --/
# | --/
# | --/ Cb
# | --/
# | --/
# | --/
# | -/ Heat
# -------------------------------------->
#
# 2. CHPs without extraction turbines, but with auxiliary boilers that can be used to divert fuel use for direct heat generation.
# At maximum electrical efficiency, some heat can be generated from the low-temperature steam output (following the backpressure (cb) line).
# For the same fuel input, electricity output can be sacrificed by diverting some fuel to direct use in a boiler, with its own efficiency.
# This leads to two sources of heat output (E = electricity output): H1 = E / cb; H2 / boiler_eff + E / turbine_eff = fuel_consumption. Total heat output H is then H1 + H2.
# The following figure shows the 2D plane of electricity and heat generation; there is a third dimension not shown here: fuel consumption.
#
# .. code-block:: text
#
# ^
# |Electricity
# |
# | --/
# | Cb --/ \-
# | --/ \-
# | --/ \-
# | --/ \-
# | --/ operating \-
# | -/ region \- Heat
# ---------------------------------------->
#
# 3. CHPs without extraction turbines and without an auxiliary boiler.
# Here, there is no operating region; the output must follow the backpressure line.
#
# .. code-block:: text
#
# ^
# |Electricity
# |
# | /--
# | /--
# | Cb /--
# | /--
# | /-
# | /--
# | /--
# | /--
# | /-
# | /-- Heat
# -------------------------------------->
#
# New technology-level parameters:
#
# * ``turbine_type`` (used to group constraints together)
# * ``power_loss_factor``
# * ``power_to_heat_ratio``
# * ``boiler_eff``

# ---

constraints:
# Extraction turbine constraints
# ~~
chp_extraction_line:
description: >
Set the extraction line for combined heat and power plants with extraction turbines.
`power_loss_factor` is also referred to as simply `cv`.
foreach: [nodes, techs, timesteps]
where: turbine_type=extraction
equations:
- expression: >
flow_out[carriers=electricity]
<= (reduce_carrier_dim(flow_in, carrier_tier=in) * energy_eff)
- (flow_out[carriers=heat] * power_loss_factor)

chp_backpressure_line_min:
description: >
Set the backpressure line as a lower bound for electricity generation in combined heat and power plants with extraction turbines.
`power_to_heat_ratio` is also referred to as the `backpressure ratio` or simply `cb`.
foreach: [nodes, techs, timesteps]
where: turbine_type=extraction
equations:
- expression: flow_out[carriers=electricity] >= flow_out[carriers=heat] * power_to_heat_ratio
# ~~

# Backpressure with direct boiler option
# ~~
chp_backpressure_line_max:
description: >
Set the backpressure line as a lower bound for heat generation in combined heat and power plants without extraction turbines, but with the option to divert fuel to use in direct heat generation (e.g., via a boiler).
`power_to_heat_ratio` is also referred to as the `backpressure ratio` or simply `cb`.
foreach: [nodes, techs, timesteps]
where: turbine_type=backpressure AND boiler_eff
equations:
- expression: flow_out[carriers=electricity] <= flow_out[carriers=heat] * power_to_heat_ratio

chp_divert_fuel_to_boiler:
description: >
Divert fuel input from use in combined heat and power generation to be used in direct heat generation (e.g., via a boiler).
`heat_eff` is the boiler efficiency.
`power_to_heat_ratio` is also referred to as the `backpressure ratio` or simply `cb`.
foreach: [nodes, techs, timesteps]
where: turbine_type=backpressure AND boiler_eff
equations:
- expression: >
flow_out[carriers=heat]
<= (reduce_carrier_dim(flow_in, carrier_tier=in) * boiler_eff)
- (flow_out[carriers=electricity] * (
(boiler_eff / energy_eff) - (1 / power_to_heat_ratio)
)
)
# ~~

# Backpressure only
chp_backpressure_line_equals:
description: >
Fix the backpressure line for combined heat and power plants without extraction turbines.
`power_to_heat_ratio` is also referred to as the `backpressure ratio` or simply `cb`.
foreach: [nodes, techs, timesteps]
where: turbine_type=backpressure AND NOT boiler_eff
equations:
- expression: flow_out[carriers=electricity] == flow_out[carriers=heat] * power_to_heat_ratio
73 changes: 73 additions & 0 deletions doc/_static/custom_math/demand_share_per_timestep_decision.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# title: Demand share per timestep as decision variable

# description: |
# Allows the model to decide on how a fraction of demand for a carrier is met by the given group of technologies, which will each have the same share in each timestep.
# Variables and constraints defined here could be extended to iterate over nodes and over carriers if desired.
# If summing over nodes, remove the summation over nodes in the constraints and add it into the list in `demand_share_per_timestep_decision_sum` (if using).
# If summing over carriers, the slicing of `sink_equals` will need to change per carrier by using a where statement in `slices: ...`.
#
# The share is relative to the flow `sink` from a specified `demand` technology (or group thereof) only.
#
# Specifying `relaxation` inside the constraint to a non-zero value allows the constraint some flexibility around a given value, making a model easier to solve.
#
# New top-level parameters:
#
# * ``relaxation`` (defined here directly)
# * ``demand_share_limit`` (defined here directly)

# ---

variables:
demand_share_per_timestep_decision:
description: Relative share of demand that a given technology must meet per node.
unit: fraction
foreach: [nodes, techs]
where: NOT config.mode=operate AND decide_demand_share
bounds:
min: 0
max: .inf

# The two main constraints enforce that the shares are the same in each timestep,
# with an optional relaxation.

constraints:
demand_share_per_timestep_decision_main_min:
description: Limit the lower bound of a technology's outflow to the share of demand that the model has decided it will meet.
foreach: [nodes, techs, timesteps]
where: demand_share_per_timestep_decision
equations:
- expression: >
flow_out[carriers=$carrier] >=
(1 - $relaxation) * select_from_lookup_arrays(sink_equals, techs=decide_demand_share) * demand_share_per_timestep_decision
sub_expressions:
# 0 == no relaxation, 0.01 == 1% relaxation (lhs == rhs -> lhs >= 0.99 * rhs & lhs <= 1.01 * rhs)
relaxation: &relaxation_component
- where: demand_share_relaxation
expression: demand_share_relaxation
- where: NOT demand_share_relaxation
expression: "0"
slices: &slice
carrier:
- expression: demand_share_carrier # assigned as a top-level parameter

demand_share_per_timestep_decision_main_max:
description: Limit the upper bound of a technology's outflow to the share of demand that the model has decided it will meet.
foreach: [nodes, techs, timesteps]
where: demand_share_per_timestep_decision
equations:
- expression: >
flow_out[carriers=$carrier] <=
(1 + $relaxation) * select_from_lookup_arrays(sink_equals, techs=decide_demand_share) * demand_share_per_timestep_decision
sub_expressions:
relaxation: *relaxation_component
slices: *slice

# The optional additional sum constraint ensures that all decision shares add up
# to a specified share of carrier demand (here, 50% = 0.5 of electricity demand).

demand_share_per_timestep_decision_sum:
description: Limit the total share of demand that can be met by technologies controlled by the `demand_share_per_timestep_decision` variable.
foreach: [nodes, timesteps]
where: demand_share_per_timestep_decision AND demand_share_limit
equations:
- expression: sum(demand_share_per_timestep_decision, over=[techs]) == demand_share_limit
Loading