Developing User Material Subroutines in CALCULIX: 3 Converting ABAQUS UMAT into CALCULIX UMAT

Converting user material subroutines from ABAQUS to CALCULIX can significantly boost flexibility in open-source finite element simulations. Thanks to the ABAQUS UMAT examples shared on GitHub and similar platforms, it is often easier to start from an existing model than to build one from scratch. In this post, we explore how to adapt one of these ABAQUS UMATs for use in CALCULIX, covering the key differences and steps in the conversion process.

Key Steps: Adapting an ABAQUS UMAT for Use in CALCULIX

Adapting an ABAQUS User Material (UMAT) subroutine for CALCULIX involves several critical steps to ensure compatibility and functionality. Building upon the foundational UMAT structure discussed in the article «Developing User Material Subroutines in CALCULIX: 1 A Comprehensive Guide with UMAT Structure Examples in ABAQUS,» the following key steps outline the process:​

Understand the ABAQUS UMAT Structure:

Familiarize yourself with the components and workflow of the ABAQUS UMAT, as detailed in the referenced article. This includes input and output variables, as well as the general structure of the subroutine.

Modify Input variables

Examine the differences in subroutine interfaces between ABAQUS and CALCULIX. While both use Fortran-based UMATs, the specific arguments and their ordering may differ. Ensure that the subroutine header and variable declarations are adjusted to match CALCULIX’s expectations. Adapt the input handling to align with CALCULIX’s data structures.

CALCULIX input variables

