or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-tools.mdexternal-data.mdfunctions-module.mdindex.mdmodel-loading.mdmodel-simulation.mdparameter-management.mdstateful-components.mdutils-module.md

functions-module.mddocs/

0

# Mathematical and Utility Functions

1

2

PySD's functions module provides a comprehensive set of mathematical and utility functions equivalent to Vensim/XMILE built-ins, enabling System Dynamics models to perform complex calculations and logic operations.

3

4

## Capabilities

5

6

### Mathematical Functions

7

8

Core mathematical operations with special handling for System Dynamics modeling requirements.

9

10

```python { .api }

11

def if_then_else(condition, val_if_true, val_if_false):

12

"""

13

Conditional logic implementation.

14

15

Parameters:

16

- condition: bool or array - Conditional expression

17

- val_if_true: scalar or array - Value when condition is True

18

- val_if_false: scalar or array - Value when condition is False

19

20

Returns:

21

scalar or array: Selected value based on condition

22

"""

23

24

def xidz(numerator, denominator, x):

25

"""

26

Division with specified result for 0/0.

27

28

Parameters:

29

- numerator: scalar or array - Numerator value

30

- denominator: scalar or array - Denominator value

31

- x: scalar or array - Value returned when both numerator and denominator are 0

32

33

Returns:

34

scalar or array: Division result or x for 0/0 case

35

"""

36

37

def zidz(numerator, denominator):

38

"""

39

Division returning 0 for 0/0.

40

41

Parameters:

42

- numerator: scalar or array - Numerator value

43

- denominator: scalar or array - Denominator value

44

45

Returns:

46

scalar or array: Division result or 0 for 0/0 case

47

"""

48

49

def integer(x):

50

"""

51

Integer truncation.

52

53

Parameters:

54

- x: scalar or array - Input value

55

56

Returns:

57

int or array: Truncated integer value

58

"""

59

60

def quantum(a, b):

61

"""

62

Quantum function - rounds a to nearest multiple of b.

63

64

Parameters:

65

- a: scalar or array - Value to round

66

- b: scalar or array - Multiple to round to

67

68

Returns:

69

scalar or array: Rounded value

70

"""

71

72

def modulo(x, m):

73

"""

74

Modulo operation.

75

76

Parameters:

77

- x: scalar or array - Input value

78

- m: scalar or array - Modulo divisor

79

80

Returns:

81

scalar or array: Remainder after division

82

"""

83

```

84

85

#### Usage Examples

86

87

```python

88

from pysd import functions

89

90

# Conditional logic

91

temperature = 25

92

comfort_level = functions.if_then_else(

93

temperature > 20,

94

"comfortable",

95

"cold"

96

)

97

98

# Safe division avoiding division by zero

99

growth_rate = functions.xidz(

100

new_population - old_population,

101

old_population,

102

0 # Return 0 if both are 0

103

)

104

105

# Integer operations

106

whole_units = functions.integer(3.7) # Returns 3

107

```

108

109

### Time Functions

110

111

Functions for time-based calculations and temporal patterns.

112

113

