or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

boundaries.mdfields.mdgrids.mdindex.mdpdes.mdsolvers.mdstorage.mdtrackers.mdvisualization.md

pdes.mddocs/

0

# PDEs

1

2

PDE classes provide mathematical descriptions of partial differential equations with automatic operator compilation and built-in support for common equations in physics and dynamical systems.

3

4

## Capabilities

5

6

### Generic PDE

7

8

General PDE class for defining custom differential equations using mathematical expressions.

9

10

```python { .api }

11

class PDE:

12

def __init__(self, rhs, *, noise=None, is_sde_value=None):

13

"""

14

Initialize generic PDE.

15

16

Parameters:

17

- rhs: callable or dict, right-hand side of PDE

18

- noise: float or FieldBase, noise strength for stochastic PDEs

19

- is_sde_value: bool, whether noise affects the value directly

20

"""

21

22

def solve(self, initial_state, t_range, *, dt=None, solver="auto",

23

tracker=None, bc=None, **kwargs):

24

"""

25

Solve the PDE with given initial conditions.

26

27

Parameters:

28

- initial_state: FieldBase, initial field configuration

29

- t_range: float or array-like, time range for integration

30

- dt: float, time step (auto-determined if None)

31

- solver: str or SolverBase, time integration method

32

- tracker: TrackerBase or list, simulation tracking

33

- bc: boundary conditions

34

- kwargs: additional solver parameters

35

36

Returns:

37

FieldBase: Final field state

38

"""

39

40

def evolution_rate(self, state, t=0):

41

"""

42

Calculate time derivative of state.

43

44

Parameters:

45

- state: FieldBase, current field state

46

- t: float, current time

47

48

Returns:

49

FieldBase: Time derivative

50

"""

51

52

@property

53

def expressions(self):

54

"""dict: Mathematical expressions defining the PDE"""

55

56

def make_post_step_hook(self, state):

57

"""

58

Create hook function called after each time step.

59

60

Parameters:

61

- state: FieldBase, current field state

62

63

Returns:

64

tuple: (hook_function, hook_data)

65

"""

66

```

67

68

### DiffusionPDE

69

70

Standard diffusion equation with optional convection and reaction terms.

71

72

```python { .api }

73

class DiffusionPDE:

74

def __init__(self, diffusivity=1, *, bc=None, noise=0, rng=None):

75

"""

76

Initialize diffusion PDE: ∂c/∂t = D∇²c + η

77

78

Parameters:

79

- diffusivity: float, diffusion coefficient

80

- bc: boundary conditions

81

- noise: float, noise strength (default: 0)

82

- rng: numpy random generator for noise (optional)

83

"""

84

85

@property

86

def diffusivity(self):

87

"""Diffusion coefficient"""

88

89

def get_initial_condition(self, grid, **kwargs):

90

"""

91

Get suitable initial condition for the grid.

92

93

Parameters:

94

- grid: GridBase, spatial grid

95

- kwargs: additional parameters

96

97

Returns:

98

ScalarField: Initial condition

99

"""

100

```

101

102

### AllenCahnPDE

103

104

Allen-Cahn equation for phase separation dynamics.

105

106

```python { .api }

107

class AllenCahnPDE:

108

def __init__(self, a=1, b=1, *, noise=None, bc=None):

109

"""

110

Initialize Allen-Cahn PDE: ∂φ/∂t = a∇²φ + bφ - bφ³ + η

111

112

Parameters:

113

- a: float, interface energy parameter

114

- b: float, bulk energy parameter

115

- noise: float or FieldBase, noise strength

116

- bc: boundary conditions

117

"""

118

119

def get_initial_condition(self, grid, **kwargs):

120

"""

121

Get random initial condition with appropriate statistics.

122

123

Parameters:

124

- grid: GridBase, spatial grid

125

- kwargs: parameters like 'amplitude' for noise level

126

127

Returns:

128

ScalarField: Random initial condition

129

"""

130

```

131

132

### CahnHilliardPDE

133

134

Cahn-Hilliard equation for conserved phase separation.

135

136

```python { .api }

137

class CahnHilliardPDE:

138

def __init__(self, a=1, b=1, *, noise=None, bc=None):

139

"""

140

Initialize Cahn-Hilliard PDE: ∂φ/∂t = ∇²[aφ - bφ³ - ∇²φ] + η

141

142

Parameters:

143

- a: float, linear coefficient

144

- b: float, nonlinear coefficient

145

- noise: float or FieldBase, noise strength

146

- bc: boundary conditions

147

"""

148

```

