0
# Model Simulation and Execution
1
2
PySD's Model class provides comprehensive simulation capabilities, supporting both batch execution and step-by-step simulation with flexible parameter management and output configuration.
3
4
## Capabilities
5
6
### Batch Simulation
7
8
Execute complete model simulations with customizable time settings, parameter overrides, and output formatting.
9
10
```python { .api }
11
def run(self, params=None, return_columns=None, return_timestamps=None,
12
initial_condition='original', final_time=None, time_step=None,
13
saveper=None, reload=False, progress=False, flatten_output=False,
14
cache_output=True, output_file=None):
15
"""
16
Execute model simulation.
17
18
Parameters:
19
- params: dict or None - Parameter values to override during simulation
20
- return_columns: list or None - Specific variables to include in output
21
- return_timestamps: list or None - Specific time points to include in output
22
- initial_condition: str or tuple - Initial condition ('original', 'current', pickle file, or (time, values))
23
- final_time: float or None - Simulation end time
24
- time_step: float or None - Integration time step
25
- saveper: float or None - Output sampling period
26
- reload: bool - Whether to reload model from file before running
27
- progress: bool - Whether to show progress bar during simulation
28
- flatten_output: bool - Whether to flatten subscripted output
29
- cache_output: bool - Whether to cache results for faster repeated access
30
- output_file: str or None - File path to save results
31
32
Returns:
33
pandas.DataFrame: Simulation results with time as index and variables as columns
34
35
Raises:
36
ValueError: If time parameters are inconsistent
37
KeyError: If parameter names in params don't exist in model
38
"""
39
```
40
41
#### Usage Examples
42
43
Basic simulation:
44
45
```python
46
import pysd
47
48
model = pysd.read_vensim('population_model.mdl')
49
50
# Run with default settings
51
results = model.run()
52
print(results.head())
53
54
# Run with custom time settings
55
results = model.run(final_time=50, time_step=0.25, saveper=1)
56
```
57
58
Parameter override during simulation:
59
60
```python
61
# Run with different parameter values
62
results = model.run(params={
63
'birth_rate': 0.05,
64
'death_rate': 0.02,
65
'initial_population': 1000
66
})
67
68
# Run multiple scenarios
69
scenarios = [
70
{'birth_rate': 0.03, 'death_rate': 0.01},
71
{'birth_rate': 0.04, 'death_rate': 0.02},
72
{'birth_rate': 0.05, 'death_rate': 0.03}
73
]
74
75
results = {}
76
for i, scenario in enumerate(scenarios):
77
results[f'scenario_{i}'] = model.run(params=scenario)
78
```
79
80
Selective output:
81
82
```python
83
# Return only specific variables
84
results = model.run(return_columns=['Population', 'Birth Rate', 'Death Rate'])
85
86
# Return specific time points
87
results = model.run(return_timestamps=[0, 10, 20, 30, 40, 50])
88
89
# Combine both
90
results = model.run(
91
return_columns=['Population'],
92
return_timestamps=list(range(0, 51, 5)) # Every 5 time units
93
)
94
```
95
96
### Step-by-Step Simulation
97
98
Execute simulations one step at a time, enabling real-time parameter adjustments and interactive simulation control.
99
100
```python { .api }
101
def set_stepper(self, output_obj, return_columns=None, **kwargs):
102
"""
103
Configure model for step-by-step execution.
104
105
Parameters:
106
- output_obj: ModelOutput - Output handler for storing step results
107
- return_columns: list or None - Variables to track during stepping
108
- **kwargs: Additional configuration options
109
110
Raises:
111
TypeError: If output_obj is not a ModelOutput instance
112
"""
113
114
def step(self, num_steps=1, step_vars={}):
115
"""
116
Execute one or more simulation steps.
117
118
Parameters:
119
- num_steps: int - Number of time steps to execute (default 1)
120
- step_vars: dict - Variable values to set for this step
121
122
Returns:
123
dict: Current values of tracked variables
124
125
Raises:
126
RuntimeError: If stepper not configured via set_stepper()
127
ValueError: If num_steps is not positive
128
"""
129
```
130
131
#### Usage Examples
132
133
```python
134
from pysd.py_backend.output import ModelOutput
135
136
model = pysd.read_vensim('population_model.mdl')
137
138
# Configure stepping
139
output = ModelOutput()
140
model.set_stepper(output, return_columns=['Population', 'Birth Rate'])
141
142
# Execute single steps
143
step_result = model.step()
144
print(f"Time {model.time()}: Population = {step_result['Population']}")
145
146
# Execute multiple steps at once
147
results = model.step(num_steps=10)
148
149
# Adjust parameters during simulation
150
for i in range(20):
151
if i == 10:
152
# Change birth rate halfway through
153
results = model.step(step_vars={'birth_rate': 0.06})
154
else:
155
results = model.step()
156
157
print(f"Step {i}: Population = {results['Population']}")
158
```
159
160
### Model State Management
161
162
Control model initialization, reloading, and state persistence.
163
164
```python { .api }
165
def initialize(self):
166
"""Initialize the model for simulation."""
167
168
def reload(self):
169
"""Reload model from file, resetting all parameters."""
170
171
def copy(self, reload=False):
172
"""
173
Create a copy of the current model.
174
175
Parameters:
176
- reload: bool - Whether to reload the copy from file
177
178
Returns:
179
Model: Independent copy of the model
180
"""
181
```
182
183
#### Usage Examples
184
185
```python
186
model = pysd.read_vensim('model.mdl', initialize=False)
187
188
# Initialize when ready
189
model.initialize()
190
191
# Create independent copy for experimentation
192
model_copy = model.copy()
193
model_copy.set_components({'parameter': 100})
194
195
# Original model unchanged
196
original_results = model.run()
197
modified_results = model_copy.run()
198
199
# Reset model to file state
200
model.reload()
201
```
202
203
### Initial Conditions
204
205
Set and manage initial conditions for simulation runs.
206
207
```python { .api }
208
def set_initial_condition(self, initial_condition):
209
"""
210
Set initial simulation conditions.
211
212
Parameters:
213
- initial_condition: str or tuple - Initial condition specification
214
- 'original': Use model's original initial values
215
- 'current': Use current model state as initial condition
216
- str path: Load initial condition from pickle file
217
- (time, dict): Set specific time and variable values
218
"""
219
220
def set_initial_value(self, time, initial_value):
221
"""
222
Set initial values for specific stocks.
223
224
Parameters:
225
- time: float - Time at which to set initial values
226
- initial_value: dict - Variable names and initial values
227
"""
228
```
229
230
#### Usage Examples
231
232
```python
233
# Use original model initial conditions
234
model.set_initial_condition('original')
235
results1 = model.run()
236
237
# Use current state as initial condition for next run
238
model.set_initial_condition('current')
239
results2 = model.run()
240
241
# Set specific initial values
242
model.set_initial_condition((0, {
243
'Population': 1500,
244
'Economic Development Index': 0.75
245
}))
246
results3 = model.run()
247
248
# Load initial condition from saved state
249
model.export('initial_state.pkl')
250
# ... later ...
251
model.set_initial_condition('initial_state.pkl')
252
```
253
254
### Output Configuration
255
256
Control simulation output format, content, and storage.
257
258
#### Progress Monitoring
259
260
```python
261
# Show progress bar for long simulations
262
results = model.run(progress=True)
263
```
264
265
#### Output File Writing
266
267
```python
268
# Save results directly to file
269
model.run(output_file='simulation_results.csv')
270
271
# Save with custom format (supported: .csv, .tab, .nc)
272
model.run(output_file='results.nc') # NetCDF format
273
```
274
275
#### Subscripted Variable Handling
276
277
```python
278
# Flatten subscripted variables to separate columns
279
results = model.run(flatten_output=True)
280
281
# Keep subscripted variables as multi-dimensional arrays (default)
282
results = model.run(flatten_output=False)
283
```
284
285
### Error Handling
286
287
Common simulation errors and their resolution:
288
289
- **ValueError**: Time parameters conflict (e.g., time_step > final_time)
290
- **KeyError**: Parameter name in `params` doesn't exist in model
291
- **RuntimeError**: Step-by-step simulation not properly configured
292
- **MemoryError**: Large models with high resolution time settings
293
294
```python
295
try:
296
results = model.run(params={'nonexistent_param': 100})
297
except KeyError as e:
298
print(f"Parameter not found: {e}")
299
# Check available parameters
300
print("Available parameters:", list(model.namespace.keys()))
301
```
302
303
### Model Introspection and Metadata
304
305
Access model structure, documentation, and metadata for analysis and debugging.
306
307
```python { .api }
308
def doc(self):
309
"""
310
Get comprehensive model documentation.
311
312
Returns:
313
pandas.DataFrame: Documentation with variables, units, limits, and descriptions
314
"""
315
316
def namespace(self):
317
"""
318
Get model variable namespace mapping.
319
320
Returns:
321
dict: Mapping of model variable names to Python function names
322
"""
323
324
def dependencies(self):
325
"""
326
Get model variable dependencies.
327
328
Returns:
329
dict: Dictionary of variable dependencies for each model element
330
"""
331
332
def subscripts(self):
333
"""
334
Get model subscript definitions.
335
336
Returns:
337
dict: Dictionary describing possible dimensions of model subscripts
338
"""
339
340
def modules(self):
341
"""
342
Get model module structure (for split-view models).
343
344
Returns:
345
dict or None: Dictionary of module names and their variables, or None for single-file models
346
"""
347
348
def get_dependencies(self, vars=[], modules=[]):
349
"""
350
Get dependencies for specific variables or modules.
351
352
Parameters:
353
- vars: list - List of variable names to get dependencies for
354
- modules: list - List of module names to get dependencies for
355
356
Returns:
357
Dependencies: Object containing variable and stateful dependencies
358
"""
359
```
360
361
### Model State Management
362
363
Initialize, reset, and manage model state and caches.
364
365
```python { .api }
366
def initialize(self):
367
"""
368
Initialize model state and prepare for simulation.
369
370
Sets up initial values, external data, and stateful components.
371
"""
372
373
def clean_caches(self):
374
"""
375
Clear all model caches to free memory.
376
377
Useful for large models or when running multiple simulations.
378
"""
379
380
def initialize_external_data(self, externals=None):
381
"""
382
Initialize external data sources.
383
384
Parameters:
385
- externals: list or None - Specific external objects to initialize
386
"""
387
388
def export(self):
389
"""
390
Export current model state.
391
392
Returns:
393
dict: Dictionary containing current values of all model variables
394
"""
395
396
def serialize_externals(self, export_path="externals.nc", encoding="zlib"):
397
"""
398
Serialize external data to NetCDF file.
399
400
Parameters:
401
- export_path: str - Path for exported NetCDF file
402
- encoding: str - Compression encoding for NetCDF file
403
"""
404
```
405
406
### Submodel Selection
407
408
Extract and work with subsets of large models.
409
410
```python { .api }
411
def select_submodel(self, vars=[], modules=[], exogenous_components={}):
412
"""
413
Create a submodel containing only specified variables and modules.
414
415
Parameters:
416
- vars: list - Variables to include in submodel
417
- modules: list - Modules to include in submodel
418
- exogenous_components: dict - External values for excluded variables
419
420
Returns:
421
Model: New Model object containing only selected components
422
"""
423
```
424
425
#### Usage Examples
426
427
Model introspection:
428
429
```python
430
# Get model documentation
431
doc_df = model.doc()
432
print(doc_df[['Variable', 'Units', 'Type']])
433
434
# Check variable namespace
435
namespace = model.namespace()
436
print("Python names:", list(namespace.values()))
437
438
# Examine dependencies
439
deps = model.dependencies()
440
print("Variables that depend on time:", [var for var, dep in deps.items() if 'time' in dep])
441
442
# View subscripts
443
subs = model.subscripts()
444
print("Available subscripts:", list(subs.keys()))
445
```
446
447
Model state management:
448
449
```python
450
# Clear caches to free memory
451
model.clean_caches()
452
453
# Re-initialize model
454
model.initialize()
455
456
# Export current state
457
current_state = model.export()
458
print("Current population:", current_state.get('Population', 'Not found'))
459
460
# Create submodel for testing
461
submodel = model.select_submodel(
462
vars=['Population', 'Birth Rate', 'Death Rate'],
463
exogenous_components={'Economic Growth': 0.03}
464
)
465
results = submodel.run()
466
```