Skip to content

Major issue in the ordering of Predict and InitializeSolutionStep (and of ConvergenceCriterion initialization) #13350

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

Open
SADPR opened this issue Apr 18, 2025 · 58 comments · May be fixed by #13432

Comments

@SADPR
Copy link
Contributor

SADPR commented Apr 18, 2025

Description

We are experiencing convergence issues when using a residual-based criterion in a nonlinear dynamic simulation with the following configuration. The solver fails due to converge (including singular matrix), even under moderate prescribed displacements. Switching to a displacement-based criterion allows convergence for some steps, but the simulation still fails eventually (possibly due to inverted elements).

Setup

  • Software versions:

    • KratosMultiphysics: master branch (latest)
    • GiD GUI: latest distributed version
  • Problem configuration:

    • Domain: 3D beam of length 43.2 m, approximate width: ~2 m, thickness: ~0.3–0.5 m
    • Element: Solid total Lagrangian
    • Constitutive law: Hyperelastic NeoHookean (HyperElastic3DLaw), also with KirchhoffSaintVenant3DLaw
    • Material: Steel
      • Density: 7850 kg/m³
      • Young's Modulus: 206.9 GPa
      • Poisson Ratio: 0.29
    • Analysis type: Dynamic nonlinear
    • Time integration: Implicit Newmark
    • Boundary conditions:
      • Left end: Fully fixed (Dirichlet = 0)
      • Right end: Prescribed displacement in the X direction: $$u_x(t) = t$$ with t being the current time in seconds.

Observed behavior

  • Using residual-based convergence criterion:

    • The simulation fails to converge at the first step.
  • Using displacement-based criterion:

    • Simulation progresses for several time steps.
    • Eventually fails — possibly due to element inversion or mesh distortion.
@SADPR
Copy link
Contributor Author

SADPR commented Apr 18, 2025

Issue.zip

@SADPR
Copy link
Contributor Author

SADPR commented Apr 18, 2025

Displacement Criterion:

Image

@AlejandroCornejo
Copy link
Member

Hi!

I've downloaded the files and managed to reproduce your problem. Let me cc @loumalouomega just in case he has some extra comments on this.

Increasing the echo_level to 1, we can see how the initial Obtained ratio = 4.96964e+11, so even though it manages to reduce it, it gets stucked in Obtained ratio = 70.5188. This is an issue that I identified in the past and, due to lack of time, I ended up increasing the abs norm tolerance, since this value is relatively low (Absolute norm = 3.9567e-06).

However, I feel that the calculation of the initial residual (the one with respect we compute the first ratio) may be not properly computed somehow. Maybe, since it is a nonlinear simulation, this is the best we can do, what do you think @loumalouomega ?

An additional tip, if you use the bossak scheme instead of newmark, besides the first step (similar behaviour), the remaining steps converge properly.

@loumalouomega
Copy link
Member

Hello, I am out of office until Wednesday. My first guess was going to test with the UL element, to check if the issue may come with a error in the reference position calculation. Your checks help too.

@matekelemen
Copy link
Contributor

matekelemen commented Apr 22, 2025

Just here to mention that I think deciding when and how to compute the initial residual of convergence criteria is something we should take a second look at.

Right now, all coupled analyses use incorrect residual ratios (#12394). ConvergenceCriteria computes its initial residual in InitializeSolutionStep, which only gets called once per time step. However, strong coupling runs SolveSolutionStep multiple times within the same time step, effectively launching nonlinear iterations with a completely unrelated initial residual.

FYI @juancamarotti

@loumalouomega
Copy link
Member

I checked my idea, with the UL element it works without any issue, but it is strange it does not work and converges for TL... I will do some further testing.

@loumalouomega
Copy link
Member

Just here to mention that I think deciding when and how to compute the initial residual of convergence criteria is something we should take a second look at.

Right now, all coupled analyses use incorrect residual ratios (#12394). ConvergenceCriteria computes its initial residual in InitializeSolutionStep, which only gets called once per time step. However, strong coupling runs SolveSolutionStep multiple times within the same time step, effectively launching nonlinear iterations with a completely unrelated initial residual.

FYI @juancamarotti

I agree, but this is a different issue. We must update the NR for this and the discussion will be painful IMHO, I recommend to open a new discussion just for this.

@loumalouomega
Copy link
Member

One more comment, using the skyline linear solver (the worst one) it crashes due to singular matrix.

@loumalouomega
Copy link
Member

The local RHS for UL and TL are the same in first 2 NL iterations, strange that the residual criterion diverges...

@loumalouomega
Copy link
Member

The local RHS for UL and TL are the same in first 2 NL iterations, strange that the residual criterion diverges...

Not exactly the same, there are some key elements where stresses differ significantly...

@loumalouomega
Copy link
Member

loumalouomega commented Apr 23, 2025

The local RHS for UL and TL are the same in first 2 NL iterations, strange that the residual criterion diverges...

Not exactly the same, there are some key elements where stresses differ significantly...

Okay, looks like a change in InvJ0, which by definition should be exactly the same... I cannot check further right now, I will continue checking later.

@loumalouomega
Copy link
Member

The local RHS for UL and TL are the same in first 2 NL iterations, strange that the residual criterion diverges...

Not exactly the same, there are some key elements where stresses differ significantly...

Okay, looks like a change in InvJ0, which by definition should be exactly the same... I cannot check further right now, I will continue checking later.

Ok, I found the error, the initial configuration is implemented twice, and the correct one is on the UL element.

@AlejandroCornejo
Copy link
Member

The local RHS for UL and TL are the same in first 2 NL iterations, strange that the residual criterion diverges...

Not exactly the same, there are some key elements where stresses differ significantly...

Okay, looks like a change in InvJ0, which by definition should be exactly the same... I cannot check further right now, I will continue checking later.

Ok, I found the error, the initial configuration is implemented twice, and the correct one is on the UL element.

wow! can you share a bit what is the problem? we should merge the bugfix asap haha. Jeeeeez we are still finding new bugs 0.0

@AlejandroCornejo
Copy link
Member

is this the method of evil?:

    /**
     * @brief Calculate the Jacobian on the initial configuration.
     * @param rGeom element geometry.
     * @param rCoords local coordinates of the current integration point.
     * @param rJ0 Jacobian on the initial configuration.
     */
    static void JacobianOnInitialConfiguration(
        GeometryType const& rGeom,
        GeometryType::CoordinatesArrayType const& rCoords,
        Matrix& rJ0
        )
    {
        Matrix delta_position(rGeom.PointsNumber(), rGeom.WorkingSpaceDimension());
        for (std::size_t i = 0; i < rGeom.PointsNumber(); ++i)
            for (std::size_t j = 0; j < rGeom.WorkingSpaceDimension(); ++j)
                delta_position(i, j) = rGeom[i].Coordinates()[j] -
                                       rGeom[i].GetInitialPosition().Coordinates()[j];
        rGeom.Jacobian(rJ0, rCoords, delta_position);
    }

@loumalouomega
Copy link
Member

is this the method of evil?:

/**
 * @brief Calculate the Jacobian on the initial configuration.
 * @param rGeom element geometry.
 * @param rCoords local coordinates of the current integration point.
 * @param rJ0 Jacobian on the initial configuration.
 */
static void JacobianOnInitialConfiguration(
    GeometryType const& rGeom,
    GeometryType::CoordinatesArrayType const& rCoords,
    Matrix& rJ0
    )
{
    Matrix delta_position(rGeom.PointsNumber(), rGeom.WorkingSpaceDimension());
    for (std::size_t i = 0; i < rGeom.PointsNumber(); ++i)
        for (std::size_t j = 0; j < rGeom.WorkingSpaceDimension(); ++j)
            delta_position(i, j) = rGeom[i].Coordinates()[j] -
                                   rGeom[i].GetInitialPosition().Coordinates()[j];
    rGeom.Jacobian(rJ0, rCoords, delta_position);
}

I have a branch with a fix, but I remember that that inconsistency is something we (@RiccardoRossi and I) discussed at the time. SO I think that should not be merged, and discussed in detail. What we can do until now, is to implement a move mesh process, because the origin of the actual issue is that the nodes moved in the BC process are not actually moved. One solution could be to implement a moving mesh process and execute it after setting the BC, this should fix the issue IMHO. Then we can discuss the inconsistency, that as I recall is on pourpose.

@loumalouomega
Copy link
Member

You can try #13366, you also need to add the following to the project parameters:

{
    "python_module" : "move_mesh_process",
    "kratos_module" : "KratosMultiphysics",
    "process_name"  : "MoveMeshProcess",
    "Parameters"    : {
        "model_part_name" : "Structure",
        "variable_name"   : "DISPLACEMENT",
        "interval"        : [0.0,"End"]
    }
}

ProjectParameters.json

@loumalouomega
Copy link
Member

You can try #13366, you also need to add the following to the project parameters:

{
"python_module" : "move_mesh_process",
"kratos_module" : "KratosMultiphysics",
"process_name" : "MoveMeshProcess",
"Parameters" : {
"model_part_name" : "Structure",
"variable_name" : "DISPLACEMENT",
"interval" : [0.0,"End"]
}
}

ProjectParameters.json

This PR only moves the mesh at the end of the BC process, so the jacobians are consistent with the UL framework. As I said, we should open a new discussion for the consistency of the solid elements.

@loumalouomega
Copy link
Member

You can try #13366, you also need to add the following to the project parameters:
{
"python_module" : "move_mesh_process",
"kratos_module" : "KratosMultiphysics",
"process_name" : "MoveMeshProcess",
"Parameters" : {
"model_part_name" : "Structure",
"variable_name" : "DISPLACEMENT",
"interval" : [0.0,"End"]
}
}
ProjectParameters.json

This PR only moves the mesh at the end of the BC process, so the jacobians are consistent with the UL framework. As I said, we should open a new discussion for the consistency of the solid elements.

I started discussion in #13367

@RiccardoRossi
Copy link
Member

sorry but here there is something very fishy to me. In my opinion the root of all evil for these elements is that we are making them to share a lot of code. IT would be way clearer to just have two very different implementations for Updated and Total, even if there is some code duplication.

In particular there is absolutely no reason for which the TotalLagrangian element would need to calculate "DeltaDisplacements" ...

you can compute J0 at the beginning (in the initialize) and the J at every step (the x is guaranteed to be changed as we always have MoveMesh=True when we are in the nonlinear range)

In short i would propose as a fix to reduce the code in common between Total and Updated to make their inner working more clear...

@RiccardoRossi
Copy link
Member

You can try #13366, you also need to add the following to the project parameters:

{
"python_module" : "move_mesh_process",
"kratos_module" : "KratosMultiphysics",
"process_name" : "MoveMeshProcess",
"Parameters" : {
"model_part_name" : "Structure",
"variable_name" : "DISPLACEMENT",
"interval" : [0.0,"End"]
}
}
ProjectParameters.json

this is NOT an option.

MoveMesh is set to True by default in all large deformation cases. This means that every time one updates displacements X is also updated

@loumalouomega
Copy link
Member

You can try #13366, you also need to add the following to the project parameters:
{
"python_module" : "move_mesh_process",
"kratos_module" : "KratosMultiphysics",
"process_name" : "MoveMeshProcess",
"Parameters" : {
"model_part_name" : "Structure",
"variable_name" : "DISPLACEMENT",
"interval" : [0.0,"End"]
}
}
ProjectParameters.json

this is NOT an option.

MoveMesh is set to True by default in all large deformation cases. This means that every time one updates displacements X is also updated

This is done AFTER setting the BC, for imposed displacements.

@loumalouomega
Copy link
Member

sorry but here there is something very fishy to me. In my opinion the root of all evil for these elements is that we are making them to share a lot of code. IT would be way clearer to just have two very different implementations for Updated and Total, even if there is some code duplication.

In particular there is absolutely no reason for which the TotalLagrangian element would need to calculate "DeltaDisplacements" ...

you can compute J0 at the beginning (in the initialize) and the J at every step (the x is guaranteed to be changed as we always have MoveMesh=True when we are in the nonlinear range)

In short i would propose as a fix to reduce the code in common between Total and Updated to make their inner working more clear...

This is a completely different discussion. We are speaking that there is an inconsitency of behaviour, precisely BECAUSE the are two different implementations, in fact the origin of the issue is that. Now we need to figure out if this was in pourpose or not.

@RiccardoRossi
Copy link
Member

well, if this is a difference than it should be fixed ... but without touching the strategy (unless someone modified it "recently")

@loumalouomega
Copy link
Member

well, if this is a difference than it should be fixed ... but without touching the strategy (unless someone modified it "recently")

It is not modified, I think it is by design, I also think that it is coherent that if we impose a displacement the mesh should be moved (even if no linear system is solved)

@RiccardoRossi
Copy link
Member

well, if this is a difference than it should be fixed ... but without touching the strategy (unless someone modified it "recently")

It is not modified, I think it is by design, I also think that it is coherent that if we impose a displacement the mesh should be moved (even if no linear system is solved)

In principle, unless there is a mistake, every time the update is called, the move mesh is also called...in particular this is done in the predict and in the update after the solution of the system.

My point is that the current settings should not be changed and if there is a change needed it should be in the element.

If at any point within the strwtegy x != x0 + disp_x that is a bug

@loumalouomega
Copy link
Member

I think the predict is not working as intended (maybe because quati static case)

@loumalouomega
Copy link
Member

I can confirm that there is something bizarre in the Predict

@loumalouomega
Copy link
Member

I can confirm that there is something bizarre in the Predict

Okay the issue is that the Predict is called after the initial residual in CC initialization. So or we move the prdict before of that of we rethink what to do. What do you suggest @RiccardoRossi ?

@RiccardoRossi
Copy link
Member

Puff...this is surely a big problem.

Can we possibly have a online call to see it together?

@loumalouomega
Copy link
Member

Puff...this is surely a big problem.

Can we possibly have a online call to see it together?

Yep, let's coordiante in a private channel.

@matekelemen
Copy link
Contributor

Just here to mention that I think deciding when and how to compute the initial residual of convergence criteria is something we should take a second look at.

Right now, all coupled analyses use incorrect residual ratios (#12394). ConvergenceCriteria computes its initial residual in InitializeSolutionStep, which only gets called once per time step. However, strong coupling runs SolveSolutionStep multiple times within the same time step, effectively launching nonlinear iterations with a completely unrelated initial residual.

Please keep this in mind during that call too.

@loumalouomega
Copy link
Member

Just here to mention that I think deciding when and how to compute the initial residual of convergence criteria is something we should take a second look at.
Right now, all coupled analyses use incorrect residual ratios (#12394). ConvergenceCriteria computes its initial residual in InitializeSolutionStep, which only gets called once per time step. However, strong coupling runs SolveSolutionStep multiple times within the same time step, effectively launching nonlinear iterations with a completely unrelated initial residual.

Please keep this in mind during that call too.

I am in favor of adding a flag and a method to set the flag, so it can be enforced to be reinitialized.

@RiccardoRossi RiccardoRossi added API Breaker Behaviour Change changes behaviour but not the API labels May 7, 2025
@RiccardoRossi RiccardoRossi changed the title Residual-based convergence criterion fails in nonlinear dynamic Neo-Hookean solid simulation Major issue in the ordering of Predict and InitializeSolutionStep (and of ConvergenceCriterion initialization) May 7, 2025
@RiccardoRossi RiccardoRossi moved this to 👀 Next meeting TODO in Technical Commiittee May 7, 2025
@RiccardoRossi
Copy link
Member

Ouch, i wrote yesterday i long post to describe the problem, and the kind of solution we need to have, but apparently it got lost when i changed the name of the issue.

So the big problem is that the AnalysisStage base class prescribes the following:

    def RunSolutionLoop(self):
        """This function executes the solution loop of the AnalysisStage
        It can be overridden by derived classes
        """
        while self.KeepAdvancingSolutionLoop():
            self.time = self._AdvanceTime()
        #--> here we first apply BCs, (for example DISPLACEMENT), than we call InitializeSolutionStep of the strategy, finally we initialize the convergence criteria : PROBLEM: when the process applied DISPLACEMENT, the coordinates are NOT changed, nor the VELOCITY and ACCELERATION in a dynamic problem. That is stuff is computed WRONGLY for structural or dynamic problems as the database is not correct.
            self.InitializeSolutionStep() 

            #this is where coordinats are changed (and VELOCITY and ACCELERATION are computed accordingly)
            self._GetSolver().Predict()

            is_converged = self._GetSolver().SolveSolutionStep()
            self.__CheckIfSolveSolutionStepReturnsAValue(is_converged)
            self.FinalizeSolutionStep()
            self.OutputSolutionStep()

in order for this to be correct we would need to do instead something of the type:

    def RunSolutionLoop(self):
        """This function executes the solution loop of the AnalysisStage
        It can be overridden by derived classes
        """
        while self.KeepAdvancingSolutionLoop():
            self.time = self._AdvanceTime()
            #--> here we first apply BCs, (for example DISPLACEMENT), 
            ApplyBCs()

            #this is where coordinats are changed (and VELOCITY and ACCELERATION are computed accordingly)
            self._GetSolver().Predict()

            self.InitializeSolutionStep() #changed

            self.InitializeConvergenceCriterion() #NEW



            is_converged = self._GetSolver().SolveSolutionStep()
            self.__CheckIfSolveSolutionStepReturnsAValue(is_converged)
            self.FinalizeSolutionStep()
            self.OutputSolutionStep()

big problem is that this is a change of the rule and would break a lot of things ... but we need to do something beacuase what is in there now is simply not correct

@AlejandroCornejo
Copy link
Member

I've been testing what @RiccardoRossi says.

As it is now, the iterative process looks like:

::[KSM Simulation]:: : STEP:  51
::[KSM Simulation]:: : TIME:  5.099999999999998
ResidualBasedNewtonRaphsonStrategy: System Construction Time: 8.9e-06 [s]
SolvingStrategy:  MESH MOVED
ResidualBasedBlockBuilderAndSolver: Build time: 0.0005 [s]
ResidualBasedBlockBuilderAndSolver: System solve time: 0.0005745 [s]
SolvingStrategy:  MESH MOVED
RESIDUAL CRITERION:  :: [ Obtained ratio = 5.36958e+09; Expected ratio = 1e-05; Absolute norm = 273819; Expected norm =  1e-09]
ResidualBasedBlockBuilderAndSolver: Build time: 0.0004964 [s]
ResidualBasedBlockBuilderAndSolver: System solve time: 0.0005337 [s]
SolvingStrategy:  MESH MOVED
RESIDUAL CRITERION:  :: [ Obtained ratio = 1.52203e+09; Expected ratio = 1e-05; Absolute norm = 77615.2; Expected norm =  1e-09]
ResidualBasedBlockBuilderAndSolver: Build time: 0.0007256 [s]
ResidualBasedBlockBuilderAndSolver: System solve time: 0.0005115 [s]
SolvingStrategy:  MESH MOVED
RESIDUAL CRITERION:  :: [ Obtained ratio = 347784; Expected ratio = 1e-05; Absolute norm = 17.7351; Expected norm =  1e-09]
ResidualBasedBlockBuilderAndSolver: Build time: 0.0007598 [s]
ResidualBasedBlockBuilderAndSolver: System solve time: 0.0005052 [s]
SolvingStrategy:  MESH MOVED
RESIDUAL CRITERION:  :: [ Obtained ratio = 51.6563; Expected ratio = 1e-05; Absolute norm = 0.00263419; Expected norm =  1e-09]
ResidualBasedBlockBuilderAndSolver: Build time: 0.0004978 [s]
ResidualBasedBlockBuilderAndSolver: System solve time: 0.0005207 [s]
SolvingStrategy:  MESH MOVED
RESIDUAL CRITERION:  :: [ Obtained ratio = 0.907096; Expected ratio = 1e-05; Absolute norm = 4.62569e-05; Expected norm =  1e-09]
ResidualBasedBlockBuilderAndSolver: Build time: 0.0004988 [s]
ResidualBasedBlockBuilderAndSolver: System solve time: 0.0005076 [s]
SolvingStrategy:  MESH MOVED
RESIDUAL CRITERION:  :: [ Obtained ratio = 0.743848; Expected ratio = 1e-05; Absolute norm = 3.79322e-05; Expected norm =  1e-09]
ResidualBasedBlockBuilderAndSolver: Build time: 0.0007224 [s]
ResidualBasedBlockBuilderAndSolver: System solve time: 0.000483 [s]
SolvingStrategy:  MESH MOVED
RESIDUAL CRITERION:  :: [ Obtained ratio = 0.868073; Expected ratio = 1e-05; Absolute norm = 4.4267e-05; Expected norm =  1e-09]
ResidualBasedBlockBuilderAndSolver: Build time: 0.0007203 [s]
ResidualBasedBlockBuilderAndSolver: System solve time: 0.0005218 [s]
SolvingStrategy:  MESH MOVED
RESIDUAL CRITERION:  :: [ Obtained ratio = 0.722733; Expected ratio = 1e-05; Absolute norm = 3.68554e-05; Expected norm =  1e-09]
ResidualBasedBlockBuilderAndSolver: Build time: 0.0007165 [s]
ResidualBasedBlockBuilderAndSolver: System solve time: 0.0005318 [s]
SolvingStrategy:  MESH MOVED
RESIDUAL CRITERION:  :: [ Obtained ratio = 0.907491; Expected ratio = 1e-05; Absolute norm = 4.62771e-05; Expected norm =  1e-09]
ResidualBasedBlockBuilderAndSolver: Build time: 0.0005262 [s]
ResidualBasedBlockBuilderAndSolver: System solve time: 0.0005063 [s]
SolvingStrategy:  MESH MOVED
RESIDUAL CRITERION:  :: [ Obtained ratio = 0.732197; Expected ratio = 1e-05; Absolute norm = 3.7338e-05; Expected norm =  1e-09]
ResidualBasedNewtonRaphsonStrategy: ATTENTION: max iterations ( 10 ) exceeded!
[WARNING] ::[MechanicalSolver]:: : Solver did not converge for step 51

And by doing the Predict() before the InitializeSolutionStep():

::[KSM Simulation]:: : STEP:  51
::[KSM Simulation]:: : TIME:  5.099999999999998
SolvingStrategy:  MESH MOVED
ResidualBasedNewtonRaphsonStrategy: System Construction Time: 4e-06 [s]
ResidualBasedBlockBuilderAndSolver: Build time: 0.0007338 [s]
ResidualBasedBlockBuilderAndSolver: System solve time: 0.0006731 [s]
SolvingStrategy:  MESH MOVED
RESIDUAL CRITERION:  :: [ Obtained ratio = 0.00494645; Expected ratio = 1e-05; Absolute norm = 277160; Expected norm =  1e-09]
ResidualBasedBlockBuilderAndSolver: Build time: 0.0004273 [s]
ResidualBasedBlockBuilderAndSolver: System solve time: 0.0005533 [s]
SolvingStrategy:  MESH MOVED
RESIDUAL CRITERION:  :: [ Obtained ratio = 0.00159701; Expected ratio = 1e-05; Absolute norm = 89484.1; Expected norm =  1e-09]
ResidualBasedBlockBuilderAndSolver: Build time: 0.0005356 [s]
ResidualBasedBlockBuilderAndSolver: System solve time: 0.0005435 [s]
SolvingStrategy:  MESH MOVED
RESIDUAL CRITERION:  :: [ Obtained ratio = 3.91857e-07; Expected ratio = 1e-05; Absolute norm = 21.9566; Expected norm =  1e-09]
RESIDUAL CRITERION: Convergence is achieved
ResidualBasedNewtonRaphsonStrategy: Convergence achieved after 3 / 10 iterations

@loumalouomega
Copy link
Member

Ouch, i wrote yesterday i long post to describe the problem, and the kind of solution we need to have, but apparently it got lost when i changed the name of the issue.

So the big problem is that the AnalysisStage base class prescribes the following:

def RunSolutionLoop(self):
    """This function executes the solution loop of the AnalysisStage
    It can be overridden by derived classes
    """
    while self.KeepAdvancingSolutionLoop():
        self.time = self._AdvanceTime()
    #--> here we first apply BCs, (for example DISPLACEMENT), than we call InitializeSolutionStep of the strategy, finally we initialize the convergence criteria : PROBLEM: when the process applied DISPLACEMENT, the coordinates are NOT changed, nor the VELOCITY and ACCELERATION in a dynamic problem. That is stuff is computed WRONGLY for structural or dynamic problems as the database is not correct.
        self.InitializeSolutionStep() 

        #this is where coordinats are changed (and VELOCITY and ACCELERATION are computed accordingly)
        self._GetSolver().Predict()

        is_converged = self._GetSolver().SolveSolutionStep()
        self.__CheckIfSolveSolutionStepReturnsAValue(is_converged)
        self.FinalizeSolutionStep()
        self.OutputSolutionStep()

in order for this to be correct we would need to do instead something of the type:

def RunSolutionLoop(self):
    """This function executes the solution loop of the AnalysisStage
    It can be overridden by derived classes
    """
    while self.KeepAdvancingSolutionLoop():
        self.time = self._AdvanceTime()
        #--> here we first apply BCs, (for example DISPLACEMENT), 
        ApplyBCs()

        #this is where coordinats are changed (and VELOCITY and ACCELERATION are computed accordingly)
        self._GetSolver().Predict()

        self.InitializeSolutionStep() #changed

        self.InitializeConvergenceCriterion() #NEW



        is_converged = self._GetSolver().SolveSolutionStep()
        self.__CheckIfSolveSolutionStepReturnsAValue(is_converged)
        self.FinalizeSolutionStep()
        self.OutputSolutionStep()

big problem is that this is a change of the rule and would break a lot of things ... but we need to do something beacuase what is in there now is simply not correct

In favour of @RiccardoRossi design. It may be useful for @matekelemen as well.

FYI @KratosMultiphysics/altair

In fact FYI @KratosMultiphysics/all

@RiccardoRossi
Copy link
Member

After iterating in the @KratosMultiphysics/technical-committee the working idea is to have the following modification to the base class analysis_stage

    def RunSolutionLoop(self):
        """This function executes the solution loop of the AnalysisStage
        It can be overridden by derived classes
        """
        while self.KeepAdvancingSolutionLoop():
            self.time = self._AdvanceTime()
            self.InitializeSolutionStep()
            ###self._GetSolver().Predict() remove this from here
            is_converged = self._GetSolver().SolveSolutionStep()
            self.__CheckIfSolveSolutionStepReturnsAValue(is_converged)
            self.FinalizeSolutionStep()
            self.OutputSolutionStep()

and to modfy the InitializeSolutionStage as follows:

    def InitializeSolutionStep(self):
        """This function performs all the required operations that should be executed
        (for each step) BEFORE solving the solution step.
        """
        self.PrintAnalysisStageProgressInformation()

        self.ApplyBoundaryConditions() #here the processes are called
        self.ChangeMaterialProperties() #this is normally empty
        self._GetSolver().Predict() ##add the predict here
        self._GetSolver().InitializeSolutionStep()

the message would then be that after "InitializeSolutionStep" everything is ready for the SolveSolutionStep.

@KratosMultiphysics/technical-committee delegates to @RiccardoRossi the coordination of this change.

@loumalouomega @AlejandroCornejo i will eventually make an online meeting also with other stakeholders about this

@loumalouomega
Copy link
Member

After iterating in the @KratosMultiphysics/technical-committee the working idea is to have the following modification to the base class analysis_stage

def RunSolutionLoop(self):
    """This function executes the solution loop of the AnalysisStage
    It can be overridden by derived classes
    """
    while self.KeepAdvancingSolutionLoop():
        self.time = self._AdvanceTime()
        self.InitializeSolutionStep()
        ###self._GetSolver().Predict() remove this from here
        is_converged = self._GetSolver().SolveSolutionStep()
        self.__CheckIfSolveSolutionStepReturnsAValue(is_converged)
        self.FinalizeSolutionStep()
        self.OutputSolutionStep()

and to modfy the InitializeSolutionStage as follows:

def InitializeSolutionStep(self):
    """This function performs all the required operations that should be executed
    (for each step) BEFORE solving the solution step.
    """
    self.PrintAnalysisStageProgressInformation()

    self.ApplyBoundaryConditions() #here the processes are called
    self.ChangeMaterialProperties() #this is normally empty
    self._GetSolver().Predict() ##add the predict here
    self._GetSolver().InitializeSolutionStep()

the message would then be that after "InitializeSolutionStep" everything is ready for the SolveSolutionStep.

@KratosMultiphysics/technical-committee delegates to @RiccardoRossi the coordination of this change.

@loumalouomega @AlejandroCornejo i will eventually make an online meeting also with other stakeholders about this

This what I did in my internal drafts and at least for the test that was failign it was working, but maybe the CI will fail...

@RiccardoRossi
Copy link
Member

yes, the point is that this implies "hiding" the predict, which is not a choice i personally love...but we have no cleaner solution!

In any case i will brief people @KratosMultiphysics/geomechanics for whom this change may be very problematic and organize a meeting about this with the different stackholders.

btw, is there someone who should be CC-d about the co-simulation? @philbucher possibly?

@mcgicjn2
Copy link
Contributor

Noted. We will assess the impact of both the problem and the proposed solution here; and please invite us to the meeting.

RiccardoRossi added a commit that referenced this issue May 15, 2025
This is the very first step towards attempting to solve #13350

@loumalouomega @AlejandroCornejo @mcgicjn2
@RiccardoRossi
Copy link
Member

on my side i would have availability for a meeting on monday or in the early afternoon of tuesday. If needed it could be also on wednesday morning

After that i am travelling until the end of the week

@RiccardoRossi
Copy link
Member

well this is a tentative meeting time for monday 14-15

Tentative Meeting about #13350
Monday, 19 May · 2:00 – 3:00pm
Time zone: Europe/Madrid
Google Meet joining info
Video call link: https://meet.google.com/kvd-kabk-evd

please propose a different slot if it is not doable

loumalouomega added a commit that referenced this issue May 21, 2025
…tive-remeshing-scripts

[ContactStructuralMechanicsApplication] Update adaptive remeshing scripts for #13350
@WPK4FEM
Copy link
Contributor

WPK4FEM commented Jun 3, 2025

From @KratosMultiphysics/geomechanics there are no objections against the change proposed by @RiccardoRossi. We can and will adapt our code accordingly. No test failures should emerge from that change. Those that failed at our first trial have been adapted/corrected and should not fail anymore. Thank you for the clarification, suggestions and help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: 👀 Next meeting TODO
Development

Successfully merging a pull request may close this issue.

8 participants