Forward-from-nodes history; semi-Lagrangian schemes named by trace and launch; every history equals serial in parallel - #800
Open
lmoresi wants to merge 5 commits into
Conversation
…lement interiors Forward from where the values are known best. A field is known exactly at its own nodes and, since its interpolant is a polynomial inside each element, at any interior point. ForwardNodesSemiLagrangian launches the values at the nodes and at the interior lattice of every element (the discontinuous basis one degree up), carries them one step forward on the shared characteristic trace, fits the arrivals in each cell at the field's own degree (the cell polynomial projector, with its thin-cell and conditioning fallbacks) and reads the fit back at the nodes. The fit never crosses an element boundary, where the interpolant has a kink; a neighbourhood fit across cells was tried first and smoothed (disc error 3.6e-2). As the DuDt of the SLCN advection-diffusion solver on the rotating diffusing Gaussian (P2 temperature, dt 0.02, kappa 0.01): half revolution on the disc 2.00e-2 (backward nodal history 2.52e-2, swarm 2.04e-2, SUPG 1.72e-2), peak 0.1873 against 0.1865 exact; the square box, where the flow crosses all four walls, 6.17e-2 (backward 6.43e-2); a full revolution 7.63e-2 (backward 8.94e-2, SUPG and swarm 8.2e-2). About twice the backward cost per step. First order, serial (the fit near a partition seam needs the other rank's arrivals). Test test_1102: disc and box, hard baselines. Underworld development team with AI support from Claude Code Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017kSkAq7oJ5J3XisuvLBovo
… forward from nodes as an advection-diffusion option ddt.SemiLagrangian(mesh, psi_fn, V_fn, vtype, trace=, launch=) selects one of four schemes: BackwardNodesSemiLagrangian (was SemiLagrangian), BackwardIntegrationPointsSemiLagrangian (was IntegrationPointSemiLagrangian), ForwardIntegrationPointsSemiLagrangian (was ForwardSemiLagrangian) and ForwardNodesSemiLagrangian. A keyword the chosen scheme does not take is a TypeError. The old class names resolve with a FutureWarning. stress_transport takes "backward_nodes" (default), "backward_integration_points", "forward_integration_points", "lagrangian", "eulerian"; the old strings map with a FutureWarning. AdvDiffusionSLCN(transport=...) chooses the value history among the four semi-Lagrangian schemes. ForwardNodesSemiLagrangian carries a field known at its nodes and refuses a flux: a stress is formed at the integration points. A cell nothing reached now keeps the field it launched (no fit carried between steps); inflow is detected by the back-reflected point leaving the domain; a moved mesh is refused. ForwardIntegrationPointsSemiLagrangian takes degree and refuses anything but 1. BackwardNodesSemiLagrangian's continuous now defaults to True. Underworld development team with AI support from Claude Code Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017kSkAq7oJ5J3XisuvLBovo
…l; forward from nodes carries a stress Forward from nodes as a stress history: the stress is committed by L2 projection onto the continuous store and launched from that field. It is offered by stress_transport="forward_nodes". The per-cell fits are projected onto the store (a shared node weighs every cell), each cell's fit uses only its own arrivals (a linear fit, their mean, or the launched field when too few), the interior lattice is two degrees up, and an arrival on a shared face is fitted in every cell that contains it. In parallel a seam node is launched by its owner, and arrivals that left a rank or sit on a face are offered to every rank. Partition dependence removed from the existing histories: - a field that is a mesh variable (T.sym as well as T) is recorded into the nodal and integration-point histories by copying its nodal data, in serial as in parallel, instead of evaluating it at nudged nodes; - the nodal trace starts from the node itself: the 0.1% nudge toward the closest cell's centroid depended on which cells a rank holds and gave a no-slip wall node a velocity; - every history projection is solved to 1e-10; - global_evaluate: a point that the migration stranded but that a rank's cell contains is evaluated there with the FE interpolant, not by the nearest-centroid rbf extrapolation (3e-2 at a steep stress). tests/parallel/test_1066: six stress and four advection histories equal serial to 1e-6 at np >= 3 (verified np 3, 4, 6); the particle history is a strict xfail at np >= 4 (1.2e-5, cause open). test_1062 tightened to 1e-6. Underworld development team with AI support from Claude Code Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017kSkAq7oJ5J3XisuvLBovo
…tory projections - forward from nodes: an inflow node is one whose back-reflected point the global restore moves (a per-rank "in domain" test called every partition face a boundary); ownership of seam nodes read from the global section (_owned_rows) instead of a write-and-read-back; the tracked field copied, not evaluated, at the nodes; a strictly-inside arrival fitted in its one cell only; containing_cells falls back to the locator for a point whose cell is not among the nearest centroids; quadrilateral centroids corrected. - global_evaluate: the containment round keeps a finite rbf value where the FE value is NaN, and runs only where the cell hint is authoritative (no DMLocatePoints collective inside it); the deadlock note says so. - every history projection is a CG/Jacobi solve (linear_solver moved to the projection mixin) to 1e-12, from zero: the warm start depended on a state a restart does not restore. - Eulerian record uses _tracked_field; _tracked_field refuses another mesh's variable; stress_transport names map through one (trace, launch) table. - tests: test_1066 resets the model per case, asserts the forward exchanges ran, gives the value histories an inflow, marks the particle case #797 (xfail, np >= 4); test_1063 covers forward_nodes; test_1102 held to 1e-4. test_1066 at np 4 is the regression test for the containment round. - TODO(DESIGN) notes: face points offered to every rank; the two forward flavours' arrival rules. np 3/4/6: 10 passed (+1 xfail at 4/6); serial: 388 passed. Underworld development team with AI support from Claude Code Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017kSkAq7oJ5J3XisuvLBovo
Member
Author
Adversarial reviewTwo review passes before the push (on c434d8a and on b20c992). Findings and disposition: Fixed
Deferred (TODO(DESIGN) in the code)
Filed: #797 (particle history, np >= 4), #798 (evalf extrapolation flag), #799 (serial evaluate near nodes). Underworld development team with AI support from Claude Code |
…Stokes velocity history offers every semi-Lagrangian scheme global_evaluate applied monotone="clamp" on the rank that asked for a point, bounding it by that rank's nearest nodes; for a departure point evaluated on another rank those are the wrong neighbourhood. The bound now runs on the evaluating rank (first pass and containment round), on non-dimensional values like the nodal data it compares with. Serial results are unchanged. #682's level-set reproduction (LeVeque swirl, 128^2 quad, P2, SLCN with clamp): volume at np 1/2/4/8 now 0.0706771442/415/438/412 (np 8 was 1.6% off). NavierStokesSLCN(velocity_transport=...) chooses the velocity history among the four semi-Lagrangian schemes, through one _value_history helper shared with AdvDiffusionSLCN(transport=...). Forward schemes need order=1; the forward integration-point fit is linear and refuses a P2 velocity. tests: test_1103 (lid-driven cavity, Re 100, three schemes against recorded values and each other); test_1066 adds the cavity (equal to serial at np 3/4/6). tests/parallel at np 4: 168 passed, 1 xfailed, 1 failed (test_1063_constrained_freeslip_parallel[ti], fails identically on #795's 05d5248). Serial set: 393 passed. Underworld development team with AI support from Claude Code Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017kSkAq7oJ5J3XisuvLBovo
Member
Author
|
Added (28314aa):
Underworld development team with AI support from Claude Code |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #795.
What changes
One entry point for the semi-Lagrangian histories.
uw.systems.ddt.SemiLagrangian(mesh, psi_fn, V_fn, vtype, trace=, launch=)selects one of four schemes:tracelaunchBackwardNodesSemiLagrangian(SemiLagrangian)BackwardIntegrationPointsSemiLagrangian(IntegrationPointSemiLagrangian)ForwardIntegrationPointsSemiLagrangian(ForwardSemiLagrangian)ForwardNodesSemiLagrangian(new)A keyword the chosen scheme does not take is a
TypeError. The former class names and the formerstress_transportstrings (semi_lagrangian,integration_point,forward) still work, with aFutureWarning.stress_transporttakesbackward_nodes(default),backward_integration_points,forward_integration_points,forward_nodes,lagrangian,eulerian;AdvDiffusionSLCN(transport=...)chooses its value history among the four semi-Lagrangian schemes.Forward from nodes. The history launches its values from the field's nodes and from a lattice inside every element (the discontinuous basis two degrees up), carries them one step forward, fits the arrivals in each cell at the field's degree, and projects the per-cell fits onto the continuous store. A cell with too few arrivals takes a linear fit to its own arrivals, or their mean; an arrival on a shared face is fitted in every cell that contains it. A stress is committed by L2 projection onto the store and launched from that field. Rotating diffusing Gaussian, P2, SLCN solver, integral error:
The box, where the flow crosses every wall, is slightly worse than the backward scheme. A serial-only version that let thin cells borrow arrivals from their neighbours reached 1.68e-2 and 6.32e-2; that borrowing depends on the partition and was removed. First order; a fixed mesh.
Every history gives the serial answer in parallel.
tests/parallel/test_1066holds the six stress histories (turned-over Maxwell box) and the four semi-Lagrangian value histories (rotating Gaussian with inflow) to 1e-6 of their serial values at np >= 3; verified at np 3, 4 and 6. Five sources of partition dependence were removed:global_evaluate: a point that the swarm migration handed to a rank whose cells do not contain it was given the nearest-centroid rbf extrapolation (3e-2 at a steep stress, np 4). The rank whose cell contains it now evaluates it with the FE interpolant. This runs only where the cell hint is authoritative (noDMLocatePointscollective inside), and a finite rbf value is kept where the FE value is NaN.Open
evalf=True, and serialevaluateoff by up to 4e-5 near nodes for an exactly represented P2 field.TODO(DESIGN): face arrivals are offered to every rank, not only across seams; the two forward schemes use different rules for an arrival exactly on a face.Tests
tests/parallel/test_1066(new),test_1062tightened to 1e-6,test_1102(new, forward from nodes against hard baselines),test_1063coversforward_nodes,test_1059covers selection, renamed strings and the Maxwell box for every history. Serial transport/NS/VE set: 388 passed. Parallel np 3/4/6: 10 passed, 1 xfail at np >= 4.🤖 Generated with Claude Code
https://claude.ai/code/session_017kSkAq7oJ5J3XisuvLBovo