Skip to content

Commit

Permalink
add paired python/notebook and according github action
Browse files Browse the repository at this point in the history
  • Loading branch information
JakobBD committed Nov 26, 2024
1 parent 0e3068a commit 37dc552
Show file tree
Hide file tree
Showing 12 changed files with 870 additions and 5 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ dist/
docs/build
docs/source/_autosummary
poetry.lock
uv.lock
sodym.egg-info
7 changes: 7 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
repos:
- repo: https://github.com/mwouts/jupytext
rev: v1.16.4
hooks:
- id: jupytext
args: [--sync, --pipe, black]
additional_dependencies:
- black==22.3.0 # Matches hook
- repo: https://github.com/psf/black
rev: 22.3.0
hooks:
Expand Down
2 changes: 1 addition & 1 deletion examples/example1.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -2061,7 +2061,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": ".venv",
"language": "python",
"name": "python3"
},
Expand Down
122 changes: 122 additions & 0 deletions examples/example1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# ---
# jupyter:
# jupytext:
# text_representation:
# extension: .py
# format_name: percent
# format_version: '1.3'
# jupytext_version: 1.16.4
# kernelspec:
# display_name: .venv
# language: python
# name: python3
# ---

# %% [markdown]
# # Example 1. System with two processes, two parameters, one material.
#
# A simple MFA system with one material, a time horizon of 30 years [1980-2010], two processes, and a time-dependent parameter is analysed.
#
# <img src="pictures/MFAExample1.png" width="404" height="490" alt="Diagram of the MFA system">
#
# The model equations are as follows:
# * $a(t) = D(t)$ (exogenous input flow)
# * $d(t) = \alpha (t)\cdot b(t)$ (recovery efficiency parameter)
# * $a(t) + d(t) = b(t) $ (mass balance process 1)
# * $b(t) = c(t) + d(t) $ (mass balance process 2)
#
# From these equations the system solution follows:
# * $c(t) = a(t) = D(t) $
# * $b(t) = \frac{1}{1-\alpha (t)}\cdot D(t) $
# * $c(t) = \frac{\alpha}{1-\alpha (t)}\cdot D(t) $
#

# %% [markdown]
# ## 1. Load sodym and other useful packages

# %%
import numpy as np
import plotly.express as px

from sodym import (
Dimension, DimensionSet, Parameter, Process, FlowDefinition, Flow, MFASystem,
)
from sodym.flow_helper import make_empty_flows

# %% [markdown]
# ## 2. Load data
# Normally data would be loaded from a file / database, but since this is just a small example, the values are input directly into the code below.

# %%
time = Dimension(name='Time', letter='t', items=list(range(1980,2011)))
elements = Dimension(name='Elements', letter='e', items=['single material', ])
dimensions = DimensionSet(dim_list=[time, elements])

parameters = {
'D': Parameter(name='inflow', dims=dimensions, values=np.arange(0, 31).reshape(31, 1)),
'alpha': Parameter(name='recovery rate', dims=dimensions, values=np.arange(2, 33).reshape(31, 1)/34)
}

processes = {
'sysenv': Process(name='sysenv', id=0),
'process 1': Process(name='process 1', id=1),
'process 2': Process(name='process 2', id=2)
}

# %% [markdown]
# ## 3. Define flows and initialise them with zero values.
# By defining them with the shape specified by the relevant dimensions, we can later ensure that when we update the values, these have the correct dimensions.
# Note that flows are automatically asigned their names based on the names of the processes they are connecting.

# %%
flow_definitions = [
FlowDefinition(from_process_name='sysenv', to_process_name='process 1', dim_letters=('t', 'e')), # input
FlowDefinition(from_process_name='process 1', to_process_name='process 2', dim_letters=('t', 'e')), # consumption
FlowDefinition(from_process_name='process 2', to_process_name='sysenv', dim_letters=('t', 'e')), # output
FlowDefinition(from_process_name='process 2', to_process_name='process 1', dim_letters=('t', 'e')), # recovered material
]
flows = make_empty_flows(processes=processes, flow_definitions=flow_definitions, dims=dimensions)


# %% [markdown]
# ## 4. Define the MFA System equations
# We define a class with our system equations in the compute method. Afterwards we create an instance of this class, using the input data defined above. The class (system equations) can then easily be reused with different input data.
#
# We just need to define the compute method with our system equations, as all the other things we need are inherited from the MFASystem class.

# %%
class SimpleMFA(MFASystem):

def compute(self):
self.flows['sysenv => process 1'][...] = self.parameters['D'] # the elipsis slice [...] ensures the dimensionality of the flow is not changed
self.flows['process 1 => process 2'][...] = 1 / (1 - self.parameters['alpha']) * self.parameters['D']
self.flows['process 2 => sysenv'][...] = self.parameters['D']
self.flows['process 2 => process 1'][...] = self.parameters['alpha'] / (1 - self.parameters['alpha']) * self.parameters['D']



# %%
mfa_example = SimpleMFA(dims=dimensions, processes=processes, parameters=parameters, flows=flows, stocks={})
mfa_example.compute()

# %%
flow_a = mfa_example.flows['sysenv => process 1']
fig = px.line(
x=flow_a.dims['t'].items,
y=flow_a['single material'].values,
title=flow_a.name,
labels={'x': 'Year', 'y': 'Mt/yr'},
)
fig.show()

# %%
flow_b = mfa_example.flows['process 1 => process 2']
fig = px.line(
x=flow_b.dims['t'].items,
y=flow_b['single material'].values,
title=flow_b.name,
labels={'x': 'Year', 'y': 'Mt/yr'},
)
fig.show()

# %%
2 changes: 1 addition & 1 deletion examples/example2.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -5161,7 +5161,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": ".venv",
"language": "python",
"name": "python3"
},
Expand Down
Loading

0 comments on commit 37dc552

Please sign in to comment.