149

150

### WavePDE

151

152

Wave equation for oscillatory dynamics.

153

154

```python { .api }

155

class WavePDE:

156

def __init__(self, speed=1, *, noise=None, bc=None):

157

"""

158

Initialize wave PDE: ∂²u/∂t² = c²∇²u + η

159

160

Parameters:

161

- speed: float, wave propagation speed

162

- noise: float or FieldBase, noise strength

163

- bc: boundary conditions

164

"""

165

166

def get_initial_condition(self, u, v=None):

167

"""

168

Create suitable initial condition with position and velocity.

169

170

Parameters:

171

- u: ScalarField, initial position field

172

- v: ScalarField, optional initial velocity field (zeros if None)

173

174

Returns:

175

FieldCollection: Initial [position, velocity] fields

176

"""

177

```

178

179

### KuramotoSivashinskyPDE

180

181

Kuramoto-Sivashinsky equation exhibiting spatiotemporal chaos.

182

183

```python { .api }

184

class KuramotoSivashinskyPDE:

185

def __init__(self, *, noise=None, bc=None):

186

"""

187

Initialize Kuramoto-Sivashinsky PDE: ∂u/∂t = -∇²u - ∇⁴u - ½|∇u|² + η

188

189

Parameters:

190

- noise: float or FieldBase, noise strength

191

- bc: boundary conditions (typically periodic)

192

"""

193

```

194

195

### SwiftHohenbergPDE

196

197

Swift-Hohenberg equation for pattern formation.

198

199

```python { .api }

200

class SwiftHohenbergPDE:

201

def __init__(self, a=1, b=1, *, noise=None, bc=None):

202

"""

203

Initialize Swift-Hohenberg PDE: ∂u/∂t = au - (1+∇²)²u - bu³ + η

204

205

Parameters:

206

- a: float, linear instability parameter

207

- b: float, nonlinear saturation parameter

208

- noise: float or FieldBase, noise strength

209

- bc: boundary conditions

210

"""

211

```

212

213

### KPZInterfacePDE

214

215

Kardar-Parisi-Zhang equation for interface growth.

216

217

```python { .api }

218

class KPZInterfacePDE:

219

def __init__(self, diffusivity=1, lambda_=1, *, noise=1, bc=None):

220

"""

221

Initialize KPZ interface PDE: ∂h/∂t = D∇²h + λ|∇h|² + η

222

223

Parameters:

224

- diffusivity: float, surface tension coefficient

225

- lambda_: float, nonlinear growth coefficient

226

- noise: float, noise strength

227

- bc: boundary conditions

228

"""

229

```

230

231

### Elliptic Equation Solvers

232

233

Direct solvers for elliptic PDEs like Laplace and Poisson equations.

234

235

```python { .api }

236

def solve_laplace_equation(grid, bc, *, solver="auto"):

237

"""

238

Solve Laplace equation ∇²u = 0.

239

240

Parameters:

241

- grid: GridBase, spatial grid

242

- bc: boundary conditions

243

- solver: str, solution method ("scipy" or "numba")

244

245

Returns:

246

ScalarField: Solution field

247

"""

248

249

def solve_poisson_equation(grid, rhs, bc, *, solver="auto"):

250

"""

251

Solve Poisson equation ∇²u = f.

252

253

Parameters:

254

- grid: GridBase, spatial grid

255

- rhs: ScalarField or callable, right-hand side

256

- bc: boundary conditions

257

- solver: str, solution method

258

259

Returns:

260

ScalarField: Solution field

261

"""

262

```

263

264

### PDEBase

265

266

Base class providing common PDE functionality.

267

268

