Skip to content

[Core] Load stepping feature#13877

Open
sunethwarna wants to merge 40 commits intomasterfrom
core/adaptive_time_abaqus_extension
Open

[Core] Load stepping feature#13877
sunethwarna wants to merge 40 commits intomasterfrom
core/adaptive_time_abaqus_extension

Conversation

@sunethwarna
Copy link
Member

📝 Description

** NO BEHAVIOR CHANGE IS THERE **

This PR adds load stepping controlling mechanism to try converging non-linear non-converged solutions by load stepping, and changing the time step. This is designed to work in two ways.

  1. Load stepping control, so the load should be dependent on t variable to this to work.
  2. In dynamic simulations, by reducing delta_t, and increasing mass effect to make the non-converging time steps to converge.

This requires all the entities used in the simulations does not hold any private member variables storing the state such as DISPLACEMENTS or VELOCITY since this requires resetting them. Currently this does not work with following element types:

  • CrBeamElement3D2N
  • CrBeamElement2D2N

I will wait until #13432 merged, so that there won't be conflicts from this branch to that.

🆕 Changelog

  • Added StepController class
  • Added DefaultStepController to have the existing behavior with no changes at all
  • Added GeometricStepController following the abaqus implementation of load stepping.

KratosMultiphysics.Logger.PrintInfo(self.__class__.__name__, f"Did not converge for time = {self.time}.")

current_step_controller_time = time_begin
while not step_controller.IsCompleted(current_step_controller_time, is_converged):
Copy link
Member

Choose a reason for hiding this comment

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

@KratosMultiphysics/technical-committee do we want to over complicate the base AnalysisStage like this? I believe that the feature is useful but...

Copy link
Member

Choose a reason for hiding this comment

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

I agree, this is lots of specialized code, IMO the base AnalysisStage is not the place for this

Copy link
Member

Choose a reason for hiding this comment

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

+1

"convergence_factor" : 1.5,
"delta_t_init" : 1.0,
"delta_t_min" : 1.0,
"delta_t_max" : 1.0,
Copy link
Member

Choose a reason for hiding this comment

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

delta_time for example would be clearer. What is divergence factor?

Copy link
Member

@RiccardoRossi RiccardoRossi left a comment

Choose a reason for hiding this comment

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

Blocking since the design needs to be reviewed and discussed by @KratosMultiphysics/technical-committee .

@sunethwarna can you schedule this for one of the upcoming meetings?

@sunethwarna
Copy link
Member Author

moved all the implementatiosn from core to the StructApp under a new derrived analysis.

@loumalouomega
Copy link
Member

 Running StructuralMechanicsApplication tests
Traceback (most recent call last):
  File "/__w/Kratos/Kratos/bin/Custom/applications/StructuralMechanicsApplication/tests/test_StructuralMechanicsApplication.py", line 247, in <module>
    from test_step_controller import TestStepControllers as TTestStepControllers
  File "/__w/Kratos/Kratos/bin/Custom/applications/StructuralMechanicsApplication/tests/test_step_controller.py", line 4, in <module>
    from KratosMultiphysics.step_controller import DefaultStepController, GeometricStepController
ModuleNotFoundError: No module named 'KratosMultiphysics.step_controller'

Looks like is missing something

Copy link
Member

@RiccardoRossi RiccardoRossi left a comment

Choose a reason for hiding this comment

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

nice PR. I have some comments (the most important is that the Predict needs to be treated as in other analysis stages), but overall i like the idea


# find the appropriate step controller for the given time frame
step_controller = None
for interval_utility, step_controller in reversed(list_of_step_controllers):
Copy link
Member

Choose a reason for hiding this comment

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

why don't you combine the step controllers in one? my guess is that it would be cleaner not to have to handle a list of step controllers

Copy link
Member Author

Choose a reason for hiding this comment

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

The reasoning is, the users wants to use different step controllers in different time ranges. This makes it possible. If you combine it to one, that granularity is gone as far as i understand.

Copy link
Contributor

Choose a reason for hiding this comment

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

What @RiccardoRossi probably means is to create smth like a CompoundStepController that applies different controllers on different time ranges.

The effect and flexibility is essentially the same, but the complexity is hidden in CompoundStepController instead of AnalysisStage. I think that's a valid point.