```python { .api }

114

def ramp(time, slope, start, finish=None):

115

"""

116

Ramp function over time.

117

118

Parameters:

119

- time: scalar or array - Current time value

120

- slope: scalar - Rate of increase per time unit

121

- start: scalar - Time when ramp begins

122

- finish: scalar or None - Time when ramp ends (None for no end)

123

124

Returns:

125

scalar or array: Ramp value at given time

126

"""

127

128

def step(time, value, tstep):

129

"""

130

Step function at specified time.

131

132

Parameters:

133

- time: scalar or array - Current time value

134

- value: scalar - Step height

135

- tstep: scalar - Time when step occurs

136

137

Returns:

138

scalar or array: 0 before tstep, value at and after tstep

139

"""

140

141

def pulse(time, start, repeat_time=0, width=None, magnitude=None, end=None):

142

"""

143

Pulse and pulse train functions.

144

145

Parameters:

146

- time: scalar or array - Current time value

147

- start: scalar - Time when first pulse begins

148

- repeat_time: scalar - Time between pulses (0 for single pulse)

149

- width: scalar or None - Pulse duration (default: time step)

150

- magnitude: scalar or None - Pulse height (default: 1/time_step)

151

- end: scalar or None - Final time of the pulse (None for no end)

152

153

Returns:

154

scalar or array: Pulse value at given time

155

"""

156

157

def get_time_value(time, relativeto, offset, measure):

158

"""

159

Extract time values with offsets.

160

161

Parameters:

162

- time: scalar - Current time

163

- relativeto: str - Reference point ("start", "end")

164

- offset: scalar - Time offset from reference

165

- measure: str - Time unit ("years", "months", "days", "hours", "minutes", "seconds")

166

167

Returns:

168

scalar: Calculated time value

169

"""

170

```

171

172

#### Usage Examples

173

174

```python

175

# Create time-based patterns

176

current_time = 15

177

178

# Gradual increase starting at time 10

179

production_ramp = functions.ramp(current_time, slope=2, start=10)

180

181

# Policy change at time 20

182

policy_effect = functions.step(current_time, value=100, tstep=20)

183

184

# Periodic maintenance every 12 time units

185

maintenance = functions.pulse(current_time, start=0, repeat_time=12, width=1)

186

```

187

188

### Array Functions

189

190

Operations on multi-dimensional arrays and subscripted variables.

191

192

```python { .api }

193

def sum(x, dim=None):

194

"""

195

Sum along specified dimensions.

196

197

Parameters:

198

- x: array - Input array

199

- dim: str or list or None - Dimensions to sum over (None for all)

200

201

Returns:

202

scalar or array: Sum result

203

"""

204

205

def prod(x, dim=None):

206

"""

207

Product along dimensions.

208

209

Parameters:

210

- x: array - Input array

211

- dim: str or list or None - Dimensions to multiply over

212

213

Returns:

214

scalar or array: Product result

215

"""

216

217

def vmin(x, dim=None):

218

"""

219

Minimum along dimensions.

220

221

Parameters:

222

- x: array - Input array

223

- dim: str or list or None - Dimensions to find minimum over

224

225

Returns:

226

scalar or array: Minimum value

227

"""

228

229

def vmax(x, dim=None):

230

"""

231

Maximum along dimensions.

232

233

Parameters:

234

- x: array - Input array

235

- dim: str or list or None - Dimensions to find maximum over

236

237

Returns:

238

scalar or array: Maximum value

239

"""

240

241

def invert_matrix(mat):

242

"""

243

Matrix inversion.

244

245

Parameters:

246

- mat: 2D array - Input matrix

247

248

Returns:

249

2D array: Inverted matrix

250

251

Raises:

252

LinAlgError: If matrix is singular

253

"""

254

```

255

256

#### Usage Examples

257

258

```python

259

import numpy as np

260

261

# Array operations on subscripted variables

262

population_by_region = np.array([1000, 1500, 800, 1200])

263

264

# Total population across all regions

265

total_pop = functions.sum(population_by_region)

266

267

# Find region with maximum population

268

max_pop = functions.vmax(population_by_region)

269

270

# Matrix operations for economic modeling

271

input_output_matrix = np.array([[0.2, 0.3], [0.4, 0.1]])

272

inverse_matrix = functions.invert_matrix(input_output_matrix)

273

```

274

275

### Vector Operations

276

277

Specialized functions for vector manipulation and analysis.

278

279

