Skip to content

Pattern formation

Pattern formation: amplitude equations and rolls.

BrusselatorElement(label, visual=None, *, u=1.0, v=3.0, a=1.0, b=3.0, Du=1.0, Dv=8.0)

Bases: BrusselatorReactionElement

Site of the Brusselator, the reactor of the Brusselator with the diffusion coefficients of its intermediates.

The four reactions of brusselator run at every site, and its diffusions read Du and Dv.

Parameters:

Name Type Description Default
label str

The label of the site or the field.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
u float

The initial concentration of u.

1.0
v float

The initial concentration of v.

3.0
a float

The feed of u.

1.0
b float

The conversion of u into v.

3.0
Du Annotated[object, ParameterSpec()]

The diffusion of u.

1.0
Dv Annotated[object, ParameterSpec()]

The diffusion of v.

8.0

Examples:

>>> from skcomplex.systems.chemistry.pattern_formation import BrusselatorElement
>>> BrusselatorElement('cell').Dv
8.0
Source code in src/skcomplex/systems/chemistry/pattern_formation/_reaction_diffusion.py
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    u: float = 1.0,
    v: float = 3.0,
    a: float = 1.0,
    b: float = 3.0,
    Du: Annotated[object, ParameterSpec()] = 1.0,
    Dv: Annotated[object, ParameterSpec()] = 8.0,
) -> None:
    super().__init__(label, visual=visual, u=u, v=v, a=a, b=b)
    self.Du = Du
    self.Dv = Dv

GrayScottElement(label, visual=None, *, u=1.0, v=0.0, Du=0.16, Dv=0.08, F=0.035, k=0.065)

Bases: Element

Site of the Gray-Scott system, the substrate u and the activator v.

The reactions of gray_scott at every site, the cubic autocatalysis of the activator on the substrate, the feed F of the substrate, and the removal F + k of the activator, read F and k, and its diffusions read Du and Dv.

Parameters:

Name Type Description Default
label str

The label of the site or the field.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
u Annotated[object, StateSpec()]

The initial substrate.

1.0
v Annotated[object, StateSpec()]

The initial activator.

0.0
Du Annotated[object, ParameterSpec()]

The diffusion of the substrate.

0.16
Dv Annotated[object, ParameterSpec()]

The diffusion of the activator.

0.08
F Annotated[object, ParameterSpec()]

The feed rate.

0.035
k Annotated[object, ParameterSpec()]

The kill rate.

0.065

Examples:

>>> from skcomplex.systems.chemistry.pattern_formation import GrayScottElement
>>> GrayScottElement('cell').k
0.065
Source code in src/skcomplex/systems/chemistry/pattern_formation/_reaction_diffusion.py
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    u: Annotated[object, StateSpec()] = 1.0,
    v: Annotated[object, StateSpec()] = 0.0,
    Du: Annotated[object, ParameterSpec()] = 0.16,
    Dv: Annotated[object, ParameterSpec()] = 0.08,
    F: Annotated[object, ParameterSpec()] = 0.035,
    k: Annotated[object, ParameterSpec()] = 0.065,
) -> None:
    super().__init__(label, visual=visual)
    self.u = u
    self.v = v
    self.Du = Du
    self.Dv = Dv
    self.F = F
    self.k = k

SchnakenbergElement(label, visual=None, *, u=1.0, v=0.9, a=0.1, b=0.9, Du=1.0, Dv=40.0)

Bases: Element

Site of the Schnakenberg system, the activator u and the inhibitor v.

The reactions of schnakenberg at every site, the productions a of u and b of v, the decay of u, and the autocatalysis 2U + V -> 3U, read a and b, and its diffusions read Du and Dv.

Parameters:

Name Type Description Default
label str

The label of the site or the field.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
u Annotated[object, StateSpec()]

The initial activator.

1.0
v Annotated[object, StateSpec()]

The initial inhibitor.

0.9
a Annotated[object, ParameterSpec()]

The production of u.

0.1
b Annotated[object, ParameterSpec()]

The production of v.

0.9
Du Annotated[object, ParameterSpec()]

The diffusion of the activator.

1.0
Dv Annotated[object, ParameterSpec()]

The diffusion of the inhibitor.

40.0

Examples:

