dragonfly_sim.core.pod

Proper orthogonal decomposition (POD) of solution snapshots, distributed over MPI with PETSc.

SnapshotMatrix keeps the snapshot matrix S = [x_1, …, x_n] only as its incrementally updated, optionally truncated SVD, in a weighted inner product (x, y)_W = x^T W y. PODBasis turns that SVD into a reduced basis for the current design point:

global          the leading rb_size left-singular vectors of S;
local_weighted  the leading left-singular vectors of S diag(w), with
                partition-of-unity weights w that decay with the distance
                between each snapshot's parameter vector and the current
                one (compact-support cubic by default).

Both bases are W-orthonormal (V^T W V = I). core/reduced_order_model.py builds W and drives the reduced solves.

Classes

PODBasis

A reduced basis from the snapshots in a SnapshotMatrix (see the module

SnapshotMatrix

Incremental weighted QR and SVD of the snapshot matrix.

Module Contents

class dragonfly_sim.core.pod.PODBasis(comm, n_dofs, basis_mode='global', subtract_mean=False, mean_weighting='snapshot_weights', IP_matrix=None, max_rank=None, qr_rank_tol=1e-10)

A reduced basis from the snapshots in a SnapshotMatrix (see the module docstring for the basis modes). basis is the current basis, a distributed MATDENSE in the state layout, rebuilt (destroyed and reallocated) by every construct_basis call.

_local_weighted_snapshot_weights(local_parametervector, weightfunction, parameter_weights, n_nonzero_weights, rb_size, cubic_cutoff=None)

Partition-of-unity weights over the accepted snapshots (one per column of VT), from the distances between their parameter vectors and local_parametervector. Duplicate-parameter (rejected) snapshots take part in the distance weighting like accepted ones, and their weight is then redistributed onto the accepted snapshots that reconstruct them.

Returns (weights, distances of the accepted snapshots).

_set_basis_from_local_block(basis_local_block)

Rebuild self.basis from this rank’s row block. (MatCreateSubMatrix is not used to slice columns of U: for MATDENSE it fails on a width change, and under MPI returns replicated columns or corrupts the heap, depending on how the column IS is split.)

construct_basis(rb_size=10, local_parametervector=None, parameter_weights=None, weightfunction='Cubic', n_nonzero_weights=None, cubic_cutoff=None, return_distance_norms=False, layout_vec=None)

(Re)build self.basis from the current snapshot SVD; with no snapshots self.basis becomes None.

local_weighted only:

local_parametervector  the current design point
parameter_weights      per-parameter factors on the distance (None: 1)
weightfunction         'Cubic' (compact support), 'Linear',
                       'Quadratic' or 'InverseDistance'
n_nonzero_weights      Cubic: number of nearest snapshots with a
                       nonzero weight (default rb_size)
cubic_cutoff           Cubic: instead of n_nonzero_weights, a
                       c in [0, 1) with support radius
                       max(c min_dist + (1 - c) max_dist, r_rb),
                       r_rb the smallest radius that leaves the
                       rb_size nearest accepted snapshots a nonzero
                       weight (utils/pod_utils.basis_size_floor)

layout_vec (the state vector) guards the one invariant the reduced solve depends on: the basis rows are distributed exactly like it. Returns the accepted snapshots’ distances with return_distance_norms (local_weighted), else None.

destroy()
IP_matrix = None
SUPPORTED_BASIS_MODES = ('global', 'local_weighted')
WEIGHT_FUNCTIONS = ('Cubic', 'Linear', 'Quadratic', 'InverseDistance')
basis = None
basis_mode = 'global'
comm
mean = None
mean_weighting = 'snapshot_weights'
n_dofs
snapshot_matrix
subtract_mean = False
class dragonfly_sim.core.pod.SnapshotMatrix(comm, n_dofs=None, W=None, qr_rank_tol=1e-10, reorthogonalize=True, max_rank=None)

Incremental weighted QR and SVD of the snapshot matrix.

Each snapshot x_k (a PETSc Vec in the state layout) updates a weighted QR decomposition S = Q R with Q^T W Q = I, then the SVD of the small R; Q is rotated into R’s left-singular basis every update (Q <- Q U_R), so Q IS the SVD’s U and only one dense n_dofs x rank matrix is stored. The rotation is also what makes truncation to max_rank the standard truncated incremental SVD.

Storage: Q distributed (MATDENSE, rows in the state layout); R, Sigma, VT small and replicated on PETSc.COMM_SELF. W is any object with W.mult(x, y) (a PETSc Mat or utils/pod_utils.DiagonalWeight), or None for the Euclidean inner product.

A snapshot is rejected (no new column) when its parameter vector duplicates an earlier one; its location and the weights reconstructing it from the existing snapshots are kept, and the local_weighted basis redistributes its weight onto those. A rank-deficient snapshot – one in the span of Q up to a weighted residual ||x - Q Q^T W x||_W below qr_rank_tol ||x||_W, a test independent of the snapshot’s scale – adds a column to R/VT but not to Q, so row i of the parameter array matches column i of R/VT, never of Q.

_apply_W(x)

(W x, owned): W x as a fresh Vec, or x itself when unweighted – owned says whether the caller must destroy it.

_is_duplicate_parameter(par_vec)
_project_onto_Q(x_k, Wx)

W-orthogonal projection of x_k onto Q: (r, e_local, rho) with r = Q^T W x_k (replicated), e_local this rank’s slice of x_k - Q r, and rho = sqrt(e^T W e). Wx is W x_k (or x_k when unweighted).

With reorthogonalize, a second projection pass (CGS2) removes the round-off a single pass leaves when x_k is nearly in span(Q), as snapshots from nearby design points are; without it orthogonality degrades catastrophically over many updates.

_update_weighted_QR_and_SVD(x_k)
_weighted_norm(x, Wx)

||x||_W = sqrt(x^T W x), given W x. Collective.

construct_snapshot_parameter_array()
destroy()
gather_dense_to_rank0_numpy(mat, root=0)

A distributed dense Mat as one numpy array on root (diagnostics).

print_info()
process_and_append_to_snapshot_lists(x_k, par_vec)

Incorporate snapshot x_k (not modified) with parameter vector par_vec. Returns True if it added a new basis direction, False if it was a duplicate parameter or rank-deficient within qr_rank_tol.

Q = None
R = None
Sigma = None
property U

The left-singular vectors: the same object as self.Q.

VT = None
W = None
comm
property full_SVD_triplet
max_rank = None
n_dofs = None
n_snapshots = 0
qr_rank_tol = 1e-10
rank = 0
rejected_snapshot_parameters = []
rejected_snapshot_reconstruction_weights = []
reorthogonalize = True
snapshot_list_parameters = []
snapshot_parameter_array