```python { .api }

269

class PDEBase:

270

@property

271

def complex_valued(self):

272

"""bool: Whether PDE involves complex values"""

273

274

@property

275

def is_sde(self):

276

"""bool: Whether this is a stochastic differential equation"""

277

278

def make_post_step_hook(self, state):

279

"""

280

Create hook function called after each time step.

281

282

Parameters:

283

- state: FieldBase, current field state

284

285

Returns:

286

tuple: (hook_function, hook_data)

287

"""

288

289

def evolution_rate(self, state, t=0):

290

"""

291

Calculate time derivative of state (abstract method).

292

293

Parameters:

294

- state: FieldBase, current field state

295

- t: float, current time

296

297

Returns:

298

FieldBase: Time derivative

299

"""

300

301

def check_rhs_consistency(self, state, t=0):

302

"""

303

Check consistency of right-hand side calculation.

304

305

Parameters:

306

- state: FieldBase, current field state

307

- t: float, current time

308

309

Returns:

310

bool: True if consistent

311

"""

312

313

def make_pde_rhs(self, state, backend='auto'):

314

"""

315

Create compiled right-hand side function.

316

317

Parameters:

318

- state: FieldBase, field state for compilation

319

- backend: str, computational backend

320

321

Returns:

322

Callable: Compiled RHS function

323

"""

324

325

def noise_realization(self, state, t=0, label=None):

326

"""

327

Generate noise realization for stochastic PDEs.

328

329

Parameters:

330

- state: FieldBase, current field state

331

- t: float, current time

332

- label: str, optional label for noise field

333

334

Returns:

335

FieldBase: Noise field

336

"""

337

338

def make_sde_rhs(self, state, backend='auto'):

339

"""

340

Create compiled SDE right-hand side function.

341

342

Parameters:

343

- state: FieldBase, field state for compilation

344

- backend: str, computational backend

345

346

Returns:

347

Callable: Compiled SDE RHS function

348

"""

349

350

def get_state_serializer(self, **kwargs):

351

"""

352

Get serializer for PDE state data.

353

354

Parameters:

355

- kwargs: serialization options

356

357

Returns:

358

Callable: State serialization function

359

"""

360

361

def check_initial_condition_compatibility(self, initial_state):

362

"""

363

Check compatibility of initial condition.

364

365

Parameters:

366

- initial_state: FieldBase, initial field state

367

368

Raises:

369

ValueError: If incompatible

370

"""

371

```

372

373

## Usage Examples

374

375

### Solving Standard PDEs

376

377

```python

378

import pde

379

import numpy as np

380

381

# Create grid and initial condition

382

grid = pde.UnitGrid([64, 64], periodic=False)

383

state = pde.ScalarField.random_uniform(grid, 0.2, 0.3)

384

385

# Solve diffusion equation

386

eq = pde.DiffusionPDE(diffusivity=0.1)

387

result = eq.solve(state, t_range=10.0, dt=0.01)

388

389

print(f"Initial average: {state.average:.3f}")

390

print(f"Final average: {result.average:.3f}")

391

```

392

393

### Custom PDE with Expression

394

395

```python

396

import pde

397

398

# Define custom reaction-diffusion PDE

399

def my_pde_rhs(state, t):

400

c = state

401

return 0.1 * c.laplace("auto_periodic_neumann") + c - c**3

402

403

# Create PDE

404

grid = pde.UnitGrid([32], periodic=True)

405

initial = pde.ScalarField.random_uniform(grid, -0.1, 0.1)

406

407

eq = pde.PDE(my_pde_rhs)

408

result = eq.solve(initial, t_range=50)

409

```

410

411

### Wave Equation Simulation

412

413

```python

414

import pde

415

import matplotlib.pyplot as plt

416

417

# Set up 1D wave equation

418

grid = pde.UnitGrid([128], periodic=False)

419

eq = pde.WavePDE(speed=1.0)

420

421

# Gaussian initial condition

422

initial = eq.get_initial_condition(grid)

423

initial[0] = pde.ScalarField.from_expression(grid, "exp(-(x-0.3)**2/0.01)")

424

425

# Solve with progress tracking

426

tracker = pde.PlotTracker(interrupts=0.1, filename="wave_evolution.mp4")

427

result = eq.solve(initial, t_range=2.0, tracker=tracker)

428

429

print("Wave simulation complete - check wave_evolution.mp4")

430

```

431

432

### Elliptic PDE Solutions

433

434

```python

435

import pde

436

437

# Solve Poisson equation with source term

438

grid = pde.CartesianGrid([[-1, 1], [-1, 1]], [64, 64])

439

440

# Source term: Gaussian

441

source = pde.ScalarField.from_expression(grid, "exp(-(x**2 + y**2)/0.1)")

442

443

# Dirichlet boundary conditions

444

bc = {"value": 0}

445

446

# Solve Poisson equation

447

solution = pde.solve_poisson_equation(grid, source, bc)

448

449

print(f"Source integral: {source.integral():.3f}")

450

print(f"Solution range: [{solution.data.min():.3f}, {solution.data.max():.3f}]")

451

```