>>> from skcomplex.systems.chemistry.pattern_formation import SchnakenbergElement
>>> SchnakenbergElement('cell').Dv
40.0
Source code in src/skcomplex/systems/chemistry/pattern_formation/_reaction_diffusion.py
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    u: Annotated[object, StateSpec()] = 1.0,
    v: Annotated[object, StateSpec()] = 0.9,
    a: Annotated[object, ParameterSpec()] = 0.1,
    b: Annotated[object, ParameterSpec()] = 0.9,
    Du: Annotated[object, ParameterSpec()] = 1.0,
    Dv: Annotated[object, ParameterSpec()] = 40.0,
) -> None:
    super().__init__(label, visual=visual)
    self.u = u
    self.v = v
    self.a = a
    self.b = b
    self.Du = Du
    self.Dv = Dv

brusselator(shape=(64, 64), *, a=1.0, b=3.0, Du=1.0, Dv=8.0, random_state=0)

Return the Brusselator reaction-diffusion system from small noise around its steady state (a, b / a).

Parameters:

Name Type Description Default
shape Sequence[int]

The number of rows and columns of the periodic lattice.

(64, 64)
a float

The feed of u.

1.0
b float

The conversion of u into v.

3.0
Du float

The diffusion of u.

1.0
Dv float

The diffusion of v.

8.0
random_state int | Generator | None

The seed or generator of the noise.

0

Returns:

Name Type Description
system System

The system, with the concentrations cells.u and cells.v.

Examples:

>>> from skcomplex.systems.chemistry.pattern_formation import brusselator
>>> brusselator((8, 8), b=2.5).elements[0].values['b']
2.5
Source code in src/skcomplex/systems/chemistry/pattern_formation/_reaction_diffusion.py
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
@register_system(
    field='chemistry/pattern_formation',
    tags=('field', 'reaction-diffusion', 'Turing', 'oscillation', 'pde'),
    references=('Prigogine and Lefever 1968', 'Gros 2015'),
    defaults={'until': 100.0, 'dt': 1.0, 'solver': RK4Solver(dt=0.01)},
)
def brusselator(
    shape: Sequence[int] = (64, 64),
    *,
    a: float = 1.0,
    b: float = 3.0,
    Du: float = 1.0,
    Dv: float = 8.0,
    random_state: int | np.random.Generator | None = 0,
) -> System:
    """Return the Brusselator reaction-diffusion system from small noise around its steady state `(a, b / a)`.

    Args:
        shape:
            The number of rows and columns of the periodic lattice.

        a:
            The feed of `u`.

        b:
            The conversion of `u` into `v`.

        Du:
            The diffusion of `u`.

        Dv:
            The diffusion of `v`.

        random_state:
            The seed or generator of the noise.

    Returns:
        system:
            The system, with the concentrations `cells.u` and `cells.v`.

    Examples:
        >>> from skcomplex.systems.chemistry.pattern_formation import brusselator
        >>> brusselator((8, 8), b=2.5).elements[0].values['b']
        2.5
    """
    shape = tuple(shape)
    values = {
        'u': a + _noise(shape, 0.01, random_state),
        'v': np.full(shape, b / a),
        'a': a,
        'b': b,
        'Du': Du,
        'Dv': Dv,
    }
    return System(
        elements=[FieldElement('cells', element=BrusselatorElement, space=LatticeSpace(shape), values=values)],
        interactions=[*_get_brusselator_reactions(), *_get_diffusions()],
    )

gray_scott(shape=(128, 128), *, Du=0.16, Dv=0.08, F=0.035, k=0.065, random_state=0)

Return the Gray-Scott reaction-diffusion system, seeded in its middle, which grows spots that replicate.

Parameters:

Name Type Description Default
shape Sequence[int]

The number of rows and columns of the periodic lattice.

(128, 128)
Du float

The diffusion of the substrate u.

0.16
Dv float

The diffusion of the activator v.

0.08
F float

The feed rate.

0.035
k float

The kill rate.

0.065
random_state int | Generator | None

The seed or generator of the noise on the seed.

0

Returns:

Name Type Description
system System

The system, with the substrate cells.u and the activator cells.v.

Examples:

