qlroms.base
qlROMBase: the shared parent of every quantized-local model.
All case qlROMs (ks1d, ks2d, split, fenics) hold the same structure -- K local charts (centroids + Phi_all), chart bookkeeping (tree/current_cluster_idx), transition operators (tmap/tshift, optional exact atlas Tgk/dgk/Tkg/dkg), augmented project/recover, and the common discrete forecast interface
apod^{n+1} = model.step(apod^n) # (r+1, 1), cluster id in the last row
What differs per family/case is only (a) the per-cluster operator (intrusive Galerkin,
OpInf (b, A, B), reservoir) reachable through _get_cluster_rom(k).step_reduced, and
(b) the inner product (ks2d overrides the M=I defaults below with its weighted ones).
Everything else lives here, once.
This is a plain mixin (no dataclass fields): concrete case classes remain dataclasses that define/construct K, centroids, Phi_all, tmap, tshift, tree, _cluster_id, _get_cluster_rom, device, rdtype.
qlROMBase
Shared behaviour of all quantized-local models; see the module docstring.
Source code in qlroms/base.py
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | |
transitions
property
Current transition maps (exact atlas when built, pairwise otherwise). Rebuilt from the model's tensors on every access -- from_model is a handful of getattrs, and this keeps the maps automatically in sync when build_global_atlas attaches the atlas after construction.
aff_fun(point)
Index of the nearest cluster centroid for a single state (torch or numpy).
Source code in qlroms/base.py
60 61 62 63 64 65 66 67 68 69 70 71 72 73 | |
compute_transition_matrix(cluster_sequence, time_index=None)
Empirical row-stochastic cluster transition matrix T[j, k] = P(next=k | current=j).
time_index: same convention as qlOpinf.fit's argument of the same name -- pass it when cluster_sequence concatenates multiple runs/non-adjacent slices (split.data.concat_wake_runs), so a consecutive pair straddling a concatenation boundary is never counted as a transition. None (default) assumes one continuous sequence.
Source code in qlroms/base.py
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | |
project_state(state, cluster_id=None)
(N,) or (N, m) physical -> (r+1, m) augmented reduced coords, per-column nearest chart with the chart id in the last row (same convention as qlroms.atlas.Atlas.project_state); cluster_id overrides the assignment.
Source code in qlroms/base.py
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | |
recover_state(apod, cluster_id=None)
Recover full states from an augmented reduced tensor (r+1, Nt), per-column cluster ids in the last row (or an explicit cluster_id override).
Source code in qlroms/base.py
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | |
project_trajectory(X)
Nearest-cluster assignment + per-cluster local POD projection of a whole trajectory. Returns (A, labels) as numpy -- the input the non-intrusive families (qlOpinf, continuous or discrete) regress on.
Source code in qlroms/base.py
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | |
step(apod, cluster_id=None)
One discrete step of a single augmented state (r+1, 1).
Strips the cluster-id row, advances the pure (r, 1) coordinate with cluster
k's own operator (self._get_cluster_rom(k).step_reduced), then applies the
shared hard nearest-centroid transition rule through self.transitions (exact
atlas maps when built, pairwise tmap/tshift otherwise) and re-appends the
updated id row. This is the one place the augmented-step + transition
logic lives.
Source code in qlroms/base.py
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | |
qlROM
Bases: qlROMBase
A quantized-local model as a COMPILATION of K single-cluster ROMs.
This is the whole point of the restructure: a case only defines its
single-cluster ROM (a qlroms.charts.Chart carrying that cluster's operators and
step_reduced); compiling K of them IS the quantized-local model -- geometry
(centroids/Phi_all/tree), Mw-weighted transition maps, augmented
project/recover, and the common step(apod) all derive from the members here.
The model family follows the member family: a compilation of Galerkin-projected
ROMs is a qlGalerkin, of OpInf-fitted ROMs a non-intrusive qlROM, and so on.
The one family this does not cover is qlSRC, whose single shared reservoir is
not a per-cluster compilation (see qlroms.data_driven_qlroms.esn_SRC).
Source code in qlroms/base.py
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | |
N
property
Physical state dimension (rows of Phi_all).
__init__(roms, dt=None, cfg=None, qbar_g=None)
Args: roms: sequence of K single-cluster ROMs (Chart subclasses), one per cluster, all with the same r and inner-product weight Mw. dt: snapshot spacing; defaults to cfg["dt"] or the members' dt. cfg: optional case-config dict (e.g. KSConfig.base_cfg / WakeConfig.base_cfg) whose entries are set as attributes -- this preserves the old case qlROM dataclass surface (device, rdtype, dt, case params) and is also stored as self.base_cfg for code that rebuilds member ROMs. qbar_g: optional atlas reference state; when given, the exact global atlas (Phi_g/Tgk/dgk/Tkg/dkg) is built immediately. The members are already charts, so the mean is the ONLY extra ingredient the atlas needs: pass the (N,) global mean state directly, or an (N, Nt) snapshot matrix whose column mean is used.
Source code in qlroms/base.py
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 | |
build_global_atlas(qbar_g, tol=1e-11, assume_tgk_transpose=True)
Attach the exact global assimilation basis (see qlroms.atlas). The members already carry the chart geometry, so the only extra ingredient is the atlas reference state: pass the (N,) global mean directly, or an (N, Nt) snapshot matrix whose column mean is used (same convention as qlroms.atlas.Atlas.build_global_atlas). Supports M = I and diagonal Mw; a full-matrix Mw (fenics mass matrix) keeps the pairwise tmap/tshift transitions instead.
Source code in qlroms/base.py
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 | |
init_ensemble(x0, m=10, std_phi=0.05, random_state=0)
Gaussian-perturb one physical initial condition into the (r+1, m) augmented ensemble, each member projected into its own nearest chart (chart id in the last row). Mirrors dynamodels.Model.init_ensemble(m, std_phi) semantics but returns the augmented ensemble instead of storing history.
Source code in qlroms/base.py
331 332 333 334 335 336 337 338 339 340 341 342 343 344 | |
forecast(apod0, n_steps)
Forecast a whole augmented ensemble: each step is one step_reduced call
per ACTIVE CLUSTER over that cluster's members (the reduced steppers are
batched over columns), followed by the same nearest-centroid transition
rule step applies per member. Frame 0 of the returned
(n_valid, r+1, m) tensor is the given IC; n_valid == n_steps unless some
member went non-finite mid-window, in which case the output truncates to
the last step where every member was still finite (at least 1).
Source code in qlroms/base.py
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 | |
free_run(model, x0, n_steps)
Single-trajectory closed-loop free run (no ensemble, no DA): project x0 into its nearest chart, advance n_steps through the common step(apod) interface (transitions included), recover each physical state.
Returns:
| Type | Description |
|---|---|
(X_rec, cluster_path)
|
(N, n_steps) recovered trajectory and the (n_steps,) |
|
active-cluster id per step. |
Source code in qlroms/base.py
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 | |