!     INPUT:
!
!     amat               material name
!     iel                element number
!     iint               integration point number
!
!     kode               material type (-100-#of constants entered
!                        under *USER MATERIAL): can be used for materials
!                        with varying number of constants
!
!     elconloc(*)        user defined constants defined by the keyword
!                        card *USER MATERIAL (actual # =
!                        -kode-100), interpolated for the
!                        actual temperature t1l
!
!     emec(6)            Lagrange mechanical strain tensor (component order:
!                        11,22,33,12,13,23) at the end of the increment
!                        (thermal strains are subtracted)
!     emec0(6)           Lagrange mechanical strain tensor at the start of the
!                        increment (thermal strains are subtracted)
!     beta(6)            residual stress tensor (the stress entered under
!                        the keyword *INITIAL CONDITIONS,TYPE=STRESS)
!
!     xokl(3,3)          deformation gradient at the start of the increment
!     voj                Jacobian at the start of the increment
!     xkl(3,3)           deformation gradient at the end of the increment
!     vj                 Jacobian at the end of the increment
!
!     ithermal           0: no thermal effects are taken into account
!                        >0: thermal effects are taken into account (triggered
!                        by the keyword *INITIAL CONDITIONS,TYPE=TEMPERATURE)
!     t1l                temperature at the end of the increment
!     dtime              time length of the increment
!     time               step time at the end of the current increment
!     ttime              total time at the start of the current step
!
!     icmd               not equal to 3: calculate stress and stiffness
!                        3: calculate only stress
!     ielas              0: no elastic iteration: irreversible effects
!                        are allowed
!                        1: elastic iteration, i.e. no irreversible
!                           deformation allowed
!
!     mi(1)              max. # of integration points per element in the
!                        model
!     nstate_            max. # of state variables in the model
!
!     xstateini(nstate_,mi(1),# of elements)
!                        state variables at the start of the increment
!     xstate(nstate_,mi(1),# of elements)
!                        state variables at the end of the increment
!
!     stre(6)            Piola-Kirchhoff stress of the second kind
!                        at the start of the increment
!
!     iorien             number of the local coordinate axis system
!                        in the integration point at stake (takes the value
!                        0 if no local system applies)
!     pgauss(3)          global coordinates of the integration point
!     orab(7,*)          description of all local coordinate systems.
!                        If a local coordinate system applies the global 
!                        tensors can be obtained by premultiplying the local
!                        tensors with skl(3,3). skl is  determined by calling
!                        the subroutine transformatrix: 
!                        call transformatrix(orab(1,iorien),pgauss,skl)

Retrieve the material properties, the elastic modulus and the Poisson ratio

      EMOD = elconloc(1)
      ENU=elconloc(2)

Compute the strain increment as the difference between the final total strain and the initial total strain. CALCULIX does not pass the strain increment directly as ABAQUS does—it must be computed manually:

C
C Strain increment
C
      DO K1=1,6
        DSTRAN(K1)=emec(K1)-emec0(K1)
      ENDDO

Retrieve the equivalent plastic strain, stored in a user variable.

        EQPLAS = xstateini(1,iint,iel)

Compute the Tangent Stiffness Matrix

Importantly, in CALCULIX the tangent stiffness must be returned in vectorial form (Voigt notation, 6×6 for 3D problems). Update accordingly, ensuring proper ordering of shear components.

         stiff(1)=G(1,1)
         stiff(2)=G(1,2)
         stiff(3)=G(2,2)
         stiff(4)=G(1,3)
         stiff(5)=G(2,3)
         stiff(6)=G(3,3)
         stiff(7)=G(1,4)
         stiff(8)=G(2,4)
         stiff(9)=G(3,4)
         stiff(10)=G(4,4)
         stiff(11)=G(1,5)
         stiff(12)=G(2,5)
         stiff(13)=G(3,5)
         stiff(14)=G(4,5)
         stiff(15)=G(5,5)
         stiff(16)=G(1,6)
         stiff(17)=G(2,6)
         stiff(18)=G(3,6)
         stiff(19)=G(4,6)
         stiff(20)=G(5,6)
         stiff(21)=G(6,6)

Update the stress

Importantly, in CALCULIX the tangent stiffness must be returned in vectorial form. Update accordingly, ensuring proper ordering of shear components.

         DO K1=1,3
            stre(K1)=FLOW(K1)*SYIELD+SHYDRO
         END DO
         DO K1=4,6
            stre(K1)=FLOW(K1)*SYIELD
         END DO

Update the equivalent plastic strain

The equivalent plastic strain (often noted as PEEQ in ABAQUS) must be manually stored and updated in the user variable.

         EQPLAS=EQPLAS+DEQPL
        xstate(1,iint,iel) = EQPLAS

UMAT subroutine

Navigate to the source directory

home = $(HOME)/ARPACK to your ARPACK directory
PLAT = SUN4 to PLAT = linux
FC = f77 to FC = gfortran
FFLAGS =      subroutine umat_user(amat,iel,iint,kode,elconloc,emec,emec0,
     &        beta,xokl,voj,xkl,vj,ithermal,t1l,dtime,time,ttime,
     &        icmd,ielas,mi,nstate_,xstateini,xstate,stre,stiff,
     &        iorien,pgauss,orab,pnewdt,ipkon)
!
!     calculates stiffness and stresses for a user defined material
!     law
!
!     icmd=3: calculates stress at mechanical strain
!     else: calculates stress at mechanical strain and the stiffness
!           matrix
!
!     INPUT:
!
!     amat               material name
!     iel                element number
!     iint               integration point number
!
!     kode               material type (-100-#of constants entered
!                        under *USER MATERIAL): can be used for materials
!                        with varying number of constants
!
!     elconloc(*)        user defined constants defined by the keyword
!                        card *USER MATERIAL (actual # =
!                        -kode-100), interpolated for the
!                        actual temperature t1l
!
!     emec(6)            Lagrange mechanical strain tensor (component order:
!                        11,22,33,12,13,23) at the end of the increment
!                        (thermal strains are subtracted)
!     emec0(6)           Lagrange mechanical strain tensor at the start of the
!                        increment (thermal strains are subtracted)
!     beta(6)            residual stress tensor (the stress entered under
!                        the keyword *INITIAL CONDITIONS,TYPE=STRESS)
!
!     xokl(3,3)          deformation gradient at the start of the increment
!     voj                Jacobian at the start of the increment
!     xkl(3,3)           deformation gradient at the end of the increment
!     vj                 Jacobian at the end of the increment
!
!     ithermal           0: no thermal effects are taken into account
!                        >0: thermal effects are taken into account (triggered
!                        by the keyword *INITIAL CONDITIONS,TYPE=TEMPERATURE)
!     t1l                temperature at the end of the increment
!     dtime              time length of the increment
!     time               step time at the end of the current increment
!     ttime              total time at the start of the current step
!
!     icmd               not equal to 3: calculate stress and stiffness
!                        3: calculate only stress
!     ielas              0: no elastic iteration: irreversible effects
!                        are allowed
!                        1: elastic iteration, i.e. no irreversible
!                           deformation allowed
!
!     mi(1)              max. # of integration points per element in the
!                        model
!     nstate_            max. # of state variables in the model
!
!     xstateini(nstate_,mi(1),# of elements)
!                        state variables at the start of the increment
!     xstate(nstate_,mi(1),# of elements)
!                        state variables at the end of the increment
!
!     stre(6)            Piola-Kirchhoff stress of the second kind
!                        at the start of the increment
!
!     iorien             number of the local coordinate axis system
!                        in the integration point at stake (takes the value
!                        0 if no local system applies)
!     pgauss(3)          global coordinates of the integration point
!     orab(7,*)          description of all local coordinate systems.
!                        If a local coordinate system applies the global 
!                        tensors can be obtained by premultiplying the local
!                        tensors with skl(3,3). skl is  determined by calling
!                        the subroutine transformatrix: 
!                        call transformatrix(orab(1,iorien),pgauss,skl)
!
!
!     OUTPUT:
!
!     xstate(nstate_,mi(1),# of elements)
!                        updated state variables at the end of the increment
!     stre(6)            Piola-Kirchhoff stress of the second kind at the
!                        end of the increment
!     stiff(21):         consistent tangent stiffness matrix in the material
!                        frame of reference at the end of the increment. In
!                        other words: the derivative of the PK2 stress with
!                        respect to the Lagrangian strain tensor. The matrix
!                        is supposed to be symmetric, only the upper half is
!                        to be given in the same order as for a fully
!                        anisotropic elastic material (*ELASTIC,TYPE=ANISO).
!                        Notice that the matrix is an integral part of the 
!                        fourth order material tensor, i.e. the Voigt notation
!                        is not used.
!     pnewdt             to be specified by the user if the material
!                        routine is unable to return the stiffness matrix
!                        and/or the stress due to divergence within the
!                        routine. pnewdt is the factor by which the time
!                        increment is to be multiplied in the next
!                        trial and should exceed zero but be less than 1.
!                        Default is -1 indicating that the user routine
!                        has converged.
!     ipkon(*)           ipkon(iel) points towards the position in field
!                        kon prior to the first node of the element's
!                        topology. If ipkon(iel) is smaller than 0, the 
!                        element is not used.
!
*      implicit none
!
      character*80 amat
!
      integer ithermal(*),icmd,kode,ielas,iel,iint,nstate_,mi(*),iorien,
     &     i,K1,K2,N
!
      real*8 elconloc(*),stiff(21),emec(6),emec0(6),beta(6),stre(6),
     &  vj,t1l,dtime,xkl(3,3),xokl(3,3),voj,pgauss(3),orab(7,*),
     &  time,ttime
!
      real*8 xstate(nstate_,mi(1),*),xstateini(nstate_,mi(1),*)
!
C ----------------------------------------------------------------
C UMAT FOR ISOTROPIC ELASTICITY AND ISOTROPIC MISES PLASTICITY
C CANNOT BE USED FOR PLANE STRESS
C ----------------------------------------------------------------
C PROPS(1) - E
C PROPS(2) - NU
C PROPS(3..) - YIELD AND HARDENING DATA
C CALLS UHARD FOR CURVE OF YIELD STRESS VS. PLASTIC STRAIN
C ----------------------------------------------------------------
C ----------------------------------------------------------------
C UMAT FOR ISOTROPIC ELASTICITY
C CANNOT BE USED FOR PLANE STRESS
C ----------------------------------------------------------------
C PROPS(1) - E
C PROPS(2) - NU
C ----------------------------------------------------------------
C
      real*8 EMOD,NU,EBULK3,EG2,EG3,ELAM,G(6,6),DSTRAN(6)
      real*8 EQPLAS,SMISES,SYIEL0,HARD,SHYDRO,FLOW(6),SYIELD,RHS
      real*8 EFFG,EFFG2,EFFG3,EFFLAM,EFFHRD
      real*8 ZERO,ONE,TWO,THREE,SIX,ENUMAX,TOLER,ENU

      INTEGER KEWTON


       PARAMETER(ZERO=0.D0, ONE=1.D0, TWO=2.D0, THREE=3.D0, SIX=6.D0,
     1 ENUMAX=.4999D0, NEWTON=10, TOLER=1.0D-6)
!
C
C Elastic matrix
C
C
      EMOD = elconloc(1)
      ENU=elconloc(2)
      if (ENU.GT.ENUMAX) THEN
         ENU = ENUMAX
      ENDIF
      EBULK3=EMOD/(ONE-TWO*ENU)
      EG2=EMOD/(ONE+ENU)
      EG=EG2/TWO
      EG3=THREE*EG
      ELAM=(EBULK3-EG2)/THREE
C
C ELASTIC STIFFNESS
C
      DO K1=1,6
        DO K2=1,6
            G(K1,K2)=0.D0
        ENDDO
      ENDDO
      DO K1=1, 3
        DO K2=1, 3
             G(K2, K1)=ELAM
          END DO
          G(K1, K1)=EG2+ELAM
       END DO
       DO K1=4, 6
          G(K1 ,K1)=EG
       END DO

C
C Strain increment
C
      DO K1=1,6
        DSTRAN(K1)=emec(K1)-emec0(K1)
      ENDDO
C
C DEFINING Initial STRESS AND STRAIN RELATION
C
       stre(1)=stre(1)+G(1,1)*DSTRAN(1)+G(1,2)*DSTRAN(2)
     &  +G(1,3)*DSTRAN(3)
       stre(2)=stre(2)+G(2,1)*DSTRAN(1)+G(2,2)*DSTRAN(2)
     &  +G(2,3)*DSTRAN(3)
       stre(3)=stre(3)+G(3,1)*DSTRAN(1)+G(3,2)*DSTRAN(2)
     &  +G(3,3)*DSTRAN(3)
       stre(4)=stre(4)+G(4,4)*DSTRAN(4)
       stre(5)=stre(5)+G(5,5)*DSTRAN(5)
       stre(6)=stre(6)+G(6,6)*DSTRAN(6)
C
C NOW THE STATE VARAIBLES WILL BE UPDATED
C
        EQPLAS = xstateini(1,iint,iel)

C
C CALCULATE EQUIVALENT VON MISES STRESS
C
       SMISES=(stre(1)-stre(2))**2+(stre(2)-stre(3))**2
     1  +(stre(3)-stre(1))**2
       DO K1=4,6
         SMISES=SMISES+SIX*stre(K1)**2
       END DO
       SMISES=SQRT(SMISES/TWO)

C
C GET YIELD STRESS FROM THE SPECIFIED HARDENING CURVE
C
       NVALUE=(-kode-100)/2-1
c
       CALL UHARD(SYIEL0, HARD, EQPLAS, elconloc(3),NVALUE)
C
C DETERMINE IF ACTIVELY YIELDING
C
      IF (SMISES.GT.(ONE+TOLER)*SYIEL0) THEN
C
C ACTIVELY YIELDING
C SEPARATE THE HYDROSTATIC FROM THE DEVIATORIC STRESS
C CALCULATE THE FLOW DIRECTION
C
         SHYDRO=(stre(1)+stre(2)+stre(3))/THREE
         DO K1=1,3
            FLOW(K1)=(stre(K1)-SHYDRO)/SMISES
         END DO
         DO K1=4, 6
            FLOW(K1)=stre(K1)/SMISES
         END DO
C
C SOLVE FOR EQUIVALENT VON MISES STRESS
C AND EQUIVALENT PLASTIC STRAIN INCREMENT USING NEWTON ITERATION
C
         SYIELD=SYIEL0
         DEQPL=ZERO
         DO KEWTON=1, NEWTON
            RHS=SMISES-EG3*DEQPL-SYIELD
            DEQPL=DEQPL+RHS/(EG3+HARD)
            CALL UHARD(SYIELD,HARD,EQPLAS+DEQPL,elconloc(3),NVALUE)
            IF(ABS(RHS).LT.TOLER*SYIEL0) GOTO 10
        END DO
C
C WRITE WARNING MESSAGE TO THE .MSG FILE
C
         WRITE(*,*) 'PLASTICITY ALGORITHM DID NOT CONVERGE'
   10    CONTINUE


C
C UPDATE STRESS, ELASTIC AND PLASTIC STRAINS AND
C EQUIVALENT PLASTIC STRAIN
C
         DO K1=1,3
            stre(K1)=FLOW(K1)*SYIELD+SHYDRO
         END DO
         DO K1=4,6
            stre(K1)=FLOW(K1)*SYIELD
         END DO
         EQPLAS=EQPLAS+DEQPL

C
C CALCULATE PLASTIC DISSIPATION
C
        xstate(1,iint,iel) = EQPLAS
c         SPD=DEQPL*(SYIEL0+SYIELD)/TWO   
C
C FORMULATE THE JACOBIAN (MATERIAL TANGENT)
C FIRST CALCULATE EFFECTIVE MODULI
C
         EFFG=EG*SYIELD/SMISES
         EFFG2=TWO*EFFG
         EFFG3=THREE/TWO*EFFG2
         EFFLAM=(EBULK3-EFFG2)/THREE
         EFFHRD=EG3*HARD/(EG3+HARD)-EFFG3
         DO K1=1, 3
            DO K2=1, 3
               G(K2, K1)=EFFLAM
            END DO
            G(K1, K1)=EFFG2+EFFLAM
         END DO
         DO K1=4, 6
            G(K1, K1)=EFFG
         END DO
         DO K1=1, 6
            DO K2=1, 6
               G(K2, K1)=G(K2, K1)+EFFHRD*FLOW(K2)*FLOW(K1)
            END DO
         END DO
      ENDIF
C
C
!
      if(icmd.ne.3) then
!
!        insert here code to calculate the stiffness matrix
!
         stiff(1)=G(1,1)
         stiff(2)=G(1,2)
         stiff(3)=G(2,2)
         stiff(4)=G(1,3)
         stiff(5)=G(2,3)
         stiff(6)=G(3,3)
         stiff(7)=G(1,4)
         stiff(8)=G(2,4)
         stiff(9)=G(3,4)
         stiff(10)=G(4,4)
         stiff(11)=G(1,5)
         stiff(12)=G(2,5)
         stiff(13)=G(3,5)
         stiff(14)=G(4,5)
         stiff(15)=G(5,5)
         stiff(16)=G(1,6)
         stiff(17)=G(2,6)
         stiff(18)=G(3,6)
         stiff(19)=G(4,6)
         stiff(20)=G(5,6)
         stiff(21)=G(6,6)

      endif
!
      return
      end



      SUBROUTINE UHARD(SYIELD,HARD,EQPLAS,TABLE,NVALUE)
C
      REAL*8 TABLE(2, NVALUE),SYIELD,HARD,EQPLAS
      REAL*8 EQPL0,EQPL1,DEQPL,SYIEL0,SYIEL1,DSYIEL
      INTEGER NVALUE
C
      PARAMETER(ZERO=0.D0)
C
C SET YIELD STRESS TO LAST VALUE OF TABLE, HARDENING TO ZERO
C
      SYIELD=TABLE(1, NVALUE)
      HARD=ZERO
c
C IF MORE THAN ONE ENTRY, SEARCH TABLE
C
      IF(NVALUE.GT.1) THEN
         DO K1=1, NVALUE-1
            EQPL1=TABLE(2,K1+1)
            IF(EQPLAS.LT.EQPL1) THEN
               EQPL0=TABLE(2, K1)
C
C CURRENT YIELD STRESS AND HARDENING
C
               DEQPL=EQPL1-EQPL0
               SYIEL0=TABLE(1, K1)
               SYIEL1=TABLE(1, K1+1)
               DSYIEL=SYIEL1-SYIEL0
               if (DEQPL.NE.ZERO) THEN
                  HARD=DSYIEL/DEQPL
               else
                  HARD = ZERO
               ENDIF
               SYIELD=SYIEL0+(EQPLAS-EQPL0)*HARD
               GOTO 10
            ENDIF
         END DO
   10    CONTINUE
      ENDIF
      RETURN
      END

Deja un comentario