-
Notifications
You must be signed in to change notification settings - Fork 0
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
Add a wrapper for Abaqus #23
Comments
@vigneshwaran-radhakrishnan given I don't really use Abaqus and I last looked at the UMAT interface ~5 years ago when I added UMAT support into ExaConstit: https://github.com/LLNL/ExaConstit/blob/exaconstit-dev/src/mechanics_umat.cpp#L306-L578 . You will need to help me in creating a wrapper over ExaCMech given my lack of expertise around the Abaqus / UMAT interfaces. So, I would need to know what quantities specifically does Abaqus provide and what quantities does it expect back from the model. From there, we can try and map those to what ExaCMech expects. Also, the initialization of models is another thing to be mindful of as best practice from the ExaCMech side of things would be to only create the object once and then re-use it for the lifetime of things rather than recreating the object every material point call. We would also need to instantiate the state / history variables during the very first time step / first call per quadrature point as well to make sure all of the lattice orientations and history variables are instantiated correctly. Hopefully, Abaqus has a way for that to be done for UMATs. If not additional logic will be required to guard against such things. I will also mention that I'm not opposed to adding these wrappers to ExaCMech as we can have them only built when an optional CMake option is defined, but I probably wouldn't be the one to create them due to time constraints. However, I would be able to do of mentoring type thing to help guide someone into creating that initial prototype / implementation of a wrapper. |
@rcarson3 Thanks. At each step, UMAT provides the following data for every integration point:
UMAT expects to return the updated Cauchy stress and the Jacobian matrix (del Stress/del Strain), and that's it. I can put effort and time on to it. Guidance would be great. What is a good starting point? Start with calling pyecmech (or the jax version) fior every integration point from umat or something else? |
You probably don't want to use the python bindings as that will be slower. Plus, the python stuff is more for prototyping new models or running material point simulation type things to get a better understanding of a material models behavior. You can take a look at the miniapp we have for the library: https://github.com/LLNL/ExaCMech/blob/develop/miniapp/ and more specifically: https://github.com/LLNL/ExaCMech/blob/develop/miniapp/orientation_evolution.cxx and it's subsequent calls to see how an application code might call the library and what data it will provide the code. So, I'd say understanding the differences in the calls there to what UMAT expects would be a good first step. I will admit the miniapp isn't the cleanest code right now, but it was meant to provide people with a model for how to use the library at a higher level. Within the miniapp itself, you'll note there is an If I recall UMATs are per quadrature point calls right and are not batch quadrature point calls right? If so we'd probably just need to tell the underlying ECMech calls that it only needs to do 1 point for the calculation which is sub-optimal from a performance point of view but should be fine for now. If Abaqus provides which newton iteration we're on for the nonlinear solve and we know the time step is 0 then that should be enough info to properly set-up the data only once ever. Since, you can put guards into the code to check for such things. I'm guessing the instantiation of the crystal orientation as it varies from element to element is an already understood solution there so I'm guessing that's something y'all already know how to handle. Outside of that, yeah I think what I mentioned up above might be the best 1st steps and we can go from there. |
@vigneshwaran-radhakrishnan could you maybe drop this in Github GIST ( https://gist.github.com/ ) and then link that back here. It's a bit harder to read some of the above given the formatting issues that appear to be going on up above. edit: Also, I think if you tell it that the file is a fortran / c++ file it should also do some auto-highlighting of the code which will likely make things easier to read. |
@rcarson3 |
I have written a wrapper, which appears to be working. I successfully compiled the code with Abaqus, and it runs, though I still need to further evaluate the accuracy and convergence. As you said, I have uploaded the wrapper to this GitHub Gist: https://gist.github.com/vigneshwaran-radhakrishnan/97843d08a86fad66886f3fda1ac0a6ec The Gist contains two files:
In the umatecmech.f90 file, I added an interface to call the C++ subroutine. For each increment, at every integration point, the previous stress, material properties, current state variables (including quaternions), and current velocity gradient are extracted and passed to umat2exacmech.cxx. The updated stress, state variables, and ddsdde are then returned from umat2exacmech.cxx to umatecmech.f90, which sends them back to Abaqus. Can you please check if things are in correct place? I have three questions for now:
|
@vigneshwaran-radhakrishnan thanks for the gist link that's much easier to read now. I have some thoughts on how things could probably be improved now that I have a better understanding of how everything works. Since, we can likely avoid creating a new material model every time step and a few other things. As for your questions:
Sorry about any confusion here that actually stands for device_velocity_gradient as it's used on the GPUs or CPUs depending on a users desire in the miniapp. So, you just need to pass in the current velocity gradient.
Yes that is correct.
This is where we can do things a bit smarter as the miniapp / that orientation_evolution is the top level function and lives for the life of the program call. I think if we make use of C++ singleton patterns here and the |
@rcarson3 Thanks for your input. I realized that in ExaCMech, v_grad represents delta_velocity/delta_time, whereas in Abaqus, it only refers to delta_velocity. I’ve updated the Fortran code accordingly. I also found another mistake—(dstran33 + drot) / dt is not the velocity gradient; it should be (dstran33 + omega) / dt, where omega is the spin derived from the incremental rotation tensor, drot. The code is converging and working well so far, but the accuracy still needs to be verified. Do you have any code snippets for adding BCC here? |
@rcarson3 Please take a look at the gist again, I was able to add BCC (voce and MTS kinetics) into the wrapper. Let me run some test cases between Exaconstit and Abaqus, and I will update you. |
The velocity gradient term still seems like it might be off to me. Since Next, I don't know if you've updated things in the ExaConstit post-processing / pre-processing function calls as it looks like you're borrowing the miniapp logic, but you'll likely want to be mindful of how Abaqus and standard Voigt notation differ which means some of the shear terms need to re-oriented. I had to do this in ExaConstit for my UMAT wrapper for both the stress and material tangent terms as seen in this function call which sets everything up and then returns things for ExaConstit: https://github.com/LLNL/ExaConstit/blob/exaconstit-dev/src/mechanics_umat.cpp#L306-L578 |
@vigneshwaran-radhakrishnan outside of my above comment I'll try and take a more in-depth look at the other portions of the code that you have tomorrow when I should have a bit more time in the afternoon. |
@rcarson3 You are correct. I missed the voigt notation ordering part. I swapped the 4th (12 component), and 6th (23 compoents) columns and/or rows accordingly after I receive stress, ddsdde arrays back from exacmech into the fortran wrapper. I also had a mistake in the line Regarding the velocity gradient: We know that \delta V = \dot F F^{-1}= D + \Omega. So, the velocity gradient can be obtained using either the deformation gradients (F_1, F_0) or the rate of deformations (D) and Spin (\Omega). I checked both approaches, and for the case I’m currently testing, they give the same result. However, as discussed by Nolan et. al 2022 (https://www.sciencedirect.com/science/article/pii/S1751616121005713), when using local orientations in Abaqus, the deformation gradient provided by Abaqus is not exactly what we expect. It is rotated to some intermediate frame. Because of this, I’m a bit hesitant towards using the deformation gradients than using the D and \Omega. What are your thoughts? |
@vigneshwaran-radhakrishnan that's sounds about right that Abaqus would do things in an undocumented way which could cause less than ideal issues. I'd probably have to look at exactly what the dstran and drot terms that Abaqus is returning again as I do have a feeling that might be missing some terms as well. Since if I did my math right vgrad (L) can also be |
@rcarson3 Two questions:
|
@vigneshwaran-radhakrishnan sorry for the slow reply I totally forgot to reply to this earlier in the week...
So in the past for some of my auto-time stepping methods in ExaConstit (still need to add this to the public facing code...) I've used a // We can now make the call to our material model set-up stage...
// Everything else that we need should live on the class.
// Within this function the model just needs to produce the Cauchy stress
// and the material tangent matrix (d \sigma / d Vgrad_{sym})
bool succeed_t = false;
bool succeed = false;
try{
if (mech_type == MechType::UMAT) {
model->ModelSetup(nqpts, nelems, space_dims, ndofs, el_jac, qpts_dshape, k);
}
else {
// Takes in k vector and transforms into into our E-vector array
P->Mult(k, px);
elem_restrict_lex->Mult(px, el_x);
model->ModelSetup(nqpts, nelems, space_dims, ndofs, el_jac, qpts_dshape, el_x);
}
succeed_t = true;
}
catch(const std::exception &exc) {
// catch anything thrown within try block that derives from std::exception
MFEM_WARNING(exc.what());
succeed_t = false;
}
catch(...) {
succeed_t = false;
}
MPI_Allreduce(&succeed_t, &succeed, 1, MPI_C_BOOL, MPI_LAND, MPI_COMM_WORLD);
if (!succeed) {
throw std::runtime_error(std::string("Material model setup portion of code failed for at least one integration point."));
} I'm not too sure the MPI_Reduce all would be necessary on your part of things as I'm guessing the UMAT just needs a flag passed up to signal that aspect of things.
The units should be unitless for things. So, if we assume the meshes are the exact same dimensions and you're going out to the same strain and at the same strain rate you should be getting identical values. ExaConstit also reports the volume average value for this which maybe is causing issues? What value is Abaqus reporting / maybe a better question is from what is Abaqus reporting that value? |
@rcarson3 See the comparison here for BCC materials using the powervoce model under loading along four directions in both tension and compression. The finite element mesh is same between the software packages. First set of comparison of results between ExaConstit and Abaqus show promising agreement. However, some difference occurs for tension along the [111] direction, likely due to Abaqus not receiving the unconvergence flag from ExaCMech. I'll need to find a way to pass this flag back. Once resolved, the wrapper should be fully functional. What do you think? P.S: The previous issue with the saturation stress was due to the wrapper reinitializing the state variables at each step, rather than using the previously updated state variables. Once this was corrected, all results aligned well. |
@rcarson3 The discrepancy in the [111] loading case does not seem to be due to handling the non-convergence issue. After implementing the try-catch method and setting pnewdt = 0.5 for Abaqus, the results remained unchanged. This suggests that other factors might be at play, such as:
By the way, is ExaConstit using C3D8 or C3D8R elements? Updated codes in the gist: |
@vigneshwaran-radhakrishnan : ExaConstit should be using either C3D8 so full integration or it's using C3D8 with a BBAR approach depending on the choice of value in the I could see it being honestly a mixture of the two causing differences in the above. Do you have the ability to easily make use of C3D8 type elements in your Abaqus runs? If so that could at least further help point if thing was having a larger effect than the other in terms of differences that is. |
@rcarson3 Yes, I have attempted using C3D8 as well as C3D8R. There is some difference between them. Interestingly, C3D8R (with a hourglass stiffness of 0.1) gets closer to the saturation stress. But, it is not helping much. So, I think the issue is probably more due to periodicity, when I look at the deformed cell, Abaqus one is sheared but ExaConstit is not. |
I'm looking for a wrapper for calling ExaCMech from Abaqus/UMAT for two reasons.
First, the wrapper will make ExaCMech more accessible to many users of UMAT. Nowadays, UMAT can be called from several FE/FFT codes, including ExaConsist. Second, ExaConsist is still being improved to support periodic boundary conditions, controlled triaxiality, and Lode loading conditions. While these features are being implemented, a wrapper for ExaCMech will allow users to run jobs in Abaqus using ExaCMech's material models.
The text was updated successfully, but these errors were encountered: