Skip to content

Fix issues #186, #191-#193, #195-#200 - #205

Merged
asalmgren merged 1 commit into
AMReX-Fluids:developmentfrom
asalmgren:fix-issues-186-200
Sep 28, 2026
Merged

asalmgren merged 1 commit into
AMReX-Fluids:developmentfrom
asalmgren:fix-issues-186-200

Conversation

@asalmgren

Copy link
Copy Markdown
Contributor

Fixes #186, #191, #192, #193, #195, #196, #197, #198, #199, #200.

Changes

Source/Diffusion.{H,cpp}, Source/NavierStokes.cpp (#200)

  • diffuse_tensor_Vsync solved with shear viscosity hard-coded to 1.0, ignoring the beta it was passed. Restored; a betaCC parameter is threaded through diffuse_Vsync so MLEBTensorOp::setEBShearViscosity gets the old-time cell-centered viscosity in EB builds.
  • diffuse_tensor_Vsync scaled only component 0 of the RHS by rhsscale while setScalars scaled the operator for all components.
  • diffuse_tensor_Vsync multiplied the rho_flag==3 RHS by old-time density while acoef and the caller both use new-time density.
  • diffuse_tensor_velocity never multiplied its RHS by rhsscale.
  • diffuse_scalar never called setCoarseFineBC on a level>0 solve with no coarse data, so MLMG assumed a refinement ratio of 2.

Source/Projection.cpp (#199)

  • The RZ branch of scaleVar zeroed velocity ghosts outside the domain in the axial direction, destroying inflow values the nodal divu stencil reads. They are now scaled by radius, as the pre-port Fortran radmpyvel did, with the inverse in rescaleVar.
  • computeRhoG's 3D y-hi face mixed density rows in rho_ii, both in the main loop and in the x-lo ext_dir edge branch; the latter also read one cell outside the rho FAB.

Source/NavierStokesBase.cpp (#198)

  • Restart with ns.gradp_in_checkpoint=0 called computeGradP on a Gradp_Type StateData that AmrLevel::restart had left undefined. It is now defined first, using the midpoint of Press's own interval so Gradp's curTime()/prevTime() match Press's exactly.

Source/NavierStokesBase.cpp (#197)

  • post_timestep_particle passed an undefined MultiFab to Timestamp whenever particles.timestamp_indices was not set.
  • post_timestep_particle and ParticleDerive built MultiFabs on level lev's BoxArray with the current level's FabFactory.
  • ParticleDerive("total_particle_count") accumulated fine into coarse with a host BoxIterator loop over device data; it is now a ParallelFor with Gpu::Atomic::AddNoRet, which also removes an OpenMP race between tiles.

Source/NavierStokesBase.cpp (#196)

  • The cut-cell CrseAdd/FineAdd overloads multiply by the EB area fraction, but AMReX-Hydro already area-weighted the fluxes, so cut coarse/fine faces were refluxed with ap^2. Those overloads now get un-weighted copies.
  • The StateRedist "state" for the mac_sync was copied from Vsync/Ssync without filling ghost cells, making the sync correction near box boundaries grid-decomposition dependent.
  • use_wts_in_divnc was sitting in ApplyMLRedistribution's fac_for_deltaR slot, so dm_as_fine was scaled by +dt even in the mac_sync, where the fluxes go to FineAdd with -dt.

Source/NavierStokesBase.{H,cpp}, Source/NS_average.cpp (#195, #186)

  • time_avg/time_avg_fluct/dt_avg were sized only in post_init and post_restart, so a level created by a later regrid indexed them out of bounds. Added grow_avg_vectors(), called from post_regrid and both init() overloads.
  • The brand-new-level init() never initialized Average_Type. It now FillCoarsePatches it, as the init(AmrLevel&) twin does, and seeds the level's accumulators from the coarser level so the interpolated integral is normalized consistently.
  • checkPoint wrote the single shared TimeAverage file once per level with trunc, so only the finest level's data survived, and dt_avg was never checkpointed. Level 0 now writes one (time_avg, time_avg_fluct, dt_avg) triple per level, and post_restart reads forward to its own level's triple.
  • time_average dereferenced Average_Type old data that is never allocated on a fresh start with ns.init_iter=0.

Source/SyncRegister.cpp (#193)

  • The bndry_mask threshold was SPACEDIM^SPACEDIM-0.5 (26.5 in 3D) but the accumulated count maxes out at 2^SPACEDIM, so in 3D no node was ever masked out of the sync-projection RHS. 2D is unchanged.
  • outflow_dirs was one element short of the number of directions the loop below can record.

Source/NS_LES.cpp (#192)

  • The Smagorinsky branch added each velocity-gradient component to itself rather than to its transpose, so mu_t was built from |grad u| instead of |S| and was overpredicted in every rotational flow.

Util/ConvertCheckpoint/ConvertCheckpointGrids.cpp (#191)

  • nsets_save was a 1-element Vector written at indices 0..ndesc-1 and resized only at lev==1. The global is gone; nsets is derived from the data pointers, the way StateData::checkPoint does.
  • ConvertData unconditionally dereferenced old_data, which is null when a state was checkpointed with nsets==1.
  • The trailing state types were given zero ghost cells, but cell_cons_interp's slope stencil reads one cell outside the coarse fab; and the source ghosts were never filled, so periodic-boundary ghosts fed the setVal(10.) sentinel into the slopes.

Util/ConvertCheckpoint/Make.package

Testing

Builds clean (no new warnings): Exec/run2d, Exec/run3d, Exec/eb_run2d, Exec/eb_run3d, Exec/run_2d_particles, Tutorials/HotSpot (2D and 3D), Util/ConvertCheckpoint.

Baseline-vs-fixed runs confirm each fix:

Baselines that move

3D multilevel sync-projection (#193), any viscous multilevel run (#200), EB cut-cell reflux (#196), RZ with axial inflow (#199), and Smagorinsky LES (#192). Affected tests include regtest.3d.rayleightaylor and the other 3D multilevel decks, regtest.2d.hotspot, Tutorials/Bubble, eb_run2d/regtest.2d.hotspot, and the eb_run3d multilevel decks.

Separately, Exec/eb_run2d/regtest.2d.shock_past_cylinder aborts with "MLMG failed" on both baseline and patched code in my environment — a pre-existing failure, unrelated to these changes.

🤖 Generated with Claude Code

…-Fluids#195-AMReX-Fluids#200

Source/Diffusion.{H,cpp}, Source/NavierStokes.cpp (AMReX-Fluids#200):
  - diffuse_tensor_Vsync solved with shear viscosity hard-coded to 1.0,
    ignoring the beta it was passed. Restore its use; thread a betaCC
    parameter through diffuse_Vsync so MLEBTensorOp::setEBShearViscosity
    gets the old-time cell-centered viscosity in EB builds.
  - diffuse_tensor_Vsync scaled only component 0 of the RHS by rhsscale
    while setScalars scaled the operator for all components.
  - diffuse_tensor_Vsync multiplied the rho_flag==3 RHS by old-time
    density while acoef and the caller both use new-time density.
  - diffuse_tensor_velocity never multiplied its RHS by rhsscale.
  - diffuse_scalar never called setCoarseFineBC on a level>0 solve with
    no coarse data, so MLMG assumed a refinement ratio of 2.

Source/Projection.cpp (AMReX-Fluids#199):
  - The RZ branch of scaleVar zeroed velocity ghosts outside the domain
    in the axial direction, destroying inflow values the nodal divu
    stencil reads. Scale them by radius instead, as the pre-port Fortran
    radmpyvel did, and mirror the change in rescaleVar.
  - computeRhoG's 3D y-hi face mixed density rows in rho_ii, both in the
    main loop and in the x-lo ext_dir edge branch; the latter also read
    one cell outside the rho FAB.

Source/NavierStokesBase.cpp (AMReX-Fluids#198):
  - Restart with ns.gradp_in_checkpoint=0 called computeGradP on a
    Gradp_Type StateData that AmrLevel::restart had left undefined.
    Define it first, using the midpoint of Press's own interval so that
    Gradp's curTime()/prevTime() match Press's exactly.

Source/NavierStokesBase.cpp (AMReX-Fluids#197):
  - post_timestep_particle passed an undefined MultiFab to Timestamp
    whenever particles.timestamp_indices was not set.
  - post_timestep_particle and ParticleDerive built MultiFabs on level
    lev's BoxArray with the *current* level's FabFactory.
  - ParticleDerive("total_particle_count") accumulated fine into coarse
    with a host BoxIterator loop over device data; it is now a
    ParallelFor with Gpu::Atomic::AddNoRet, which also removes an
    OpenMP race between tiles.

Source/NavierStokesBase.cpp (AMReX-Fluids#196):
  - The cut-cell CrseAdd/FineAdd overloads multiply by the EB area
    fraction, but AMReX-Hydro already area-weighted the fluxes, so cut
    c/f faces were refluxed with ap^2. Hand those overloads un-weighted
    copies.
  - The StateRedist "state" for the mac_sync was copied from Vsync/Ssync
    without filling ghost cells, making the sync correction near box
    boundaries grid-decomposition dependent.
  - use_wts_in_divnc was sitting in ApplyMLRedistribution's
    fac_for_deltaR slot, so dm_as_fine was scaled by +dt even in the
    mac_sync, where the fluxes go to FineAdd with -dt.

Source/NavierStokesBase.{H,cpp}, Source/NS_average.cpp (AMReX-Fluids#195, AMReX-Fluids#186):
  - time_avg/time_avg_fluct/dt_avg were sized only in post_init and
    post_restart, so a level created by a later regrid indexed them out
    of bounds. Add grow_avg_vectors() and call it from post_regrid and
    from both init() overloads.
  - The brand-new-level init() never initialized Average_Type.
    FillCoarsePatch it, as the init(AmrLevel&) twin does, and seed the
    level's accumulators from the coarser level so that the interpolated
    integral is normalized consistently.
  - checkPoint wrote the single shared TimeAverage file once per level
    with trunc, so only the finest level's data survived, and dt_avg was
    never checkpointed. Level 0 now writes one
    (time_avg, time_avg_fluct, dt_avg) triple per level, and post_restart
    reads forward to its own level's triple.
  - time_average dereferenced Average_Type old data that is never
    allocated on a fresh start with ns.init_iter=0.

Source/SyncRegister.cpp (AMReX-Fluids#193):
  - The bndry_mask threshold was SPACEDIM^SPACEDIM-0.5 (26.5 in 3D) but
    the accumulated count maxes out at 2^SPACEDIM, so in 3D no node was
    ever masked out of the sync-projection RHS. 2D is unchanged; 3D
    multilevel answers move.
  - outflow_dirs was one element short of the number of directions the
    loop below can record.

Source/NS_LES.cpp (AMReX-Fluids#192):
  - The Smagorinsky branch added each velocity-gradient component to
    itself rather than to its transpose, so mu_t was built from
    |grad u| instead of |S| and was overpredicted in every rotational
    flow. Pair each component with its transpose.

Util/ConvertCheckpoint/ConvertCheckpointGrids.cpp (AMReX-Fluids#191):
  - nsets_save was a 1-element Vector written at indices 0..ndesc-1 and
    resized only at lev==1. Drop the global and derive nsets from the
    data pointers, the way StateData::checkPoint does.
  - ConvertData unconditionally dereferenced old_data, which is null
    when a state was checkpointed with nsets==1.
  - The trailing state types were given zero ghost cells, but
    cell_cons_interp's slope stencil reads one cell outside the coarse
    fab; and the source ghosts were never filled, so periodic-boundary
    ghosts fed the setVal(10.) sentinel into the slopes.

Util/ConvertCheckpoint/Make.package:
  - Drop the reference to AMReX_FABUTIL_$(DIM)D.F, which no longer
    exists in AMReX; without this the utility does not build at all.

Note that regression baselines move for 3D multilevel runs (AMReX-Fluids#193), any
viscous multilevel run (AMReX-Fluids#200), EB cut-cell reflux (AMReX-Fluids#196), RZ with axial
inflow (AMReX-Fluids#199) and Smagorinsky LES (AMReX-Fluids#192).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

time_average null-derefs Average_Type old data on fresh start with init_iter=0

1 participant