Skip to content

Fix SemiImplicitBDF start-up order off-by-one - #355

Open
NopeCharon wants to merge 1 commit into
dynamicslab:mainfrom
NopeCharon:fix/bdf-startup-order
Open

NopeCharon wants to merge 1 commit into
dynamicslab:mainfrom
NopeCharon:fix/bdf-startup-order

Conversation

@NopeCharon

Copy link
Copy Markdown
Contributor

Closes #354

SemiImplicitBDF.step() indexed its start-up solvers off by one. startup_solvers[j] is the order-j+1 scheme, but step iter used startup_solvers[iter - 1]. So iter = 0 wrapped around to the highest start-up order, iter = 1 fell back to first order, and the full scheme only took over at iter = k:

order before after
1 1, 1, ... 1, 1, ...
2 1, 1, 2, ... 1, 2, 2, ...
3 2, 1, 2, 3, ... 1, 2, 3, 3, ...

Changes

  • At step iter the history holds iter + 1 solutions. The solver now uses the full scheme once iter >= k - 1 and startup_solvers[iter] before that, i.e. order min(iter + 1, k). This also covers k == 1, so the special case from Fix indexing error in BDF with k=1 #189 is no longer needed.
  • test_bdf_startup_order (in test/test_cyl.py) records which scheme order runs at each step for k = 1, 2, 3.

Validation

All runs used the firedrakeproject/firedrake-vanilla-default container.

  • On main, test_bdf_startup_order[2] and [3] fail ([1, 1, 2] and [2, 1, 2, 3]). With this change all three pass.
  • test_integrate[1], test_integrate[3], test_env and test_control in test/test_cyl.py pass.
  • test_steady_rotation fails on main too: CL ≈ -0.46 against the expected -0.06, with or without this change. This PR doesn't touch it.
  • Accuracy check: a developed Re=100 cylinder flow (medium mesh), integrated to t = 0.1 with order=3 from a fresh solver. Velocity error (fd.errornorm) against a dt = 1e-3 reference:
dt = 1e-2 dt = 5e-3
main 2.06e-3 9.05e-4
this PR 1.09e-4 2.65e-5
  • ruff check, ruff format --check, isort --check-only and codespell pass.

SemiImplicitBDF ramps up from first order to the full order-k BDF/EXT
scheme while the history of previous solutions is filled, but step()
indexed its start-up solvers off by one:

    if (self.k == 1) or (iter > self.k - 1):
        self.petsc_solver.solve()
    else:
        self.startup_solvers[iter - 1].solve()

startup_solvers[j] is the order-(j+1) scheme, so iter = 0 wrapped
around to startup_solvers[-1] (the highest start-up order), iter = 1
fell back to first order, and the full scheme only took over at
iter = k. With the default order=3 the first steps ran with orders
2, 1, 2, 3 instead of 1, 2, 3, 3; with order=2 they ran 1, 1, 2.

At step iter the history holds iter + 1 solutions, so use the order
min(iter + 1, k) scheme: the full solver once iter >= k - 1 and
startup_solvers[iter] before that. This also covers k == 1 without the
special case added in dynamicslab#189.

For a developed Re=100 cylinder flow integrated to t = 0.1 from a
fresh solver, the velocity error against a dt = 1e-3 reference drops
from 2.06e-3 to 1.09e-4 at dt = 1e-2 and from 9.05e-4 to 2.65e-5 at
dt = 5e-3.

Add test_bdf_startup_order to test/test_cyl.py, which records the order
of the scheme used at each step for k = 1, 2, 3.

Fixes dynamicslab#354

This branch has not been deployed

No deployments
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.

[Bug] SemiImplicitBDF start-up steps use the wrong scheme order

1 participant