Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix hist_hi and iteration outputs #2534

Merged
merged 5 commits into from
May 2, 2022
Merged

Fix hist_hi and iteration outputs #2534

merged 5 commits into from
May 2, 2022

Conversation

johnomotani
Copy link
Contributor

@johnomotani johnomotani commented Apr 11, 2022

This PR fixes two issues that I think are bugs:

  1. hist_hi counts the number of steps of the most frequent Monitor, which is not necessarily the output monitor. I think we always want to count the number of output steps. Fixed in this PR by moving the increment of Solver::iteration to a SolverMonitor, which is called with the same frequency as the output monitor. The SolverMonitor is called before writing dump and output files, so hist_hi behaves the same as at present when the output monitor is the most frequent monitor.
  2. iteration, as saved to the dump files, is too low by 1. I think the value should be: the same as hist_hi when the simulation was started from iteration 0 (i.e. not restarted); the same as the value printed to stdout at the same time as it is being saved. Fixed by 6b8eff8.

Question: is issue 2 actually slightly more general, and we should actually call call_monitors with the iter argument one greater (so that it counts the number of iterations that have been completed)? Proposed change to do this in #2535.

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

return 0;
}
};
SolverMonitor solver_monitor;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: member variable solver_monitor has protected visibility [cppcoreguidelines-non-private-member-variables-in-classes]

SolverMonitor solver_monitor;
              ^

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was deliberate - I used it to make the SolverTest.RemoveMonitor test work by providing a getter for solver_monitor in the FakeSolver class.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could maybe make solver_monitor private and add a protected getter?

@ZedThree
Copy link
Member

I like removing the duplicated iteration++ from each solver!

Instead of adding a new monitor, does it make sense to do the iteration increment in the output monitor itself?

@johnomotani
Copy link
Contributor Author

Instead of adding a new monitor, does it make sense to do the iteration increment in the output monitor itself?

That does seem nicer! Just need to add a method to Solver to increment the iteration count, rather than define a whole new monitor...

@ZedThree
Copy link
Member

We could also make iteration private then, which would be nice

@johnomotani
Copy link
Contributor Author

Should I rebase this branch to get rid of stuff that was added and then removed (e.g. SolverMonitor)?

Comment on lines 330 to 332
/// Add one to the iteration count, used by BoutMonitor, but could be called by a
//user-defined monitor (if `bout_run()` is not used)
void incrementIterationCounter() { ++iteration; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small suggestion:

Suggested change
/// Add one to the iteration count, used by BoutMonitor, but could be called by a
//user-defined monitor (if `bout_run()` is not used)
void incrementIterationCounter() { ++iteration; }
/// Add one to the iteration count, used by BoutMonitor, but could be called by a
/// user-defined monitor (if `bout_run()` is not used).
/// Returns the incremented value
int incrementIterationCounter() { return ++iteration; }

means below we can do:

  // Get updated iteration count
  iteration = solver->incrementIterationCounter();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I'll put that in.

@ZedThree
Copy link
Member

Should I rebase this branch to get rid of stuff that was added and then removed (e.g. SolverMonitor)?

Sure, that might be nice -- but it's not a blocker if you don't :)

@ZedThree
Copy link
Member

Tests are failing because there's a use of ++iteration in slepc.cxx -- making it private was definitely a good idea, it caught a potential bug! 😄

@johnomotani
Copy link
Contributor Author

Tests are failing because there's a use of ++iteration in slepc.cxx -- making it private was definitely a good idea, it caught a potential bug!

It looked to me as though the uses of iteration in SlepcSolver would be alright, because SlepcSolver doesn't actually call the monitors (i.e. BoutMonitor is not called, except once before SlepcSolver::run() starts) - SlepcSolver is just in charge of iteration. So I've kept Solver::iteration private, but added a protected Solver::resetIterationCounter() for SlepcSolver to use. If someone who understands SlepcSolver could check that this PR doesn't break it (I hope we've got tests!), that would be nice 😄

Previously, the `iteration` saved into dump files was inconsistent with
`hist_hi`: in a simulation that is not restarted (so starts from
iteration 0), `iteration` would always be 1 less than `hist_hi`.
`hist_hi` counts the number of output steps that have been completed,
which seems more sensible, so this commit adds 1 to the value of
`iteration` that is saved. Note this also makes the value that is saved
the same as the value that is printed to stdout at the same time.
Make `Solver::iteration` private, and add methods to get or increment
its value.

Allows the iteration counter to be updated directly in
`BoutMonitor::call()`.

Previously, `Solver::iteration` was updated in the implementations of
`Solver::run()`, but if there is any monitor that is called more
frequently than the output monitor, this meant that `iteration` counted
the number of calls to the more frequent monitor, not the number of
output steps. Not an issue now, since it is incremented in
`BoutMonitor`, which is the one that does the output.
SlepcSolver uses `Solver::iteration`. Adding the protected
`Solver::resetIterationCounter()` method allows `Solver::iteration` to
be private, while allowing `SlepcSolver` to work.
include/bout/solver.hxx Outdated Show resolved Hide resolved
@ZedThree
Copy link
Member

If someone who understands SlepcSolver could check that this PR doesn't break it (I hope we've got tests!), that would be nice

We do indeed have a SlepcSolver test, and that's passing so I assume it's correct 😄

Need to use `++iteration`, not `iteration++`, so that the returned value is the after-increment value.

Co-authored-by: Peter Hill <peter.hill@york.ac.uk>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants