Table of contents
You might be asking yourself, “What type of problem could benefit from the solver’s ability to independently terminate a step or the entire analysis?”
Well, let’s take the model below as an example. It’s a simplified representation of a 3-point bend test, used during TECHNIA Simulation training sessions to examine the impact of different non-linearities on the best simulation strategy to employ. All elements are present: contact (with friction), geometric non-linearity, and, crucially for this discussion, plasticity, which is simplified to a bi-linear elastic-plastic response.
The simulation comprises two static steps. Mechanically, the two lower rollers are fixed, and the upper crosshead is moved downward to bend the bar and induce plastic deformation during the first step of the simulation. In the second step, the crosshead is returned to its original position to observe the elastic springback and residual deformation of the part.
To enhance convergence in the loading step (where the residual forces in the bar are balanced solely by the contact forces on both its top and bottom faces) and, importantly, to efficiently return the crosshead to its initial position in the unloading step, the crosshead is driven under displacement control.
Upon running this model, we observe the expected overall mechanical response. If we plot the reaction force at the crosshead, we can see the change in gradient of the reaction force due to the evolving non-linearity in the system.
NB: You might notice that the reaction force does not reduce to zero as the crosshead displacement moves it out of contact with the bar. In this case, a small amount of automatic stabilization is used in the unloading step to prevent the bar from wandering off, and no other loads are applied. As the crosshead is also moving against the viscosity of this automatic stabilization, a small force is needed to achieve that. Part of the learning from the tutorial is judging if automatic stabilization is significantly affecting the underlying mechanical behavior.
This model solves very efficiently under displacement control in both steps, and we achieve the desired response.
But what if we examine these results and realize that what we actually want to achieve is a reaction force of, for example, -4500N in the first step to better replicate the physical test and not just apply a fixed displacement and see what happens?
Well, there are several ways to achieve this, but as the model and study get more complex, it may be more convenient to maintain the displacement-control workflow and allow the Abaqus solver to autonomously terminate the displacement control loading step at a predefined crosshead (reaction) load.
So, what options do we have in Abaqus/Standard?
While the XIT subroutine utility doesn’t quite hit the mark for our goals, which is something we’re aiming for, it’s a straightforward tool for ending an analysis when certain conditions are met. If you’re new to Abaqus subroutines and need help setting up compilers, check out our guide or reach out for assistance.
Also, as a general point, using Abaqus subroutines inevitably requires some Fortran programming skills. Therefore, it’s worth noting that this blog is not an exhaustive guide to implementing subroutines but does outline possible solutions for this specific analysis scenario.
The first thing we need to do is prepare the model to allow a subroutine to interact with it, passing data between the solver and the subroutine. In this case, we’ll use the UAMP subroutine. Some of these modifications can be achieved in Abaqus/CAE, but in this case, we’ll do it by hand. The necessary keyword edits to the basic model are shown below.
To the ‘model data’ of the input file (everything defining the model itself before the step data), we need to define an amplitude, which will be the way the analysis interacts with the UAMP subroutine, and a NSET at the location we want to define a ‘sensor’ to monitor the reaction force. In this case, the control node for the crosshead where the displacement is applied is the obvious location for our sensor.
Now, in the step data for the loading step, we’ll define a dummy CLOAD of zero force for the amplitude to operate on as we’re applying a displacement to the crosshead which follows the default RAMP definition.
And finally, also in the step data for the loading step, we create the sensor history output for the reaction force at the crosshead loading point, in the direction the displacement is applied, which will be passed to the subroutine for the conditional check.
So, now we’ve adjusted the Abaqus input file to pass useful data out to a subroutine. We now need to create a subroutine, using the documented UAMP template as a basis, and add the following statements, which will:
The XIT command is recognized by most Abaqus subroutines; we’ve just used UAMP conveniently here to investigate other options later.
Assuming a Fortran compiler is installed and linked to the version of Abaqus executed, we can execute this job with the command line options:
abaqus job=<Job-name> user=<subroutine_name>.f
When we run the job, the solution proceeds as normal, until reaching the first converged increment where the reaction force at the sensor node is of a greater magnitude than the user-specified threshold value. At this point the XIT command is executed, and the analysis terminates cleanly.
The status file message “THE ANALYSIS HAS NOT BEEN COMPLETED” is issued as the solver sees that something happened to stop it reaching the end of the loading history.
This is quite neat and easy to set up, but it doesn’t meet our requirements in two ways:
Improving on the XIT utility, the UAMP subroutine offers a built-in variable that tells the solver to either continue or end a step. By tweaking the subroutine and input file, we can end a step at a specified reaction force and smoothly transition to the next step. This method gets us closer to our goal, but achieving the precise threshold value remains a challenge.
The first thing to observe is that there is a handy inbuilt variable to the UAMP subroutine that we can set, and that the solver knows what to do with.
If we set:
So, by simply replacing the XIT command lFlagsDefine(iConcludeStep) = 1 in our subroutine, we achieve the same outcome with functionality already built into the subroutine, not an external command. This is an improvement in functionality compared to XIT, as only the step is terminated, and the solver moves on to any subsequent steps in the loading sequence.
However, in the second/unloading step, the solver simply moves on to the next step as another loading event, as the first step was terminated. So, the jump from a large crosshead displacement at the termination point of the loading step, to zero displacement defined in the unloading step, is too severe to achieve.
But, with a few tweaks to the input file to control the displacement of the unloading step via an AMPLITUDE that we calculate in the UAMP subroutine, by tracking the step time, total time, and crosshead displacement, we can achieve a process which:
When we visualize those results, we do get what we want, but this process could be easier, and more accurate as we still don’t achieve the required termination force exactly.
The step control keyword, introduced in the latest Abaqus update, elegantly solves our step termination challenge. With just a couple of lines in the input file, we can define conditions for ending a step and refine the step time as we approach the termination point. This native functionality simplifies our workflow significantly, eliminating the need for Abaqus subroutines and compilers.
To use step control in our workflow, all we need to do to our original Abaqus model of the loading and unloading scenario is:
These two lines in the input file define the following sequence of events:
Those two lines of a native keyword are taking care of a lot of valuable work. Now, because we don’t need the subroutine, we don’t need a Fortran compiler either, and we can simply execute the job as we would any other, at the command line:
However, when the loading step is terminated, the solver still moves on to the unloading step. So the jump from the end to the terminated loading step and on to the start of the unloading step is too large for the unloading step to even start to converge.
Thankfully, we can overcome this with more recently added native keywords. This functionality takes the idea of the existing Abaqus restart capability and extends, simplifies, and augments it significantly.
Here’s what we’ll do:
Execute this manifest Abaqus job as we would with any other input file
All the input files referenced under the MANIFEST keyword are then executed in sequence. But, critically, the “BASE STATE = YES” option means that the base state for the unloading step contained in the second input file is the final state of the terminated loading step from the first input file.
Additionally, all the data from the execution of both files is contained within a single Abaqus file structure (the redacted status file is shown below) – including the .odb file.
So, when we interrogate the .odb file for this manifest analysis, everything is available for both steps in one place. This wouldn’t be the case if a restart sequence was created, and additional tools would be needed to combine the odb files.
The Abaqus solver is continuously improving, bringing advanced capabilities right into the hands of all users through the input file.
Now, adding a touch of autonomy to your Abaqus/Standard analysis is straightforward, even if you’re just getting to grips with the input file basics. And while Abaqus subroutines are valuable tools for many complex tasks, they’re taking a back seat in this particular process.
If you’d like to keep learning about new functionalities in Abaqus, then reach out to the TECHNIA Simulation experts for information about the Continuous Learning Program for Abaqus.