>>> from skcomplex.systems.chemistry.pattern_formation import gray_scott
>>> gray_scott((32, 32), F=0.04).elements[0].values['F']
0.04
Source code in src/skcomplex/systems/chemistry/pattern_formation/_reaction_diffusion.py
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
@register_system(
    field='chemistry/pattern_formation',
    tags=('field', 'reaction-diffusion', 'self-replication', 'pde'),
    references=('Gray and Scott 1984', 'Pearson 1993'),
    defaults={'until': 2000.0, 'dt': 20.0, 'solver': RK4Solver(dt=1.0)},
)
def gray_scott(
    shape: Sequence[int] = (128, 128),
    *,
    Du: float = 0.16,
    Dv: float = 0.08,
    F: float = 0.035,
    k: float = 0.065,
    random_state: int | np.random.Generator | None = 0,
) -> System:
    """Return the Gray-Scott reaction-diffusion system, seeded in its middle, which grows spots that replicate.

    Args:
        shape:
            The number of rows and columns of the periodic lattice.

        Du:
            The diffusion of the substrate `u`.

        Dv:
            The diffusion of the activator `v`.

        F:
            The feed rate.

        k:
            The kill rate.

        random_state:
            The seed or generator of the noise on the seed.

    Returns:
        system:
            The system, with the substrate `cells.u` and the activator `cells.v`.

    Examples:
        >>> from skcomplex.systems.chemistry.pattern_formation import gray_scott
        >>> gray_scott((32, 32), F=0.04).elements[0].values['F']
        0.04
    """
    shape = tuple(shape)
    u, v = np.ones(shape), np.zeros(shape)
    middle = tuple(slice(size // 2 - size // 10, size // 2 + size // 10) for size in shape)
    u[middle], v[middle] = 0.5, 0.25
    noise = _noise(shape, 0.01, random_state)
    values = {'u': u + noise, 'v': v + np.abs(noise), 'Du': Du, 'Dv': Dv, 'F': F, 'k': k}
    return System(
        elements=[FieldElement('cells', element=GrayScottElement, space=LatticeSpace(shape), values=values)],
        interactions=[*_get_gray_scott_reactions(), *_get_diffusions()],
    )

schnakenberg(shape=(64, 64), *, a=0.1, b=0.9, Du=1.0, Dv=40.0, spacing=1.0, random_state=0)

Return the Schnakenberg reaction-diffusion system, which forms Turing patterns from noise when Dv >> Du.

The steady state u = a + b, v = b / (a + b)^2 is stable without diffusion and unstable to perturbations of a band of wavelengths with it.

Parameters:

Name Type Description Default
shape Sequence[int]

The number of sites along every dimension of the periodic lattice.

(64, 64)
a float

The production of u.

0.1
b float

The production of v.

0.9
Du float

The diffusion of the activator u.

1.0
Dv float

The diffusion of the inhibitor v.

40.0
spacing float

The distance between sites.

1.0
random_state int | Generator | None

The seed or generator of the noise.

0

Returns:

Name Type Description
system System

The system, with the concentrations cells.u and cells.v.

Examples:

>>> from skcomplex.systems.chemistry.pattern_formation import schnakenberg
>>> schnakenberg((8, 8)).elements[0].values['Dv']
40.0
Source code in src/skcomplex/systems/chemistry/pattern_formation/_reaction_diffusion.py
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
@register_system(
    field='chemistry/pattern_formation',
    tags=('field', 'reaction-diffusion', 'Turing', 'pde'),
    references=('Schnakenberg 1979', 'Turing 1952', 'Murray 2003'),
    defaults={'until': 200.0, 'dt': 5.0, 'solver': RK4Solver(dt=0.005)},
)
def schnakenberg(
    shape: Sequence[int] = (64, 64),
    *,
    a: float = 0.1,
    b: float = 0.9,
    Du: float = 1.0,
    Dv: float = 40.0,
    spacing: float = 1.0,
    random_state: int | np.random.Generator | None = 0,
) -> System:
    """Return the Schnakenberg reaction-diffusion system, which forms Turing patterns from noise when `Dv >> Du`.

    The steady state `u = a + b`, `v = b / (a + b)^2` is stable without diffusion and unstable to perturbations of a
    band of wavelengths with it.

    Args:
        shape:
            The number of sites along every dimension of the periodic lattice.

        a:
            The production of `u`.

        b:
            The production of `v`.

        Du:
            The diffusion of the activator `u`.

        Dv:
            The diffusion of the inhibitor `v`.

        spacing:
            The distance between sites.

        random_state:
            The seed or generator of the noise.

    Returns:
        system:
            The system, with the concentrations `cells.u` and `cells.v`.

    Examples:
        >>> from skcomplex.systems.chemistry.pattern_formation import schnakenberg
        >>> schnakenberg((8, 8)).elements[0].values['Dv']
        40.0
    """
    shape = tuple(shape)
    steady_u, steady_v = a + b, b / (a + b) ** 2
    values = {
        'u': steady_u * (1 + _noise(shape, 0.01, random_state)),
        'v': np.full(shape, steady_v),
        'a': a,
        'b': b,
        'Du': Du,
        'Dv': Dv,
    }
    return System(
        elements=[
            FieldElement(
                'cells',
                element=SchnakenbergElement,
                space=LatticeSpace(shape, spacing=spacing),
                values=values,
            ),
        ],
        interactions=[*_get_schnakenberg_reactions(), *_get_diffusions()],
    )