```python { .api }

280

def vector_select(selection_array, expression_array, dim, missing_vals, numerical_action, error_action):

281

"""

282

Vector selection operations implementing Vensim's VECTOR SELECT function.

283

284

Parameters:

285

- selection_array: xarray.DataArray - Selection array with zeros and non-zero values

286

- expression_array: xarray.DataArray - Expression that elements are selected from

287

- dim: list - Dimensions to apply the function over

288

- missing_vals: float - Value to use when there are only zeroes in selection array

289

- numerical_action: int - Action to take (0=sum, 1=product, 2=min, 3=max)

290

- error_action: int - Error handling action

291

292

Returns:

293

xarray.DataArray: Selected vector elements based on selection criteria

294

"""

295

296

def vector_sort_order(vector, direction=1):

297

"""

298

Vector sorting indices.

299

300

Parameters:

301

- vector: array - Input vector

302

- direction: int - Sort direction (1 for ascending, -1 for descending)

303

304

Returns:

305

array: Indices that would sort the vector

306

"""

307

308

def vector_reorder(vector, svector):

309

"""

310

Vector reordering based on sort indices.

311

312

Parameters:

313

- vector: array - Vector to reorder

314

- svector: array - Sort indices

315

316

Returns:

317

array: Reordered vector

318

"""

319

320

def vector_rank(vector, direction=1):

321

"""

322

Vector ranking.

323

324

Parameters:

325

- vector: array - Input vector

326

- direction: int - Ranking direction (1 for ascending, -1 for descending)

327

328

Returns:

329

array: Rank of each element (1-based)

330

"""

331

```

332

333

#### Usage Examples

334

335

```python

336

# Vector analysis

337

sales_data = np.array([150, 200, 120, 180, 220])

338

339

# Get sorting order

340

sort_indices = functions.vector_sort_order(sales_data, direction=-1) # Descending

341

342

# Reorder vector

343

sorted_sales = functions.vector_reorder(sales_data, sort_indices)

344

345

# Get rankings

346

sales_ranks = functions.vector_rank(sales_data, direction=-1)

347

print(f"Sales rankings: {sales_ranks}")

348

```

349

350

### Utility Functions

351

352

Helper functions for model development and debugging.

353

354

```python { .api }

355

def active_initial(stage, expr, init_val):

356

"""

357

Active initial value handling.

358

359

Parameters:

360

- stage: str - Initialization stage

361

- expr: callable - Expression to evaluate

362

- init_val: scalar - Initial value

363

364

Returns:

365

scalar: Appropriate value based on stage

366

"""

367

368

def incomplete(*args):

369

"""

370

Placeholder for incomplete functions.

371

372

Parameters:

373

- *args: Any arguments

374

375

Returns:

376

float: Returns 0.0

377

378

Note:

379

Used as placeholder during model development

380

"""

381

382

def not_implemented_function(*args):

383

"""

384

Placeholder for unimplemented functions.

385

386

Parameters:

387

- *args: Any arguments

388

389

Raises:

390

NotImplementedError: Always raises this error

391

392

Note:

393

Used to mark functions that need implementation

394

"""

395

```

396

397

### Function Usage in Models

398

399

These functions are automatically available within translated System Dynamics models and can also be used directly:

400

401

```python

402

import pysd

403

from pysd import functions

404

405

# Load model that uses these functions internally

406

model = pysd.read_vensim('complex_model.mdl')

407

408

# Functions are used automatically during simulation

409

results = model.run()

410

411

# Can also use functions directly for custom calculations

412

custom_result = functions.if_then_else(

413

results['Population'].iloc[-1] > 10000,

414

"High population",

415

"Low population"

416

)

417

```

418

419

### Error Handling

420

421

Functions include appropriate error handling for System Dynamics contexts:

422

423

- Division by zero returns appropriate defaults or specified values

424

- Array dimension mismatches are handled gracefully

425

- Missing values are managed according to SD conventions

426

427

```python

428

# Safe operations that won't crash simulations

429

safe_ratio = functions.zidz(numerator, 0) # Returns 0 instead of error

430

conditional_value = functions.if_then_else(

431

denominator != 0,

432

numerator / denominator,

433

0

434

)

435

```