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

feat: minimum interval for time-step increase after time-step cut #3338

Merged
merged 17 commits into from
Sep 20, 2024

Conversation

victorapm
Copy link
Contributor

This PR addresses an issue where the simulation oscillates between time-step increases and cuts due to Newton loop stagnation.

For example, in one simulation, the time-step gradually increases up to a point leading to Newton loop stagnation. Then, the time-step was subsequently reduced, allowing the Newton loop to converge, but it quickly tried to revert back to the original large time-step, causing the same stagnation. This cycle would repeat for many cycles in the simulation.

This PR introduces a parameter to enforce a minimum interval before the time-step can increase again after a reduction occurs, thus preventing the repeated back-and-forth time-step adjustments and avoiding Newton iteration failures in both parts of the simulation.

Side question: we have places where we use "time step" and "time-step". Should we choose one format and use it consistently?

@victorapm victorapm self-assigned this Sep 9, 2024
@victorapm victorapm changed the title feature: minimum interval for time-step increase after time-step cut feat: minimum interval for time-step increase after time-step cut Sep 9, 2024
Copy link

codecov bot commented Sep 9, 2024

Codecov Report

Attention: Patch coverage is 70.27027% with 11 lines in your changes missing coverage. Please review.

Project coverage is 56.32%. Comparing base (5368ee3) to head (f2d5cac).
Report is 82 commits behind head on develop.

Files with missing lines Patch % Lines
...nents/physicsSolvers/NonlinearSolverParameters.cpp 55.55% 8 Missing ⚠️
...sSolvers/fluidFlow/CompositionalMultiphaseBase.cpp 40.00% 3 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #3338   +/-   ##
========================================
  Coverage    56.32%   56.32%           
========================================
  Files         1065     1065           
  Lines        90210    90230   +20     