Copy link
Contributor

Choose a reason for hiding this comment

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

By the way, why is the list reversed?

@RiccardoRossi RiccardoRossi moved this from 👀 Next meeting TODO to 🏗 In progress in Technical Commiittee Feb 23, 2026

IsCompleted(current_time: float, is_converged: bool) -> bool
Check if the stepping process has been completed.
"""
Copy link
Contributor

Choose a reason for hiding this comment

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

Please convert all docstrings to doxygen style.

Comment on lines +80 to +82
default_parameters = Kratos.Parameters("""{
"type": "default_step_controller"
}""")
Copy link
Contributor

Choose a reason for hiding this comment

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

For future compatibility with JSON schemas, it'd be great if you could pull default params to a separate function (smth like GetDefaultParameters).

Comment on lines +121 to +135
Attributes:
__divergence_factor: Factor by which the time step is reduced after a failed attempt.
__convergence_factor: Factor by which the time step is increased after successful attempts.
__delta_t_init: Initial time step size.
__delta_t_min: Minimum allowed time step size.
__delta_t_max: Maximum allowed time step size.
__max_number_of_sub_steps: Maximum number of sub-steps allowed.
__number_of_successful_attempts_for_increment: Number of successful steps required to increase the time step.
__number_of_failed_attempts_for_termination: Number of failed steps allowed before termination.
__sub_stepping_iteration: Counter for the current sub-step iteration.
__success_full_attempts_count: Counter for successful attempts.
__failed_attempts_count: Counter for failed attempts.
__delta_time: Current time step size.
__time_begin: Start time of the stepping process.
__time_end: End time of the stepping process.
Copy link
Contributor

Choose a reason for hiding this comment

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

These are internal variables and must not be in the docs.

Comment on lines +19 to +31
@abstractmethod
def Initialize(self, time_begin: float, time_end: float) -> None:
"""
Initializes the step controller with the specified start and end times for current time step from the solver.

Args:
time_begin (float): The starting time of the current time step from the solver.
time_end (float): The ending time of the current time step from the solver.

Returns:
None
"""
pass
Copy link
Contributor

Choose a reason for hiding this comment

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

Why have a separate Initialize function? I'd rather construct a fresh step controller for every time step that gets initialized on construction and destroyed at the end of the time step.

This would help reduce confusion with the initialize/finalize chaos we have with solvers/processes/elements/schemes/strategies. I don't think we need yet another layer of init/fin ops to keep track of.

if self.__success_full_attempts_count > self.__number_of_successful_attempts_for_increment:
# now we increment the step
self.__delta_time = min(self.__convergence_factor * self.__delta_time, self.__delta_t_max)
Kratos.Logger.PrintInfo(self.__class__.__name__, f"Incrementing the delta time to {self.__delta_time}")
Copy link
Contributor

Choose a reason for hiding this comment

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

Please hide printing status info behind a verbosity check. We don't always need to pollute our output with this.


# find the appropriate step controller for the given time frame
step_controller = None
for interval_utility, step_controller in reversed(list_of_step_controllers):
Copy link
Contributor

Choose a reason for hiding this comment

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

What @RiccardoRossi probably means is to create smth like a CompoundStepController that applies different controllers on different time ranges.

The effect and flexibility is essentially the same, but the complexity is hidden in CompoundStepController instead of AnalysisStage. I think that's a valid point.


# find the appropriate step controller for the given time frame
step_controller = None
for interval_utility, step_controller in reversed(list_of_step_controllers):
Copy link
Contributor

Choose a reason for hiding this comment

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

By the way, why is the list reversed?

Comment on lines +28 to +29
def __get_serializer():
return Kratos.FileSerializer("serialization", Kratos.SerializerTraceType.SERIALIZER_NO_TRACE, True)
Copy link
Contributor

Choose a reason for hiding this comment

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

ugh

I'd like to see an in-memory solution to this. Please open a new PR or issue while we still have this in mind.

parameters = Kratos.Parameters(parameter_file.read())

model = Kratos.Model()
simulation = StructuralMechanicsAnalysis(model, parameters)
Copy link
Contributor

Choose a reason for hiding this comment

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

I thought you defined the new analysis type for a reason.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: 🏗 In progress

Development

Successfully merging this pull request may close these issues.

6 participants