0
# Fields
1
2
Field classes represent data on discrete grids and provide mathematical operations for solving PDEs. py-pde supports scalar, vector, and tensor fields with automatic differentiation and high-performance numba-compiled operations.
3
4
## Capabilities
5
6
### ScalarField
7
8
Represents scalar-valued functions on grids, providing differential operators and field manipulations.
9
10
```python { .api }
11
class ScalarField:
12
def __init__(self, grid, data=None, *, label=None):
13
"""
14
Initialize scalar field on a grid.
15
16
Parameters:
17
- grid: GridBase, the spatial grid
18
- data: array-like, field values (if None, initializes to zeros)
19
- label: str, optional label for the field
20
"""
21
22
@classmethod
23
def random_uniform(cls, grid, vmin=0, vmax=1, **kwargs):
24
"""
25
Create field with random uniform values.
26
27
Parameters:
28
- grid: GridBase, the spatial grid
29
- vmin: float, minimum value
30
- vmax: float, maximum value
31
32
Returns:
33
ScalarField with random data
34
"""
35
36
@classmethod
37
def random_normal(cls, grid, mean=0, std=1, **kwargs):
38
"""
39
Create field with random normal values.
40
41
Parameters:
42
- grid: GridBase, the spatial grid
43
- mean: float, mean value
44
- std: float, standard deviation
45
46
Returns:
47
ScalarField with random normal data
48
"""
49
50
@classmethod
51
def from_expression(cls, grid, expression, *, user_funcs=None, consts=None, label=None, dtype=None):
52
"""
53
Create field from mathematical expression.
54
55
Parameters:
56
- grid: GridBase, the spatial grid
57
- expression: str or callable, mathematical expression or function
58
- user_funcs: dict, optional user-defined functions
59
- consts: dict, optional constants
60
- label: str, optional field label
61
- dtype: data type for field values
62
63
Returns:
64
ScalarField created from expression
65
"""
66
67
@classmethod
68
def from_image(cls, filename, bounds=None, grid=None, *, periodic=None, label=None, dtype=None):
69
"""
70
Create field from image file.
71
72
Parameters:
73
- filename: str, path to image file
74
- bounds: sequence, spatial bounds for the image
75
- grid: GridBase, optional target grid
76
- periodic: bool or sequence, periodicity per axis
77
- label: str, optional field label
78
- dtype: data type for field values
79
80
Returns:
81
ScalarField created from image data
82
"""
83
84
def laplace(self, bc, **kwargs):
85
"""
86
Apply Laplacian operator.
87
88
Parameters:
89
- bc: boundary conditions
90
- kwargs: additional arguments for operator
91
92
Returns:
93
ScalarField with Laplacian applied
94
"""
95
96
def gradient(self, bc):
97
"""
98
Calculate gradient.
99
100
Parameters:
101
- bc: boundary conditions
102
103
Returns:
104
VectorField representing the gradient
105
"""
106
107
def gradient_squared(self, bc=None, *, args=None, **kwargs):
108
"""
109
Calculate squared magnitude of gradient.
110
111
Parameters:
112
- bc: boundary conditions
113
- args: additional arguments for operator
114
- kwargs: additional keyword arguments
115
116
Returns:
117
ScalarField with squared gradient magnitudes
118
"""
119
120
def project(self, axes, method='integral'):
121
"""
122
Project field onto lower-dimensional space.
123
124
Parameters:
125
- axes: int or sequence, axes to project onto
126
- method: str, projection method ('integral' or 'mean')
127
128
Returns:
129
ScalarField projected onto specified axes
130
"""
131
132
def slice(self, indices, *, label=None):
133
"""
134
Extract slice of the field.
135
136
Parameters:
137
- indices: slice indices for each axis
138
- label: str, optional label for sliced field
139
140
Returns:
141
ScalarField containing the slice
142
"""
143
144
def to_scalar(self, scalar='auto'):
145
"""
146
Convert to scalar field.
147
148
Parameters:
149
- scalar: str, conversion method
150
151
Returns:
152
ScalarField representation
153
"""
154
155
def get_boundary_field(self, axis, upper, bc_type='auto_periodic_neumann'):
156
"""
157
Extract boundary field values.
158
159
Parameters:
160
- axis: int, axis along which to extract boundary
161
- upper: bool, whether to use upper boundary
162
- bc_type: str, boundary condition type
163
164
Returns:
165
ScalarField containing boundary values
166
"""
167
168
@property
169
def average(self):
170
"""float: Average value of the field"""
171
172
@property
173
def std(self):
174
"""float: Standard deviation of field values"""
175
176
def integral(self):
177
"""
178
Calculate field integral over the domain.
179
180
Returns:
181
float: Integral value
182
"""
183
184
def interpolate_to_grid(self, grid, *, bc=None, args=None, **kwargs):
185
"""
186
Interpolate field to different grid.
187
188
Parameters:
189
- grid: GridBase, target grid
190
- bc: boundary conditions for interpolation
191
- args: additional arguments
192
- kwargs: additional keyword arguments
193
194
Returns:
195
ScalarField interpolated to new grid
196
"""
197
```
198
199
### VectorField
200
201
Represents vector-valued functions on grids with vector calculus operations.
202
203
```python { .api }
204
class VectorField:
205
def __init__(self, grid, data=None, *, label=None):
206
"""
207
Initialize vector field on a grid.
208
209
Parameters:
210
- grid: GridBase, the spatial grid
211
- data: array-like, field values (shape: [grid_shape, dim])
212
- label: str, optional label for the field
213
"""
214
215
@classmethod
216
def random_uniform(cls, grid, vmin=0, vmax=1, **kwargs):
217
"""
218
Create vector field with random uniform values.
219
220
Parameters:
221
- grid: GridBase, the spatial grid
222
- vmin: float or array-like, minimum values
223
- vmax: float or array-like, maximum values
224
225
Returns:
226
VectorField with random data
227
"""
228
229
@classmethod
230
def from_scalars(cls, fields, *, label=None, dtype=None):
231
"""
232
Create vector field from scalar field components.
233
234
Parameters:
235
- fields: list of ScalarField, component fields
236
- label: str, optional label for vector field
237
- dtype: data type for field values
238
239
Returns:
240
VectorField created from scalar components
241
"""
242
243
@classmethod
244
def from_expression(cls, grid, expressions, *, user_funcs=None, consts=None, label=None, dtype=None):
245
"""
246
Create vector field from mathematical expressions.
247
248
Parameters:
249
- grid: GridBase, the spatial grid
250
- expressions: list of str or callable, expressions for each component
251
- user_funcs: dict, optional user-defined functions
252
- consts: dict, optional constants
253
- label: str, optional field label
254
- dtype: data type for field values
255
256
Returns:
257
VectorField created from expressions
258
"""
259
260
def divergence(self, bc):
261
"""
262
Calculate divergence.
263
264
Parameters:
265
- bc: boundary conditions
266
267
Returns:
268
ScalarField representing the divergence
269
"""
270
271
def curl(self, bc):
272
"""
273
Calculate curl (2D and 3D only).
274
275
Parameters:
276
- bc: boundary conditions
277
278
Returns:
279
VectorField (3D) or ScalarField (2D) representing the curl
280
"""
281
282
def magnitude(self):
283
"""
284
Calculate magnitude at each point.
285
286
Returns:
287
ScalarField with vector magnitudes
288
"""
289
290
def dot(self, other, out=None, *, label=None):
291
"""
292
Calculate dot product with another vector field.
293
294
Parameters:
295
- other: VectorField, field to dot with
296
- out: optional output field
297
- label: str, optional label for result
298
299
Returns:
300
ScalarField containing dot product
301
"""
302
303
def outer_product(self, other, out=None, *, label=None):
304
"""
305
Calculate outer product with another vector field.
306
307
Parameters:
308
- other: VectorField, field for outer product
309
- out: optional output field
310
- label: str, optional label for result
311
312
Returns:
313
Tensor2Field containing outer product
314
"""
315
316
def make_outer_prod_operator(self, backend='auto'):
317
"""
318
Create operator for efficient outer product calculations.
319
320
Parameters:
321
- backend: str, computational backend to use
322
323
Returns:
324
Callable outer product operator
325
"""
326
327
def gradient(self, bc=None, *, args=None, **kwargs):
328
"""
329
Calculate gradient (tensor field).
330
331
Parameters:
332
- bc: boundary conditions
333
- args: additional arguments for operator
334
- kwargs: additional keyword arguments
335
336
Returns:
337
Tensor2Field representing the gradient
338
"""
339
340
def laplace(self, bc=None, *, args=None, **kwargs):
341
"""
342
Apply vector Laplacian operator.
343
344
Parameters:
345
- bc: boundary conditions
346
- args: additional arguments for operator
347
- kwargs: additional keyword arguments
348
349
Returns:
350
VectorField with Laplacian applied
351
"""
352
353
def integral(self):
354
"""
355
Calculate field integral over the domain.
356
357
Returns:
358
np.ndarray: Integral values for each component
359
"""
360
361
def to_scalar(self, scalar='auto'):
362
"""
363
Convert to scalar field.
364
365
Parameters:
366
- scalar: str, conversion method ('auto', 'norm', etc.)
367
368
Returns:
369
ScalarField representation
370
"""
371
372
def get_vector_data(self, transpose=True):
373
"""
374
Get data for vector visualization.
375
376
Parameters:
377
- transpose: bool, whether to transpose data
378
379
Returns:
380
dict with vector visualization data
381
"""
382
383
def interpolate_to_grid(self, grid, *, bc=None, args=None, **kwargs):
384
"""
385
Interpolate field to different grid.
386
387
Parameters:
388
- grid: GridBase, target grid
389
- bc: boundary conditions for interpolation
390
- args: additional arguments
391
- kwargs: additional keyword arguments
392
393
Returns:
394
VectorField interpolated to new grid
395
"""
396
```
397
398
### Tensor2Field
399
400
Represents second-rank tensor fields on grids.
401
402
```python { .api }
403
class Tensor2Field:
404
def __init__(self, grid, data=None, *, label=None):
405
"""
406
Initialize tensor field on a grid.
407
408
Parameters:
409
- grid: GridBase, the spatial grid
410
- data: array-like, field values (shape: [grid_shape, dim, dim])
411
- label: str, optional label for the field
412
"""
413
414
@classmethod
415
def from_expression(cls, grid, expressions, *, user_funcs=None, consts=None, label=None, dtype=None):
416
"""
417
Create tensor field from mathematical expressions.
418
419
Parameters:
420
- grid: GridBase, the spatial grid
421
- expressions: nested list or callable, expressions for tensor components
422
- user_funcs: dict, optional user-defined functions
423
- consts: dict, optional constants
424
- label: str, optional field label
425
- dtype: data type for field values
426
427
Returns:
428
Tensor2Field created from expressions
429
"""
430
431
def trace(self):
432
"""
433
Calculate trace of the tensor field.
434
435
Returns:
436
ScalarField with tensor traces
437
"""
438
439
def transpose(self, label='transpose'):
440
"""
441
Calculate transpose of the tensor field.
442
443
Parameters:
444
- label: str, label for transposed field
445
446
Returns:
447
Tensor2Field with transposed tensors
448
"""
449
450
def dot(self, other, out=None, *, axes=None, label=None):
451
"""
452
Calculate dot product with vector or tensor field.
453
454
Parameters:
455
- other: VectorField or Tensor2Field, field to dot with
456
- out: optional output field
457
- axes: tuple, axes for contraction
458
- label: str, optional label for result
459
460
Returns:
461
DataFieldBase containing dot product result
462
"""
463
464
def divergence(self, bc=None, *, args=None, **kwargs):
465
"""
466
Calculate divergence of tensor field.
467
468
Parameters:
469
- bc: boundary conditions
470
- args: additional arguments for operator
471
- kwargs: additional keyword arguments
472
473
Returns:
474
VectorField representing the divergence
475
"""
476
477
def integral(self):
478
"""
479
Calculate field integral over the domain.
480
481
Returns:
482
np.ndarray: Integral values for tensor components
483
"""
484
485
def symmetrize(self, make_traceless=False, *, label=None):
486
"""
487
Symmetrize the tensor field.
488
489
Parameters:
490
- make_traceless: bool, whether to make traceless
491
- label: str, optional label for result
492
493
Returns:
494
Tensor2Field with symmetrized tensors
495
"""
496
497
def to_scalar(self, scalar='auto'):
498
"""
499
Convert to scalar field.
500
501
Parameters:
502
- scalar: str, conversion method
503
504
Returns:
505
ScalarField representation
506
"""
507
508
def plot_components(self, **kwargs):
509
"""
510
Plot tensor field components.
511
512
Parameters:
513
- kwargs: plotting arguments
514
515
Returns:
516
PlotReference with component plots
517
"""
518
```
519
520
### FieldCollection
521
522
Manages collections of multiple fields for coupled PDE systems.
523
524
```python { .api }
525
class FieldCollection:
526
def __init__(self, fields, *, label=None, copy_fields=False):
527
"""
528
Initialize collection of fields.
529
530
Parameters:
531
- fields: list of FieldBase, the fields to collect
532
- label: str, optional label for the collection
533
- copy_fields: bool, whether to copy the fields
534
"""
535
536
@classmethod
537
def from_state(cls, attributes, data=None):
538
"""
539
Create field collection from state information.
540
541
Parameters:
542
- attributes: dict, field attributes and metadata
543
- data: array-like, optional field data
544
545
Returns:
546
FieldCollection created from state
547
"""
548
549
def __getitem__(self, index):
550
"""Access individual fields by index or slice"""
551
552
def __len__(self):
553
"""Number of fields in collection"""
554
555
@property
556
def grid(self):
557
"""GridBase: Grid shared by all fields"""
558
559
def copy(self):
560
"""
561
Create copy of the field collection.
562
563
Returns:
564
FieldCollection with copied fields
565
"""
566
567
@property
568
def fields(self):
569
"""list: Individual fields in the collection"""
570
571
@property
572
def labels(self):
573
"""list: Labels of fields in the collection"""
574
575
def assert_field_compatible(self, other, accept_scalar=False):
576
"""
577
Check field compatibility for operations.
578
579
Parameters:
580
- other: FieldBase or FieldCollection, field to check
581
- accept_scalar: bool, whether to accept scalar fields
582
"""
583
584
def integrals(self):
585
"""
586
Calculate integrals of all fields.
587
588
Returns:
589
list: Integral values for each field
590
"""
591
592
def averages(self):
593
"""
594
Calculate averages of all fields.
595
596
Returns:
597
list: Average values for each field
598
"""
599
600
def magnitudes(self):
601
"""
602
Calculate magnitudes of all fields.
603
604
Returns:
605
np.ndarray: Magnitude values for each field
606
"""
607
608
def get_image_data(self, index=0, **kwargs):
609
"""
610
Get image data for visualization.
611
612
Parameters:
613
- index: int, field index to visualize
614
- kwargs: additional visualization parameters
615
616
Returns:
617
dict: Image data and metadata
618
"""
619
```
620
621
### FieldBase
622
623
Abstract base class for all field types providing common functionality.
624
625
```python { .api }
626
class FieldBase:
627
@property
628
def grid(self):
629
"""GridBase: Grid on which field is defined"""
630
631
@property
632
def data(self):
633
"""np.ndarray: Raw field data"""
634
635
@property
636
def label(self):
637
"""str: Field label"""
638
639
def copy(self, *, label=None):
640
"""
641
Create copy of the field.
642
643
Parameters:
644
- label: str, optional new label
645
646
Returns:
647
FieldBase copy of same type
648
"""
649
650
def interpolate_to_grid(self, grid, *, bc=None, fill=None):
651
"""
652
Interpolate field to different grid.
653
654
Parameters:
655
- grid: GridBase, target grid
656
- bc: boundary conditions for interpolation
657
- fill: value for points outside domain
658
659
Returns:
660
FieldBase interpolated to new grid
661
"""
662
```
663
664
## Usage Examples
665
666
### Basic Field Operations
667
668
```python
669
import pde
670
import numpy as np
671
672
# Create a 2D Cartesian grid
673
grid = pde.CartesianGrid([[0, 10], [0, 10]], [64, 64])
674
675
# Initialize scalar field with Gaussian
676
def gaussian(x, y):
677
return np.exp(-(x-5)**2/2 - (y-5)**2/2)
678
679
field = pde.ScalarField.from_expression(grid, gaussian)
680
681
# Apply Laplacian with Neumann boundary conditions
682
bc = {"derivative": 0}
683
laplacian = field.laplace(bc)
684
685
print(f"Original field integral: {field.integral():.3f}")
686
print(f"Laplacian integral: {laplacian.integral():.3f}")
687
```
688
689
### Vector Field Operations
690
691
```python
692
import pde
693
694
# Create 2D grid
695
grid = pde.CartesianGrid([[-5, 5], [-5, 5]], [32, 32])
696
697
# Create a vortex vector field
698
def vortex_field(x, y):
699
return [-y, x]
700
701
vector_field = pde.VectorField.from_expression(grid, vortex_field)
702
703
# Calculate divergence and curl
704
bc = {"derivative": 0}
705
div = vector_field.divergence(bc)
706
curl = vector_field.curl(bc)
707
708
print(f"Divergence range: [{div.data.min():.3f}, {div.data.max():.3f}]")
709
print(f"Curl range: [{curl.data.min():.3f}, {curl.data.max():.3f}]")
710
```