dragonfly_sim.utils.pod_utils
Helpers for core/pod.py: PETSc dense-matrix plumbing for the distributed snapshot SVD, and the compact-support cubic weight function of the local_weighted basis. Also the distributed thin QR (tsqr) of the reduced adjoint in core/reduced_order_model.py.
Storage convention (see core/pod.py:SnapshotMatrix):
Q (the basis), distributed MATDENSE with the row layout of the state vector; its column count (the rank) is the same on every rank.
R, Sigma, VT, small PETSc objects on PETSc.COMM_SELF, one identical copy per rank. Their size scales with the number of snapshots, not with the mesh, so there is nothing to gain from distributing them.
Rank-sized quantities such as Q^T W x are formed as a local dense product on each rank’s row block followed by one Allreduce, which keeps them available as replicated numpy arrays.
Classes
A diagonal inner-product weight W = diag(w) with the .mult(x, y) that |
Functions
|
The smallest cubic support radius that leaves the rb_size snapshots |
|
The cubic weight's support radius dist_hat such that exactly the |
|
The cubic weight's support radius from a user-set c in [0, 1): |
|
The cubic Hermite weight with w(min_dist) = 1, w(dist_hat) = 0 and zero |
|
A new distributed MATDENSE with one column more than old_mat (None for |
|
A distributed MATDENSE whose local row block is local_block |
A small numpy array as a PETSc.COMM_SELF MATDENSE (the caller builds |
|
A small 1D numpy array as a PETSc.COMM_SELF Vec (replicated). |
|
|
V^T x as a numpy array on every rank, for a distributed MATDENSE V |
|
Thin QR, X = Q R, of a tall matrix X (N x k) distributed by rows, |
Module Contents
- class dragonfly_sim.utils.pod_utils.DiagonalWeight(w)
A diagonal inner-product weight W = diag(w) with the .mult(x, y) that core/pod.py:SnapshotMatrix calls, w a Vec in the state layout.
- destroy()
- mult(x, y)
- w
- dragonfly_sim.utils.pod_utils.basis_size_floor(accepted_distnorm, rb_size, spread, margin_scale=0.001)
The smallest cubic support radius that leaves the rb_size snapshots nearest the query point (among accepted_distnorm, the snapshots that carry a basis column) with a nonzero weight.
The cubic weight vanishes AT its support radius, so the radius has to lie strictly beyond d_k, the k-th smallest distance (k = min(rb_size, number of snapshots)): it is the next larger distance (that snapshot gets zero weight), but at least d_k + margin_scale * spread, with spread the spread of all distances (max - min). The margin keeps the k-th weight clear of the 1e-10 pruning threshold when the next distance is barely larger, and places the radius beyond d_k when no larger distance exists. Snapshots tied with d_k all stay inside.
- dragonfly_sim.utils.pod_utils.cubic_dist_hat(parameter_distnorm, min_dist, max_dist, n_nonzero_weights, tail_eps_scale=0.001, tie_rtol=1e-09)
The cubic weight’s support radius dist_hat such that exactly the k = min(n_nonzero_weights, n_snapshots) snapshots nearest the query point get a nonzero weight and the (k+1)-th nearest gets zero.
k >= n_snapshots: there is no (k+1)-th neighbour to cut at, so dist_hat is pushed a small relative distance beyond max_dist (tail_eps_scale keeps the farthest snapshot’s weight above the 1e-10 pruning threshold in PODBasis.construct_basis).
k or more snapshots tied at min_dist (e.g. a symmetric pair of design perturbations) would put dist_hat at min_dist; k is walked forward past the tie first. Ties exactly at the (k+1)-th boundary need no handling: both snapshots land on dist_hat and both get zero.
- dragonfly_sim.utils.pod_utils.cubic_dist_hat_fixed(min_dist, max_dist, c)
The cubic weight’s support radius from a user-set c in [0, 1):
dist_hat = c min_dist + (1 - c) max_dist.
c = 0 puts dist_hat at the farthest snapshot (only it gets zero weight); larger c narrows the support towards the nearest snapshot.
- dragonfly_sim.utils.pod_utils.cubic_weights(parameter_distnorm, min_dist, dist_hat)
The cubic Hermite weight with w(min_dist) = 1, w(dist_hat) = 0 and zero slope at both ends, zero beyond dist_hat:
w = 2 t^3 - 3 t^2 + 1, t = (d - min_dist) / (dist_hat - min_dist).
This closed form is the exact solution of the 4x4 monomial interpolation system, without that system’s ill-conditioning at large absolute distances. The zeroing beyond dist_hat is required: the polynomial turns back up for t > 1.
- dragonfly_sim.utils.pod_utils.petsc_append_dense_column(comm, old_mat, new_col_local)
A new distributed MATDENSE with one column more than old_mat (None for a fresh single-column matrix): its data, then new_col_local (this rank’s slice of the new column) as the last column.
- dragonfly_sim.utils.pod_utils.petsc_dense_from_local_block(comm, local_block, M_global=None)
A distributed MATDENSE whose local row block is local_block (shape (m_local, ncols)).
- dragonfly_sim.utils.pod_utils.petsc_small_mat_from_numpy(arr)
A small numpy array as a PETSc.COMM_SELF MATDENSE (the caller builds arr identically on every rank).
- dragonfly_sim.utils.pod_utils.petsc_small_mat_to_numpy(mat)
- dragonfly_sim.utils.pod_utils.petsc_small_vec_from_numpy(arr)
A small 1D numpy array as a PETSc.COMM_SELF Vec (replicated).
- dragonfly_sim.utils.pod_utils.replicated_transpose_product(comm, V, x_local)
V^T x as a numpy array on every rank, for a distributed MATDENSE V and this rank’s owned entries x_local of a vector in V’s row layout.
- dragonfly_sim.utils.pod_utils.tsqr(comm, X_local)
Thin QR, X = Q R, of a tall matrix X (N x k) distributed by rows, X_local being this rank’s rows (TSQR): each rank factors its block, the k x k factors are gathered in rank order and factored once more.
Returns (Q_local, R): this rank’s rows of Q (Q^T Q = I) and the k x k upper-triangular R, identical on every rank (every rank factors the same gathered stack). A rank with fewer than k rows (or none) pads its factor with zero rows.