-
Notifications
You must be signed in to change notification settings - Fork 251
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
base: master
Are you sure you want to change the base?
Changes from 13 commits
3df6c93
af922ed
800d260
d3009b1
0e67804
a176a87
9bd1ee3
9a936a0
0bca4e1
32f4198
18e69e1
449ac95
b6d6e6c
407d2cf
f14881b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -19,9 +19,10 @@ | |||||||||||||||||||||
namespace Kratos | ||||||||||||||||||||||
{ | ||||||||||||||||||||||
|
||||||||||||||||||||||
AdaptiveTimeIncrementor::AdaptiveTimeIncrementor(double StartTime, | ||||||||||||||||||||||
double EndTime, | ||||||||||||||||||||||
double StartIncrement, | ||||||||||||||||||||||
AdaptiveTimeIncrementor::AdaptiveTimeIncrementor(double StartTime, | ||||||||||||||||||||||
double EndTime, | ||||||||||||||||||||||
double StartIncrement, | ||||||||||||||||||||||
std::pair<std::string, double> MinAllowableDeltaTime, | ||||||||||||||||||||||
std::size_t MaxNumOfCycles, | ||||||||||||||||||||||
double ReductionFactor, | ||||||||||||||||||||||
double IncreaseFactor, | ||||||||||||||||||||||
|
@@ -31,6 +32,7 @@ AdaptiveTimeIncrementor::AdaptiveTimeIncrementor(double StartTime, | |||||||||||||||||||||
: TimeIncrementor(), | ||||||||||||||||||||||
mEndTime(EndTime), | ||||||||||||||||||||||
mDeltaTime(std::min(StartIncrement, EndTime - StartTime)), // avoid exceeding the end time | ||||||||||||||||||||||
mMinAllowableDeltaTime(std::move(MinAllowableDeltaTime)), | ||||||||||||||||||||||
mMaxNumOfCycles(MaxNumOfCycles), | ||||||||||||||||||||||
mReductionFactor(ReductionFactor), | ||||||||||||||||||||||
mIncreaseFactor(IncreaseFactor), | ||||||||||||||||||||||
|
@@ -73,21 +75,31 @@ double AdaptiveTimeIncrementor::GetIncrement() const { return mDeltaTime; } | |||||||||||||||||||||
|
||||||||||||||||||||||
void AdaptiveTimeIncrementor::PostTimeStepExecution(const TimeStepEndState& rResultantState) | ||||||||||||||||||||||
{ | ||||||||||||||||||||||
if (rResultantState.NonConverged() || | ||||||||||||||||||||||
(rResultantState.Converged() && (rResultantState.num_of_iterations == mMaxNumOfIterations))) { | ||||||||||||||||||||||
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 | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.num_of_iterations < mMinNumOfIterations) { | ||||||||||||||||||||||
mDeltaTime = std::min(mDeltaTime * mIncreaseFactor, mMaxDeltaTime); | ||||||||||||||||||||||
} else if (rResultantState.num_of_iterations == mMaxNumOfIterations) { | ||||||||||||||||||||||
mDeltaTime *= mReductionFactor; | ||||||||||||||||||||||
} | ||||||||||||||||||||||
Comment on lines
+84
to
+86
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? |
||||||||||||||||||||||
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; | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I'm correct this could be const auto
Suggested change
|
||||||||||||||||||||||
rResultantState.time + mDeltaTime > mEndTime - small_time_increment) { | ||||||||||||||||||||||
mDeltaTime = mEndTime - rResultantState.time; | ||||||||||||||||||||||
} | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Note that similar changes are required in the Python code. |
||||||||||||||||||||||
} | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
// Avoid incrementing the time beyond the end time | ||||||||||||||||||||||
mDeltaTime = std::min(mDeltaTime, mEndTime - rResultantState.time); | ||||||||||||||||||||||
|
||||||||||||||||||||||
// Avoid very small remaining time steps | ||||||||||||||||||||||
const auto small_time_increment = 1.E-3 * mDeltaTime; | ||||||||||||||||||||||
if ((mEndTime - (rResultantState.time + mDeltaTime)) < small_time_increment) { | ||||||||||||||||||||||
mDeltaTime = mEndTime - rResultantState.time; | ||||||||||||||||||||||
else { | ||||||||||||||||||||||
// non converged, scale down step and restart | ||||||||||||||||||||||
mDeltaTime *= mReductionFactor; | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
KRATOS_ERROR_IF(mDeltaTime < mMinAllowableDeltaTime.second) | ||||||||||||||||||||||
<< "Delta time (" << mDeltaTime << ") is smaller than " << mMinAllowableDeltaTime.first << " minimum allowable value " | ||||||||||||||||||||||
<< mMinAllowableDeltaTime.second << std::endl; | ||||||||||||||||||||||
} | ||||||||||||||||||||||
|
||||||||||||||||||||||
} // namespace Kratos |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,37 +15,40 @@ | |
|
||
#include "includes/kratos_export_api.h" | ||
#include "time_incrementor.h" | ||
#include <string> | ||
|
||
namespace Kratos | ||
{ | ||
|
||
class KRATOS_API(GEO_MECHANICS_APPLICATION) AdaptiveTimeIncrementor : public TimeIncrementor | ||
{ | ||
public: | ||
AdaptiveTimeIncrementor(double StartTime, | ||
double EndTime, | ||
double StartIncrement, | ||
std::size_t MaxNumOfCycles = 10, | ||
double ReductionFactor = 0.5, | ||
double IncreaseFactor = 2.0, | ||
double MaxTimeStepFactor = 1000.0, | ||
std::size_t MinNumOfIterations = 3, | ||
std::size_t MaxNumOfIterations = 15); | ||
AdaptiveTimeIncrementor(double StartTime, | ||
double EndTime, | ||
double StartIncrement, | ||
std::pair<std::string, double> MinAllowableDeltaTime, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
std::size_t MaxNumOfCycles = 10, | ||
double ReductionFactor = 0.5, | ||
double IncreaseFactor = 2.0, | ||
double MaxTimeStepFactor = 1000.0, | ||
std::size_t MinNumOfIterations = 3, | ||
std::size_t MaxNumOfIterations = 15); | ||
|
||
[[nodiscard]] bool WantNextStep(const TimeStepEndState& rPreviousState) const override; | ||
[[nodiscard]] bool WantRetryStep(std::size_t CycleNumber, const TimeStepEndState& rPreviousState) const override; | ||
[[nodiscard]] double GetIncrement() const override; | ||
void PostTimeStepExecution(const TimeStepEndState& rResultantState) override; | ||
|
||
private: | ||
double mEndTime; | ||
double mDeltaTime; | ||
std::size_t mMaxNumOfCycles; | ||
double mReductionFactor; | ||
double mIncreaseFactor; | ||
double mMaxDeltaTime; | ||
std::size_t mMinNumOfIterations; | ||
std::size_t mMaxNumOfIterations; | ||
double mEndTime; | ||
double mDeltaTime; | ||
std::pair<std::string, double> mMinAllowableDeltaTime; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would suggest to change the type to Please also note that so far, it doesn't seem like you were using the string value. |
||
std::size_t mMaxNumOfCycles; | ||
double mReductionFactor; | ||
double mIncreaseFactor; | ||
double mMaxDeltaTime; | ||
std::size_t mMinNumOfIterations; | ||
std::size_t mMaxNumOfIterations; | ||
}; | ||
|
||
} // namespace Kratos |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,6 +39,8 @@ def __init__(self, model, project_parameters): | |
self.min_iterations = solver_settings["min_iterations"].GetInt() | ||
self.max_delta_time_factor = solver_settings["time_stepping"]["max_delta_time_factor"].GetDouble() if solver_settings["time_stepping"].Has("max_delta_time_factor") else 1000.0 | ||
self.max_delta_time = self.delta_time * self.max_delta_time_factor | ||
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can use a single attribute that is set to |
||
self.number_cycles = solver_settings["number_cycles"].GetInt() | ||
self.max_iterations = solver_settings["max_iterations"].GetInt() | ||
self.solution_type = solver_settings["solution_type"].GetString() | ||
|
@@ -70,7 +72,16 @@ def FinalizeSolutionStep(self): | |
super().FinalizeSolutionStep() | ||
|
||
if self._GetSolver().GetComputingModelPart().ProcessInfo[KratosMultiphysics.NL_ITERATION_NUMBER] > self.max_iterations: | ||
raise Exception("max_number_of_iterations_exceeded") | ||
raise RuntimeError("max_number_of_iterations_exceeded") | ||
|
||
def _check_delta_time_size(self): | ||
if self.delta_time < self.min_delta_time: | ||
if self.min_delta_time_set: | ||
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 settings in Project Parameters and Materials Files.") | ||
raise RuntimeError('The time step is too small!') | ||
|
||
def RunSolutionLoop(self): | ||
"""This function executes the solution loop of the AnalysisStage | ||
|
@@ -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() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
|
||
# start the new step | ||
self._GetSolver().GetComputingModelPart().ProcessInfo[KratosMultiphysics.STEP] += 1 | ||
self._GetSolver().main_model_part.CloneTimeStep(new_time) | ||
|
@@ -146,14 +159,15 @@ def RunSolutionLoop(self): | |
# scale down step and restart | ||
KratosMultiphysics.Logger.PrintInfo(self._GetSimulationName(), "Down-scaling with factor: ", self.reduction_factor) | ||
self.delta_time *= self.reduction_factor | ||
self._check_delta_time_size() | ||
# Reset displacements to the initial | ||
KratosMultiphysics.VariableUtils().UpdateCurrentPosition(self._GetSolver().GetComputingModelPart().Nodes, KratosMultiphysics.DISPLACEMENT,1) | ||
for node in self._GetSolver().GetComputingModelPart().Nodes: | ||
dold = node.GetSolutionStepValue(KratosMultiphysics.DISPLACEMENT,1) | ||
node.SetSolutionStepValue(KratosMultiphysics.DISPLACEMENT, 0, dold) | ||
|
||
if not converged: | ||
raise Exception('The maximum number of cycles is reached without convergence!') | ||
raise RuntimeError('The maximum number of cycles is reached without convergence!') | ||
|
||
if self._GetSolver().settings["reset_displacements"].GetBool(): | ||
for idx, node in enumerate(self._GetSolver().GetComputingModelPart().Nodes): | ||
|
@@ -210,7 +224,7 @@ def _GetSimulationName(self): | |
err_msg += ' "python geomechanics_analysis.py"\n' | ||
err_msg += '- With custom parameter file:\n' | ||
err_msg += ' "python geomechanics_analysis.py <my-parameter-file>.json"\n' | ||
raise Exception(err_msg) | ||
raise TypeError(err_msg) | ||
|
||
if len(argv) == 2: # ProjectParameters is being passed from outside | ||
parameter_file_name = argv[1] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ | |
// | ||
// Main authors: Wijtze Pieter Kikstra | ||
// Anne van de Graaf | ||
// Richard Faasse | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not Gennady too? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because Richard gave more tests. I adapted them a little. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you still should add your own name here as well :) |
||
// | ||
|
||
#include "custom_workflows/adaptive_time_incrementor.h" | ||
|
@@ -21,24 +22,25 @@ namespace | |
{ | ||
|
||
struct AdaptiveTimeIncrementorSettings { | ||
double StartTime{0.0}; | ||
double EndTime{8.0}; | ||
double StartIncrement{0.5}; | ||
std::size_t MaxNumOfCycles{8}; | ||
double ReductionFactor{0.5}; | ||
double IncreaseFactor{2.0}; | ||
double MaxDeltaTimeFactor{1000.0}; | ||
std::size_t MinNumOfIterations{3}; | ||
std::size_t MaxNumOfIterations{15}; | ||
double StartTime{0.0}; | ||
double EndTime{8.0}; | ||
double StartIncrement{0.5}; | ||
std::pair<std::string, double> MinAllowableDeltaTime{"given", 1e-06}; | ||
std::size_t MaxNumOfCycles{8}; | ||
double ReductionFactor{0.5}; | ||
double IncreaseFactor{2.0}; | ||
double MaxDeltaTimeFactor{1000.0}; | ||
std::size_t MinNumOfIterations{3}; | ||
std::size_t MaxNumOfIterations{15}; | ||
}; | ||
|
||
AdaptiveTimeIncrementor MakeAdaptiveTimeIncrementor(const AdaptiveTimeIncrementorSettings& rSettings) | ||
{ | ||
return AdaptiveTimeIncrementor{rSettings.StartTime, rSettings.EndTime, | ||
rSettings.StartIncrement, rSettings.MaxNumOfCycles, | ||
rSettings.ReductionFactor, rSettings.IncreaseFactor, | ||
rSettings.MaxDeltaTimeFactor, rSettings.MinNumOfIterations, | ||
rSettings.MaxNumOfIterations}; | ||
rSettings.StartIncrement, rSettings.MinAllowableDeltaTime, | ||
rSettings.MaxNumOfCycles, rSettings.ReductionFactor, | ||
rSettings.IncreaseFactor, rSettings.MaxDeltaTimeFactor, | ||
rSettings.MinNumOfIterations, rSettings.MaxNumOfIterations}; | ||
} | ||
|
||
} // namespace | ||
|
@@ -427,4 +429,38 @@ KRATOS_TEST_CASE_IN_SUITE(ScaleIncrementToAvoidExtraSmallTimeStep, KratosGeoMech | |
KRATOS_EXPECT_DOUBLE_EQ(8.0, time_incrementor.GetIncrement()); | ||
} | ||
|
||
KRATOS_TEST_CASE_IN_SUITE(ThrowExceptionWhenDeltaTimeSmallerThanTheLimit, KratosGeoMechanicsFastSuiteWithoutKernel) | ||
{ | ||
AdaptiveTimeIncrementorSettings settings; // with EndTime = 8.0 | ||
settings.StartIncrement = 8.0; // We jump to the end time right away | ||
auto time_incrementor = MakeAdaptiveTimeIncrementor(settings); | ||
auto previous_state = TimeStepEndState{}; | ||
previous_state.convergence_state = TimeStepEndState::ConvergenceState::converged; | ||
previous_state.time = 7.9999999; // to have a zero time step | ||
|
||
KRATOS_EXPECT_EXCEPTION_IS_THROWN( | ||
time_incrementor.PostTimeStepExecution(previous_state), | ||
"Delta time (1e-07) is smaller than given minimum allowable value 1e-06"); | ||
|
||
previous_state.convergence_state = TimeStepEndState::ConvergenceState::non_converged; | ||
|
||
KRATOS_EXPECT_EXCEPTION_IS_THROWN( | ||
time_incrementor.PostTimeStepExecution(previous_state), | ||
"Delta time (5e-08) is smaller than given minimum allowable value 1e-06"); | ||
} | ||
|
||
KRATOS_TEST_CASE_IN_SUITE(HalfTimeStepAtNonConverged, KratosGeoMechanicsFastSuiteWithoutKernel) | ||
{ | ||
AdaptiveTimeIncrementorSettings settings; // with EndTime = 8.0 | ||
settings.StartIncrement = 8.0; // We jump to the end time right away | ||
auto time_incrementor = MakeAdaptiveTimeIncrementor(settings); | ||
auto previous_state = TimeStepEndState{}; | ||
previous_state.convergence_state = TimeStepEndState::ConvergenceState::non_converged; | ||
previous_state.time = 8.0; | ||
|
||
time_incrementor.PostTimeStepExecution(previous_state); | ||
// The increment should be halved, since the step didn't converge | ||
KRATOS_EXPECT_DOUBLE_EQ(4.0, time_incrementor.GetIncrement()); | ||
} | ||
|
||
} // namespace Kratos::Testing |
There was a problem hiding this comment.
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.