========================================
+ Hits         50807    50823   +16     
- Misses       39403    39407    +4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@@ -401,14 +426,14 @@ real64 SolverBase::setNextDtBasedOnNewtonIter( real64 const & currentDt )
if( newtonIter < iterIncreaseLimit )
{
// Easy convergence, let's increase the time-step.
nextDt = currentDt * m_nonlinearSolverParameters.timeStepIncreaseFactor();
nextDt = round( currentDt * m_nonlinearSolverParameters.timeStepIncreaseFactor() );
Copy link
Contributor

Choose a reason for hiding this comment

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

this is experimental, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it's not the main purpose of this PR. If the time-steps are larger than O(10) rounding shouldn't be an issue, right?

Copy link
Contributor

Choose a reason for hiding this comment

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

how about < 0.5 ? or i am missing something...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, then this doesn't work

Copy link
Collaborator

Choose a reason for hiding this comment

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

yeah, we should not use round here. For some cases we need very tiny time steps.

* */
if( dt < m_nextDt )
{
m_lastDtCut = -1;
Copy link
Contributor

Choose a reason for hiding this comment

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

so the logic only works with current "execute", no transfer to next cycle?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I did this because the current execute might decrease the time-step to meet a exact time target for the event. Then, suppose you come from a recent time-step cut, If I didn't reset m_lastDtCut, the code would not be able to increase the time step again (after having decreased not because of a noncoverged Newton, but because it had to meet a target time). Hope this explanation is not too confusing

Copy link
Contributor

Choose a reason for hiding this comment

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

it's ok, just might be confusing that logic is not applied across cycles
let's say we set minTimeStepIncreaseInterval=5 and it does a cut inside one cycle, then does let's say 2 succesful subtimesteps and goes into another cycle - then that 5-2 counter is lost?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right, in this scenario, the cut information is lost for the next subEvent and I agree it shouldn't.

Maybe it's possible to improve the logic here. If you have some ideas, feel free to implement!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

PS: in your scenario, if the time-step is not decreased to meet a exact target time, then the cut information is not lost in the next subEvent

@CusiniM
Copy link
Collaborator

CusiniM commented Sep 9, 2024

This PR addresses an issue where the simulation oscillates between time-step increases and cuts due to Newton loop stagnation.

For example, in one simulation, the time-step gradually increases up to a point leading to Newton loop stagnation. Then, the time-step was subsequently reduced, allowing the Newton loop to converge, but it quickly tried to revert back to the original large time-step, causing the same stagnation. This cycle would repeat for many cycles in the simulation.

This PR introduces a parameter to enforce a minimum interval before the time-step can increase again after a reduction occurs, thus preventing the repeated back-and-forth time-step adjustments and avoiding Newton iteration failures in both parts of the simulation.

Side question: we have places where we use "time step" and "time-step". Should we choose one format and use it consistently?

I think that if we wanted to follow proper grammatical rules, it should be time step whenever it's a noun and time-step whenever it's adjectivized (e.g., time-step size, time-step control strategy).

@castelletto1
Copy link
Contributor

This PR addresses an issue where the simulation oscillates between time-step increases and cuts due to Newton loop stagnation.

For example, in one simulation, the time-step gradually increases up to a point leading to Newton loop stagnation. Then, the time-step was subsequently reduced, allowing the Newton loop to converge, but it quickly tried to revert back to the original large time-step, causing the same stagnation. This cycle would repeat for many cycles in the simulation.

This PR introduces a parameter to enforce a minimum interval before the time-step can increase again after a reduction occurs, thus preventing the repeated back-and-forth time-step adjustments and avoiding Newton iteration failures in both parts of the simulation.

Side question: we have places where we use "time step" and "time-step". Should we choose one format and use it consistently?

I think that if we wanted to follow proper grammatical rules, it should be time step whenever it's a noun and time-step whenever it's adjectivized (e.g., time-step size, time-step control strategy).

Why not simply timestep (Collins dictionary)? The timestep is set to ..., The timestep size ...

@@ -1008,6 +1011,9 @@ class SolverBase : public ExecutableGroup
/// timestep of the next cycle
real64 m_nextDt;

/// Number of cycles since last timestep cut
integer m_lastDtCut;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
integer m_lastDtCut;
integer m_numTimestepsSinceLastDtCut;

@CusiniM
Copy link
Collaborator

CusiniM commented Sep 9, 2024

This PR addresses an issue where the simulation oscillates between time-step increases and cuts due to Newton loop stagnation.
For example, in one simulation, the time-step gradually increases up to a point leading to Newton loop stagnation. Then, the time-step was subsequently reduced, allowing the Newton loop to converge, but it quickly tried to revert back to the original large time-step, causing the same stagnation. This cycle would repeat for many cycles in the simulation.
This PR introduces a parameter to enforce a minimum interval before the time-step can increase again after a reduction occurs, thus preventing the repeated back-and-forth time-step adjustments and avoiding Newton iteration failures in both parts of the simulation.
Side question: we have places where we use "time step" and "time-step". Should we choose one format and use it consistently?

I think that if we wanted to follow proper grammatical rules, it should be time step whenever it's a noun and time-step whenever it's adjectivized (e.g., time-step size, time-step control strategy).

Why not simply timestep (Collins dictionary)? The timestep is set to ..., The timestep size ...

The Oxford dictionary does not have the entry as a single word but it would really simplify our life. Spellcheckers don't recognize it though.

@CusiniM
Copy link
Collaborator

CusiniM commented Sep 9, 2024

Talking about the actual goal of the PR... The logic is a bit clunky but we certainly need to include some more info about past convergence when selecting the new dt so this could be a start.

I don't think we can have all those round calls though coz we have often test cases (for like lab scale models) in which we use dt~ 1e-3 s so that would mess up things. @victorapm if you were tyring to round up the values to improve the readability of the output we can probably do it using the units utilities

struct TimeFormatInfo

@victorapm
Copy link
Contributor Author

Updated the variable name and removed round in 2302936

Let me know what you guys think!

I suggest voting for deciding wheter to use timestep, time-step, ...

@victorapm victorapm added ci: run CUDA builds Allows to triggers (costly) CUDA jobs ci: run integrated tests Allows to run the integrated tests in GEOS CI labels Sep 12, 2024
@paveltomin
Copy link
Contributor

please also merge https://github.com/GEOS-DEV/SPE11/tree/paludettomag1/spe11c once this PR is done

@victorapm
Copy link
Contributor Author

It seems we'll need to rebaseline given the new logic and default value for m_numTimestepsSinceLastDtCut, which I think is good to have. @CusiniM

Copy link
Member

@rrsettgast rrsettgast left a comment

Choose a reason for hiding this comment

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

When increasing tilmestep, wouldn't it be appropriate to modify the time-step increase size based on the number of newton iterations the current step took to converge? So instead of: "if numNewtonIter < 8 then nextDt = dt * factor" we have the factor be dependent on numNewtonIter?

registerWrapper( viewKeysStruct::minTimeStepIncreaseIntervalString(), &m_minTimeStepIncreaseInterval ).
setApplyDefaultValue( 10 ).
setInputFlag( InputFlags::OPTIONAL ).
setDescription( "Value of the minimum interval, since the last time-step cut, for increasing the time-step." );
Copy link
Member

Choose a reason for hiding this comment

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

what does "minimum interval" mean? It is hard to tell from this description. is it "minimum number of time steps"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right, it's minimum number of time steps. Let me update the comment

Copy link
Contributor

@castelletto1 castelletto1 Sep 18, 2024

Choose a reason for hiding this comment

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

I find the comment below very clear:

GEOS_LOG_LEVEL_RANK_0( 1, GEOS_FMT( "{}: time-step size will be kept the same since it's been {} cycles since last cut.",
                                        getName(), m_numTimestepsSinceLastDtCut ) );

What about renaming m_minNumCyclesFixedTimeStepAfterCut. It's a bit wordy but a probably clearer?

Copy link
Contributor

Choose a reason for hiding this comment

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

Better m_minFixedTimeStepNumCyclesAfterCut

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am fine with all options presented


registerWrapper( viewKeysStruct::timeStepDecreaseFactorString(), &m_timeStepDecreaseFactor ).
setApplyDefaultValue( 0.5 ).
setInputFlag( InputFlags::OPTIONAL ).
setDescription( "Factor by which the time step is decreased when the number of Newton iterations is large." );
setDescription( "Factor by which the time-step is decreased when the number of Newton iterations is large." );

registerWrapper( viewKeysStruct::timeStepIncreaseFactorString(), &m_timeStepIncreaseFactor ).
setApplyDefaultValue( 2.0 ).
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this default should be 2.0....should it?

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree that the default could be a little more conservative.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That makes sense, but this is not the variable I'm adding in this PR (m_timeStepIncreaseFactor). Should we make the change here or in another PR?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, not in this PR

@rrsettgast rrsettgast added the flag: requires rebaseline Requires rebaseline branch in integratedTests label Sep 18, 2024
Copy link
Contributor

@castelletto1 castelletto1 left a comment

Choose a reason for hiding this comment

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

Except for the suggestion on rewording (optional), looks good to me. Thank you!

Co-authored-by: Nicola Castelletto <38361926+castelletto1@users.noreply.github.com>
@castelletto1
Copy link
Contributor

I suggest voting for deciding whether to use timestep, time-step, ...

Let's postpone the renaming to a future PR and consistently apply the change everywhere in GEOS.

With all due respect to the Oxford Dictionary, my preference is to use timestep.

@rrsettgast rrsettgast merged commit 1616ea4 into develop Sep 20, 2024
25 checks passed
@rrsettgast rrsettgast deleted the feature/paludettomag1/timestep branch September 20, 2024 06:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ci: run CUDA builds Allows to triggers (costly) CUDA jobs ci: run integrated tests Allows to run the integrated tests in GEOS CI flag: ready for review flag: requires rebaseline Requires rebaseline branch in integratedTests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants