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

[GeoMechanicsApplication] DSettlement non-convergence exit takes a lot longer than before #13176

Open
wants to merge 13 commits into
base: master
Choose a base branch
from

Conversation

markelov208
Copy link
Contributor

@markelov208 markelov208 commented Feb 28, 2025

📝 Description
A brief description of the PR.

  • added minimum allowable value for the time step to stop a computations when time step is too small
  • added unit tests for this change.

@markelov208 markelov208 self-assigned this Feb 28, 2025
Comment on lines 87 to 90
constexpr auto small_increment = 1.0e-3;
if (rResultantState.time + mDeltaTime > mEndTime - small_increment * mDeltaTime) {
mDeltaTime = mEndTime - rResultantState.time;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This condition is rewritten and does the same. It is now in a more logical place, executing the check less often.
However, the meaning of the variable small_increment has been changed from a time increment to a small factor.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Use the small_time_increment now to be consistent with python scrip

KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(), "The time step ", self.delta_time, " is smaller than a given minimum value of ", self.min_delta_time)
else:
KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(), "The time step ", self.delta_time, " is smaller than a default minimum value of ", self.min_delta_time)
KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(), "Please check the case settings.")
Copy link
Contributor

Choose a reason for hiding this comment

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

What does case refer to here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

changed to "Please check settings in Project Parameters and Materials Files."

@@ -102,6 +113,8 @@ def RunSolutionLoop(self):
self.delta_time = new_time - t
KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(), "Up-scaling to reach end_time without small increments: ", self.delta_time)

self._check_delta_time_size()
Copy link
Contributor

Choose a reason for hiding this comment

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

The lower limit for the delta_time is determined at line 106, line 113 could still slightly increase it. Therefore I understand that the check is here and not immediately after line 106.

Comment on lines 197 to 199
KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(), "STEP : ", self._GetSolver().GetComputingModelPart().ProcessInfo[KratosMultiphysics.STEP])
KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(), "DELTA_TIME : ", self._GetSolver().GetComputingModelPart().ProcessInfo[KratosMultiphysics.DELTA_TIME])
KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(), "TIME : ", self._GetSolver().GetComputingModelPart().ProcessInfo[KratosMultiphysics.TIME])
Copy link
Contributor

Choose a reason for hiding this comment

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

Why this change of layout, if its a real layout improved that increases readability of the log I'm o.k. with it, but generally we should be careful with changes like this. Users may have scripts that filter the log to retrieve stepping information. These scripts are likely to be dependent on the formatting.

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 added more info for debugging then removed. Reverted changes now.

@@ -9,6 +9,7 @@
//
// Main authors: Wijtze Pieter Kikstra
// Anne van de Graaf
// Richard Faasse
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not Gennady too?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because Richard gave more tests. I adapted them a little.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think you still should add your own name here as well :)

Comment on lines 99 to 101
KRATOS_ERROR_IF(mDeltaTime < mMinAllowableDeltaTime.second)
<< "Delta time (" << mDeltaTime << ") is smaller than minimum allowable value "
<< mMinAllowableDeltaTime.second << std::endl;
Copy link
Contributor

Choose a reason for hiding this comment

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

Like in the python route, I would expect the notice whether the minimum allowable value is the result of user input or a default. Now in adaptive_time_incrementor.h a std::pair is set up, but only its second value is ever used in a c++ piece of coding.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A very good catch

Copy link
Contributor

@rfaasse rfaasse left a comment

Choose a reason for hiding this comment

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

Clear improvement, I think this is almost ready to go, I just have a few minor suggestions/questions left

