diff --git a/Expt_Grains/Particle_numbers.txt b/Expt_Grains/Particle_numbers.txt new file mode 100644 index 000000000..032afab8e --- /dev/null +++ b/Expt_Grains/Particle_numbers.txt @@ -0,0 +1,556 @@ +0 0 +1 0 +2 0 +3 0 +4 0 +5 0 +6 0 +7 0 +8 0 +9 0 +10 0 +11 0 +12 0 +13 0 +14 0 +15 0 +16 0 +17 0 +18 0 +19 0 +20 0 +21 0 +22 0 +23 0 +24 0 +25 0 +26 0 +27 0 +28 0 +29 0 +30 0 +31 0 +32 0 +33 0 +34 0 +35 0 +36 0 +37 0 +38 0 +39 0 +40 0 +41 0 +42 0 +43 0 +44 0 +45 0 +46 0 +47 0 +48 0 +49 0 +50 0 +51 0 +52 0 +53 0 +54 0 +55 0 +56 0 +57 0 +58 0 +59 0 +60 0 +61 0 +62 0 +63 0 +64 0 +65 0 +66 0 +67 0 +68 0 +69 0 +70 0 +71 0 +72 0 +73 0 +74 0 +75 0 +76 0 +77 0 +78 0 +79 0 +80 0 +81 0 +82 0 +83 0 +84 0 +85 0 +86 0 +87 0 +88 0 +89 0 +90 0 +91 0 +92 0 +93 0 +94 0 +95 0 +96 0 +97 0 +98 0 +99 0 +100 0 +101 0 +102 0 +103 0 +104 0 +105 0 +106 0 +107 0 +108 0 +109 0 +110 0 +111 0 +112 0 +113 0 +114 0 +115 0 +116 0 +117 0 +118 0 +119 0 +120 0 +121 0 +122 0 +123 0 +124 0 +125 0 +126 0 +127 0 +128 0 +129 0 +130 0 +131 0 +132 0 +133 0 +134 0 +135 0 +136 0 +137 0 +138 0 +139 0 +140 0 +141 0 +142 0 +143 0 +144 0 +145 0 +146 0 +147 0 +148 0 +149 0 +150 0 +151 0 +152 0 +153 0 +154 0 +155 0 +156 0 +157 0 +158 0 +159 0 +160 0 +161 0 +162 0 +163 0 +164 0 +165 0 +166 0 +167 0 +168 0 +169 0 +170 0 +171 0 +172 0 +173 0 +174 0 +175 0 +176 0 +177 0 +178 0 +179 0 +180 0 +181 0 +182 0 +183 0 +184 0 +185 0 +186 0 +187 0 +188 0 +189 0 +190 0 +191 0 +192 0 +193 0 +194 0 +195 0 +196 0 +197 0 +198 0 +199 0 +200 0 +201 0 +202 0 +203 0 +204 0 +205 0 +206 0 +207 0 +208 0 +209 0 +210 0 +211 0 +212 0 +213 0 +214 0 +215 0 +216 0 +217 0 +218 0 +219 0 +220 0 +221 0 +222 0 +223 0 +224 0 +225 0 +226 0 +227 0 +228 0 +229 0 +230 0 +231 0 +232 0 +233 0 +234 0 +235 0 +236 0 +237 0 +238 0 +239 0 +240 0 +241 0 +242 0 +243 0 +244 0 +245 0 +246 0 +247 0 +248 0 +249 0 +250 0 +251 0 +252 0 +253 0 +254 0 +255 0 +256 0 +257 0 +258 0 +259 0 +260 0 +261 0 +262 0 +263 0 +264 0 +265 0 +266 0 +267 0 +268 0 +269 0 +270 0 +271 0 +272 0 +273 0 +274 0 +275 0 +276 0 +277 0 +278 0 +279 0 +280 0 +281 0 +282 0 +283 0 +284 0 +285 0 +286 0 +287 0 +288 0 +289 0 +290 0 +291 0 +292 0 +293 0 +294 0 +295 0 +296 0 +297 0 +298 0 +299 0 +300 0 +301 0 +302 0 +303 0 +304 0 +305 0 +306 0 +307 0 +308 0 +309 0 +310 0 +311 0 +312 0 +313 0 +314 0 +315 0 +316 0 +317 0 +318 0 +319 0 +320 0 +321 0 +322 0 +323 0 +324 0 +325 0 +326 0 +327 0 +328 0 +329 0 +330 0 +331 0 +332 0 +333 0 +334 0 +335 0 +336 0 +337 0 +338 0 +339 0 +340 0 +341 0 +342 0 +343 0 +344 0 +345 0 +346 0 +347 0 +348 0 +349 0 +350 0 +351 0 +352 0 +353 0 +354 0 +355 0 +356 0 +357 0 +358 0 +359 0 +360 0 +361 0 +362 0 +363 0 +364 0 +365 0 +366 0 +367 0 +368 0 +369 0 +370 0 +371 0 +372 0 +373 0 +374 0 +375 0 +376 0 +377 0 +378 0 +379 0 +380 0 +381 0 +382 0 +383 0 +384 0 +385 0 +386 0 +387 0 +388 0 +389 0 +390 0 +391 0 +392 0 +393 0 +394 0 +395 0 +396 0 +397 0 +398 0 +399 0 +400 0 +401 0 +402 0 +403 0 +404 0 +405 0 +406 0 +407 0 +408 0 +409 0 +410 0 +411 0 +412 0 +413 0 +414 0 +415 0 +416 0 +417 0 +418 0 +419 0 +420 0 +421 0 +422 0 +423 0 +424 0 +425 0 +426 0 +427 0 +428 0 +429 0 +430 0 +431 0 +432 0 +433 0 +434 0 +435 0 +436 0 +437 0 +438 0 +439 0 +440 0 +441 0 +442 0 +443 0 +444 0 +445 0 +446 0 +447 0 +448 0 +449 0 +450 0 +451 0 +452 0 +453 0 +454 0 +455 0 +456 0 +457 0 +458 0 +459 0 +460 0 +461 0 +462 0 +463 0 +464 0 +465 0 +466 0 +467 0 +468 0 +469 0 +470 0 +471 0 +472 0 +473 0 +474 0 +475 0 +476 0 +477 0 +478 0 +479 0 +480 0 +481 0 +482 0 +483 0 +484 0 +485 0 +486 0 +487 0 +488 0 +489 0 +490 0 +491 0 +492 0 +493 0 +494 0 +495 0 +496 0 +497 0 +498 0 +499 0 +500 0 +501 0 +502 0 +503 0 +504 0 +505 0 +506 0 +507 0 +508 0 +509 0 +510 0 +511 0 +512 0 +513 0 +514 0 +515 0 +516 0 +517 0 +518 0 +519 0 +520 0 +521 0 +522 0 +523 0 +524 0 +525 0 +526 0 +527 0 +528 0 +529 0 +530 0 +531 0 +532 0 +533 0 +534 0 +535 0 +536 0 +537 0 +538 0 +539 0 +540 0 +541 0 +542 0 +543 0 +544 0 +545 0 +546 0 +547 0 +548 0 +549 0 +550 0 +551 0 +552 0 +553 0 +554 0 +555 0 diff --git a/docs/blog/free-surface-without-advecting-it.md b/docs/blog/free-surface-without-advecting-it.md new file mode 100644 index 000000000..df4120bd9 --- /dev/null +++ b/docs/blog/free-surface-without-advecting-it.md @@ -0,0 +1,188 @@ +# A free surface you never advect + +*Draft blog post — Underworld development team. Status: held pending a possible +method paper (the scheme is plausibly novel; see the +[method note](../developer/design/FREESLIP_DYNAMIC_TOPOGRAPHY_FREESURFACE.md) +and its cited novelty assessment). Not wired into the published docs toctree +yet — release at the team's discretion.* + +--- + +## The mystery: convection that quietly gives up + +We were running a very ordinary experiment: isoviscous convection in an annulus, +Rayleigh number 10⁵, with a deforming free surface on top. Nothing exotic. The +kind of thing that should just work. + +It didn't. The Nusselt number — our measure of how vigorously the system carries +heat — started at a healthy 13.6 and then *decayed*, drifting down toward +sub-critical values as if the convection were running out of steam. The interior +slowly cooled. Swap in a different free-surface scheme and the same thing +happened. Relax-to-equilibrium, kinematic finite-element, kinematic-exact — every +way we knew to move a free surface produced the same slow death. + +The frustrating part: by every conservation check we threw at it, the simulation +was *fine*. Mass was conserved. The surface amplitude was reasonable. There was +no obvious blow-up, no NaN, no tangled mesh. The model just... lost interest in +convecting. + +## The diagnosis: it's a lag, and the lag is a cold pump + +The breakthrough was realising the failure had nothing to do with how much the +surface moved, and everything to do with *when* it moved relative to the flow. + +Here is the mechanism. We advect temperature semi-Lagrangian: to find the new +temperature at a point, we trace backwards along the velocity to where that +parcel came from, and read the old temperature there. At a downwelling — cold +material plunging into the interior — the flow at the surface is pushing +*inward*. If the surface itself hasn't kept up (because the integrator +under-moved it, or smoothed it, or relaxed it too slowly), then the backward +trace lands *outside* the lagging surface — in the thin layer the surface should +have occupied but doesn't quite, where the only thing to read is the cold `T = 0` +boundary condition. + +So every step, at every downwelling, the scheme reaches past its own surface and +pulls in a little bit of cold. A **cold pump**, running on the lag between where +the surface *is* and where the velocity *thinks* it is. It is utterly silent — +mass is conserved, nothing diverges — but it steadily drains the thermal energy +that drives the convection. Hence the slow death. + +Any surface lag does it. Fourier truncation of the surface shape: lag. Smoothing +to keep the mesh clean: lag. Relaxation that under-moves: lag. There was no +setting that made the lag zero, because the lag is structural. + +## The trap inside the trap + +Our first instinct was to make the surface track the velocity *better* — reduce +the lag rather than live with it. That is when we found the second, deeper +problem. + +We isolated the surface normal velocity — the `v·n` that a kinematic scheme +integrates to move the surface — and watched it while holding the surface +essentially at its equilibrium shape. It should have been tiny: if the surface is +already where it wants to be, it shouldn't be moving. Instead it was *enormous* — +around 65 in our non-dimensional units — and it barely decayed. + +That number isn't the surface trying to move. It's **convective throughflow**: +downwellings slamming into the top boundary and the return flow sweeping back. +The fluid is moving vigorously *past* the surface, not *carrying* it. Reading +`v·n` as a rate-of-change-of-topography is reading the wrong quantity entirely. +Any scheme that integrates it is integrating noise a hundred times larger than +the signal, and it will overshoot no matter how carefully you step it. + +So the kinematic free surface is built on a contradiction: the very velocity it +uses to move the surface is dominated by flow that isn't moving the surface at +all. + +## The fix: stop advecting the surface + +If `v·n` at the surface is mostly throughflow, the cleanest thing to do is *not +let there be any throughflow*. Make the top boundary **free-slip**: `v·n = 0` by +construction. The fluid slides along the boundary but never crosses it. The +backward trace can no longer reach past the surface, because there is no normal +velocity carrying material across it. The cold pump is gone. + +But now the surface can't move kinematically — we just forbade the normal +velocity that would move it. So where does topography come from? + +From the **stress**. A free-slip lid still feels a normal stress pushing up under +upwellings and down under downwellings. Geodynamicists have computed *dynamic +topography* from exactly this normal stress for decades — it's the height the +surface would take if it were free to deform and compensate that stress +instantaneously. The twist is that this quantity has always been a **diagnostic**: +something you compute and plot *after* the fact, on a surface you keep flat. We +use it as a **prognostic** variable — we let it actually move the surface. + +So the surface is no longer carried by the flow. It *relaxes toward* the +stress-derived equilibrium topography. The flow solve stays clean and free-slip; +the surface evolves on its own, driven by the stress the flow produces. + +## Three numbers and a guarantee + +How do you step a relaxing surface? The naive answer — height plus rate, stepped +forward — is exactly the scheme that gives geodynamics its infamous "drunken +sailor" instability: the surface overshoots its target, the overshoot drives a +stress that pushes it back too hard, and it sloshes itself to pieces unless you +take agonizingly small time steps. + +The cure is a third number. Track the height `h`, its rate `ḣ`, *and* the +equilibrium it's heading for, `h_∞`. Those three pin a simple local model — the +surface decays exponentially toward equilibrium — with a rate + +> γ = ḣ / (h_∞ − h) + +and an exact update over the step: + +> h ← h_∞ + (h − h_∞) · e^(−γ Δt) + +This is **L-stable by construction**. The update always lands *between* the +current height and the equilibrium — it physically cannot overshoot, for any time +step, ever. The drunken sailor can't stagger because the scheme won't let him +past the target. And it's robust even when `ḣ` is corrupted by that throughflow +noise, because it only needs the *direction* of relaxation (`γ > 0`), not an +accurate rate. + +We'll be honest about lineage here: this exponential step is not something we +invented. It's first-order *exponential time differencing*, well known in applied +mathematics (Cox & Matthews, 2002; the no-overshoot property is proven cleanly by +Aursand et al., 2014). What appears to be new is bringing it to a geodynamic free +surface, and pairing it with a stress-derived equilibrium instead of a +kinematically-advected one. + +## One solve, two answers + +There's a small elegance that makes the whole thing cheap. You might expect to +need two Stokes solves per step: one to get the velocity for advecting +temperature, and another, with a held lid, to get the normal stress for `h_∞`. + +You don't. Under free-slip, the lithostatic part of the body force is a pure +gradient — it produces hydrostatic pressure and no flow. So a single *free-slip, +driving-only* solve gives you the advection velocity directly, and its normal +stress is exactly the `h_∞` you need, with no double-counting of the topographic +load. **One solve supplies both.** + +## What it buys + +With free-slip on top and the surface relaxing exponentially toward its +stress-equilibrium, the convection stops dying. Nusselt stays vigorous and +steady. The temperature field stays clean in [0, 1] — no cold injection, no +speckle. The surface tracks `h_∞` and oscillates *physically* with the flow +instead of marching off in a monotone runaway. The residual normal velocity at +the boundary drops from ~65 to ~0.4 — a hundred-fold — which is the throughflow +finally gone. + +It is worth being clear about where this lives. The scheme assumes surface +evolution is relaxation toward instantaneous isostatic compensation — exact in +the long-wavelength limit that matters for whole-mantle dynamic topography, where +the surface is stiff (buoyancy small compared to the restoring force) and +deflections are a few percent. Push it into a genuinely soft regime, where +buoyancy overwhelms the surface, and there simply isn't a smooth surface to track +— that's physics, not a bug. + +## So is it new? + +We ran a careful literature check, including a targeted sweep of the major +geodynamics codes' manuals and changelogs. The verdict: a **novel combination of +established parts**. Computing free-slip dynamic topography from stress is old +(Zhong, Gurnis & Moresi, 1996; Crameri et al., 2012). The exponential integrator +is older still, just from a different field. The closest relative — the implicit +free surface in Fluidity / G-ADOPT (Kramer, Wilson & Davies, 2012) — co-solves +the surface height with no time-step penalty, but it uses a stress boundary +condition rather than free-slip, and the height *is* the evolving surface rather +than an equilibrium target it relaxes toward. + +What we couldn't find anywhere was the synthesis: keep the lid free-slip, treat +the stress-derived dynamic topography as the equilibrium a separate surface +variable relaxes toward, and step that relaxation exponentially. Each ingredient +is published; the recipe doesn't appear to be. + +That's why this post is a draft. If the novelty holds up to a proper paper +search, the right venue for this story is a methods paper, not a blog. But the +core idea is too clean not to write down: **the best way to move a free surface +might be to stop advecting it.** + +--- + +*Technical details, the stability argument, the two deformed-geometry bugs we had +to fix first, and full citations are in the +[developer method note](../developer/design/FREESLIP_DYNAMIC_TOPOGRAPHY_FREESURFACE.md).* diff --git a/docs/developer/design/FREESLIP_DYNAMIC_TOPOGRAPHY_FREESURFACE.md b/docs/developer/design/FREESLIP_DYNAMIC_TOPOGRAPHY_FREESURFACE.md new file mode 100644 index 000000000..f372c28e9 --- /dev/null +++ b/docs/developer/design/FREESLIP_DYNAMIC_TOPOGRAPHY_FREESURFACE.md @@ -0,0 +1,677 @@ +# Free-slip + prognostic dynamic topography: an exponential free-surface scheme + +**Status:** design / method note. Describes the free-surface time-integration scheme +validated for old-frame semi-Lagrangian mantle convection in Underworld3, with a +[benchmark suite](#benchmarks) against Crameri et al. (2012). The two +deformed-geometry bug fixes it depends on landed in **PR #264**. The scheme is a +research method, not yet a public API. + +**Reproducibility.** The benchmark driver and analysis scripts live in +`~/+Simulations/FreeSurface/crameri_study/`; they require Underworld3 with the +swarm-proxy advection fix ([#289](https://github.com/underworldcode/underworld3/issues/289)). + +Related: [lagged-clone-sl-history](lagged-clone-sl-history.md), +[CONSTRAINED_FREESLIP_MULTIPLIER](CONSTRAINED_FREESLIP_MULTIPLIER.md), +[../../advanced/semi-lagrangian-time-integration](../../advanced/semi-lagrangian-time-integration.md). + +--- + +## TL;DR + +Instead of advecting a kinematic free surface with the fluid velocity (and +fighting the "drunken sailor" instability with FSSA or sticky air), we **decouple +the surface evolution from the kinematic velocity**: + +1. Evolve the surface topography `h` as a **prognostic variable** that relaxes + toward the **stress-derived equilibrium topography** `h_∞` — the instantaneous + isostatic compensation of the normal stress on a held free-slip lid — rather + than being advected by the kinematic normal velocity. +2. Advance `h` with an **L-stable exponential integrator** built from three numbers + per surface node — the current height `h`, its rate `ḣ`, and `h_∞`: + + $$\gamma = \frac{\dot h}{h_\infty - h}, \qquad + h \leftarrow h_\infty + (h - h_\infty)\,e^{-\gamma\,\Delta t}.$$ + + The update lands between `h` and `h_∞` and **cannot overshoot for any `Δt`**. +3. Supply the three numbers from Stokes solves on the same mesh: a **held + free-slip** solve gives `h_∞` (its normal stress `σ_nn`), a **stress-free** solve + gives the rate `ḣ = u_n`, and — when material crosses matter, i.e. in convection + — a **consistent** solve gives a velocity whose surface-normal equals the + *realized* relaxed rate, so the surface stays a material boundary. In the linear + / stagnant-lid limit these collapse to a single solve. + +This combination is, to the best of a 2026 literature survey, **novel in +geodynamics** — see [Novelty and related work](#novelty-and-related-work). The +integrator's *mathematics* is established exponential time differencing (ETD); its +*application to a geodynamic free surface*, and the prognostic use of free-slip +stress topography in place of kinematic advection, are not in the prior art +surveyed. A [benchmark suite](#benchmarks) against Crameri et al. (2012) confirms +the per-mode relaxation rate, the no-overshoot property, and the dynamic-topography +response, and shows the exponential integrator is **uniquely both stable and +accurate** among the surface time-steppers compared. + +--- + +## The problem this solves + +A kinematically advected free surface in old-frame semi-Lagrangian convection +makes isoviscous Ra = 1e5 convection **spuriously decay toward sub-critical** +(Nu 13.6 → 5; the interior cools), across every kinematic scheme tried +(relax-to-`h_eq`, kinematic-FE, kinematic-exact). + +The cause is **not** mass flux or amplitude. It is a **lag between the surface +position and the advecting velocity**. At a downwelling the old-frame +semi-Lagrangian foot `x − v·Δt` lands *beyond* the under-moved / smoothed / +relaxation-lagging surface, into the cold `T = 0` boundary condition → cold is +advected inward. Any surface lag (Fourier truncation, smoothing, relaxation +under-move) becomes a **cold pump**. + +The trap is the surface normal velocity itself. The free-surface `u_n` is huge +(~65 in non-dimensional units) and barely decays even when the surface is +essentially at equilibrium (`h ≈ h_∞`). That residual is **convective +throughflow** (downwellings impinging on the boundary), **not** a rate of +topographic change. So raw `v·n̂` is a corrupted `ḣ`; any scheme that integrates +it overshoots. + +**Free-slip removes the throughflow.** With `v·n̂ = 0` imposed by construction, +the semi-Lagrangian foot cannot reach beyond the surface, and the cold pump is +gone. Topography then evolves *only* through the exponential relaxation toward +the stress-derived `h_∞`. Result: Nu vigorous and steady (no crash), `T` clean +in `[0,1]`, and the surface tracks `h_∞` (oscillating physically with the flow, +not the monotone runaway of kinematic schemes). The residual `|u_n|` drops to +~0.4 — roughly 150× smaller than the free-surface ~65. + +--- + +## The method + +### 1. The held free-slip lid + +The equilibrium topography is read from a **held free-slip lid** solve (`v·n̂ = 0`, +traction-free tangentially) — one of the [three solves](#the-three-solve-scheme-material-surface-advection) +assembled below. In Underworld3 this is `add_nitsche_bc` with a moderate penalty +(`g ≈ 10`). **The normal must be the deformed facet normal**, supplied by +`mesh.boundary_normal(label)` — see [The two enabling bug +fixes](#the-two-enabling-bug-fixes-pr-264). The held lid is a *diagnostic* solve; it +does not itself move the surface. + +### 2. Equilibrium topography `h_∞` from the normal stress + +The "infinite-time" dynamic topography is the **instantaneous isostatic +compensation** of the normal stress on the free-slip lid: + +$$h_\infty = -\frac{\sigma_{nn} - \overline{\sigma_{nn}}}{\Delta\rho\,g},$$ + +with `σ_nn = n̂·σ·n̂` the projected normal stress. Two non-negotiables: + +- **Mean-relative `σ_nn`.** The held free-slip solve (no-slip inner + free-slip + outer) has a pressure null space → absolute `σ_nn` carries an arbitrary + constant. Subtracting the surface mean removes it and *is* the correct + isostatic datum. +- **Driving-only body force.** `h_∞` must be measured from the **Eulerian + driving** (buoyancy) body force only. On a deformed mesh the topography is + geometric, so including the Lagrangian surface-crossing `ρ_ref` restoring term + **double-counts** the load and flips the sign of `h_∞`. + +This stress-derived value is the classical free-slip dynamic-topography +*diagnostic* (Zhong, Gurnis & Moresi 1996; Crameri et al. 2012). What is +different here is that we use it **prognostically** — as the relaxation target of +a time integrator, not as a post-hoc output. + +### 3. The three-number exponential integrator + +Standard explicit free-surface stepping uses **two numbers** (`h`, `ḣ`) and is +forward-Euler — the "drunken sailor" sloshing instability (Kaus, Mühlhaus & May +2010), requiring a tiny time step. We add a **third** number, `h_∞`, which pins a +local exponential relaxation model: + +$$\frac{dh}{dt} = -\gamma\,(h - h_\infty), \qquad + \gamma = \frac{\dot h}{h_\infty - h} \ge 0,$$ + +integrated exactly over the step: + +$$h^{n+1} = h_\infty + (h^n - h_\infty)\,e^{-\gamma\,\Delta t}.$$ + +This is **L-stable by construction**: the update always lands *between* `h^n` and +`h_∞` and **cannot overshoot** for any `Δt`. It is robust even with a corrupted +`ḣ`, because it only needs `γ > 0` (the *direction* of relaxation), not an +accurate rate. Short-wavelength, high-`γ` modes snap to `h_∞` and cannot grow; +there is no drunken sailor. + +> **Per-mode, not per-node.** A *per-mode* clamp on `γ ≥ 0` is fine. The earlier +> `relax` scheme broke the integrator with **per-node** noisy `γ` plus a clamp +> that *froze* individual nodes plus mean-removal — the per-node freeze is fatal. +> Keep `γ` a smooth per-mode (or smoothed) quantity. + +The mathematics is first-order exponential time differencing for a monotonic +relaxation ODE — established applied mathematics (Cox & Matthews 2002; Aursand et +al. 2014), whose proven *monotonic asymptotic stability / no-overshoot* property +is exactly the L-stability claimed here. See +[Novelty and related work](#novelty-and-related-work) for the honest attribution. + +### 4. The single-solve collapse (linear / stagnant-lid limit) + +> **This collapse is exact only in the linear limit** (Frank–Kamenetskii viscosity, +> which is linear in `v`; a stagnant lid with no material crossing the surface). For +> **convecting** runs the surface is a *material* boundary and the scheme uses up to +> **three** Stokes solves per step — see +> [The hardened three-solve scheme](#the-hardened-three-solve-scheme-material-surface-advection) +> below. This is the version validated in the [Benchmarks](#benchmarks). + +A single **free-slip, driving-only** Stokes solve supplies **both**: + +- the **advection velocity** for the temperature field, and +- the **`σ_nn`** that gives `h_∞`. + +This is exact under free-slip: the lithostatic `−ρg r̂` is a pure gradient, so it +produces only hydrostatic pressure and no flow — the driving-only velocity equals +the full-body-force velocity for advection. And the driving-only `σ_nn` is +exactly what `h_∞` needs, with no topo-load double-counting. One solve, both +products. + +### Surface motion and interior propagation + +- **Radial prediction + tangential semi-Lagrangian transport.** Predict the new + surface height radially; transport `h` laterally along the tangential velocity + `u_t` by semi-Lagrangian trace-back. This is needed for surface-*shape* accuracy where + the surface flow converges or rotates. Note the trade-off: the SL trace-back is *not* + volume-conservative and is the dominant volume-drift source at finite amplitude (see + [Honest limitations](#honest-limitations)); a conservative transport is the eventual fix. +- **Smooth the stress, not the velocity.** Stress ~ `∇v` amplifies high + wavenumbers; smoothing the held-stress projection over ~1 cell size cuts + high-`k` topography 3–10×. P1-projecting or smoothing the *velocity* does + essentially nothing. +- **Propagate inward.** The surface ring moves to `h_∞`; the interior follows. A + plain Laplacian diffuser works; replacing it with a **T-aware node-moving + mover** so the same update both carries the topography *and* refines the + thermal boundary layers is the adaptive-meshing follow-up (see + [Next steps](#next-steps)). + +### The three-solve scheme (material-surface advection) + +The [single-solve collapse](#4-the-single-solve-collapse-linear--stagnant-lid-limit) +is exact in the linear / stagnant-lid limit. For **convecting** runs the free surface +is a **material boundary** and the scheme uses up to **three Stokes solves per step** +on the same mesh. This is the version validated in the [Benchmarks](#benchmarks). + +The three solves and what each supplies: + +1. **Free solve** — *stress-free* top (no velocity BC; the stress-free condition pins + the pressure datum). Its surface normal velocity `u_n` **is** the kinematic rate + `ḣ` that drives `γ`. A *free-slip* top would force `u_n = 0` and give no rate. +2. **Held-lid solve** — rigid free-slip lid (`u_n = 0`, Nitsche on the *deformed* + normal), driving-only body force → normal stress `σ_nn` → `h_∞ = −(σ_nn−mean)/Δρg`. + The free solve forces `σ_nn = 0`, so `h_∞` *must* come from this held solve. +3. **Consistent solve** — same buoyancy as the free solve, but the surface normal + velocity is **prescribed** to the *realized* relaxed rate `ũ_n = Δh/Δt` (penalty + BC, tangential stress-free). Its velocity advects `T`, so the surface stays a + material boundary. + +**Why the consistent solve (the key correctness fix).** Advecting `T` with the +*stress-free* `u_n` while the surface moves by the L-stable *relaxed* rate +`ũ_n ≤ u_n` lets net material cross the surface — a runaway (the cold lid leaks in, +plumes punch through; observed `u_n` 42→125→285→445). A free surface is a material +boundary: advect with a velocity whose surface-normal equals `ũ_n`. Two realizations: + +- **`consistent`** (correct in general): the third solve, prescribing `v·n̂ = ũ_n`. +- **`blend`** `α v_free + (1−α) v_held`, `α = φ₁(γΔt) = (1−e^{−γΔt})/(γΔt)`: by Stokes + linearity this **is** the prescribed-`ũ_n` solve for *uniform* `α` (and is exact/free + for the linear FK lid). Once `γ` varies per surface node the single mean-`α` collapse + is not close enough (the planform diverges), so the per-node `consistent` third solve + is required for structured convection — this is the [single-solve + collapse](#4-the-single-solve-collapse-linear--stagnant-lid-limit) breaking down away + from the linear limit. + +The cost is intrinsic: three Stokes solves per step on a deforming mesh, whose geometric +FMG hierarchy rebuilds each step (no warm-start / PC-reuse win). The unified-penalty +single-operator form (`penalty·(v·n̂ − V₁·n̂)·n̂`; `penalty=0`→free, `V₁=0`→held, +`V₁=ũ_n`→consistent — held and consistent share the matrix) is the cleanest formulation +but does not cut the solve count. + +Additional hardening for deformed / graded / higher-order meshes (all in the reference +driver): **tangential topography advection** (`v_t·∂_s h`, an operator split — +semi-Lagrangian transport of the surface shape, then the normal relaxation); +**free-slip inner boundary** — the rigid rotation `[-y,x]` is *not* a nullspace once the +surface deforms, so it is not attached to the held/consistent solves (a post-solve +projection strips the gauge instead); **finest-cell surface-ring detection** and a **P1 +velocity projection** to drive node movement order-consistently with the P1 mesh +geometry; **physical-length stress smoothing** so `h_∞` is mesh/order-independent. See +the `free-surface-convection` method note for the full symptom→cause failure table. + +--- + +## Why free-slip + stress, not kinematic + FSSA + +The standard geodynamic free surface is **kinematic**: the surface moves with the +fluid velocity. That coupling is what produces the sloshing / "drunken sailor" +instability and a severe time-step restriction relative to a free-slip lid (Kaus +et al. 2010; Rose, Buffett & Heister 2017). FSSA and sticky-air are devices to +**stabilise that same coupled velocity+surface solve**. + +This scheme instead **decouples** the two: + +- The *flow* sees a clean free-slip lid (no throughflow, no kinematic surface, no + sloshing eigenvalue). +- The *surface* evolves by exponential relaxation toward a stress-derived + equilibrium, which is L-stable independent of `Δt`. + +The price is a modelling assumption: surface evolution is treated as relaxation +toward the instantaneous isostatic-compensation topography, with a relaxation +rate `γ`. This is exact in the long-wavelength isostatic limit and is the regime +of interest for whole-mantle dynamic topography (`ρg ≫ Ra`, ≲ a few % surface +deflection). Stay in that physical regime: stiff surfaces (`ρg/Ra ≳ 1`, e.g. +`ρg = 2e6` at Ra = 1e5) are clean; genuinely soft surfaces (`ρg/Ra = 0.2`) are +unphysical (buoyancy exceeds the surface restoring force) and there is no +sustainable smooth surface to track. + +--- + +## Non-negotiables (each was a debugging round) + +- **External upper surface only.** Internal interfaces fail: penalty/Nitsche are + one-sided boundary operators with no consistency term, so the constitutive + `n·σ·n` projects to ≈ 0 on an internal interface and only the penalty reaction + carries the load. (Deferred; get the external surface right first.) +- **Driving-only body force** in the `h_∞` solve (full body force on the deformed + mesh double-counts the topo load and flips `h_∞`). +- **Mean-relative `σ_nn`** (pressure null space). +- **Sign:** `h_∞ = −(σ_nn − mean)/(Δρg)`; held-lid `σ_rr` is negative for an + upward bulge. Use `ETD_TOPO_SIGN = −1` on the external upper surface. +- **Radial prediction + tangential SL transport**, not raw normal advection. +- **Smooth the stress, not the velocity.** +- **Per-mode `γ ≥ 0` clamp**, never per-node freeze. + +--- + +## The two enabling bug fixes (PR #264) + +The scheme depends on two fixes for **analytic/cached undeformed geometry +surviving a deform** — both landed in PR #264 on `bugfix/gamma-p1-deformed-normal`: + +1. **Deformed facet normal.** `mesh.Gamma_P1` returns the *analytic* + coordinate-system normal (radial, for an annulus), not the deformed facet + normal — so `add_nitsche_bc` was imposing free-slip along `r̂`, not the true + `n̂`, leaking `v·n̂` on a deformed surface. Fix: new `mesh.boundary_normal(label)` + assembles exact PETSc facet normals per boundary (corners not averaged across + discontinuities), and `Mesh.deform()` re-assembles them after remesh so the BC + never reads a stale setup-time normal. `add_nitsche_bc` (Stokes + Scalar) + migrated to it; global `Gamma_P1` left unchanged for back-compat. + +2. **Deformed-domain membership.** `points_in_domain` / + `uw.function.evaluate` built their boundary-skeleton kd-tree from + `_nav_coords`, captured once at `__init__` and never refreshed on deform — so + on a deformed mesh, points inside the bulge were flagged *outside* the domain + and `evaluate` cold-clamped them to the old boundary value, cooling + upwellings. Fix: `nuke_coords_and_rebuild` now refreshes `_nav_coords` and the + boundary kd-tree caches from the current DM coordinates. + +Both bugs are the same class — undeformed geometry (analytic-radial normal; +stale `_nav_coords`) surviving a deform. Tests: `test_0056` (deformed annulus + +Cartesian corner, tier_a), `test_1060` (Nitsche), green serial + np2. Open +follow-up in the PR: ADD-reduce of partition-seam boundary vertices. + +--- + +## Novelty and related work + +A 2026 literature survey (5-angle fan-out, 19 sources, adversarial +verification; plus a targeted search of ASPECT/StagYY/LaMEM/pTatin/CitcomS/ +Underworld/G-ADOPT docs, changelogs and method papers) places this scheme as a +**novel combination of established parts**. Each ingredient has prior art; the +*synthesis* was not located. + +### Component 1 — free-slip + prognostic stress topography + +**Prior art (as a diagnostic).** Computing dynamic topography from the normal +stress on a **free-slip lid** is long-standing. Zhong, Gurnis & Moresi (1996) +state it directly: "the top surface is traditionally approximated as a free-slip +boundary, and the dynamic topography is obtained by assuming that the normal +stress on the free-slip boundary is compensated instantaneously through surface +deformation." Crameri et al. (2012) call this the *normal-stress method* — +"commonly used by the convection community" — with the surface kept **flat** and +topography **post-calculated**. Same in CitcomS/CitcomCU and the ASPECT +dynamic-topography postprocessor (output only). + +**Novel.** In all of that, free-slip stress topography is a **post-hoc +diagnostic** on a fixed flat surface. Using it **prognostically** — to actually +move the surface/mesh, decoupled from the kinematic velocity — was **not found** +in the surveyed prior art. The codes that *do* move the surface (ASPECT +free-surface plugin, LaMEM, I2VIS/I3ELVIS, pTatin3d, Underworld2) advect it +**kinematically** with `v` under a true (stress-free) surface, not from stress +under free-slip. + +### Component 2 — the three-number exponential integrator + +**Prior art (the numerics).** `h ← h_∞ + (h − h_∞)·exp(−γΔt)` is structurally +identical to first-order exponential time differencing for a monotonic relaxation +ODE. Cox & Matthews (2002) is the canonical ETD reference; **Aursand et al. +(2014)** give exactly `V ← V_eq + (V − V_eq)·exp(−λΔt)` for `dV/dt = −λ(V − V_eq)` +and **prove** "monotonic asymptotic stability, guaranteeing that no overshoots of +the equilibrium value are possible" with "no restriction on the time step" — the +L-stability claimed here (formally, the stronger property of unconditional +non-overshoot). So this component is honestly **borrowed mathematics**. + +**Novel.** No surveyed source applies this exponential-relaxation-to-equilibrium +step to a **geodynamic free surface / topography variable**. The relaxation +*timescale* is recognised (Crameri 2012's "instantaneous isostatic adjustment"; +Rose et al. 2017 tie a stabilisation parameter to "the smallest relaxation +timescale of the free surface"), but it is handled by implicit θ-schemes (Kramer +et al. 2012; ASPECT/FSSA) or nonstandard-finite-difference stabilisation (Rose et +al. 2017), never by an `exp(−γΔt)` relaxation toward a separately-computed `h_∞`. +ETD *does* appear in geodynamics — but for advection–diffusion time-stepping of +temperature/momentum, not for the surface. + +### Component 3 — `h_∞` from a held-lid solve + the single-solve collapse + +**Prior art.** That free-slip normal-stress topography is the **equilibrium +target** a true surface relaxes toward is established (Zhong et al. 1996: +"surface relaxation retards the topography… the topography is history-dependent"). +The `h_∞` value is the standard free-slip diagnostic, and it necessarily comes +from the same Stokes solve as `v`. + +**Novel (firmed up to high confidence).** The explicit framing of held-lid +`σ_nn` as the **relaxation target of a time integrator**, with a **single +driving-only free-slip solve serving as both the advection velocity source and +the `h_∞` source**, was **not found** in any surveyed code or paper. The standard +normal-stress method computes the same value but **discards/post-processes** it +rather than evolving the surface toward it. + +### The most important near-misses (cite these in any paper) + +- **Normal-stress method** — Crameri et al. (2012, GJI 189:38); CitcomS; ASPECT + dynamic-topography postprocessor. The key conceptual ancestor for Components 1 + & 3: free-slip top + `h = σ_n/(Δρg)`, but as a **diagnostic on a fixed flat + surface**, explicitly *not* solving the time-dependent relaxation. +- **FSSA** — Kaus, Mühlhaus & May (2010, PEPI 181:12). The near-miss to + distinguish most carefully: implicit-in-time **stabilisation of a still + kinematically-advected** free surface (a surface traction in the momentum weak + form), **not** prognostic-from-stress under free-slip. Note: FSSA via a signed + traction term **diverges** the UW3 Stokes solve (indefinite); a positive + Nitsche penalty is the well-conditioned stabilising-sign equivalent but + penalises a physical quantity (`u_n`). +- **Kramer, Wilson & Davies (2012) / G-ADOPT / Fluidity implicit free surface.** + Closest in spirit to Components 1+3 — `η` co-solved in one coupled system, no + time-step constraint — **but** it applies a *stress* free-surface BC + (`n·σ′·n = −Δρ_fs g η`), **not free-slip**, and `η` *is* the evolving surface, + not a held equilibrium target; no exponential relaxation, no `h_∞` concept. +- **Rose, Buffett & Heister (2017, PEPI 262:90).** *Analyses* the surface's + exponential-decay relaxation and ties a stabilisation parameter to the + relaxation timescale, but implements NSFD stabilisation, not an ETD integrator. +- **Surface-process diffusion** (`κ∇²h`) in LaMEM/pTatin and the ASPECT + "diffusion" mesh-deformation plugin — adjacent "relaxation" of topography, but + landscape smoothing toward flat, not stress-driven relaxation toward `h_∞`. + +### Overall verdict + +A **novel combination** for computational geodynamics: prognostic exponential +relaxation of a free-slip-derived equilibrium topography, in lieu of kinematic +free-surface advection. Not a wholly new method (the ETD step and the free-slip +stress diagnostic are both published), and not a re-derivation of a single +published technique (no source combines them this way). + +**Caveats.** The novelty rests on *absence of evidence* in the surveyed +literature, not a proof of non-existence; very recent unreleased PRs cannot be +fully excluded. Pull the Crameri (2012) and Kaus (2010) PDFs locally for verbatim +methods-section quotes before submitting a paper, and refresh the search at +submission time — free-surface methods continue to evolve. + +--- + +## Benchmarks + +The scheme is validated against the standard geodynamic free-surface benchmark of +**Crameri et al. (2012)**, reproduced in a 2-D Cartesian box — a faithful port of the +annulus reference driver (same three-solve / three-number scheme; only the geometry +changes: top `y=H`, normal `ŷ`, cosine modes on `x`, free-slip side walls). Runs, +driver and analysis live in `~/+Simulations/FreeSurface/crameri_study/`. + +### A. Topographic relaxation — per-mode decay rate (analytic) + +A single viscous layer in a free-slip-walled box with an initial cosine top-surface +perturbation `h(x,0) = A cos(mπx/L)` relaxes to flat (`h_∞ = 0`): + +![Relaxation benchmark: setup (mesh + initial cosine) and the surface relaxing to flat](figures/relax_setup_evolution.png) + +Each mode should decay at the analytic viscous (Cathles) rate `γ_k = ρg/(2ηk)`, +`k = mπ/L`, in the deep limit `kH ≫ 1`. The exponential integrator recovers it to +**≤ 0.1 %** across modes 2–6 (`kH ≥ 2π`); mode 1 (`kH = π`) sits **2.6 %** below the +half-space value — the expected finite-depth reduction. Every mode is a clean single +exponential (log-fit residuals `1e-5 … 3e-3`), confirming the integrator is exact for the +relaxation ODE. + +![Per-mode relaxation-rate recovery vs analytic Cathles γ](figures/relax_gamma_recovery.png) + +![Relaxation decay curves vs analytic exponential](figures/relax_decay_curves.png) + +In the decay-curve figure the analytic lines are **anchored at the first numerical sample +`t₀`** (one integration step in), so both are normalised at the same time; the residual +constant offset from the time-origin mismatch is removed. Modes 2–6 then lie on the +analytic line; mode 1's points drift gently above it — the true **accumulating** +finite-depth error, now separated from the start-up offset. + +### B. Crameri Case 1 — finite-depth layered relaxation + +The actual Crameri geometry: a stiff lithospheric lid (`η_L/η_M = 100`, thickness +`100/700` of the box height) over mantle, no-slip base, `cos(2πx/L)` surface +perturbation (7 km / 2800 km). Crameri's characteristic relaxation time +**τ = 14.825 ka** is itself **≈ 3.4×** the half-space reference +`t_rlx = 4πη_M/(ρgλ) ≈ 4.4 ka` — the finite-depth + rigid-base + stiff-lid slowdown +(their Ramberg three-layer analytic). The scheme reproduces this: the recovered `τ` is +**3.46×** the half-space `t_rlx` (vs Crameri 3.37–3.44, within ≈ 3 %). It therefore +captures not just the half-space limit but the finite-depth, layered relaxation. + +### C. No-overshoot / L-stability at large `Δt` + +For mode 1, sweeping `Δt` over `γΔt = 0.08 … 2.55`: the recovered rate is +**`Δt`-independent** (`γ_fit` constant to the fifth digit, 0.15495–0.15501) and the +surface **never overshoots** (`min A/A₀ > 0` throughout, even at `γΔt = 2.55`). A +forward-Euler kinematic surface (the "drunken sailor") would oscillate and diverge for +`γΔt > 1`. This is the headline L-stability property realised in practice — the +integrator trades nothing for stability: accuracy is preserved as `Δt` grows. + +![dt-independence and no overshoot at large γ·Δt](figures/relax_dt_stability.png) + +### D. Crameri Case 2 — dynamic topography over a rising plume + +A buoyant plume (`r = 50 km`, `Δρ = −100 kg/m³`, viscosity `η_P = 0.1 η_M`) is released +mid-mantle beneath a 100 km stiff lid (`η_L/η_M = 100`) and rises under a free surface. The +composition is carried on a **particle swarm** (a top-hat circle with **zero numerical +diffusion** — a field-advected blob diffuses away on this slow-Stokes timescale), and its +proxy feeds both the buoyancy and the composition-dependent viscosity. The plume rises, +**ponds beneath the lid**, and the free surface uplifts; the surface stays a clean +quasi-equilibrium with the stress-derived `h_∞` throughout, with **excellent volume +conservation** (`dVol < 0.002 %`). + +The plume rises (centroid 0.107 → 0.198 of the box height, ponding just beneath the lid +base) and the surface topography traces a **rise → peak → relax**, crossing the published +early-checkpoint value (≈ 398 m) and growing toward Crameri's ~800 m peak. Volume +conservation stays `dVol < 0.002 %`. + +> **A genuine numerical pitfall, diagnosed and fixed (the surface-stress recovery).** With +> the default **continuous (Taylor–Hood P1) pressure**, the surface developed a node-to-node +> **checkerboard** — a clean dome plus a Nyquist mode reaching ~40 % of the amplitude — which +> inflated and scattered the apparent peak (the earlier ~0.9–1.05 km values). It is **not** +> the `σ_nn` formula (that uses the *total* Cauchy stress `σ = τ − pI`, pressure included), +> nor the buoyancy (Stokes smooths the RHS), nor the swarm. Localising it, the deviatoric +> `τ_nn` is smooth (≈ 3 %) and the **checkerboard lives entirely in the pressure**: the +> viscosity jumps make the pressure genuinely *discontinuous*, which a **continuous** P1 +> field cannot represent, so it oscillates — and the P1 stress projection passes a +> continuous-P1 zigzag through unchanged (it only averages *discontinuous* sources). +> Switching to a **discontinuous pressure** lets the projection average the per-element +> values: the checkerboard drops to **~9–11 %** (stable throughout the run), the surface +> profile is smooth, and the solve stays stable. The full discontinuous-pressure resolution +> sweep (res 48 / 64 / 96 / 128) gives a cleanly-recovered peak topography of +> **0.69–0.89 km (mean ≈ 0.78 km)**, bracketing Crameri's ~0.8 km peak — and well below the +> checkerboard-inflated ~0.9–1.3 km of the continuous-pressure runs. The peak still carries a +> residual ±0.1 km resolution sensitivity (the plume is only ~1–2 cells across at these +> resolutions, so it is not yet in a clean monotone-convergence regime), but the magnitude +> and the smooth rise→pond→relax history are robust. This is a boundary-stress *recovery* +> issue; the Consistent Boundary Flux (Zhong 1993) is the standard, more robust alternative. + +![Plume composition + deformed free surface: rise → pond under lid → relax](figures/case2_faithful_fields.png) + +![Left: the surface uplift integral ∫max(h,0)dx evolves smoothly (rise → peak → relax) at every resolution. Right: peak surface height vs resolution against Crameri's ~800 m.](figures/case2_convergence.png) + +> **What to measure at the surface (a diagnostic caveat, not a physics defect).** The +> natural-looking "peak topography" — `max|y − H|` over the discrete top-ring nodes — is a +> **poor time-series diagnostic**, and reading it literally suggests the surface evolves in +> *steps*: it can sit bit-for-bit constant for tens of timesteps and then jump. That is an +> artifact of two things acting together, **not** the surface freezing. (i) A `max(...)` +> reduction is dominated by a **single apex node**, blind to smooth motion everywhere else. +> (ii) The EXP integrator's **no-overshoot clamp** `γ = max(u_n/(h_∞ − h), 0)` sets `γ = 0` +> for any node whose realized normal velocity `u_n` transiently disagrees in sign with its +> distance-to-target `(h_∞ − h)` — and because `γ` enters an exponential, +> `h ← h_∞ + (h − h_∞)e^{−γΔt}` returns `h` *exactly* (`e^0 = 1`) when clamped. So the apex +> above a ponding plume, sitting near its own equilibrium while `u_n` flips sign with each +> small convective pulse, is held **identically** between pulses and "slips" only when a +> coherent ascent pulse re-aligns `u_n` with the target. The clamp is deliberate — `γ ≥ 0` +> *is* the L-stability / no-overshoot guarantee (Benchmarks C, E): a node never moves the +> wrong way, so it can stick but never wander. Meanwhile the driving `h_∞`, the trough, and +> the **uplift integral** `U = ∫ max(h,0)\,dx` all evolve smoothly — the stuck apex +> contributes a constant while the moving flanks integrate continuously. The figure +> therefore reports `U(t)` (left) for the *evolution*, reserving the node-max peak height +> (right) only for the Crameri *magnitude* comparison, where it is the quantity Crameri +> tabulates. + +> **Coupling requirements (not properties of the surface scheme).** Two conditions must +> hold for the coupled plume benchmark. (i) The composition must be carried on a **particle +> swarm**: a field-advected sharp blob is destroyed by numerical diffusion on the +> slow-Stokes timescale (`√(κt) ≫` blob radius), which silently weakens the buoyancy. +> (ii) The swarm proxy must be refreshed after advection (`material._update()`); on builds +> before the fix in [#289](https://github.com/underworldcode/underworld3/issues/289), +> `swarm.advection()` leaves the proxy stale and the solver reads a **frozen** plume — a +> static artifact that mimics a steady state. Both concern the swarm–solver coupling; the +> free-surface integrator is validated independently by Benchmarks A–C and E. + +### E. Integrator head-to-head — EXP vs explicit time-stepping + +The relaxation benchmark (Case A, analytic answer) is the clean place to compare the +**surface time-integrator** while holding everything else fixed. Each scheme advances the +*same* per-node relaxation ODE `dh/dt = −γ(h − h_∞)` with `γ` from the step's Stokes solve; +they differ only in how that ODE is integrated. We compare our **EXP** (the exact +exponential update) against the explicit integrators of the same model — **forward Euler**, +**RK2**, **RK4** — and against **FSSA**, the standard *stabilised kinematic* free surface +(Kaus et al. 2010): a kinematically-advected surface with an implicit `0.5 ρg Δt (n̂·v) n̂` +traction. We sweep `γΔt` from 0.16 to 5 (pure unstabilised kinematic advection coincides +with forward Euler on this test). + +![Integrator head-to-head on the relaxation benchmark](figures/integrator_compare.png) + +- **EXP** recovers the rate to `γ_fit/γ_deep = 0.974` **independent of `Δt`**, and **never + overshoots**, for *every* `γΔt` tested — it is the exact solution of the per-step linear + relaxation, so it is unconditionally stable *and* accurate. +- **Forward Euler / kinematic** overshoots below flat (the drunken sailor) for `γΔt > 1` and + diverges for `γΔt > 2`. +- **RK2 / RK4** are accurate at small `γΔt` but lose accuracy as `γΔt` grows and go unstable + past their stability limits (`γΔt = 2` and `2.785`) — they stall or diverge. +- **FSSA** *bounds* the kinematic instability (overshoot only `−0.1 … −0.4` vs forward + Euler's `−3`), but at a real **accuracy cost**: the recovered rate is biased + (`γ_fit/γ_deep` rises to ~1.14 at moderate `γΔt`) and then **collapses to ~0.17 by + `γΔt = 5`** — i.e. it badly **under-deforms** the surface. This is exactly the + stability-for-accuracy trade FSSA is known for, and the trade this scheme avoids. + +This is the core methods result: among all of these, the **exponential integrator is +uniquely both unconditionally stable and accurate** — no accuracy penalty for its stability, +where FSSA buys stability by under-deforming and the explicit schemes lose both. It directly +answers whether the magnitude differences in Case D could be "a limitation of the exponential +scheme": they cannot — EXP is the most accurate member of the family, and the surface +response in the quasi-equilibrium plume regime is set by the stress `h_∞`, not the +integrator. + +--- + +## Honest limitations + +- **Volume conservation.** The surface update is not exactly volume-conserving, and the + drift scales strongly with deformation amplitude. It is small in the + small-deflection benchmarks (`dVol ≲ 0.005 %` for the plume / per-mode relaxation, + deflection ≲ 0.1 % of the domain) but reaches **~0.2–0.9 %** at a 15 %-amplitude + relaxation. The **dominant contributor at finite amplitude is the semi-Lagrangian + tangential surface advection** — a departure-point interpolation that carries the + topography pattern along the surface but is itself **not volume-conservative**. Toggling + it (`--no-tangent-advect`) isolates the effect: at the tiny plume deflection it is + negligible (0.0033 % on vs 0.0020 % off), but at 15 % amplitude it **triples** the drift + (0.90 % on vs 0.26 % off). + + ![Volume drift vs the SL tangential surface advection, at two deformation amplitudes](figures/volume_conservation.png) + + This is a genuine trade: the tangential transport is needed for surface-*shape* accuracy + (without it, the topography pattern is not carried where the surface flow converges / + rotates), but its SL form leaks volume. A **conservative** tangential-transport scheme + (flux-form, or a conservative remap of the surface field) would remove this contribution + — the main remaining accuracy improvement available to the surface scheme. (On the + annulus the enclosed area is additionally sensitive to the surface position through the + nonlinear `r²` element, so the amplitude scaling is steeper there.) +- **Elastic-plate flexure `h_∞`** (`--flexure-D`, spectral) sets a smooth, physically + grounded *set-point* with the correct amplitude response (stiffer plate → less + deflection), but filtering `h_∞` alone does **not** low-pass the *surface*: + short-wavelength content still enters via the tangential transport and partial + relaxation. Filtering the geometry `h` instead injects a spurious smooth-the-mesh + motion and runs the flow away. A true surface low-pass without destabilising is open. +- **Smoothing is a real dynamics bias** — physical-length stress smoothing elevates + `Vrms` when dialled up; keep it minimal (a fraction of a feature wavelength). +- **Surface-ring detection** is by radius / `|y−H|` with a finest-cell tolerance; the + cleaner route is the DMPlex `Top`/`Upper` stratum label (removes the heuristic). + +--- + +## Next steps + +- **Adaptive meshing.** Replace the Laplacian inner diffuser with a T-aware + node-moving mover (`smooth_mesh_interior(spring)` with a `|∇T|` / T-Hessian + metric, or `follow_metric`), surface ring pinned at `h_∞`, inner boundary + pinned — so the same mesh update carries the topography *and* refines the + thermal boundary layers + plume stems. Old-frame already carries `T` through + `mesh.deform` / `mesh.adapt`. Watch the known pitfalls: Winslow end-of-step + Lagrangian-`T` coupling, low-order (P0/P1) metric/viscosity fields, and judging + adaptation by bounded-range + clean no-overlay renders. +- **Flexural `h_∞`.** Replace ad-hoc stress smoothing with an equivalent elastic + thickness `Te` → flexural rigidity `D = E·Te³/12(1−ν²)` → + `h_∞(k) = σ_nn / (Δρg + D·k⁴)`, a *physical* high-`k` cutoff at the flexural + wavelength; the exponential relaxation is unchanged. +- **Further benchmarking.** The relaxation rate, Crameri Case-1 and Case-2, the + no-overshoot guarantee, and the head-to-head against FSSA and the explicit integrators + are validated ([Benchmarks](#benchmarks)). Still open: a comparison against the + **Rose–Buffett–Heister** quasi-implicit scheme (accuracy / cost per unit accuracy), and + a quantitative match of Crameri Case-2 against the published topography-vs-time curve at + matched physical time (the present run reproduces the rise→peak→relax and the ~0.7–0.9 km + magnitude; an exact-stage comparison needs the published time series). + +--- + +## References + +- Aursand, Evje, Flåtten, Giljarhus & Munkejord (2014). *An exponential + time-differencing method for monotonic relaxation systems.* Applied Numerical + Mathematics. — first/second-order ETD for monotonic relaxation ODEs; the + no-overshoot proof. +- Cathles (1975). *The Viscosity of the Earth's Mantle.* Princeton Univ. Press. — + the per-mode viscous relaxation rate `γ_k = ρg/(2ηk)` (postglacial rebound). +- Cox & Matthews (2002). *Exponential time differencing for stiff systems.* + J. Comput. Phys. 176(2):430–455. — canonical ETD reference. +- Crameri, Schmeling, Golabek, Duretz, Orendt, Buiter, May, Kaus, Gerya & + Tackley (2012). *A comparison of numerical surface topography calculations in + geodynamic modelling: an evaluation of the "sticky air" method.* GJI + 189(1):38–54. — the normal-stress method (free-slip + diagnostic topography). +- Kaus, Mühlhaus & May (2010). *A stabilization algorithm for geodynamic + numerical simulations with a free surface.* Phys. Earth Planet. Inter. + 181:12–20. — FSSA; the "drunken sailor"/sloshing instability. +- Kramer, Wilson & Davies (2012). *An implicit free surface algorithm for + geodynamical simulations.* Phys. Earth Planet. Inter. 194–195:25–37. — + implicit co-solved free surface (G-ADOPT / Fluidity). +- Pysklywec & Shahnas (2003). *Time-dependent surface topography in a coupled + lithosphere–mantle convection model.* GJI 154(2):268–278. — ALE kinematic + surface tracking. +- Ramberg (1967). *Gravity, Deformation and the Earth's Crust.* Academic Press. — + the layered-viscous analytic relaxation model underlying Crameri Case 1. +- Turcotte & Schubert (2002). *Geodynamics* (2nd ed.). Cambridge Univ. Press. — + the isostatic relaxation time `t_rlx = 4πη/(ρgλ)`. +- Rose, Buffett & Heister (2017). *Stability and accuracy of free surface + time integration in viscous flows.* Phys. Earth Planet. Inter. 262:90–100. — + drunken-sailor normal-mode analysis; quasi-implicit stabilisation. +- Zhong, Gurnis & Moresi (1996). *Free-surface formulation of mantle convection, + Part I.* GJI 127(3):708–718. — free-slip normal-stress topography as the + instantaneous-compensation diagnostic; history-dependent surface relaxation. +- Arnould, Coltice, Flament, Seigneur & Müller (2018). *On the scales of dynamic + topography in whole-mantle convection models.* G3, 10.1029/2018GC007516. — + free-slip diagnostic dynamic topography in StagYY. diff --git a/docs/developer/design/figures/case2_convergence.png b/docs/developer/design/figures/case2_convergence.png new file mode 100644 index 000000000..a9313647e Binary files /dev/null and b/docs/developer/design/figures/case2_convergence.png differ diff --git a/docs/developer/design/figures/case2_faithful_fields.png b/docs/developer/design/figures/case2_faithful_fields.png new file mode 100644 index 000000000..87add2e64 Binary files /dev/null and b/docs/developer/design/figures/case2_faithful_fields.png differ diff --git a/docs/developer/design/figures/case2_fields.png b/docs/developer/design/figures/case2_fields.png new file mode 100644 index 000000000..d9cb1f6aa Binary files /dev/null and b/docs/developer/design/figures/case2_fields.png differ diff --git a/docs/developer/design/figures/case2_topography.png b/docs/developer/design/figures/case2_topography.png new file mode 100644 index 000000000..0fcbadcdd Binary files /dev/null and b/docs/developer/design/figures/case2_topography.png differ diff --git a/docs/developer/design/figures/integrator_compare.png b/docs/developer/design/figures/integrator_compare.png new file mode 100644 index 000000000..778db2d68 Binary files /dev/null and b/docs/developer/design/figures/integrator_compare.png differ diff --git a/docs/developer/design/figures/relax_decay_curves.png b/docs/developer/design/figures/relax_decay_curves.png new file mode 100644 index 000000000..8cb0947c1 Binary files /dev/null and b/docs/developer/design/figures/relax_decay_curves.png differ diff --git a/docs/developer/design/figures/relax_dt_stability.png b/docs/developer/design/figures/relax_dt_stability.png new file mode 100644 index 000000000..1d8dde992 Binary files /dev/null and b/docs/developer/design/figures/relax_dt_stability.png differ diff --git a/docs/developer/design/figures/relax_gamma_recovery.png b/docs/developer/design/figures/relax_gamma_recovery.png new file mode 100644 index 000000000..e6203afa1 Binary files /dev/null and b/docs/developer/design/figures/relax_gamma_recovery.png differ diff --git a/docs/developer/design/figures/relax_setup_evolution.png b/docs/developer/design/figures/relax_setup_evolution.png new file mode 100644 index 000000000..2197d45cc Binary files /dev/null and b/docs/developer/design/figures/relax_setup_evolution.png differ diff --git a/docs/developer/design/figures/volume_conservation.png b/docs/developer/design/figures/volume_conservation.png new file mode 100644 index 000000000..7719fa72b Binary files /dev/null and b/docs/developer/design/figures/volume_conservation.png differ diff --git a/pixi.lock b/pixi.lock index 84c3c9e3b..cd4d53cf8 100644 --- a/pixi.lock +++ b/pixi.lock @@ -7,8 +7,7 @@ environments: - https://pypi.org/simple packages: linux-64: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alabaster-1.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.1-hb03c661_0.conda @@ -195,6 +194,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzip-1.11.2-h6991a6a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/make-4.4.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_1.conda @@ -219,7 +219,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/netcdf4-1.7.3-nompi_py312hf6400b3_100.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.0-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openldap-2.6.10-he970967_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda @@ -532,7 +532,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/netcdf4-1.7.3-nompi_py312h947358d_100.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.0-py312ha003a3f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hbfb3c88_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openmpi-5.0.10-h899237b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.0-h5503f6c_0.conda @@ -650,8 +650,7 @@ environments: - https://pypi.org/simple packages: linux-64: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.6.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.13.2-py312h27b7581_0.conda @@ -724,8 +723,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.3-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-1.9.0-py312hf23773a_0_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-cpu-1.9.0-h718b53a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-1.10.0-cpu_mkl_py312_hd7bdcb3_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-cpu-1.10.0-h718b53a_100.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ffmpeg-8.0.1-gpl_hb3f9226_906.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexcache-0.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexparser-0.4-pyhd8ed1ab_1.conda @@ -851,7 +850,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfabric-2.4.0-ha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfabric1-2.4.0-h6c8fc0a_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libfaiss-1.9.0-h72e5a87_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libfaiss-1.10.0-cpu_openblas_hfcc2109_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libflac-1.5.0-he200343_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.1-ha770c72_0.conda @@ -936,6 +935,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzip-1.11.2-h6991a6a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/loguru-0.7.3-pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda @@ -976,8 +976,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.2.1-he2c55a7_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.0-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ocl-icd-2.3.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openblas-0.3.30-pthreads_h6ec200e_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/opencl-headers-2025.06.13-h5888daf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openh264-2.6.0-hc22cd8d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda @@ -1259,8 +1260,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/expat-2.7.3-haf25636_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-1.9.0-py312h423fd24_0_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-cpu-1.9.0-hd610c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-1.10.0-cpu_openblas_py312_hcaa93c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-cpu-1.10.0-hd610c6a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ffmpeg-8.0.1-gpl_hd70ab68_107.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexcache-0.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexparser-0.4-pyhd8ed1ab_1.conda @@ -1376,7 +1377,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfabric-2.4.0-hce30654_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfabric1-2.4.0-hc919400_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfaiss-1.9.0-h682f5e0_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfaiss-1.10.0-cpu_openblas_hcda87cf_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.1-hce30654_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.14.1-h6da58f4_0.conda @@ -1474,7 +1475,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nlohmann_json-3.12.0-h248ca61_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.2.1-h5230ea7_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.0-py312ha003a3f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openblas-0.3.30-openmp_hea878ba_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openh264-2.6.0-hb5b2745_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hbfb3c88_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openldap-2.6.10-hbe55e7a_0.conda @@ -1662,8 +1664,7 @@ environments: - https://pypi.org/simple packages: linux-64: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.6.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.13.2-py312h27b7581_0.conda @@ -1736,8 +1737,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.3-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-1.9.0-py312hf23773a_0_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-cpu-1.9.0-h718b53a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-1.10.0-cpu_mkl_py312_hd7bdcb3_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-cpu-1.10.0-h718b53a_100.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ffmpeg-8.0.1-gpl_hb3f9226_906.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexcache-0.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexparser-0.4-pyhd8ed1ab_1.conda @@ -1863,7 +1864,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfabric-2.4.0-ha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfabric1-2.4.0-h6c8fc0a_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libfaiss-1.9.0-h72e5a87_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libfaiss-1.10.0-cpu_openblas_hfcc2109_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libflac-1.5.0-he200343_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.1-ha770c72_0.conda @@ -1948,6 +1949,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzip-1.11.2-h6991a6a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/loguru-0.7.3-pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda @@ -1988,8 +1990,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.2.1-he2c55a7_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.0-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ocl-icd-2.3.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openblas-0.3.30-pthreads_h6ec200e_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/opencl-headers-2025.06.13-h5888daf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openh264-2.6.0-hc22cd8d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda @@ -2271,8 +2274,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/expat-2.7.3-haf25636_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-1.9.0-py312h423fd24_0_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-cpu-1.9.0-hd610c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-1.10.0-cpu_openblas_py312_hcaa93c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-cpu-1.10.0-hd610c6a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ffmpeg-8.0.1-gpl_hd70ab68_107.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexcache-0.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexparser-0.4-pyhd8ed1ab_1.conda @@ -2388,7 +2391,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfabric-2.4.0-hce30654_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfabric1-2.4.0-hc919400_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfaiss-1.9.0-h682f5e0_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfaiss-1.10.0-cpu_openblas_hcda87cf_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.1-hce30654_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.14.1-h6da58f4_0.conda @@ -2486,7 +2489,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nlohmann_json-3.12.0-h248ca61_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.2.1-h5230ea7_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.0-py312ha003a3f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openblas-0.3.30-openmp_hea878ba_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openh264-2.6.0-hb5b2745_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hbfb3c88_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openldap-2.6.10-hbe55e7a_0.conda @@ -2674,7 +2678,7 @@ environments: - https://pypi.org/simple packages: linux-64: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alabaster-1.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda @@ -2861,6 +2865,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzip-1.11.2-h6991a6a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/make-4.4.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda @@ -2885,7 +2890,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/netcdf4-1.7.4-nompi_py312h25f8dc5_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.0-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openldap-2.6.10-hbde042b_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda @@ -3196,7 +3201,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/netcdf4-1.7.4-nompi_py312h5d59a02_102.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.0-py312ha003a3f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hd9e9057_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda @@ -3312,7 +3317,7 @@ environments: - https://pypi.org/simple packages: linux-64: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/accessible-pygments-0.0.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.6.1-pyhd8ed1ab_0.conda @@ -3386,8 +3391,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.4-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-1.9.0-py312hf23773a_0_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-cpu-1.9.0-h718b53a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-1.10.0-cpu_mkl_py312_hd7bdcb3_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-cpu-1.10.0-h718b53a_100.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ffmpeg-8.0.1-gpl_hcddb375_914.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexcache-0.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexparser-0.4-pyhd8ed1ab_1.conda @@ -3513,7 +3518,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfabric-2.4.0-ha770c72_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfabric1-2.4.0-h8f87c3e_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libfaiss-1.9.0-h72e5a87_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libfaiss-1.10.0-cpu_openblas_hfcc2109_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libflac-1.5.0-he200343_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.2-ha770c72_0.conda @@ -3600,6 +3605,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzip-1.11.2-h6991a6a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/loguru-0.7.3-pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda @@ -3640,8 +3646,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.7.0-he4ff34a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.0-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ocl-icd-2.3.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openblas-0.3.30-pthreads_h6ec200e_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/opencl-headers-2025.06.13-h5888daf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openh264-2.6.0-hc22cd8d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda @@ -3922,8 +3929,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/expat-2.7.4-hf6b4638_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-1.9.0-py312h423fd24_0_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-cpu-1.9.0-hd610c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-1.10.0-cpu_openblas_py312_hcaa93c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-cpu-1.10.0-hd610c6a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ffmpeg-8.0.1-gpl_ha5d8480_114.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexcache-0.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexparser-0.4-pyhd8ed1ab_1.conda @@ -4038,7 +4045,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.4-hf6b4638_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfabric-2.4.0-hce30654_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfabric1-2.4.0-h84a0fba_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfaiss-1.9.0-h682f5e0_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfaiss-1.10.0-cpu_openblas_hcda87cf_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.2-hce30654_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.14.2-hdfa99f5_0.conda @@ -4139,7 +4146,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nlohmann_json-3.12.0-h784d473_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.7.0-hbfc8e16_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.0-py312ha003a3f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openblas-0.3.30-openmp_hea878ba_4.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openh264-2.6.0-hb5b2745_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hd9e9057_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openldap-2.6.10-hf7f56bc_1.conda @@ -4325,7 +4333,7 @@ environments: - https://pypi.org/simple packages: linux-64: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alabaster-1.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda @@ -4514,6 +4522,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzip-1.11.2-h6991a6a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/make-4.4.1-hb9d3cd8_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda @@ -4537,7 +4546,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/netcdf4-1.7.4-nompi_py312h25f8dc5_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.0-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openldap-2.6.10-hbde042b_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openmpi-5.0.10-h611b0e2_0.conda @@ -4851,7 +4860,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/netcdf4-1.7.4-nompi_py312h5d59a02_102.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.0-py312ha003a3f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hd9e9057_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openmpi-5.0.10-h899237b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda @@ -4968,7 +4977,7 @@ environments: - https://pypi.org/simple packages: linux-64: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/accessible-pygments-0.0.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.6.1-pyhd8ed1ab_0.conda @@ -5042,8 +5051,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.4-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-1.9.0-py312hf23773a_0_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-cpu-1.9.0-h718b53a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-1.10.0-cpu_mkl_py312_hd7bdcb3_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-cpu-1.10.0-h718b53a_100.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ffmpeg-8.0.1-gpl_hcddb375_914.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexcache-0.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexparser-0.4-pyhd8ed1ab_1.conda @@ -5170,7 +5179,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfabric-2.4.0-ha770c72_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfabric1-2.4.0-h8f87c3e_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libfaiss-1.9.0-h72e5a87_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libfaiss-1.10.0-cpu_openblas_hfcc2109_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libflac-1.5.0-he200343_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.2-ha770c72_0.conda @@ -5258,6 +5267,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzip-1.11.2-h6991a6a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/loguru-0.7.3-pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda @@ -5297,8 +5307,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.7.0-he4ff34a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.0-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ocl-icd-2.3.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openblas-0.3.30-pthreads_h6ec200e_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/opencl-headers-2025.06.13-h5888daf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openh264-2.6.0-hc22cd8d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda @@ -5581,8 +5592,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/expat-2.7.4-hf6b4638_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-1.9.0-py312h423fd24_0_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-cpu-1.9.0-hd610c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-1.10.0-cpu_openblas_py312_hcaa93c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-cpu-1.10.0-hd610c6a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ffmpeg-8.0.1-gpl_ha5d8480_114.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexcache-0.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexparser-0.4-pyhd8ed1ab_1.conda @@ -5698,7 +5709,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.4-hf6b4638_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfabric-2.4.0-hce30654_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfabric1-2.4.0-h84a0fba_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfaiss-1.9.0-h682f5e0_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfaiss-1.10.0-cpu_openblas_hcda87cf_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.2-hce30654_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.14.2-hdfa99f5_0.conda @@ -5799,7 +5810,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nlohmann_json-3.12.0-h784d473_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.7.0-hbfc8e16_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.0-py312ha003a3f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openblas-0.3.30-openmp_hea878ba_4.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openh264-2.6.0-hb5b2745_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hd9e9057_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openldap-2.6.10-hf7f56bc_1.conda @@ -5986,8 +5998,7 @@ environments: - https://pypi.org/simple packages: linux-64: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.6.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.13.2-py312h27b7581_0.conda @@ -6244,6 +6255,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzip-1.11.2-h6991a6a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/loguru-0.7.3-pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/make-4.4.1-hb9d3cd8_2.conda @@ -6276,7 +6288,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/netcdf4-1.7.3-nompi_py312hf6400b3_100.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.0-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ocl-icd-2.3.3-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/opencl-headers-2025.06.13-h5888daf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openh264-2.6.0-hc22cd8d_0.conda @@ -6712,7 +6724,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/netcdf4-1.7.3-nompi_py312h947358d_100.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nlohmann_json-3.12.0-h248ca61_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.0-py312ha003a3f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openh264-2.6.0-hb5b2745_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hbfb3c88_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openldap-2.6.10-hbe55e7a_0.conda @@ -7073,7 +7085,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzip-1.11.2-h6991a6a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-21.1.8-h4922eb0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_0.conda @@ -7100,7 +7112,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/netcdf4-1.7.3-nompi_py312hf6400b3_100.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.0-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openldap-2.6.10-he970967_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.0-h26f9b46_0.conda @@ -7432,7 +7444,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/netcdf4-1.7.3-nompi_py312h947358d_100.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.0-py312ha003a3f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hbfb3c88_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openmpi-5.0.10-h899237b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.0-h5503f6c_0.conda @@ -7627,8 +7639,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.3-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-1.9.0-py312hf23773a_0_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-cpu-1.9.0-h718b53a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-1.10.0-cpu_mkl_py312_hd7bdcb3_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-cpu-1.10.0-h718b53a_100.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ffmpeg-8.0.1-gpl_hb3f9226_906.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fftw-3.3.10-mpi_mpich_h084ba78_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexcache-0.3-pyhd8ed1ab_1.conda @@ -7762,7 +7774,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.3-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfabric-2.4.0-ha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfabric1-2.4.0-h6c8fc0a_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libfaiss-1.9.0-h72e5a87_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libfaiss-1.10.0-cpu_openblas_hfcc2109_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h9ec8514_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libflac-1.5.0-he200343_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.1-ha770c72_0.conda @@ -7853,7 +7865,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzip-1.11.2-h6991a6a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-21.1.8-h4922eb0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/loguru-0.7.3-pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda @@ -7896,8 +7908,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.2.1-he2c55a7_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.0-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ocl-icd-2.3.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openblas-0.3.30-openmp_hd77311e_4.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/opencl-headers-2025.06.13-h5888daf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openh264-2.6.0-hc22cd8d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda @@ -8183,8 +8196,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/expat-2.7.3-haf25636_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-1.9.0-py312h423fd24_0_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-cpu-1.9.0-hd610c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-1.10.0-cpu_openblas_py312_hcaa93c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-cpu-1.10.0-hd610c6a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ffmpeg-8.0.1-gpl_hd70ab68_107.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fftw-3.3.10-mpi_openmpi_h83537c7_12.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexcache-0.3-pyhd8ed1ab_1.conda @@ -8308,7 +8321,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.3-haf25636_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfabric-2.4.0-hce30654_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfabric1-2.4.0-hc919400_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfaiss-1.9.0-h682f5e0_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfaiss-1.10.0-cpu_openblas_hcda87cf_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-he5f378a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.1-hce30654_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.14.1-h6da58f4_0.conda @@ -8414,7 +8427,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nlohmann_json-3.12.0-h248ca61_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.2.1-h5230ea7_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.0-py312ha003a3f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openblas-0.3.30-openmp_hea878ba_3.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openh264-2.6.0-hb5b2745_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hbfb3c88_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openldap-2.6.10-hbe55e7a_0.conda @@ -8804,7 +8818,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/netcdf4-1.7.4-nompi_py311ha0596eb_105.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.0-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openldap-2.6.10-hbde042b_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda @@ -8941,7 +8955,7 @@ environments: - https://pypi.org/simple packages: linux-64: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alabaster-1.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda @@ -9061,14 +9075,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.0.0-h0aef613_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libaec-1.1.5-h088129d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libamd-3.3.3-h456b2da_7100101.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_hc00574d_netlib.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-8_h4a7cf45_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbtf-2.3.2-hf02c80a_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcamd-3.3.3-hf02c80a_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcap-2.77-h3ff7636_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h8e06fc2_netlib.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-8_h0358290_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libccolamd-3.3.4-hf02c80a_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcholmod-5.3.1-h9cf07ce_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp22.1-22.1.0-default_h99862b1_0.conda @@ -9101,7 +9115,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libklu-2.3.5-h95ff59c_7100101.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-7_h8876d29_netlib.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-8_h47877c9_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.0-hf7376ad_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnetcdf-4.9.3-nompi_hbf2fc22_104.conda @@ -9109,6 +9123,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libnl-3.11.0-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libntlm-1.8-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-openmp_hd680484_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopengl-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.18-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpng-1.6.55-h421ea60_0.conda @@ -9139,6 +9154,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzip-1.11.2-h6991a6a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_1.conda @@ -9165,7 +9181,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/netcdf4-1.7.4-nompi_py312h25f8dc5_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.0-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openldap-2.6.10-hbde042b_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.6.1-h35e630c_1.conda @@ -9495,7 +9511,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/netcdf4-1.7.4-nompi_py312h5d59a02_102.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.0-py312ha003a3f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hd9e9057_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/overrides-7.7.0-pyhd8ed1ab_1.conda @@ -9616,7 +9632,7 @@ environments: - https://pypi.org/simple packages: linux-64: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/accessible-pygments-0.0.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.6.1-pyhd8ed1ab_0.conda @@ -9689,8 +9705,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.4-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-1.9.0-py312hf23773a_0_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-cpu-1.9.0-h718b53a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-1.10.0-cpu_mkl_py312_hd7bdcb3_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-cpu-1.10.0-h718b53a_100.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ffmpeg-8.0.1-gpl_hcddb375_914.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fftw-3.3.10-mpi_mpich_h084ba78_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexcache-0.3-pyhd8ed1ab_1.conda @@ -9798,7 +9814,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libaec-1.1.5-h088129d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libamd-3.3.3-h456b2da_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libass-0.17.4-h96ad9f0_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_hc00574d_netlib.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-8_h4a7cf45_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-1.88.0-hd24cca6_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-devel-1.88.0-hfcd1e18_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-headers-1.88.0-ha770c72_7.conda @@ -9808,7 +9824,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libbtf-2.3.2-hf02c80a_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcamd-3.3.3-hf02c80a_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcap-2.77-h3ff7636_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h8e06fc2_netlib.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-8_h0358290_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libccolamd-3.3.4-hf02c80a_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcholmod-5.3.1-h9cf07ce_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp22.1-22.1.0-default_h99862b1_0.conda @@ -9824,7 +9840,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfabric-2.4.0-ha770c72_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfabric1-2.4.0-h8f87c3e_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libfaiss-1.9.0-h72e5a87_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libfaiss-1.10.0-cpu_openblas_hfcc2109_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libflac-1.5.0-he200343_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.2-ha770c72_0.conda @@ -9848,7 +9864,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libjxl-0.11.2-ha09017c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libklu-2.3.5-h95ff59c_7100101.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-7_h8876d29_netlib.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-8_h47877c9_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm20-20.1.8-hf7376ad_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.0-hf7376ad_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda @@ -9859,6 +9875,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libntlm-1.8-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libogg-1.3.5-hd0c01bc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-openmp_hd680484_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopengl-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopengl-devel-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenvino-2026.0.0-hb56ce9e_1.conda @@ -9916,6 +9933,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzip-1.11.2-h6991a6a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/loguru-0.7.3-pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda @@ -9958,8 +9976,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.7.0-he4ff34a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.0-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ocl-icd-2.3.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openblas-0.3.33-openmp_hd77311e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/opencl-headers-2025.06.13-h5888daf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openh264-2.6.0-hc22cd8d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda @@ -10244,8 +10263,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/expat-2.7.4-hf6b4638_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-1.9.0-py312h423fd24_0_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-cpu-1.9.0-hd610c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-1.10.0-cpu_openblas_py312_hcaa93c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-cpu-1.10.0-hd610c6a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ffmpeg-8.0.1-gpl_ha5d8480_114.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fftw-3.3.10-mpi_mpich_h6eb47b5_11.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexcache-0.3-pyhd8ed1ab_1.conda @@ -10368,7 +10387,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.4-hf6b4638_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfabric-2.4.0-hce30654_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfabric1-2.4.0-h84a0fba_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfaiss-1.9.0-h682f5e0_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfaiss-1.10.0-cpu_openblas_hcda87cf_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.2-hce30654_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.14.2-hdfa99f5_0.conda @@ -10477,7 +10496,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nlohmann_json-3.12.0-h784d473_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.7.0-hbfc8e16_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.0-py312ha003a3f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openblas-0.3.30-openmp_hea878ba_4.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openh264-2.6.0-hb5b2745_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hd9e9057_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openldap-2.6.10-hf7f56bc_1.conda @@ -10668,7 +10688,7 @@ environments: - https://pypi.org/simple packages: linux-64: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/alabaster-1.0.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/alsa-lib-1.2.15.3-hb03c661_0.conda @@ -10788,14 +10808,14 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/lerc-4.0.0-h0aef613_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libaec-1.1.5-h088129d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libamd-3.3.3-h456b2da_7100101.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_hc00574d_netlib.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-8_h4a7cf45_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlicommon-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlidec-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbrotlienc-1.2.0-hb03c661_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libbtf-2.3.2-hf02c80a_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcamd-3.3.3-hf02c80a_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcap-2.77-h3ff7636_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h8e06fc2_netlib.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-8_h0358290_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libccolamd-3.3.4-hf02c80a_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcholmod-5.3.1-h9cf07ce_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp22.1-22.1.0-default_h99862b1_0.conda @@ -10829,7 +10849,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.18-h3b78370_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libklu-2.3.5-h95ff59c_7100101.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-7_h8876d29_netlib.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-8_h47877c9_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.0-hf7376ad_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnetcdf-4.9.3-nompi_hbf2fc22_104.conda @@ -10837,6 +10857,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libnl-3.11.0-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libntlm-1.8-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-openmp_hd680484_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopengl-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpciaccess-0.18-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libpmix-5.0.8-h9b03745_3.conda @@ -10868,6 +10889,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzip-1.11.2-h6991a6a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-4.0.0-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-3.0.3-py312h8a5da7c_1.conda @@ -10893,7 +10915,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-h2d0b736_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/netcdf4-1.7.4-nompi_py312h25f8dc5_102.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.0-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openldap-2.6.10-hbde042b_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openmpi-5.0.10-h611b0e2_0.conda @@ -11226,7 +11248,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h5e97a16_3.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/netcdf4-1.7.4-nompi_py312h5d59a02_102.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.0-py312ha003a3f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hd9e9057_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openmpi-5.0.10-h899237b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.6.1-hd24854e_1.conda @@ -11348,7 +11370,7 @@ environments: - https://pypi.org/simple packages: linux-64: - - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-7_kmp_llvm.conda - conda: https://conda.anaconda.org/conda-forge/noarch/_python_abi3_support-1.0-hd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/accessible-pygments-0.0.5-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/aiohappyeyeballs-2.6.1-pyhd8ed1ab_0.conda @@ -11421,8 +11443,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/expat-2.7.4-hecca717_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-1.9.0-py312hf23773a_0_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-cpu-1.9.0-h718b53a_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-1.10.0-cpu_mkl_py312_hd7bdcb3_100.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-cpu-1.10.0-h718b53a_100.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ffmpeg-8.0.1-gpl_hcddb375_914.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/fftw-3.3.10-mpi_openmpi_h76e6d66_12.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexcache-0.3-pyhd8ed1ab_1.conda @@ -11530,7 +11552,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libaec-1.1.5-h088129d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libamd-3.3.3-h456b2da_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libass-0.17.4-h96ad9f0_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_hc00574d_netlib.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-8_h4a7cf45_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-1.88.0-hd24cca6_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-devel-1.88.0-hfcd1e18_7.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libboost-headers-1.88.0-ha770c72_7.conda @@ -11540,7 +11562,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libbtf-2.3.2-hf02c80a_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcamd-3.3.3-hf02c80a_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcap-2.77-h3ff7636_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h8e06fc2_netlib.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-8_h0358290_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libccolamd-3.3.4-hf02c80a_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libcholmod-5.3.1-h9cf07ce_7100101.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libclang-cpp22.1-22.1.0-default_h99862b1_0.conda @@ -11557,7 +11579,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libexpat-2.7.4-hecca717_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfabric-2.4.0-ha770c72_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfabric1-2.4.0-h8f87c3e_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/libfaiss-1.9.0-h72e5a87_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libfaiss-1.10.0-cpu_openblas_hfcc2109_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libflac-1.5.0-he200343_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libfreetype-2.14.2-ha770c72_0.conda @@ -11581,7 +11603,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-3.1.2-hb03c661_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libjxl-0.11.2-ha09017c_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libklu-2.3.5-h95ff59c_7100101.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-7_h8876d29_netlib.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-8_h47877c9_openblas.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm20-20.1.8-hf7376ad_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libllvm22-22.1.0-hf7376ad_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/liblzma-5.8.2-hb03c661_0.conda @@ -11592,6 +11614,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libnsl-2.0.1-hb9d3cd8_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libntlm-1.8-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libogg-1.3.5-hd0c01bc_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-openmp_hd680484_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopengl-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopengl-devel-1.7.0-ha4b6fd6_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libopenvino-2026.0.0-hb56ce9e_1.conda @@ -11650,6 +11673,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzip-1.11.2-h6991a6a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/locket-1.0.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/loguru-0.7.3-pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda @@ -11691,8 +11715,9 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nodejs-25.7.0-he4ff34a_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.0-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ocl-icd-2.3.3-hb9d3cd8_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/openblas-0.3.33-openmp_hd77311e_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/opencl-headers-2025.06.13-h5888daf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openh264-2.6.0-hc22cd8d_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.4-h55fea9a_0.conda @@ -11979,8 +12004,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/execnet-2.1.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/executing-2.2.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/expat-2.7.4-hf6b4638_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-1.9.0-py312h423fd24_0_cpu.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-cpu-1.9.0-hd610c6a_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-1.10.0-cpu_openblas_py312_hcaa93c7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-cpu-1.10.0-hd610c6a_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ffmpeg-8.0.1-gpl_ha5d8480_114.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/fftw-3.3.10-mpi_openmpi_h83537c7_12.conda - conda: https://conda.anaconda.org/conda-forge/noarch/flexcache-0.3-pyhd8ed1ab_1.conda @@ -12104,7 +12129,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libexpat-2.7.4-hf6b4638_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfabric-2.4.0-hce30654_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfabric1-2.4.0-h84a0fba_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfaiss-1.9.0-h682f5e0_0_cpu.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfaiss-1.10.0-cpu_openblas_hcda87cf_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libffi-3.5.2-hcf2aa1b_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype-2.14.2-hce30654_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfreetype6-2.14.2-hdfa99f5_0.conda @@ -12213,7 +12238,8 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nlohmann_json-3.12.0-h784d473_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nodejs-25.7.0-hbfc8e16_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.0-py312ha003a3f_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openblas-0.3.30-openmp_hea878ba_4.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openh264-2.6.0-hb5b2745_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hd9e9057_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openldap-2.6.10-hf7f56bc_1.conda @@ -12674,7 +12700,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/libxslt-1.1.43-h711ed8c_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzip-1.11.2-h6991a6a_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/libzlib-1.3.1-hb9d3cd8_2.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-21.1.8-h4922eb0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/loguru-0.7.3-pyh707e725_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/lz4-c-1.10.0-h5888daf_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/markdown-it-py-3.0.0-pyhd8ed1ab_1.conda @@ -12709,7 +12735,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/netcdf4-1.7.3-nompi_py312hf6400b3_100.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/nlohmann_json-3.12.0-h54a6638_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.0-py312h33ff503_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ocl-icd-2.3.3-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/opencl-headers-2025.06.13-h5888daf_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openh264-2.6.0-hc22cd8d_0.conda @@ -13164,7 +13190,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/netcdf4-1.7.3-nompi_py312h947358d_100.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/nlohmann_json-3.12.0-h248ca61_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.0-py312ha003a3f_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openh264-2.6.0-hb5b2745_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openjpeg-2.5.4-hbfb3c88_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openldap-2.6.10-hbe55e7a_0.conda @@ -13325,13 +13351,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/a6/b0/a5c659d2b5180c037ff2304e459e0c142015de510ac68d4f100770c7d89d/gmsh-4.15.1-py2.py3-none-macosx_12_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/6e/67/9d4ac4b0d683aaa4170da59a1980740b281fd38fc253e1830fde4dac3d4f/pygmsh-7.1.17-py3-none-any.whl packages: -- conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 - sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726 - md5: d7c89558ba9fa0495403155b64376d81 - license: None - purls: [] - size: 2562 - timestamp: 1578324546067 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-20_gnu.conda build_number: 20 sha256: 1dd3fffd892081df9726d7eb7e0dea6198962ba775bd88842135a4ddb4deb3c9 @@ -13346,20 +13365,6 @@ packages: purls: [] size: 28948 timestamp: 1770939786096 -- conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 - build_number: 16 - sha256: fbe2c5e56a653bebb982eda4876a9178aedfc2b545f25d0ce9c4c0b508253d22 - md5: 73aaf86a425cc6e73fcf236a5a46396d - depends: - - _libgcc_mutex 0.1 conda_forge - - libgomp >=7.5.0 - constrains: - - openmp_impl 9999 - license: BSD-3-Clause - license_family: BSD - purls: [] - size: 23621 - timestamp: 1650670423406 - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-7_kmp_llvm.conda build_number: 7 sha256: c0cddb66070dd6355311f7667ce2acccf70d1013edaa6e97f22859502fefdb22 @@ -15769,70 +15774,72 @@ packages: purls: [] size: 132957 timestamp: 1771260052321 -- conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-1.9.0-py312hf23773a_0_cpu.conda - sha256: 4054eb28f6b9f9de9accdb31896935182ee7004478627ca42a2c8a7ca3bf2bd6 - md5: 491cf749a5f0afd80e9ee55eeced9029 +- conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-1.10.0-cpu_mkl_py312_hd7bdcb3_100.conda + sha256: 537be392afbbea8f1a708652cf44636801b3fcd6cea2a60d45524ad6e9a1293b + md5: 309de90db13801d06d3cb649ec3affed depends: - __glibc >=2.17,<3.0.a0 + - _openmp_mutex * *_llvm - _openmp_mutex >=4.5 - - libfaiss 1.9.0 *_cpu - - libgcc >=13 - - libstdcxx >=13 - - numpy >=1.26.4,<2.0a0 + - libfaiss 1.10.0.* cpu* + - libgcc >=14 + - libstdcxx >=14 + - llvm-openmp >=22.1.0 + - numpy >=1.23,<3 - packaging - python >=3.12,<3.13.0a0 - python_abi 3.12.* *_cp312 constrains: + - faiss-proc * cpu - faiss-gpu <0.0a0 - - faiss-proc =*=cpu license: MIT license_family: MIT purls: - pkg:pypi/faiss?source=hash-mapping - size: 1500631 - timestamp: 1734665823257 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-1.9.0-py312h423fd24_0_cpu.conda - sha256: d79d763bae39b68aa2ac62fb1d7b0a93b22ca47072d11bf074cf5fffc17869e5 - md5: 7b98a658056890986382b35913e7a723 + size: 1511476 + timestamp: 1773944045576 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-1.10.0-cpu_openblas_py312_hcaa93c7_0.conda + sha256: 7a2bd49e6135525321f0cbb9082b56bc43d9314d090611f26ec87c346c0e71c1 + md5: fc0c1d2747d66b7cdc61d8dfecb09cf0 depends: - __osx >=11.0 - - libcxx >=18 - - libfaiss 1.9.0 *_cpu - - llvm-openmp >=18.1.8 - - numpy >=1.26.4,<2.0a0 + - libcxx >=19 + - libfaiss 1.10.0.* cpu* + - llvm-openmp >=19.1.7 + - numpy >=1.23,<3 - packaging - python >=3.12,<3.13.0a0 - python >=3.12,<3.13.0a0 *_cpython - python_abi 3.12.* *_cp312 constrains: - faiss-gpu <0.0a0 - - faiss-proc =*=cpu + - faiss-proc * cpu license: MIT license_family: MIT purls: - pkg:pypi/faiss?source=hash-mapping - size: 1218618 - timestamp: 1734666078711 -- conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-cpu-1.9.0-h718b53a_0.conda - sha256: 977f57426553923c2cb3a4637b1357c5b071b311c60696d57ec4392a72e16233 - md5: 1b6350943cb03666539e1995fd45894d + size: 1300854 + timestamp: 1773945664366 +- conda: https://conda.anaconda.org/conda-forge/linux-64/faiss-cpu-1.10.0-h718b53a_100.conda + sha256: e66c118b1906407611b5e6f23b39317a5e215c50751d3d38ad60bec9b442cc3e + md5: 495edcaa46501eeaa10f2804dcdf9400 depends: - - faiss 1.9.0 *_cpu + - faiss 1.10.0.* cpu* license: MIT license_family: MIT purls: [] - size: 18216 - timestamp: 1734666100137 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-cpu-1.9.0-hd610c6a_0.conda - sha256: 6f8fbad673730de45381b6602ca1e02c3ad1cbdcff1df61107ae81b87bf6ceca - md5: c3dafc1d6ff23a6167045afabaacc411 + size: 17931 + timestamp: 1773944408955 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/faiss-cpu-1.10.0-hd610c6a_0.conda + sha256: 1519c59ecfd493e503b87c8dc6e76017234f2e6877363977183d5735f5a0de13 + md5: 4c36a5225fbb390c2d871c37d7029e6d depends: - - faiss 1.9.0 *_cpu + - faiss 1.10.0.* cpu* license: MIT license_family: MIT purls: [] - size: 18446 - timestamp: 1734666205997 + size: 18005 + timestamp: 1773945671352 - conda: https://conda.anaconda.org/conda-forge/linux-64/ffmpeg-8.0.1-gpl_hb3f9226_906.conda sha256: 7992f272a45d90731771b36db0acd3565f22ebc285829385262900e59f75db12 md5: 48787f2eab82ef1d90ccd9c24b64981e @@ -19320,25 +19327,24 @@ packages: purls: [] size: 18213 timestamp: 1765818813880 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-7_hc00574d_netlib.conda - build_number: 7 - sha256: 464608528e7b188fa3a602c503c7f73b3b446bbfd7b259d1c8b56470c34166fc - md5: bdc18b0a31b3141c6fc1b3bd9fa30fa4 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libblas-3.11.0-8_h4a7cf45_openblas.conda + build_number: 8 + sha256: b2da6bfd72a1c9cb143ccf64bf5b28790cb4eb58bd1cb978f6537b2322f7d48b + md5: 00fc660ab1b2f5ca07e92b4900d10c79 depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - libgfortran - - libgfortran5 >=14.3.0 + - libopenblas >=0.3.33,<0.3.34.0a0 + - libopenblas >=0.3.33,<1.0a0 constrains: - - blas * netlib - track_features: - - blas_netlib - - blas_netlib_2 + - blas 2.308 openblas + - mkl <2027 + - libcblas 3.11.0 8*_openblas + - liblapack 3.11.0 8*_openblas + - liblapacke 3.11.0 8*_openblas license: BSD-3-Clause license_family: BSD purls: [] - size: 222771 - timestamp: 1763440535188 + size: 18804 + timestamp: 1779859100675 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libblas-3.11.0-5_h51639a9_openblas.conda build_number: 5 sha256: 620a6278f194dcabc7962277da6835b1e968e46ad0c8e757736255f5ddbfca8d @@ -19649,24 +19655,21 @@ packages: purls: [] size: 18194 timestamp: 1765818837135 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-7_h8e06fc2_netlib.conda - build_number: 7 - sha256: 7940cc63673587cb7946831431b0527ce5707e24a54df87644c199e40c2714b4 - md5: 5febfe8ecc44ffab4f03b026fd63abb8 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libcblas-3.11.0-8_h0358290_openblas.conda + build_number: 8 + sha256: 1a2bc77bb26520255904a3d9b1f40e6bf0bf9d8d3405c7709dd162282820915a + md5: 33a413f1095f8325e5c30fde3b0d2445 depends: - - __glibc >=2.17,<3.0.a0 - - libblas 3.11.0.* - - libgcc >=14 - - libgfortran - - libgfortran5 >=14.3.0 - track_features: - - blas_netlib - - blas_netlib_2 + - libblas 3.11.0 8_h4a7cf45_openblas + constrains: + - blas 2.308 openblas + - liblapacke 3.11.0 8*_openblas + - liblapack 3.11.0 8*_openblas license: BSD-3-Clause license_family: BSD purls: [] - size: 50122 - timestamp: 1763440541127 + size: 18778 + timestamp: 1779859107964 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libcblas-3.11.0-5_hb0561ab_openblas.conda build_number: 5 sha256: 38809c361bbd165ecf83f7f05fae9b791e1baa11e4447367f38ae1327f402fc0 @@ -20263,39 +20266,43 @@ packages: purls: [] size: 330444 timestamp: 1765927087518 -- conda: https://conda.anaconda.org/conda-forge/linux-64/libfaiss-1.9.0-h72e5a87_0_cpu.conda - sha256: 1d8b64888a3d0ddcebd2f70ed90919c22ea31307b5d9d394c43f54180950e1bb - md5: 95069767db711a0e1e3df3237998c04d +- conda: https://conda.anaconda.org/conda-forge/linux-64/libfaiss-1.10.0-cpu_openblas_hfcc2109_0.conda + sha256: aa98ac39455e19dcb03a25a2164e1358a33041736e982683d468fb28f46d9ff0 + md5: d7a301d1c81e26a5ae22a204acdba865 depends: - __glibc >=2.17,<3.0.a0 + - _openmp_mutex * *_llvm - _openmp_mutex >=4.5 - - libblas >=3.9.0,<4.0a0 - - libgcc >=13 - - liblapack >=3.9.0,<4.0a0 - - libstdcxx >=13 + - libblas * *openblas + - libgcc >=14 + - libstdcxx >=14 + - llvm-openmp >=22.1.0 + - openblas constrains: + - faiss-proc * cpu - faiss-gpu <0.0a0 - - faiss-proc =*=cpu license: MIT license_family: MIT purls: [] - size: 1641914 - timestamp: 1734665536812 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfaiss-1.9.0-h682f5e0_0_cpu.conda - sha256: 962c99c09c3289d46bd4c69be884023af6b9818bdecbf4146e9a36931688f6e1 - md5: 3f9f51332a2b610c67ca75ed4eebff3f + size: 1677941 + timestamp: 1773943924093 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/libfaiss-1.10.0-cpu_openblas_hcda87cf_0.conda + sha256: aeb9ef778c5a45711e6f7ae3df6b1a3118b18fe80f52db2ddc3fcdcd5c71c2c1 + md5: 638acb4250e6818f5353085fffa9d313 depends: - __osx >=11.0 - - libcxx >=18 - - llvm-openmp >=18.1.8 + - libblas * *openblas + - libcxx >=19 + - llvm-openmp >=19.1.7 + - openblas constrains: - faiss-gpu <0.0a0 - - faiss-proc =*=cpu + - faiss-proc * cpu license: MIT license_family: MIT purls: [] - size: 1226909 - timestamp: 1734665696032 + size: 1227674 + timestamp: 1773944612289 - conda: https://conda.anaconda.org/conda-forge/linux-64/libffi-3.5.2-h3435931_0.conda sha256: 31f19b6a88ce40ebc0d5a992c131f57d919f73c0b92cd1617a5bec83f6e961e6 md5: a360c33a5abe61c07959e449fa1453eb @@ -20993,24 +21000,21 @@ packages: purls: [] size: 18200 timestamp: 1765818857876 -- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-7_h8876d29_netlib.conda - build_number: 7 - sha256: 4de5b6aef4b2d42b4f71c6a3673118f99e323aed2ba2a66a3ed435b574010b1e - md5: 3bb4c3696602a7d3a4243d165e8fd867 +- conda: https://conda.anaconda.org/conda-forge/linux-64/liblapack-3.11.0-8_h47877c9_openblas.conda + build_number: 8 + sha256: 168e327d737059553e15cc6ec36d76b9bbb3931c2a7721555fd68b4c9348b247 + md5: 809be8ba8712c77bc7d44c2d99390dc4 depends: - - __glibc >=2.17,<3.0.a0 - - libblas 3.11.0.* - - libgcc >=14 - - libgfortran - - libgfortran5 >=14.3.0 - track_features: - - blas_netlib - - blas_netlib_2 + - libblas 3.11.0 8_h4a7cf45_openblas + constrains: + - blas 2.308 openblas + - libcblas 3.11.0 8*_openblas + - liblapacke 3.11.0 8*_openblas license: BSD-3-Clause license_family: BSD purls: [] - size: 2901209 - timestamp: 1763440547062 + size: 18790 + timestamp: 1779859115086 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/liblapack-3.11.0-5_hd9741b5_openblas.conda build_number: 5 sha256: 735a6e6f7d7da6f718b6690b7c0a8ae4815afb89138aa5793abe78128e951dbb @@ -21506,6 +21510,26 @@ packages: purls: [] size: 5927939 timestamp: 1763114673331 +- conda: https://conda.anaconda.org/conda-forge/linux-64/libopenblas-0.3.33-openmp_hd680484_0.conda + sha256: f046726a8d8fcbaf350b5bd053add16c99abff0c47326c9c6c26ae188668725b + md5: 1c1c23660b30e79955cdcc9ac039b646 + depends: + - __glibc >=2.17,<3.0.a0 + - _openmp_mutex * *_llvm + - _openmp_mutex >=4.5 + - libgcc >=14 + - libgfortran + - libgfortran5 >=14.3.0 + - llvm-openmp >=22.1.4 + constrains: + - openblas >=0.3.33,<0.3.34.0a0 + track_features: + - openblas_threading_openmp + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 5949782 + timestamp: 1776993684707 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/libopenblas-0.3.30-openmp_ha158390_3.conda sha256: dcc626c7103503d1dfc0371687ad553cb948b8ed0249c2a721147bdeb8db4a73 md5: a18a7f471c517062ee71b843ef95eb8a @@ -23569,19 +23593,19 @@ packages: purls: [] size: 46438 timestamp: 1727963202283 -- conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-21.1.8-h4922eb0_0.conda - sha256: a5a7ad16eecbe35cac63e529ea9c261bef4ccdd68cb1db247409f04529423989 - md5: f8640b709b37dc7758ddce45ea18d000 +- conda: https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-22.1.8-h4922eb0_0.conda + sha256: a37aba21b85800af1e7c5b04ba76abab96b6e591eedf99dc6e4df83b0fefd7a5 + md5: 7bbfdc5a6eca997d3b0873a575c3e155 depends: - __glibc >=2.17,<3.0.a0 constrains: - intel-openmp <0.0a0 - - openmp 21.1.8|21.1.8.* + - openmp 22.1.8|22.1.8.* license: Apache-2.0 WITH LLVM-exception license_family: APACHE purls: [] - size: 6127279 - timestamp: 1765964409311 + size: 6123597 + timestamp: 1781736521736 - conda: https://conda.anaconda.org/conda-forge/osx-arm64/llvm-openmp-21.1.8-h4a912ad_0.conda sha256: 56bcd20a0a44ddd143b6ce605700fdf876bcf5c509adc50bf27e76673407a070 md5: 206ad2df1b5550526e386087bef543c7 @@ -25127,44 +25151,45 @@ packages: - pkg:pypi/notebook-shim?source=hash-mapping size: 16817 timestamp: 1733408419340 -- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.26.4-py312heda63a1_0.conda - sha256: fe3459c75cf84dcef6ef14efcc4adb0ade66038ddd27cadb894f34f4797687d8 - md5: d8285bea2a350f63fab23bf460221f3f +- conda: https://conda.anaconda.org/conda-forge/linux-64/numpy-2.5.0-py312h33ff503_0.conda + sha256: c8d5f70715fc6cd3dcd16fdd11b51879ed4484963f066b33fbaf20c4ffb153af + md5: 24f70d3db040fc69ee72cc38e55bc8e3 depends: - - libblas >=3.9.0,<4.0a0 + - python + - libgcc >=14 + - libstdcxx >=14 + - __glibc >=2.17,<3.0.a0 + - python_abi 3.12.* *_cp312 - libcblas >=3.9.0,<4.0a0 - - libgcc-ng >=12 - liblapack >=3.9.0,<4.0a0 - - libstdcxx-ng >=12 - - python >=3.12,<3.13.0a0 - - python_abi 3.12.* *_cp312 + - libblas >=3.9.0,<4.0a0 constrains: - numpy-base <0a0 license: BSD-3-Clause license_family: BSD purls: - - pkg:pypi/numpy?source=hash-mapping - size: 7484186 - timestamp: 1707225809722 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-1.26.4-py312h8442bc7_0.conda - sha256: c8841d6d6f61fd70ca80682efbab6bdb8606dc77c68d8acabfbd7c222054f518 - md5: d83fc83d589e2625a3451c9a7e21047c + - pkg:pypi/numpy?source=compressed-mapping + size: 8911732 + timestamp: 1782112536981 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/numpy-2.5.0-py312ha003a3f_0.conda + sha256: 36f7062ce484ce45b8fdb2ee48cbbc7c0023004ba01e692efd5cd70034d93609 + md5: f223ea9a1ca019ddbcfe28ce02ec366c depends: - - libblas >=3.9.0,<4.0a0 + - python + - libcxx >=19 + - __osx >=11.0 - libcblas >=3.9.0,<4.0a0 - - libcxx >=16 - liblapack >=3.9.0,<4.0a0 - - python >=3.12,<3.13.0a0 - - python >=3.12,<3.13.0a0 *_cpython - python_abi 3.12.* *_cp312 + - libblas >=3.9.0,<4.0a0 constrains: - numpy-base <0a0 license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/numpy?source=hash-mapping - size: 6073136 - timestamp: 1707226249608 + size: 6964084 + timestamp: 1782112554625 - conda: https://conda.anaconda.org/conda-forge/linux-64/ocl-icd-2.3.3-hb9d3cd8_0.conda sha256: 2254dae821b286fb57c61895f2b40e3571a070910fdab79a948ff703e1ea807b md5: 56f8947aa9d5cf37b0b3d43b83f34192 @@ -25177,6 +25202,60 @@ packages: purls: [] size: 106742 timestamp: 1743700382939 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openblas-0.3.30-openmp_hd77311e_4.conda + sha256: df796e5e6f32d2b3132528114b695cf9038d62edbb5d38498a76c6dbf638de4f + md5: 525e2455ed342f2aef93c59ac5db2e28 + depends: + - libopenblas 0.3.30 openmp_hd680484_4 + track_features: + - openblas_threading_openmp + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6055815 + timestamp: 1763114810577 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openblas-0.3.30-pthreads_h6ec200e_4.conda + sha256: c2451f69728b318a1558db14f7a55a6ddec951340a752b09e008a7f7b02854eb + md5: 379ec5261b0b8fc54f2e7bd055360b0c + depends: + - libopenblas 0.3.30 pthreads_h94d23a6_4 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6044349 + timestamp: 1763114684496 +- conda: https://conda.anaconda.org/conda-forge/linux-64/openblas-0.3.33-openmp_hd77311e_0.conda + sha256: 7f60393f865771840c6822e970216513f3d78940f3fe303c15365586c0cd3c0e + md5: 82fd8ac93bdd598ec1f327cfefbd65ca + depends: + - libopenblas 0.3.33 openmp_hd680484_0 + track_features: + - openblas_threading_openmp + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 6072188 + timestamp: 1776993694424 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openblas-0.3.30-openmp_hea878ba_3.conda + sha256: 93ada5bf3cd776da4a3c5428f939e31e3af653033bf15501bb60929155d87dc8 + md5: e2ac7faef48fe36f7eca79b0ee0d9a05 + depends: + - libopenblas 0.3.30 openmp_ha158390_3 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 3147047 + timestamp: 1761749519013 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/openblas-0.3.30-openmp_hea878ba_4.conda + sha256: e8308ec73dd6a745afebc3d53d57474fc8209fdd690edfa7fdbe318e7423b0d0 + md5: 5ddea21df4fed5b5830aeb402efbe036 + depends: + - libopenblas 0.3.30 openmp_ha158390_4 + license: BSD-3-Clause + license_family: BSD + purls: [] + size: 3144413 + timestamp: 1768547084685 - conda: https://conda.anaconda.org/conda-forge/linux-64/opencl-headers-2025.06.13-h5888daf_0.conda sha256: 2b6ce54174ec19110e1b3c37455f7cd138d0e228a75727a9bba443427da30a36 md5: 45c3d2c224002d6d0d7769142b29f986 diff --git a/pixi.toml b/pixi.toml index e2436c07e..b767642b1 100644 --- a/pixi.toml +++ b/pixi.toml @@ -68,7 +68,7 @@ python = "3.12.*" # Build requirements cython = ">=3.1,<4" -numpy = "<2" +numpy = ">=2" pip = ">=25,<26" setuptools = ">=75,<76" compilers = "*" diff --git a/src/underworld3/discretisation/discretisation_mesh.py b/src/underworld3/discretisation/discretisation_mesh.py index 7628e5034..2362bf2a8 100644 --- a/src/underworld3/discretisation/discretisation_mesh.py +++ b/src/underworld3/discretisation/discretisation_mesh.py @@ -1276,8 +1276,11 @@ def _reduce(val, op): a = np.linalg.norm(v1 - v2, axis=1) b = np.linalg.norm(v2 - v0, axis=1) cl_ = np.linalg.norm(v0 - v1, axis=1) - A = np.maximum( - 0.5 * np.abs(np.cross(v1 - v0, v2 - v0)), 1.0e-300) + # 2-D triangle area from the z-component of the edge cross product + # (numpy 2.0 removed the 2-D np.cross that returned this scalar). + _e1, _e2 = v1 - v0, v2 - v0 + _cross_z = _e1[:, 0] * _e2[:, 1] - _e1[:, 1] * _e2[:, 0] + A = np.maximum(0.5 * np.abs(_cross_z), 1.0e-300) q = 4.0 * np.sqrt(3.0) * A / (a * a + b * b + cl_ * cl_) def _ang(o, p, r): diff --git a/src/underworld3/discretisation/discretisation_mesh_variables.py b/src/underworld3/discretisation/discretisation_mesh_variables.py index e79e2c09b..aadc1e400 100644 --- a/src/underworld3/discretisation/discretisation_mesh_variables.py +++ b/src/underworld3/discretisation/discretisation_mesh_variables.py @@ -1343,8 +1343,8 @@ def read_timestep( -1, n_components ) else: - X_src = np.empty((0, dim), dtype=np.double) - D_src = np.empty((0, n_components), dtype=np.double) + X_src = np.empty((0, dim), dtype=np.float64) + D_src = np.empty((0, n_components), dtype=np.float64) src_size_before = max(source_swarm.dm.getLocalSize(), 0) source_swarm.add_particles_with_global_coordinates(X_src, migrate=False) @@ -1424,7 +1424,7 @@ def read_timestep( # Reorder by original_index and write into self.data idx = origin_index_var.array[:, 0, 0] - out = np.zeros((n_query_local, n_components), dtype=np.double) + out = np.zeros((n_query_local, n_components), dtype=np.float64) out[idx, :] = result.array[:, 0, :] self.data[...] = out @@ -2267,9 +2267,17 @@ def __repr__(self): units_str = f", units='{self.units}'" if self.units else "" return f"SimpleMeshArrayView(shape={self.shape}, dtype={self.dtype}{units_str})" - def __array__(self): - """Support for numpy functions like np.allclose(), np.isfinite(), etc.""" - return self._get_array_data() + def __array__(self, dtype=None, copy=None): + """Support for numpy functions like np.allclose(), np.isfinite(), etc. + + numpy 2.0 calls __array__ with dtype/copy keywords; honour them. + """ + arr = self._get_array_data() + if dtype is not None: + arr = arr.astype(dtype, copy=bool(copy)) + elif copy: + arr = arr.copy() + return arr def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): """Support for numpy universal functions""" @@ -2576,9 +2584,17 @@ def __repr__(self): units_str = f", units='{self.units}'" if self.units else "" return f"TensorMeshArrayView(shape={self.shape}, dtype={self.dtype}{units_str})" - def __array__(self): - """Support for numpy functions like np.allclose(), np.isfinite(), etc.""" - return self._get_array_data() + def __array__(self, dtype=None, copy=None): + """Support for numpy functions like np.allclose(), np.isfinite(), etc. + + numpy 2.0 calls __array__ with dtype/copy keywords; honour them. + """ + arr = self._get_array_data() + if dtype is not None: + arr = arr.astype(dtype, copy=bool(copy)) + elif copy: + arr = arr.copy() + return arr def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): """Support for numpy universal functions""" diff --git a/src/underworld3/function/_function.pyx b/src/underworld3/function/_function.pyx index 96eb230bd..ec2aaeebb 100644 --- a/src/underworld3/function/_function.pyx +++ b/src/underworld3/function/_function.pyx @@ -415,7 +415,7 @@ def global_evaluate_nd( expr, # Python wrapper in functions_unit_system.py handles dimensional conversions # CRITICAL: Use np.array() to force copy and strip subclass (e.g. UnitAwareArray) # np.asarray() preserves subclass if dtype matches, causing downstream issues - coords_array = np.array(coords, dtype=np.double, copy=False).view(np.ndarray) + coords_array = np.array(coords, dtype=np.float64, copy=False).view(np.ndarray) mesh, varfns, derivfns = uw.function.expressions.mesh_vars_in_expression(expr) @@ -527,7 +527,7 @@ def global_evaluate_nd( expr, # Pre-allocate with NaN so the shape is always correct. If any points # are lost during the migration round-trip, they remain NaN rather than # causing a shape mismatch or returning uninitialised data. - return_value = np.full((n_input_points,) + expr_shape, np.nan, dtype=np.double) + return_value = np.full((n_input_points,) + expr_shape, np.nan, dtype=np.float64) return_mask = np.full((n_input_points, 1, 1), True, dtype=bool) n_returned = original_index.array.shape[0] @@ -590,7 +590,7 @@ def global_evaluate_nd( expr, comm = uw.mpi.comm ext_idx = np.where(return_mask[:, 0, 0])[0] - ext_coords = np.ascontiguousarray(coords_array[ext_idx], dtype=np.double) + ext_coords = np.ascontiguousarray(coords_array[ext_idx], dtype=np.float64) counts = np.array(comm.allgather(ext_coords.shape[0]), dtype=int) n_ext_total = int(counts.sum()) @@ -606,16 +606,16 @@ def global_evaluate_nd( expr, expr, all_ext, rbf=True, evalf=False, verbose=False, check_extrapolated=True,) ext_vals = np.ascontiguousarray( - np.asarray(ext_vals, dtype=np.double).reshape((n_ext_total,) + expr_shape)) + np.asarray(ext_vals, dtype=np.float64).reshape((n_ext_total,) + expr_shape)) ext_flag = np.asarray(ext_flag).reshape(n_ext_total).astype(np.int32) # Nearest-local-cell distance for every point (local kd-tree query). mesh._build_kd_tree_index() dist2, _ = mesh._centroid_index.query(all_ext, k=1, sqr_dists=True) - dist2 = np.ascontiguousarray(np.asarray(dist2, dtype=np.double).ravel()) + dist2 = np.ascontiguousarray(np.asarray(dist2, dtype=np.float64).ravel()) # Globally-nearest cell per point, lowest rank as the tie-break. - min_dist2 = np.empty(n_ext_total, dtype=np.double) + min_dist2 = np.empty(n_ext_total, dtype=np.float64) comm.Allreduce([dist2, MPI.DOUBLE], [min_dist2, MPI.DOUBLE], op=MPI.MIN) my_claim = np.where(dist2 <= min_dist2 * (1.0 + 1e-12) + 1e-300, comm.rank, comm.size).astype(np.int32) @@ -941,7 +941,7 @@ def evaluate_nd( expr, # Python wrapper in functions_unit_system.py handles dimensional conversions # CRITICAL: Use np.array() to force copy and strip subclass (e.g. UnitAwareArray) # np.asarray() preserves subclass if dtype matches, causing downstream issues - coords_array = np.array(coords, dtype=np.double, copy=False).view(np.ndarray) + coords_array = np.array(coords, dtype=np.float64, copy=False).view(np.ndarray) dim = coords_array.shape[1] mesh, varfns, derivfns = uw.function.fn_mesh_vars_in_expression(expr) @@ -1153,7 +1153,7 @@ def petsc_interpolate( expr, "Note also that it is inefficient to call this function for a single evaluation,\n" "and you should instead stack up all necessary evaluations into your `coords` array\n" "and call this function once.") - if coords.dtype != np.double: + if coords.dtype != np.float64: raise ValueError("Provided `coords` must be an array of doubles.") if other_arguments: raise RuntimeError("`other_arguments` functionality not yet implemented.") @@ -1275,7 +1275,7 @@ def petsc_interpolate( expr, cached_info = mesh._dminterpolation_cache.get_structure(coords, dofcount) # Create output array - cdef np.ndarray outarray = np.empty([len(coords), dofcount], dtype=np.double) + cdef np.ndarray outarray = np.empty([len(coords), dofcount], dtype=np.float64) if cached_info is not None: # CACHE HIT - Fast path. Evaluate using cached structure @@ -1439,7 +1439,7 @@ def rbf_evaluate( expr, "Note also that it is inefficient to call this function for a single evaluation,\n" "and you should instead stack up all necessary evaluations into your `coords` array\n" "and call this function once.") - if coords.dtype != np.double: + if coords.dtype != np.float64: raise ValueError("Provided `coords` must be an array of doubles.") if other_arguments: raise RuntimeError("`other_arguments` functionality not yet implemented.") diff --git a/src/underworld3/function/functions_unit_system.py b/src/underworld3/function/functions_unit_system.py index 914ed70b5..c43af05b8 100644 --- a/src/underworld3/function/functions_unit_system.py +++ b/src/underworld3/function/functions_unit_system.py @@ -197,18 +197,18 @@ def _evaluate_impl( # Convert coordinates if isinstance(coords, UnitAwareArray): coords_nondim = uw.non_dimensionalise(coords) - coords_for_eval = np.asarray(coords_nondim, dtype=np.double) + coords_for_eval = np.asarray(coords_nondim, dtype=np.float64) elif isinstance(coords, UWQuantity): coords_nondim = uw.non_dimensionalise(coords) if hasattr(coords_nondim, 'value'): - coords_for_eval = np.asarray(coords_nondim.value, dtype=np.double) + coords_for_eval = np.asarray(coords_nondim.value, dtype=np.float64) else: - coords_for_eval = np.asarray(coords_nondim, dtype=np.double) + coords_for_eval = np.asarray(coords_nondim, dtype=np.float64) elif isinstance(coords, np.ndarray): - coords_for_eval = np.asarray(coords, dtype=np.double) + coords_for_eval = np.asarray(coords, dtype=np.float64) else: coords_nondim = uw.non_dimensionalise(coords) - coords_for_eval = np.asarray(coords_nondim, dtype=np.double) + coords_for_eval = np.asarray(coords_nondim, dtype=np.float64) # Evaluate using optimized lambdification raw_values = evaluate_pure_sympy(expr_unwrapped, coords_for_eval) @@ -292,21 +292,21 @@ def _evaluate_impl( if isinstance(coords, UnitAwareArray): # Unit-aware array - need to non-dimensionalise coords_nondim = uw.non_dimensionalise(coords) - coords_for_eval = np.asarray(coords_nondim, dtype=np.double) + coords_for_eval = np.asarray(coords_nondim, dtype=np.float64) elif isinstance(coords, UWQuantity): # UWQuantity from arithmetic operations (e.g., coords - dt * velocity) coords_nondim = uw.non_dimensionalise(coords) if hasattr(coords_nondim, 'value'): - coords_for_eval = np.asarray(coords_nondim.value, dtype=np.double) + coords_for_eval = np.asarray(coords_nondim.value, dtype=np.float64) else: - coords_for_eval = np.asarray(coords_nondim, dtype=np.double) + coords_for_eval = np.asarray(coords_nondim, dtype=np.float64) elif isinstance(coords, np.ndarray): # Plain numpy array - assume it's already [0-1] non-dimensional - coords_for_eval = np.asarray(coords, dtype=np.double) + coords_for_eval = np.asarray(coords, dtype=np.float64) else: # Other type - try to non-dimensionalise coords_nondim = uw.non_dimensionalise(coords) - coords_for_eval = np.asarray(coords_nondim, dtype=np.double) + coords_for_eval = np.asarray(coords_nondim, dtype=np.float64) # Ensure coordinates are 2D: shape (N, ndim) not (ndim,) # This handles single coordinate evaluation: coords[60] -> shape (2,) -> (1, 2) @@ -489,18 +489,18 @@ def _global_evaluate_impl( # Convert coordinates if isinstance(coords, UnitAwareArray): coords_nondim = uw.non_dimensionalise(coords) - coords_for_eval = np.asarray(coords_nondim, dtype=np.double) + coords_for_eval = np.asarray(coords_nondim, dtype=np.float64) elif isinstance(coords, UWQuantity): coords_nondim = uw.non_dimensionalise(coords) if hasattr(coords_nondim, 'value'): - coords_for_eval = np.asarray(coords_nondim.value, dtype=np.double) + coords_for_eval = np.asarray(coords_nondim.value, dtype=np.float64) else: - coords_for_eval = np.asarray(coords_nondim, dtype=np.double) + coords_for_eval = np.asarray(coords_nondim, dtype=np.float64) elif isinstance(coords, np.ndarray): - coords_for_eval = np.asarray(coords, dtype=np.double) + coords_for_eval = np.asarray(coords, dtype=np.float64) else: coords_nondim = uw.non_dimensionalise(coords) - coords_for_eval = np.asarray(coords_nondim, dtype=np.double) + coords_for_eval = np.asarray(coords_nondim, dtype=np.float64) # Evaluate using optimized lambdification raw_result = evaluate_pure_sympy(expr, coords_for_eval) @@ -524,18 +524,18 @@ def _global_evaluate_impl( if isinstance(coords, UnitAwareArray): # Extract base array and non-dimensionalize if needed coords_nondim = uw.non_dimensionalise(coords) - coords_for_cython = np.asarray(coords_nondim, dtype=np.double) + coords_for_cython = np.asarray(coords_nondim, dtype=np.float64) elif isinstance(coords, UWQuantity): # UWQuantity from arithmetic operations (e.g., coords - dt * velocity) # Extract the underlying value and non-dimensionalize coords_nondim = uw.non_dimensionalise(coords) # coords_nondim might be a scalar or array - ensure it's an array if hasattr(coords_nondim, 'value'): - coords_for_cython = np.asarray(coords_nondim.value, dtype=np.double) + coords_for_cython = np.asarray(coords_nondim.value, dtype=np.float64) else: - coords_for_cython = np.asarray(coords_nondim, dtype=np.double) + coords_for_cython = np.asarray(coords_nondim, dtype=np.float64) elif isinstance(coords, np.ndarray): - coords_for_cython = np.asarray(coords, dtype=np.double) + coords_for_cython = np.asarray(coords, dtype=np.float64) else: coords_for_cython = coords else: diff --git a/src/underworld3/function/pure_sympy_evaluator.py b/src/underworld3/function/pure_sympy_evaluator.py index 3699563c3..fa7764412 100644 --- a/src/underworld3/function/pure_sympy_evaluator.py +++ b/src/underworld3/function/pure_sympy_evaluator.py @@ -256,7 +256,7 @@ def evaluate_pure_sympy(expr, coords, coord_symbols=None): - ~10,000x faster than sympy.subs() for many points """ # Ensure coords is 2D numpy array - coords_array = np.asarray(coords, dtype=np.double) + coords_array = np.asarray(coords, dtype=np.float64) if coords_array.ndim == 1: coords_array = coords_array.reshape(1, -1) diff --git a/src/underworld3/function/unit_conversion.py b/src/underworld3/function/unit_conversion.py index 322eb0f6f..e3effb256 100644 --- a/src/underworld3/function/unit_conversion.py +++ b/src/underworld3/function/unit_conversion.py @@ -1018,7 +1018,7 @@ def _convert_coords_to_si(coords): - lists/tuples of coordinates (each coordinate can be UWQuantity, Pint Quantity, or float/int) - lists/tuples of tuples (for multiple points) - Returns numpy array of shape (n_points, n_dims) with dtype=np.double in model coordinates. + Returns numpy array of shape (n_points, n_dims) with dtype=np.float64 in model coordinates. """ import pint @@ -1047,10 +1047,10 @@ def convert_single_coord(coord): # If already numpy array with correct dtype, assume it's in model coordinates if isinstance(coords, np.ndarray): - if coords.dtype == np.double: + if coords.dtype == np.float64: return coords else: - return np.array(coords, dtype=np.double) + return np.array(coords, dtype=np.float64) # Convert list/tuple input if isinstance(coords, (list, tuple)): @@ -1067,7 +1067,7 @@ def convert_single_coord(coord): model_value = convert_single_coord(coord) model_point.append(model_value) model_coords.append(model_point) - return np.array(model_coords, dtype=np.double) + return np.array(model_coords, dtype=np.float64) else: # Flat list of coordinates - could be single point [x, y] or [x, y, z] # Check if all elements are coordinate values (not lists/tuples) @@ -1083,7 +1083,7 @@ def convert_single_coord(coord): model_value = convert_single_coord(coord) model_point.append(model_value) # Return as 2D array with single point - return np.array([model_point], dtype=np.double) + return np.array([model_point], dtype=np.float64) else: raise TypeError(f"Unable to parse coordinate format. Expected list of tuples like " f"[(x1,y1), (x2,y2)] or single point like [x, y].") diff --git a/src/underworld3/meshing/smoothing.py b/src/underworld3/meshing/smoothing.py index 4163c45e7..aed82e746 100644 --- a/src/underworld3/meshing/smoothing.py +++ b/src/underworld3/meshing/smoothing.py @@ -561,7 +561,7 @@ def _winslow_spring(mesh, metric, pinned_labels, verbose, if edges.shape[0] == 0: return deg = np.bincount( - edges.ravel(), minlength=n_verts).astype(np.double) + edges.ravel(), minlength=n_verts).astype(np.float64) deg[deg == 0.0] = 1.0 _SPRING_CACHE[key] = (edges, deg) else: @@ -572,7 +572,7 @@ def _winslow_spring(mesh, metric, pinned_labels, verbose, v0 = edges[:, 0] v1 = edges[:, 1] - coords = np.asarray(mesh.X.coords, dtype=np.double).copy() + coords = np.asarray(mesh.X.coords, dtype=np.float64).copy() # Boundary tangential slip via the mesh-owned contract # (boundary-slip-strategy.md): each slip vertex slides tangentially and @@ -1052,7 +1052,7 @@ def _patch_volumes(tris, coords, n_verts, vol_field=None): if vol_field is not None and uw.mpi.size > 1: return _lumped_vertex_volumes(vol_field) area = np.abs(_signed_areas(coords, tris)) / 3.0 - patch = np.zeros(n_verts, dtype=np.double) + patch = np.zeros(n_verts, dtype=np.float64) for k in range(3): np.add.at(patch, tris[:, k], area) patch[patch <= 0.0] = patch[patch > 0.0].mean() @@ -1291,7 +1291,7 @@ def _wire(s, singular=False, elliptic=True): patch = _patch_volumes(tris, old_coords, n_verts, vol_field) patch /= float(np.mean(patch)) else: - patch = np.ones(n_verts, dtype=np.double) + patch = np.ones(n_verts, dtype=np.float64) _va = vol_field.array _va[...] = patch.reshape(_va.shape) @@ -1603,7 +1603,7 @@ def _wire(s, singular=False, elliptic=True): # --- compute V (patch volumes) on current mesh --------- if tris is None: - patch = np.ones(n_verts, dtype=np.double) + patch = np.ones(n_verts, dtype=np.float64) else: patch = _patch_volumes(tris, old_coords, n_verts, vol_field) # Normalise so the mean over the domain is the cell mean. @@ -3135,7 +3135,7 @@ def _dM_dx(cen): vloc = coord_dm.getLocalVec() vglob = coord_dm.getGlobalVec() - coords = np.asarray(local_vec.array, dtype=np.double).reshape(-1, cdim).copy() + coords = np.asarray(local_vec.array, dtype=np.float64).reshape(-1, cdim).copy() # Fixed computational reference = coords at first call, cached on mesh # (ghosted: this rank's local array including halo). @@ -3698,11 +3698,11 @@ def _smooth_mesh_interior_bare( parallel = uw.mpi.size > 1 coords = np.asarray( - local_vec.array, dtype=np.double).reshape(-1, cdim).copy() + local_vec.array, dtype=np.float64).reshape(-1, cdim).copy() for sweep in range(n_iters): new_int = np.empty((int_owned_local.shape[0], cdim), - dtype=np.double) + dtype=np.float64) # For each coordinate component, do A @ coord_comp (PETSc # handles cross-rank communication), then divide by degree # to get the per-vertex neighbour average. diff --git a/src/underworld3/swarm.py b/src/underworld3/swarm.py index 527411482..5b159944d 100644 --- a/src/underworld3/swarm.py +++ b/src/underworld3/swarm.py @@ -713,9 +713,17 @@ def shape(self): def dtype(self): return self._get_array_data().dtype - def __array__(self): - """Support for numpy functions like np.allclose(), np.isfinite(), etc.""" - return self._get_array_data() + def __array__(self, dtype=None, copy=None): + """Support for numpy functions like np.allclose(), np.isfinite(), etc. + + numpy 2.0 calls __array__ with dtype/copy keywords; honour them. + """ + arr = self._get_array_data() + if dtype is not None: + arr = arr.astype(dtype, copy=bool(copy)) + elif copy: + arr = arr.copy() + return arr def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): """Support for numpy universal functions""" @@ -920,9 +928,17 @@ def shape(self): def dtype(self): return self._get_array_data().dtype - def __array__(self): - """Support for numpy functions like np.allclose(), np.isfinite(), etc.""" - return self._get_array_data() + def __array__(self, dtype=None, copy=None): + """Support for numpy functions like np.allclose(), np.isfinite(), etc. + + numpy 2.0 calls __array__ with dtype/copy keywords; honour them. + """ + arr = self._get_array_data() + if dtype is not None: + arr = arr.astype(dtype, copy=bool(copy)) + elif copy: + arr = arr.copy() + return arr def __array_ufunc__(self, ufunc, method, *inputs, **kwargs): """Support for numpy universal functions""" @@ -2027,8 +2043,8 @@ def read_timestep( X_chunk = h5f_swarm["coordinates"][()].reshape(-1, dim) D_chunk = h5f_data["data"][()].reshape(-1, n_components) else: - X_chunk = np.empty((0, dim), dtype=np.double) - D_chunk = np.empty((0, n_components), dtype=np.double) + X_chunk = np.empty((0, dim), dtype=np.float64) + D_chunk = np.empty((0, n_components), dtype=np.float64) tmp_swarm = uw.swarm.Swarm(self.swarm.mesh) saved = SwarmVariable( diff --git a/src/underworld3/utilities/nd_array_callback.py b/src/underworld3/utilities/nd_array_callback.py index fc5ba488d..5ce1b0867 100644 --- a/src/underworld3/utilities/nd_array_callback.py +++ b/src/underworld3/utilities/nd_array_callback.py @@ -267,11 +267,18 @@ def __array_wrap__(self, result, context=None, return_scalar=False): # Use numpy's view to avoid recursion try: self_as_ndarray = np.ndarray.view(self, np.ndarray) + # NB: require a NON-None shared base for the base-equality branch. + # A fresh ufunc result (e.g. scalar * arr) has base=None; if self + # also owns its data (base=None) then `result.base is self.base` + # is `None is None` == True, which under numpy 2.0's ufunc dispatch + # wrongly returned `self` and dropped the operation (scalar * arr == + # arr). Only a genuine in-place/view result shares a non-None base. if result is self_as_ndarray or ( - hasattr(result, "base") and hasattr(self, "base") and result.base is self.base + self.base is not None + and getattr(result, "base", None) is self.base ): return self - except: + except Exception: # If view comparison fails, fall back to simple check pass diff --git a/src/underworld3/utilities/unit_aware_array.py b/src/underworld3/utilities/unit_aware_array.py index bef1d283d..3304ff96c 100644 --- a/src/underworld3/utilities/unit_aware_array.py +++ b/src/underworld3/utilities/unit_aware_array.py @@ -1441,7 +1441,7 @@ def cross_impl(a, b, *args, **kwargs): b_units = getattr(b, "_units", None) # Compute cross product using numpy's default behavior - result = np.core.numeric.cross(np.asarray(a), np.asarray(b), *args, **kwargs) + result = np.cross(np.asarray(a), np.asarray(b), *args, **kwargs) # Determine result units if a_units is not None and b_units is not None: @@ -1472,7 +1472,7 @@ def dot_impl(a, b, *args, **kwargs): b_units = getattr(b, "_units", None) # Compute dot product - result = np.core.multiarray.dot(np.asarray(a), np.asarray(b), *args, **kwargs) + result = np.dot(np.asarray(a), np.asarray(b), *args, **kwargs) # Determine result units if a_units is not None and b_units is not None: @@ -1518,7 +1518,7 @@ def concatenate_impl(arrays, *args, **kwargs): ) # Perform concatenation - result = np.core.multiarray.concatenate( + result = np.concatenate( [np.asarray(arr) for arr in arrays], *args, **kwargs ) @@ -1552,13 +1552,13 @@ def hstack_impl(arrays, *args, **kwargs): def array_equal_impl(a1, a2, *args, **kwargs): """Compare arrays for equality, ignoring units.""" # Convert to plain numpy arrays and compare - return np.core.numeric.array_equal(np.asarray(a1), np.asarray(a2), *args, **kwargs) + return np.array_equal(np.asarray(a1), np.asarray(a2), *args, **kwargs) @implements(np.allclose) def allclose_impl(a, b, *args, **kwargs): """Check if arrays are close, ignoring units.""" # Convert to plain numpy arrays and compare - return np.core.numeric.allclose(np.asarray(a), np.asarray(b), *args, **kwargs) + return np.allclose(np.asarray(a), np.asarray(b), *args, **kwargs) @implements(np.shape) def shape_impl(a): @@ -1580,10 +1580,8 @@ def column_stack_impl(tup): """Column stack arrays (convert to plain arrays, units not preserved).""" return np.column_stack([np.asarray(arr) for arr in tup]) - @implements(np.row_stack) - def row_stack_impl(tup): - """Row stack arrays (convert to plain arrays, units not preserved).""" - return np.row_stack([np.asarray(arr) for arr in tup]) + # (np.row_stack was removed in numpy 2.0; it aliased np.vstack, which is + # already handled by vstack_impl above — no separate handler needed.) @implements(np.dstack) def dstack_impl(tup): diff --git a/src/underworld3/visualisation/visualisation.py b/src/underworld3/visualisation/visualisation.py index 5eabb659b..1d73f3fb4 100644 --- a/src/underworld3/visualisation/visualisation.py +++ b/src/underworld3/visualisation/visualisation.py @@ -141,7 +141,7 @@ def mesh_to_pv_mesh(mesh, jupyter_backend=None): # Use non-dimensional [0-1] coordinates for PyVista # PyVista only needs coordinates for spatial positioning (visualization) # evaluate() expects non-dimensional coords to query PETSc KDTrees - mesh_coordinates_nd = np.asarray(mesh.X.coords, dtype=np.double) + mesh_coordinates_nd = np.asarray(mesh.X.coords, dtype=np.float64) # Store units metadata for labeling and axis annotation mesh_units = mesh.units if mesh.units is not None else uw.units.dimensionless @@ -176,7 +176,7 @@ def mesh_to_pv_mesh(mesh, jupyter_backend=None): cells_array = np.hstack((cells_size, cells_array), dtype=int) # Use non-dimensional [0-1] coordinates for PyVista (see meshio path above) - mesh_coordinates_nd = np.asarray(mesh.X.coords, dtype=np.double) + mesh_coordinates_nd = np.asarray(mesh.X.coords, dtype=np.float64) pv_mesh = pv.UnstructuredGrid(cells_array, cells_type, coords_to_pv_coords(mesh_coordinates_nd)) # Store units metadata for labeling @@ -268,7 +268,7 @@ def meshVariable_to_pv_cloud(meshVar): # These may be dimensional (UnitAwareArray with meters) when units are active # The alpha parameter in meshVariable_to_pv_mesh_object is now computed from # these coordinates directly, ensuring scale consistency - coords = np.asarray(meshVar.coords, dtype=np.double) + coords = np.asarray(meshVar.coords, dtype=np.float64) points = np.zeros((coords.shape[0], 3)) points[:, 0] = coords[:, 0]