Class GridProcess#
- class tools.addprocess.GridProcess[source]#
When running goSPL on a 2D grid (i.e. not a global simulation), this class defines two processes solved directly on the unstructured mesh:
Flexural isostasy: it allows to compute isostatic deflections of Earth’s lithosphere with uniform or non-uniform flexural rigidity. Evolving surface loads are defined from erosion/deposition values associated to modelled surface processes.
Orographic rain: it accounts for change in rainfall patterns associated to change in topography. The orographic precipitation function is based on the Smith & Barstad (2004) linear model, solved directly on the unstructured mesh in parallel as two steady advection–relaxation equations (cloud water → hydrometeors → precipitation). The stratified airflow (mountain-wave) term of the original spectral solution is dropped, so the windward/lee rain-shadow is retained while no regular grid or FFT is required.
For global simulation, the library pyshtools provides a framework to estimate global-scale flexural isostasy.
Methods
This function computes the flexural isostasy equilibrium based on topographic change.
Initialise
__init__()Initialisation of the gridProcess class.
Public Methods
This function computes the flexural isostasy equilibrium based on topographic change.
Private Methods
_buildOroMat(diag, offcoeff[, dirichlet])Assemble a PETSc operator on the DMPlex from a per-row diagonal and the upwind off-diagonal coefficients returned by
advecupwind(one column per neighbour,FVmesh_ngbIDgiving the neighbour indices)._oroSolve(matrix, rhs, sol)Solve one orographic advection-relaxation system with a dedicated (cached) GMRES + block-Jacobi KSP.
Finds current elastic thickness map for the considered time interval.
Build the Driscoll-Healy (DH2, shape N x 2N) target grid for global flexure and precompute the interpolation weights linking the unstructured spherical mesh (
self.mCoords) and the DH grid._unstr2dh(field)Inverse-distance interpolation of a 1-D unstructured field defined at
self.mCoordsonto the DH2 grid (shape(dh_N, 2*dh_N))._dh2unstr(field_dh)Bilinear interpolation of a DH2-grid array back to the unstructured mesh.
_cmptFlexGlobal(erodep_dh, te_dh[, ...])Spectral thin-elastic-shell flexure solve on the precomputed Driscoll-Healy (DH2) grid.
_cmptFlexFEM(dzLocal)Parallel finite-volume biharmonic flexure for FLAT (2D) models (
flexure: method: 'fem'— the flat-model flexure solver)._buildFlexFEM(Te)Assemble (and cache) the flat-model FV biharmonic operator
A = Lm·diag(D)·Lm + Δρg·Iwith its boundary conditions, and set up the reusable KSP.
Public functions#
- GridProcess.applyFlexure()[source]#
This function computes the flexural isostasy equilibrium based on topographic change. It is a simple routine that accounts for flexural isostatic rebound associated with erosional loading/unloading.
The function takes an initial (at time t) and final topography (at time t+Dt) (i.e. before and after erosion/deposition) and returns a corrected final topography that includes the effect of erosional/depositional unloading/loading. It uses a spectral method to solve the bi-harmonic equation governing the bending/flexure of a thin elastic plate floating on an inviscid fluid (the asthenosphere).
\[D (d^4 w / d^4 x ) + \Delta \rho g w = q\]where \(D\) is the flexural rigidity, \(w\) is vertical deflection of the plate, \(q\) is the applied surface load, and \(\Delta \rho = \rho_m − \rho_f\) is the density of the mantle minus the density of the infilling material.
- GridProcess.cptOrography()[source]#
Linear Theory of Orographic Precipitation following Smith & Barstad (2004), solved directly on the unstructured mesh in parallel.
The model is cast as two steady, vertically-integrated advection-relaxation equations for the cloud-water density \(q_c\) and the hydrometeor density \(q_s\), advected by a uniform wind \(\mathbf{v}\):
\[(\mathbf{v}\cdot\nabla + 1/\tau_c)\,q_c = C_w\,\mathbf{v}\cdot\nabla h, \qquad (\mathbf{v}\cdot\nabla + 1/\tau_f)\,q_s = q_c/\tau_c,\]with the precipitation rate \(P = q_s/\tau_f\). The source is the terrain-forced uplift \(C_w\,\mathbf{v}\cdot\nabla h\): positive (condensation) on windward slopes, negative (evaporation) on lee slopes, which together with the downwind advection of \(q_c, q_s\) produces the windward-wet / lee-dry rain shadow. The elevation in the source is clamped to sea level, so submarine bathymetry produces no orographic forcing (the airflow follows the flat sea surface, not the seafloor).
In Fourier space these equations recover the Smith-Barstad transfer function with the stratified mountain-wave term \((1-i\,h_w m)\) set to one. That airflow term is therefore dropped (and the parameters
nm,hwandlatitudeare inert); everything else is identical. The advection operator is the first-order upwind finite-volume scheme on the Voronoi mesh, so the operators depend only on the (uniform, constant) wind and are assembled once and cached.Note
Please refer to the original manuscript of Smith and Barstad (2004) to understand the model physics and limitations.
Common bounds:
precip_base : 0-10 [mm/h]
precip_min : 0.001 - 1 [mm/h]
conv_time : 200-2000 [s]
fall_time : 200-2000 [s]
cw : 0.001-0.02 [kg/m^3]
rainfall_frequency : 0.1 - 24 [number of storms of 1 hour duration per day]
Private functions#
- GridProcess._buildOroMat(diag, offcoeff, dirichlet=False)[source]#
Assemble a PETSc operator on the DMPlex from a per-row diagonal and the upwind off-diagonal coefficients returned by
advecupwind(one column per neighbour,FVmesh_ngbIDgiving the neighbour indices). This is the same incremental local-CSR assembly used for the tectonic advection matrix.- Parameters:
diag – diagonal entries (length
lpoints)offcoeff – off-diagonal coefficients, shape
(lpoints, maxnb)dirichlet – when True, the (non-cyclic) domain edge rows are replaced by an identity row so the precipitation tracers are pinned to zero there (clean inflow / zero-padding equivalent).
- Returns:
assembled PETSc matrix
- GridProcess._oroSolve(matrix, rhs, sol)[source]#
Solve one orographic advection-relaxation system with a dedicated (cached) GMRES + block-Jacobi KSP. The operators are non-symmetric but diagonally-dominant M-matrices, so this converges quickly; the solution is warm-started from the previous step.
- GridProcess._updateTe()[source]#
Finds current elastic thickness map for the considered time interval.
- GridProcess._buildDHGrid()[source]#
Build the Driscoll-Healy (DH2, shape N x 2N) target grid for global flexure and precompute the interpolation weights linking the unstructured spherical mesh (
self.mCoords) and the DH grid.Forward direction (mesh -> DH): 3-D inverse-distance weighting via
scipy.spatial.cKDTreeon the existing Cartesian coordinates, which avoids polar / dateline singularities.Backward direction (DH -> mesh): bilinear interpolation with precomputed integer indices and fractional offsets. The DH grid is implicitly extended at call time with a south-pole row and a wrap-around longitude column so every mesh point sits inside a 2 x 2 stencil.
Because the unstructured mesh is fixed for a given simulation, weights are built once and reused for every flexure step.
- GridProcess._unstr2dh(field)[source]#
Inverse-distance interpolation of a 1-D unstructured field defined at
self.mCoordsonto the DH2 grid (shape(dh_N, 2*dh_N)).
- GridProcess._dh2unstr(field_dh)[source]#
Bilinear interpolation of a DH2-grid array back to the unstructured mesh. The grid is padded at call time with a south-pole row (mean of the southernmost DH row) and a wrap-around longitude column.
- GridProcess._cmptFlexGlobal(erodep_dh, te_dh, rho_infill=0.0, max_iter=50, flex_tol=0.0005, relax=1.0, anderson_depth=5)[source]#
Spectral thin-elastic-shell flexure solve on the precomputed Driscoll-Healy (DH2) grid.
- Parameters:
- erodep_dhnp.ndarray, shape
(dh_N, 2*dh_N) Erosion(-) / deposition(+) thickness in metres on the DH2 grid. Produced by
_unstr2dh()from the unstructured mesh field.- te_dhfloat or np.ndarray of shape
(dh_N, 2*dh_N) Elastic thickness in metres. Scalar -> constant-Te spectral solve. Array (same grid as
erodep_dh) -> iterative varying-Te solve.- rho_infillfloat
Density (kg/m^3) of the material filling the flexural moat (0 = air, 1030 = sea water).
- max_iter, flex_tol, relax, anderson_depthint, float, float, int
Picard / Anderson iteration controls for the varying-Te branch.
relax < 1damps the update (useful for strong Te contrasts).
- erodep_dhnp.ndarray, shape
- Returns:
- np.ndarray, shape
(dh_N, 2*dh_N) Flexural deflection in metres on the DH2 grid. Sign: negative = down (subsidence under deposition; rebound gives positive w under erosion).
- np.ndarray, shape
- GridProcess._cmptFlexFEM(dzLocal)[source]#
Parallel finite-volume biharmonic flexure for FLAT (2D) models (
flexure: method: 'fem'— the flat-model flexure solver).Solves the plate equation with a single PETSc solve directly on the DMPlex: fully parallel, no gather-to-root, no regular grid, and varying elastic thickness in one linear solve (no iteration over the rigidity contrast). It replaced the former serial
'FD'and'FFT'solvers, which gathered the load to one rank, solved on a regular grid, and interpolated back.Solves the thin-plate-on-elastic-foundation equation with a spatially varying rigidity \(D(x)=E\,T_e(x)^3/[12(1-\nu^2)]\)
\[\nabla^2\!\big(D\,\nabla^2 w\big) + \Delta\rho\,g\,w = q, \qquad q = \rho_s\,g\,\mathrm{(erodep)}\]Discretised with the cached finite-volume negative-Laplacian
Lm(\(= -\nabla^2\), the hillslope stencil) applied twice, this is the single-field SPD-structured system\[\big[\,L_m\,\mathrm{diag}(D)\,L_m + \Delta\rho g\,I\,\big]\,w = q,\]solved with GMRES + GAMG (
Lmis row-area-normalised, hence slightly non-symmetric, so GMRES rather than CG). The elastic foundation \(\Delta\rho g\,I\) (a positive diagonal) makes the operator well-posed — it pins the absolute deflection, so there is no nullspace and no mean removal (unlike the closed-sphere spectral solver). The solver defaults to a cached DIRECT factorisation — serial PETSc LU, parallel MUMPS — reused every step (only the RHS changes); it is options-prefixed (flexfem_) so an iterative Krylov method can be requested for meshes too large to factorise.When this solver replaced the former regular-grid solver it agreed with it on a flat mesh where the deflection decays inside the domain: correlation 0.998 (natural BC), 0.9996 (clamped). Where the flexural wavelength approaches the domain size the two boundary discretisations differ by ~10 %.
Note
Boundary conditions (per side, from
flex_bcN/S/E/W):0Slope0ShearandMirror— the natural zero-flux FV boundary (w'=0, w'''=0; a thin plate’s Mirror is 0Slope0Shear), imposed for free by the FV Laplacian — no modification.0Displacement0Slope(clamped) — pinw=0(DirichletzeroRowson that side’s nodes); the naturalw'=0from the inner FV Laplacian completes the clamp.
Sides map geographically.
0Moment0ShearandPeriodicare not implemented.The operator
Aand its KSP are CACHED and reused across steps: the geometry (Lm) is fixed and, for constant or piecewise-constantTe,Aonly changes when theTeinterval advances. Each step then re-uses the factorisation / preconditioner and only the RHS changes — so after the one-off setup a step costs a back-substitution (serial) or a few warm Krylov iterations (parallel). Serial runs use a direct LU (fast on small meshes); parallel runs use GMRES+GAMG. The KSP is options-prefixed (flexfem_) to override.- Parameters:
dzLocal – local (lpoints) elevation change = surface load thickness (m).
- Returns:
local (lpoints) flexural deflection (m), same sign convention as
_cmptFlexGlobal(negative = subsidence under deposition).
- GridProcess._buildFlexFEM(Te)[source]#
Assemble (and cache) the flat-model FV biharmonic operator
A = Lm·diag(D)·Lm + Δρg·Iwith its boundary conditions, and set up the reusable KSP. Called from_cmptFlexFEM()on the first flexure step and whenever the elastic-thickness interval advances; the result is reused for every step in between (only the RHS changes).