mDeltaTime *= mReductionFactor;
} else if (rResultantState.Converged() && (rResultantState.num_of_iterations < mMinNumOfIterations)) {
mDeltaTime = std::min(mDeltaTime * mIncreaseFactor, mMaxDeltaTime);
if (rResultantState.Converged()) // it is converged also at the beginning of the cycles
Copy link
Contributor

Choose a reason for hiding this comment

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

This comment is not completely clear to me yet, what do you mean with it?

if (rResultantState.time < mEndTime) {
// Up-scaling to reach end_time without small increments
constexpr auto small_increment_factor = 1.0e-3;
if (auto small_time_increment = small_increment_factor * mDeltaTime;
Copy link
Contributor

Choose a reason for hiding this comment

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

If I'm correct this could be const auto

Suggested change
if (auto small_time_increment = small_increment_factor * mDeltaTime;
if (const auto small_time_increment = small_increment_factor * mDeltaTime;

Comment on lines +82 to +84
} else if (rResultantState.num_of_iterations == mMaxNumOfIterations) {
mDeltaTime *= mReductionFactor;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems quite a rare case to me: The calculation has converged exactly with the maximum number of iterations. Do we then want to reduce the time-step?

AdaptiveTimeIncrementor(double StartTime,
double EndTime,
double StartIncrement,
std::pair<std::string, double> MinAllowableDeltaTime,
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we also need to include , but probably better is to use a std::optional instead of a pair.

@@ -9,6 +9,7 @@
//
// Main authors: Wijtze Pieter Kikstra
// Anne van de Graaf
// Richard Faasse
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you still should add your own name here as well :)

Copy link
Contributor

@avdg81 avdg81 left a comment

Choose a reason for hiding this comment

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

A very nice PR that makes the code more robust and consistent. Well done! I have a few suggestions that may help to simplify the code a bit more. I'll share a patch with you through Teams, just so you don't have to redo my suggestions.

std::size_t mMaxNumOfIterations;
double mEndTime;
double mDeltaTime;
std::pair<std::string, double> mMinAllowableDeltaTime;
Copy link
Contributor

Choose a reason for hiding this comment

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

I would suggest to change the type to std::optional<double>, to make clear that it may or may not have a user-defined value. Perhaps we should rename the data member to reflect that, e.g. mMaybeMinDeltaTime?

Please also note that so far, it doesn't seem like you were using the string value.

AdaptiveTimeIncrementor::AdaptiveTimeIncrementor(double StartTime,
double EndTime,
double StartIncrement,
std::pair<std::string, double> MinAllowableDeltaTime,
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's move this new function parameter close to MaxTimeStepFactor, since the two parameters both bound the time increment.

Comment on lines +87 to +91
constexpr auto small_increment_factor = 1.0e-3;
if (auto small_time_increment = small_increment_factor * mDeltaTime;
rResultantState.time + mDeltaTime > mEndTime - small_time_increment) {
mDeltaTime = mEndTime - rResultantState.time;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's avoid introducing a second minimum time increment. Let's use the minimum time increment that you'll introduce with this PR. For instance:

Suggested change
constexpr auto small_increment_factor = 1.0e-3;
if (auto small_time_increment = small_increment_factor * mDeltaTime;
rResultantState.time + mDeltaTime > mEndTime - small_time_increment) {
mDeltaTime = mEndTime - rResultantState.time;
}
if (rResultantState.time < mEndTime && mEndTime - rResultantState.time - mDeltaTime <
mMaybeMinDeltaTime.value_or(default_min_delta_time)) {
// Up-scaling to reach end_time without small increment
mDeltaTime = mEndTime - rResultantState.time;
}

Note that similar changes are required in the Python code.

Comment on lines +42 to +43
self.min_delta_time_set = solver_settings["time_stepping"].Has("minimum_allowable_value")
self.min_delta_time = solver_settings["time_stepping"]["minimum_allowable_value"].GetDouble() if self.min_delta_time_set else 1e-10
Copy link
Contributor

Choose a reason for hiding this comment

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

We can use a single attribute that is set to None when the user didn't provide a value. If we then make a getter for the minimum delta time, we can account for the default value when the value equals None.

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.

4 participants