SEM equations¶
The equation classes of sweep.sem.equations, all importable as
sweep.sem.<Class>. A class is not constructed by hand: it is passed to
PropSEM, which builds the mesh, interpolates the models onto
its nodes and calls the class's build:
from sweep.sem import PropSEM, AcousticPotentialSEM2D
solver = PropSEM(AcousticPotentialSEM2D, shape=(141, 681), dh=25.0, dt=0.002)
seis = solver(wavelet, sources, receivers, models=[vp])
build(mesh, <models>, *, ...) is that call. Its positional arguments after
the mesh are the models as element arrays (vp_e is vp at the GLL nodes of
every element), in the order models= takes them, except rho on
AcousticPotentialSEM2D, which PropSEM fills from density=. Its keywords
are what PropSEM sets up from its own options, such as the free surface and
the C-PML profile. The mesh family, the models, the CUDA kernels and the
boundary-saving coverage of every class are in the
SEM family table;
sweep show <Class> prints the fields and the source and receiver types.
Registry¶
Equations are discovered, not listed: every class with field_specs in a
module of sweep.sem.equations is one.
sweep.sem.equations.equation_classes ¶
{class name: class} for every equation in this package.
sweep.sem.equations.summary ¶
What picks an equation, as data -- the columns of :func:describe.
mesh ("quad4", "quad9", "hex8" or "hex27"), ndim,
topography (the mesh family admits one), cpml ("yes",
"split" or "NO", see :func:describe), fields (the state, in
order), sources and receivers (the fields a source drives and the
receivers sample) and derived (the receiver components computed from
those, such as p). sweep show prints it.
sweep.sem.equations.describe ¶
One line per equation: everything needed to pick one.
The columns exist because none of this is inferable from the class name.
AcousticPotentialSEM2D has no "Deformed" in its name yet runs on a
curved mesh and supports topography; ElasticVSSEM3D has none either and
does not. And VS (velocity-stress) is a different FORMULATION, not a
different mesh -- read it off the recorded fields: u_* is the 2nd-order
displacement scheme, v_* the 1st-order velocity-stress one.
topo says the mesh family admits a topography; cpml says
build() accepts an absorbing profile at all. An equation with
cpml no is a reflecting box: PropSEM refuses an abcn for it.
Acoustic¶
The potential form (SPECFEM's) is the FWI workhorse: shot batching, per-shot
models and batched boundary saving on impl='c' are there. Its build takes
a density model; PropSEM gives it the constant density=. The other four
take vp alone, one per mesh family.
sweep.sem.AcousticPotentialSEM2D ¶
AcousticPotentialSEM2D(
mesh: Quad9Mesh,
vp_e: Tensor,
rho_e: Tensor,
mass: Tensor,
_inv_M: Tensor,
dirichlet: tuple[str, ...],
dirichlet_idx: Tensor,
cpml: Optional[CPMLProfile],
domain: Optional[DomainMask],
_mask_e: Tensor,
_alive: Tensor,
kappa_node: Tensor,
mass_geo: Tensor,
_inv_M_geo: Tensor,
_D: Tensor,
_inv_rho: Tensor,
_w_J: Tensor,
_ixx: Tensor,
_ixz: Tensor,
_iex: Tensor,
_iez: Tensor,
)
Bases: sweep.sem.fields.DerivedInitState, sweep.sem.fields.DirichletNodes
SPECFEM-normalized variable-density acoustic (potential χ) on Quad9.
build
classmethod
¶
build(
mesh: Quad9Mesh,
vp_e: Tensor,
rho_e: Tensor,
*,
dirichlet: tuple[str, ...] = ("top",),
domain: Optional[DomainMask] = None,
cpml: Optional[CPMLProfile] = None
) -> AcousticPotentialSEM2D
domain restricts the fluid to its acoustic elements: the operators
are assembled over those only, and χ on nodes outside them is a dead DOF
pinned to exactly 0 (inv_M = 0). None = the whole mesh is fluid.
cpml enables the double-convolution absorbing bands (potential
flavor — the flux (1/ρ)∇χ rides inside the directional operators).
sweep.sem.AcousticSEM2D ¶
AcousticSEM2D(
mesh: Quad4Mesh,
vp_e: Tensor,
vp_squared_node: Tensor,
mass: Tensor,
_inv_M: Tensor,
dirichlet: tuple[str, ...],
dirichlet_idx: Tensor,
cpml: Optional[CPMLProfile],
_D: Tensor,
_w_jx_noc2: Tensor,
_w_jz_noc2: Tensor,
_w_jac: Tensor,
_inv_half_dx: float,
_inv_half_dz: float,
)
Bases: sweep.sem.fields.DerivedInitState, sweep.sem.fields.DirichletNodes
Cached factors + ops for 2-D acoustic SEM on a :class:Quad4Mesh.
build
classmethod
¶
build(
mesh: Quad4Mesh,
vp_e: Tensor,
*,
dirichlet: tuple[str, ...] = ("top",),
cpml: Optional[CPMLProfile] = None
) -> AcousticSEM2D
sweep.sem.AcousticSEM2DDeformed ¶
AcousticSEM2DDeformed(
mesh: Quad9Mesh,
vp_e: Tensor,
vp_squared_node: Tensor,
mass: Tensor,
_inv_M: Tensor,
dirichlet: tuple[str, ...],
dirichlet_idx: Tensor,
cpml: Optional[CPMLProfile],
_D: Tensor,
_w_J: Tensor,
_ixx: Tensor,
_ixz: Tensor,
_iex: Tensor,
_iez: Tensor,
)
Bases: sweep.sem.fields.DerivedInitState, sweep.sem.fields.DirichletNodes
Cached factors + ops for 2-D acoustic SEM on a :class:Quad9Mesh.
build
classmethod
¶
build(
mesh: Quad9Mesh,
vp_e: Tensor,
*,
dirichlet: tuple[str, ...] = ("top",),
cpml: Optional[CPMLProfile] = None
) -> AcousticSEM2DDeformed
sweep.sem.AcousticSEM3D ¶
AcousticSEM3D(
mesh: Hex8Mesh,
vp_e: Tensor,
vp_squared_node: Tensor,
mass: Tensor,
_inv_M: Tensor,
dirichlet: tuple[str, ...],
dirichlet_idx: Tensor,
cpml: Optional[CPML3DProfile],
_D: Tensor,
_w_jx_noc2: Tensor,
_w_jy_noc2: Tensor,
_w_jz_noc2: Tensor,
_w_jac: Tensor,
_inv_half_dx: float,
_inv_half_dy: float,
_inv_half_dz: float,
)
Bases: sweep.sem.fields.DerivedInitState, sweep.sem.fields.DirichletNodes
Cached factors + ops for 3-D acoustic SEM on a :class:Hex8Mesh.
build
classmethod
¶
build(
mesh: Hex8Mesh,
vp_e: Tensor,
*,
dirichlet: tuple[str, ...] = ("top",),
cpml: Optional[CPML3DProfile] = None
) -> AcousticSEM3D
sweep.sem.AcousticSEM3DDeformed ¶
AcousticSEM3DDeformed(
mesh: Hex27Mesh,
vp_e: Tensor,
vp_squared_node: Tensor,
mass: Tensor,
_inv_M: Tensor,
dirichlet: tuple,
dirichlet_idx: Tensor,
cpml: Optional[CPML3DProfile],
_D: Tensor,
_w_J: Tensor,
_I: tuple,
)
Bases: sweep.sem.fields.DerivedInitState, sweep.sem.fields.DirichletNodes
Cached factors + ops for 3-D acoustic SEM on a :class:Hex27Mesh.
Elastic, displacement form¶
Second-order in time (SPECFEM's Newmark scheme); the source and receiver fields
are u_x, u_z (and u_y). ElasticSEM2D, ElasticSEM3D and
ElasticSEM3DDeformed model no C-PML: PropSEM refuses an abcn for them.
sweep.sem.ElasticSEM2D ¶
ElasticSEM2D(
mesh: Quad4Mesh,
vp_e: Tensor,
vs_e: Tensor,
rho_e: Tensor,
mass: Tensor,
_inv_M: Tensor,
_D: Tensor,
_w_lam2mu_Jx: Tensor,
_w_lam: Tensor,
_w_lam2mu_Jz: Tensor,
_w_mu_Jz: Tensor,
_w_mu: Tensor,
_w_mu_Jx: Tensor,
)
Bases: sweep.sem.fields.DerivedInitState
Cached SEM operators for 2-D isotropic elastic on a :class:Quad4Mesh.
build
classmethod
¶
sweep.sem.ElasticSEM2DDeformed ¶
ElasticSEM2DDeformed(
mesh: Quad9Mesh,
vp_e: Tensor,
vs_e: Tensor,
rho_e: Tensor,
mass: Tensor,
_inv_M: Tensor,
cpml: Optional[ElasticCPMLProfile],
_D: Tensor,
_lam: Tensor,
_mu: Tensor,
_lam2mu: Tensor,
_w_J: Tensor,
_w_rho_J: Tensor,
_ixx: Tensor,
_ixz: Tensor,
_iex: Tensor,
_iez: Tensor,
domain: Optional[DomainMask] = None,
_mask_e: Optional[Tensor] = None,
_alive: Optional[Tensor] = None,
)
Bases: sweep.sem.fields.DerivedInitState
Elastic SEM on a deformed Quad9 mesh.
build
classmethod
¶
build(
mesh: Quad9Mesh,
vp_e: Tensor,
vs_e: Tensor,
rho_e: Tensor,
*,
cpml: Optional[ElasticCPMLProfile] = None,
domain: Optional[DomainMask] = None
) -> ElasticSEM2DDeformed
domain restricts the solid to its elastic elements (fluid–solid
coupling): the operators are assembled over those only and u outside
them is a dead DOF pinned to exactly 0. None = the whole mesh.
sweep.sem.ElasticSEM3D ¶
ElasticSEM3D(
mesh: Hex8Mesh,
vp_e: Tensor,
vs_e: Tensor,
rho_e: Tensor,
mass: Tensor,
_inv_M: Tensor,
_D: Tensor,
_w3: Tensor,
_lam: Tensor,
_mu: Tensor,
_lam2mu: Tensor,
_Gxx: float,
_Gyy: float,
_Gzz: float,
_Gxy: float,
_Gxz: float,
_Gyz: float,
)
Bases: sweep.sem.fields.DerivedInitState
Cached SEM operators for 3-D isotropic elastic on a :class:Hex8Mesh.
build
classmethod
¶
sweep.sem.ElasticSEM3DDeformed ¶
ElasticSEM3DDeformed(
mesh: Hex27Mesh,
vp_e: Tensor,
vs_e: Tensor,
rho_e: Tensor,
mass: Tensor,
_inv_M: Tensor,
_D: Tensor,
_lam: Tensor,
_mu: Tensor,
_lam2mu: Tensor,
_w_J: Tensor,
_I: tuple,
)
Bases: sweep.sem.fields.DerivedInitState
Cached factors + ops for 3-D isotropic elastic SEM on a Hex27 mesh.
Elastic, velocity-stress form¶
First-order in time; the source and receiver fields are v_x, v_z (and
v_y). The stresses are element-local, so they take no receivers.
sweep.sem.ElasticVSSEM2DDeformed ¶
ElasticVSSEM2DDeformed(
mesh: Quad9Mesh,
vp_e: Tensor,
vs_e: Tensor,
rho_e: Tensor,
mass_rho: Tensor,
_inv_M: Tensor,
cpml: Optional[SimpleElasticCPMLProfile],
free_top: bool,
top_elem_ids: Tensor,
_tx_top: Tensor,
_tz_top: Tensor,
_D: Tensor,
_lam: Tensor,
_mu: Tensor,
_lam2mu: Tensor,
_w_J: Tensor,
_ixx: Tensor,
_ixz: Tensor,
_iex: Tensor,
_iez: Tensor,
)
Bases: sweep.sem.fields.DerivedInitState
1st-order velocity-stress elastic SEM on a deformed Quad9 mesh.
build
classmethod
¶
build(
mesh: Quad9Mesh,
vp_e: Tensor,
vs_e: Tensor,
rho_e: Tensor,
*,
free_top: bool = False,
cpml: Optional[SimpleElasticCPMLProfile] = None
) -> ElasticVSSEM2DDeformed
Build the equation operators.
free_top=False (default) → natural free-surface BC, weakly
imposed by dropping the boundary integral. free_top=True →
strong essential BC (σ·n=0 in local coords at the top row).
sweep.sem.ElasticVTISEM2DDeformed ¶
ElasticVTISEM2DDeformed(
mesh: Quad9Mesh,
vp_e: Tensor,
vs_e: Tensor,
rho_e: Tensor,
mass_rho: Tensor,
_inv_M: Tensor,
cpml: Optional[SimpleElasticCPMLProfile],
free_top: bool,
top_elem_ids: Tensor,
_tx_top: Tensor,
_tz_top: Tensor,
_D: Tensor,
_lam: Tensor,
_mu: Tensor,
_lam2mu: Tensor,
_w_J: Tensor,
_ixx: Tensor,
_ixz: Tensor,
_iex: Tensor,
_iez: Tensor,
)
Bases: sweep.sem.equations.elastic_vs_deformed.ElasticVSSEM2DDeformed
VTI velocity-stress elastic SEM (vertical symmetry axis).
build
classmethod
¶
build(
mesh: Quad9Mesh,
vp_e: Tensor,
vs_e: Tensor,
rho_e: Tensor,
epsilon_e: Tensor,
delta_e: Tensor,
*,
free_top: bool = False,
cpml: Optional[SimpleElasticCPMLProfile] = None
) -> ElasticVTISEM2DDeformed
Build a VTI equation. vp_e / vs_e are the vertical P / S
velocities; epsilon_e / delta_e are the Thomsen parameters
(all (E, ngll, ngll) GLL-node tensors).
sweep.sem.ElasticVSSEM3D ¶
ElasticVSSEM3D(
mesh: Hex8Mesh,
vp_e: Tensor,
vs_e: Tensor,
rho_e: Tensor,
mass_rho: Tensor,
_inv_M: Tensor,
cpml: Optional[SimpleElasticCPML3DProfile],
_D: Tensor,
_lam: Tensor,
_mu: Tensor,
_lam2mu: Tensor,
_w3: Tensor,
_wHx: Tensor,
_wHy: Tensor,
_wHz: Tensor,
_inv_half_dx: float,
_inv_half_dy: float,
_inv_half_dz: float,
)
Bases: sweep.sem.fields.DerivedInitState
1st-order velocity-stress elastic SEM on an axis-aligned Hex8 mesh.
build
classmethod
¶
build(
mesh: Hex8Mesh,
vp_e: Tensor,
vs_e: Tensor,
rho_e: Tensor,
*,
cpml: Optional[SimpleElasticCPML3DProfile] = None
) -> ElasticVSSEM3D
sweep.sem.ElasticVSSEM3DDeformed ¶
ElasticVSSEM3DDeformed(
mesh: Hex8Mesh,
vp_e: Tensor,
vs_e: Tensor,
rho_e: Tensor,
mass_rho: Tensor,
_inv_M: Tensor,
cpml: Optional[SimpleElasticCPML3DProfile],
_D: Tensor,
_lam: Tensor,
_mu: Tensor,
_lam2mu: Tensor,
_w3: Tensor,
_wHx: Tensor,
_wHy: Tensor,
_wHz: Tensor,
_inv_half_dx: float,
_inv_half_dy: float,
_inv_half_dz: float,
_inv_J: Optional[Tensor] = None,
_w_jac: Optional[Tensor] = None,
)
Bases: sweep.sem.equations.elastic_vs3d.ElasticVSSEM3D
Velocity-stress elastic on Hex27, with the per-GLL Jacobian chain rule.
build
classmethod
¶
build(
mesh: Hex27Mesh,
vp_e: Tensor,
vs_e: Tensor,
rho_e: Tensor,
*,
cpml: Optional[SimpleElasticCPML3DProfile] = None
) -> ElasticVSSEM3DDeformed
Coupled fluid-solid¶
An acoustic potential in the water over an elastic solid, with a C-PML on
each; records chi, u_x, u_z and the derived p, vx, vz.
sweep.sem.AcousticElasticSEM2D ¶
AcousticElasticSEM2D(
mesh: Quad9Mesh,
ac: AcousticPotentialSEM2D,
el: ElasticSEM2DDeformed,
ifc: FluidSolidInterface,
domain: DomainMask,
mass: Tensor,
cpml: Optional[object] = None,
)
Bases: sweep.sem.fields.DerivedInitState
Fluid–solid coupled SEM. State: (χ, χ_prev, u_x, u_z, u_x_prev, u_z_prev).
build
classmethod
¶
build(
mesh: Quad9Mesh,
vp_e,
vs_e,
rho_e,
*,
dirichlet: tuple[str, ...] = ("top",),
domain: Optional[DomainMask] = None,
cpml_ac=None,
cpml_el=None
) -> AcousticElasticSEM2D
domain defaults to SPECFEM's rule: an element is acoustic iff
vs==0. cpml_ac (acoustic :class:CPMLProfile) and cpml_el
(:class:ElasticCPMLProfile) enable the absorbing bands — both or
neither. The interface may cross an X-only or Z-only band (plain
coupling term there, SPECFEM-style); a corner region touching the
interface is rejected at build time.
Poroelastic (Biot)¶
The FD sweep.equations.Biot on the spectral-element mesh: solid velocity
and pore pressure on the continuous nodes, Darcy flux and total stress in the
elements, with the same eight coefficients [H, mu, C, M, rho, rho_f, m, b]
and the same source and receiver names. See
Poroelastic waves (Biot).
sweep.sem.BiotVSSEM2DDeformed ¶
BiotVSSEM2DDeformed(
mesh: Quad9Mesh,
H_e: Tensor,
mu_e: Tensor,
C_e: Tensor,
M_e: Tensor,
rho_e: Tensor,
rho_f_e: Tensor,
m_e: Tensor,
b_e: tuple,
dirichlet: tuple,
dirichlet_idx: Tensor,
viscous_q: Optional[tuple],
mass_rho: Tensor,
_inv_M: Tensor,
_inv_Mm: Tensor,
_inv_Mp: Tensor,
_inv_M1: Tensor,
_lam_d: Tensor,
_alpha: Tensor,
_solid_e: Tensor,
_fluid_e: Tensor,
_qmask: Tensor,
ifc: FluidSolidInterface,
_tau: tuple,
_slot_idx: Tensor,
_kmax: int,
_wm: Tensor,
_wr: Tensor,
_wb: tuple,
_share: Tensor,
cpml: Optional[SimpleElasticCPMLProfile],
_D: Tensor,
_w_J: Tensor,
_ixx: Tensor,
_ixz: Tensor,
_iex: Tensor,
_iez: Tensor,
source_mode: str = "load",
_drag: tuple = None,
)
1st-order velocity-stress Biot poroelastic SEM on a deformed Quad9 mesh.
build
classmethod
¶
build(
mesh: Quad9Mesh,
H_e: Tensor,
mu_e: Tensor,
C_e: Tensor,
M_e: Tensor,
rho_e: Tensor,
rho_f_e: Tensor,
m_e: Tensor,
b_e: Tensor,
*,
dirichlet: tuple = (),
cpml: Optional[SimpleElasticCPMLProfile] = None,
viscous_q: Optional[tuple] = None
) -> BiotVSSEM2DDeformed
Build the operators from the eight Biot coefficients at the GLL nodes;
dirichlet names the open-pore sides, viscous_q = (Q0, f0) turns on the
viscous attenuation.
sweep.sem.BiotAnisoPermSEM2DDeformed ¶
BiotAnisoPermSEM2DDeformed(
mesh: Quad9Mesh,
H_e: Tensor,
mu_e: Tensor,
C_e: Tensor,
M_e: Tensor,
rho_e: Tensor,
rho_f_e: Tensor,
m_e: Tensor,
b_e: tuple,
dirichlet: tuple,
dirichlet_idx: Tensor,
viscous_q: Optional[tuple],
mass_rho: Tensor,
_inv_M: Tensor,
_inv_Mm: Tensor,
_inv_Mp: Tensor,
_inv_M1: Tensor,
_lam_d: Tensor,
_alpha: Tensor,
_solid_e: Tensor,
_fluid_e: Tensor,
_qmask: Tensor,
ifc: FluidSolidInterface,
_tau: tuple,
_slot_idx: Tensor,
_kmax: int,
_wm: Tensor,
_wr: Tensor,
_wb: tuple,
_share: Tensor,
cpml: Optional[SimpleElasticCPMLProfile],
_D: Tensor,
_w_J: Tensor,
_ixx: Tensor,
_ixz: Tensor,
_iex: Tensor,
_iez: Tensor,
source_mode: str = "load",
_drag: tuple = None,
)
Bases: sweep.sem.equations.biot_vs_deformed.BiotVSSEM2DDeformed
:class:BiotVSSEM2DDeformed with an anisotropic permeability: the drag
eta kappa^-1 is the symmetric tensor [[b_xx, b_xz], [b_xz, b_zz]] (x right, z
down), SPECFEM2D's kxx, kxz, kzz; build it with
:func:sweep.equations.biot_params.biot_drag_tensor. The flux copies at a node then
advance with both components coupled through the drag.
build
classmethod
¶
build(
mesh: Quad9Mesh,
H_e: Tensor,
mu_e: Tensor,
C_e: Tensor,
M_e: Tensor,
rho_e: Tensor,
rho_f_e: Tensor,
m_e: Tensor,
b_xx_e: Tensor,
b_xz_e: Tensor,
b_zz_e: Tensor,
*,
dirichlet: tuple = (),
cpml: Optional[SimpleElasticCPMLProfile] = None,
viscous_q: Optional[tuple] = None
) -> BiotAnisoPermSEM2DDeformed
Build from the seven Biot coefficients and the three drag components at the GLL nodes.