General Linear Stepper¤
exponax.stepper.GeneralLinearStepper
¤
Bases: BaseStepper
Source code in exponax/stepper/_linear.py
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 |
|
__init__
¤
__init__(
num_spatial_dims: int,
domain_extent: float,
num_points: int,
dt: float,
*,
coefficients: tuple[float, ...] = (0.0, -0.1, 0.01)
)
General timestepper for a d-dimensional (d ∈ {1, 2, 3}
) linear
equation with an arbitrary combination of derivative terms and
respective coefficients. To simplify the interface, only isotropicity is
supported. For example, the advection speed is the same in all spatial
dimensions, or diffusion is equally strong in all spatial dimensions.
In 1d the equation is given by
uₜ = sum_j a_j uₓˢ
with uₓˢ
denoting the s-th derivative of u
with respect to x
. The
coefficient corresponding to this derivative is a_j
.
The isotropic version in higher dimensions can expressed as
uₜ = sum_j a_j (1⋅∇ʲ)u
with 1⋅∇ʲ
denoting the j-th repeated elementwise product of the nabla
operator with itself in an inner product with the one vector. For
example, 1⋅∇¹
is the collection of first derivatives, 1⋅∇²
is the
collection of second derivatives (=Laplace operator), etc.
The interface to this general stepper is the list of coefficients
containing the a_j
. Its length determines the highes occuring order of
derivative. Note that this list starts at zero. If only one specific
linear term is wanted, have all prior coefficients set to zero.
The default configuration is an advection-diffusion equation with a_0 =
0
, a_1 = -0.1
, and a_2 = 0.01
.
Arguments:
- num_spatial_dims
: The number of spatial dimensions d
.
- domain_extent
: The size of the domain L
; in higher dimensions
the domain is assumed to be a scaled hypercube Ω = (0, L)ᵈ
.
- num_points
: The number of points N
used to discretize the
domain. This includes the left boundary point and
excludes the right boundary point. In higher dimensions; the
number of points in each dimension is the same. Hence, the total
number of degrees of freedom is Nᵈ
.
- dt
: The timestep size Δt
between two consecutive states.
- coefficients
(keyword-only): The list of coefficients a_j
corresponding to the derivatives. Default: [0.0, -0.1, 0.01]
.
Notes:
- There is a repeating pattern in the effect of orders of
derivatives:
- Even derivatives (i.e., 0, 2, 4, 6, ...) scale the
solution. Order 0 scales all wavenumbers/modes equally (if
its coefficient is negative, this is also called a drag).
Order 2 scales higher wavenumbers/modes stronger with the
dependence on the effect on the wavenumber being
quadratically. Order 4 also scales but stronger than order
4. Its dependency on the wavenumber is quartically. This
pattern continues for higher orders.
- Odd derivatives (i.e, 1, 3, 5, 7, ...) rotate the solution in
Fourier space. In state space, this is observed as
advection. Order 1 rotates all wavenumbers/modes equally. In
state space, this is observed in that the initial condition
just moves over the domain. Order 3 rotates higher
wavenumbers/modes stronger with the dependence on the
wavenumber being quadratic. If certain wavenumbers are
rotated at a different speed, there is still advection in
state space but certain patterns in the initial condition
are advected at different speeds. As such, it is observed
that the shape of the initial condition dissolves. The
effect continues for higher orders with the dependency on
the wavenumber becoming continuously stronger.
- Take care of the signs of coefficients. In contrast to the
indivial linear steppers (exponax.stepper.Advection
,
exponax.stepper.Diffusion
, etc.), the signs are not
automatically taken care of to produce meaningful coefficients.
For the general linear stepper all linear derivatives are on the
right-hand side of the equation. This has the following effect
based on the order of derivative (this a consequence of squaring
the imaginary unit returning -1):
- Zeroth-Order: A negative coeffcient is a drag and removes
energy from the system. A positive coefficient adds energy
to the system.
- First-Order: A negative coefficient rotates the solution
clockwise. A positive coefficient rotates the solution
counter-clockwise. Hence, negative coefficients advect
solutions to the right, positive coefficients advect
solutions to the left.
- Second-Order: A positive coefficient diffuses the solution
(i.e., removes energy from the system). A negative
coefficient adds energy to the system.
- Third-Order: A negative coefficient rotates the solution
counter-clockwise. A positive coefficient rotates the
solution clockwise. Hence, negative coefficients advect
solutions to the left, positive coefficients advect
solutions to the right.
- Fourth-Order: A negative coefficient diffuses the solution
(i.e., removes energy from the system). A positive
coefficient adds energy to the system.
- ...
- The stepper is unconditionally stable, no matter the choice of
any argument because the equation is solved analytically in
Fourier space. However, note if you have odd-order
derivative terms (e.g., advection or dispersion) and your
initial condition is not bandlimited (i.e., it contains
modes beyond the Nyquist frequency of (N//2)+1
) there is a
chance spurious oscillations can occur.
- Ultimately, only the factors a_j Δt / Lʲ
affect the
characteristic of the dynamics. See also
exponax.normalized.NormalizedLinearStepper
with
normalized_coefficients = [0, alpha_1, alpha_2, ...]
with
alpha_j = coefficients[j] * dt / domain_extent**j
. You can use
the function exponax.normalized.normalize_coefficients
to
obtain the normalized coefficients.
Source code in exponax/stepper/_linear.py
588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 |
|
__call__
¤
__call__(
u: Float[Array, "C ... N"]
) -> Float[Array, "C ... N"]
Performs a check
Source code in exponax/_base_stepper.py
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
|