1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# ---
# jupyter:
# jupytext:
# text_representation:
# extension: .py
# format_name: percent
# format_version: '1.3'
# jupytext_version: 1.16.4
# kernelspec:
# display_name: Python 3 (ipykernel)
# language: python
# name: python3
# ---
# %% [markdown]
# # Model state serialisation
#
# It can be useful to be able to be able to capture the current state of a model
# and serialise it for later use.
#
# We provide an TOML representation of a model's state that provides a human-readable
# description of the model, including its components and state.
# %%
# %%
# Create a simple example coupled model with some exogenous data
=
# %%
# We can then step the model forward in time
# %% [markdown]
# We can log the state of a model using TOML.
#
# This format is human-readable and can be used to store the state of a model to disk.
# A binary-format could be used to store the state of a model in a more compact way.
#
# %%
=
# %% [markdown]
# ## Recreating the model state
#
# A new model can be initialised using the TOML representation.
# The new model will have the same state and components as the original model
# %%
=
# %% [markdown]
# It will also on the same timestep as the original model.
# %%
assert ==
# %% [markdown]
# The newly created model can then be run as normal.
# %%
# %% [markdown]
# Currently we don't provide many hooks to modify the state of the model post-creation.
# A `Model` configuration is effectively immutable after creation.
#
# A `ModelBuilder` could be created using the contents of the model state to enable
# modification or to provide the initial conditions for a later run.
# The common use case that we are aiming to support is to be able to spin a model up
# over a historical period with a given set of parameters,
# and then run multiple different future scenarios with the same parameters.
#
# The historical period does not need to be run for every scenario.
# Instead a model can be created from the state of the historical model and run with
# the new scenario data for the future period.
# %% [markdown]
# Some psuedo-code that illustrates the desired operation is shown below:
#
# ```py
# historical_time_axis = TimeAxis.from_values(np.arange(1850, 2015 + 1))
# scenario_time_axis = TimeAxis.from_values(np.arange(2015, 2100))
# historical_exogenous_data: TimeseriesCollection = get_historical_data()
#
#
# model_builder = get_builder_with_components()
#
# historical_model = (
# get_builder_with_components()
# .with_time_axis(historical_time_axis)
# .with_exogenous_collection(historical_exogenous_data)
# ).build()
#
# historical_model.run()
#
# historical_model_state = historical_model.to_toml()
#
# # This state can be archived for later use
#
# for scenario in get_list_of_scenarios():
# model = (
# ModelBuilder
# .from_model_state(historical_model_state)
# # Some components may require more than one previous timestep
# # so we should merge time axes rather than dropping the historical data
# .with_time_axis(scenario_time_axis.merge(historical_time_axis))
# .with_current_time_step(2015.0)
# .with_exogenous_collection(scenario)
# ).build()
#
# model.run()
#
# # Save results
# ```
#
# %%