├── docs └── images │ ├── abaqusJob_Image.PNG │ └── abaqus_axiNotchedDamage.PNG ├── LICENSE ├── README.md ├── nonLocalLemaitre └── lemaitreDamageNonLocal.f └── HETVAL_nonLocalLemaitre └── HETVAL_lemaitreDamageNonLocal.f /docs/images/abaqusJob_Image.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awhelanUCD/Lemaitre-damage-UMAT-Public/HEAD/docs/images/abaqusJob_Image.PNG -------------------------------------------------------------------------------- /docs/images/abaqus_axiNotchedDamage.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awhelanUCD/Lemaitre-damage-UMAT-Public/HEAD/docs/images/abaqus_axiNotchedDamage.PNG -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Andrew Whelan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lemaitre-damage-UMAT 2 | Lemaitre non-local damage user sub-routines for Abaqus software (public) 3 | 4 | ## Overview 5 | 6 | This repository contains implementations of the non-local Lemaitre damage model. It takes advantage of Abaqus' software in-built ability to solve the (steady-state) heat equation to solve the non-local gradient equations by analagous treatment of these equations. For more information on this analagous treatment see Navidtehrani et al. (Doi - 10.3390/ma14081913). In addition, a axisymmetric notched bar test case is provided. 7 | 8 | ## Usage 9 | 10 | 1. nonLocalLemaitre: compatible with Abaqus/2020 or newer 11 | 2. HETVAL_nonLocalLemaitre: Compatible with older versions of Abaqus (at least as old as Abaqus/2018) 12 | 13 | To run using the Abaqus GUI, select file-->import in the menu bar and select the .inp file. 14 | Create a new Job and link the user sub-routine (the .f file) using the 'User subroutine file' option 15 | 16 |

17 |
18 | 19 |

20 | 21 | To run case using Abaqus command enter relevant directory and enter the following commands: 22 | 23 | - for nonLocalLemaitre 24 | ``` 25 | $ abaqus job=axiSymmetricNotchedBar.inp user=lemaitreDamageNonLocal.f interactive 26 | ``` 27 | - for HETVAL_nonLocalLemaitre 28 | ``` 29 | $ abaqus job=HETVAL_axiSymmetricNotchedBar.inp user=HETVAL_lemaitreDamageNonLocal.f interactive 30 | ``` 31 | 32 | ### Example Result: 33 |

34 |
35 | 36 |

37 | -------------------------------------------------------------------------------- /nonLocalLemaitre/lemaitreDamageNonLocal.f: -------------------------------------------------------------------------------- 1 | ! User material subroutine for plasticity combined with non-local Lemaitre damage, compatible with Abaqus/2020 or newer 2 | ! The code is distributed under a BSD license 3 | 4 | 5 | ! Andrew Whelan (andrew.whelan@ucdconnect.ie) 6 | ! University College Dublin 7 | 8 | subroutine umat(stress,statev,ddsdde,sse,spd,scd,rpl,ddsddt, 9 | 1 drplde,drpldt,stran,dstran,time,dtime,temp,dtemp,predef,dpred, 10 | 2 cmname,ndi,nshr,ntens,nstatv,props,nprops,coords,drot,pnewdt, 11 | 3 celent,dfgrd0,dfgrd1,noel,npt,layer,kspt,jstep,kinc) 12 | 13 | include 'aba_param.inc' 14 | 15 | character*8 cmname 16 | dimension stress(ntens),statev(nstatv),ddsdde(ntens,ntens), 17 | 1 ddsddt(ntens),drplde(ntens),stran(ntens),dstran(ntens), 18 | 2 time(2),predef(1),dpred(1),props(nprops),coords(3),drot(3,3), 19 | 3 dfgrd0(3,3),dfgrd1(3,3),jstep(4) 20 | 21 | dimension eelas(ntens),eplas(ntens),stress0(ntens),flow(ntens), olds(ntens),oldpl(ntens) 22 | 23 | parameter(toler=1.d-6,newton=20) 24 | 25 | ! Initialization 26 | ddsdde=0.d0 27 | E=props(1) ! Young's modulus 28 | xnu=props(2) ! Poisson's ratio 29 | Sy=props(3) ! Yield stress multiplier 30 | xn=props(4) ! Strain hardening exponent 31 | sDam=props(5) ! Lemaitre damage denominator 32 | bDam=props(6) ! Lemaitre damage exponent 33 | charLength=props(7) ! Characterisitic length 34 | damage=statev(2+2*ntens) ! Local damage 35 | damageNL=temp+dtemp ! Non-local damage 36 | damageNLOld=temp+dtemp ! Old value of the non-local damage 37 | damageOld=damage ! Old value of the local damage 38 | 39 | gd=1.d0-damageNL ! Degredation due to damage 40 | 41 | do k1=1,ntens 42 | stress0(k1)=statev(k1+2+2*ntens) !Recover undegraded stress 43 | enddo 44 | 45 | call rotsig(statev(1),drot,eelas,2,ndi,nshr) 46 | call rotsig(statev(ntens+1),drot,eplas,2,ndi,nshr) 47 | eqplas=statev(1+2*ntens) 48 | olds=stress 49 | oldpl=eplas 50 | 51 | ! Build elastic stiffness matrix 52 | eg=E/(1.d0+xnu)/2.d0 53 | elam=(E/(1.d0-2.d0*xnu)-2.d0*eg)/3.d0 54 | ek=E/(3.d0*(1.d0-2.d0*xnu)) 55 | 56 | do i=1,3 57 | do j=1,3 58 | ddsdde(j,i)=elam 59 | end do 60 | ddsdde(i,i)=2.d0*eg+elam 61 | end do 62 | do i=4,ntens 63 | ddsdde(i,i)=eg 64 | end do 65 | 66 | ! Calculate predictor stress and elastic strain 67 | stress0=stress0+matmul(ddsdde,dstran) 68 | eelas=eelas+dstran 69 | 70 | ! Calculate equivalent von Mises stress 71 | Smises=(stress0(1)-stress0(2))**2+(stress0(2)-stress0(3))**2 72 | 1 +(stress0(3)-stress0(1))**2 73 | do i=4,ntens 74 | Smises=Smises+6.d0*stress0(i)**2 75 | end do 76 | Smises=sqrt(Smises/2.d0) 77 | 78 | ! Get yield stress from the specified hardening curve 79 | Sf=Sy*(0.0001+eqplas)**xn 80 | 81 | ! Determine if active yielding 82 | if (Smises.gt.(1.d0+toler)*Sf) then 83 | 84 | ! Calculate the flow direction 85 | Sh=(stress0(1)+stress0(2)+stress0(3))/3.d0 86 | flow(1:3)=(stress0(1:3)-Sh)/Smises 87 | flow(4:ntens)=stress0(4:ntens)/Smises 88 | 89 | deqpl=0.d0 90 | Et=xn*Sy*(0.0001+eqplas)**(xn-1.d0) 91 | 92 | ! Newton loop to calculate plastic multiplier 93 | do kewton=1,newton 94 | rhs=Smises-(3.d0*eg*deqpl)/gd-Sf 95 | deqpl=deqpl+rhs/((3.d0*eg/gd)+Et) 96 | Sf=Sy*(0.0001+eqplas+deqpl)**xn 97 | Et=xn*Sy*(0.0001+eqplas+deqpl)**(xn-1.d0) 98 | 99 | if(abs(rhs).lt.toler*Sy) exit 100 | end do 101 | if (kewton.eq.newton) write(7,*)'WARNING: plasticity loop failed' 102 | 103 | if (deqpl.lt.0.d0) then 104 | deqpl=0.d0 105 | endif 106 | 107 | ! Energy release rate associated with the damage 108 | Y=-((Sf**2)/(6*eg)+(Sh**2)/(2*ek)) 109 | YStar=((-Y/sDam)**bDam) 110 | 111 | ! Update local damage 112 | damage=damageOld+YStar*deqpl/gd 113 | 114 | if (damage.GT.1.d0) then 115 | damage=0.99 116 | endif 117 | 118 | 119 | ! update stresses and strains 120 | stress0(1:3)=flow(1:3)*Sf+Sh 121 | eplas(1:3)=eplas(1:3)+3.d0/2.d0*flow(1:3)*deqpl/gd 122 | eelas(1:3)=eelas(1:3)-3.d0/2.d0*flow(1:3)*deqpl/gd 123 | stress0(4:ntens)=flow(4:ntens)*Sf 124 | eplas(4:ntens)=eplas(4:ntens)+3.d0*flow(4:ntens)*deqpl/gd 125 | eelas(4:ntens)=eelas(4:ntens)-3.d0*flow(4:ntens)*deqpl/gd 126 | eqplas=eqplas+deqpl 127 | 128 | stress=stress0 129 | 130 | 131 | ! Calculate the plastic strain energy density 132 | do i=1,ntens 133 | spd=spd+deqpl*Sf 134 | end do 135 | 136 | sse = 0.d0 137 | do k1 = 1, ntens 138 | sse=sse+stress0(k1)*eelas(k1)/2.d0 !Update specific elastic strain energy 139 | enddo 140 | 141 | ! Formulate the jacobian (material tangent) 142 | effg=eg*Sf/Smises 143 | efflam=(E/(1.d0-2.d0*xnu)-2.d0*effg)/3.d0 144 | effhrd=3.d0*eg*Et/(3.d0*eg+Et)-3.d0*effg 145 | do i=1,3 146 | do j=1,3 147 | ddsdde(j,i)=efflam 148 | end do 149 | ddsdde(i,i)=2.d0*effg+efflam 150 | end do 151 | do i=4,ntens 152 | ddsdde(i,i)=effg 153 | end do 154 | 155 | do i=1,ntens 156 | do j=1,ntens 157 | ddsdde(j,i)=ddsdde(j,i)+effhrd*flow(j)*flow(i) 158 | end do 159 | end do 160 | endif 161 | 162 | ! Degrade stress and material tangent 163 | stress=gd*stress0 164 | ddsdde=gd*ddsdde 165 | 166 | ! Update state variables 167 | statev(1:ntens)=eelas 168 | statev((ntens+1):2*ntens)=eplas 169 | statev(1+2*ntens)=eqplas 170 | statev(2+2*ntens)=damage 171 | 172 | statev(3+2*ntens:2+2*ntens+ntens)=stress0 173 | statev(3+2*ntens+ntens)=damageNLOld 174 | 175 | ! Variables for calculating of non-local damage 176 | rpl=(damage-damageNL)/charLength**2 177 | drpldt=-1.d0/charLength**2 178 | 179 | return 180 | end 181 | -------------------------------------------------------------------------------- /HETVAL_nonLocalLemaitre/HETVAL_lemaitreDamageNonLocal.f: -------------------------------------------------------------------------------- 1 | ! User material subroutine for plasticity combined with non-local Lemaitre damage, non-local damage incorporated using a HETVAL routine 2 | ! The code is distributed under a BSD license 3 | 4 | 5 | ! Andrew Whelan (andrew.whelan@ucdconnect.ie) 6 | ! University College Dublin 7 | 8 | c***************************************************************** 9 | 10 | subroutine hetval(cmname,temp,time,dtime,statev,flux,predef,dpred) 11 | 12 | include 'aba_param.inc' 13 | 14 | character*80 cmname 15 | 16 | dimension temp(2),statev(*),predef(*),time(2),flux(2),dpred(*) 17 | 18 | phi=temp(1) 19 | charL=statev(1) 20 | 21 | flux(1)=(damageL-phi)/charL**2 22 | flux(2)=-1.d0/charL**2 23 | 24 | return 25 | end 26 | 27 | c***************************************************************** 28 | 29 | subroutine umat(stress,statev,ddsdde,sse,spd,scd,rpl,ddsddt, 30 | 1 drplde,drpldt,stran,dstran,time,dtime,temp,dtemp,predef,dpred, 31 | 2 cmname,ndi,nshr,ntens,nstatv,props,nprops,coords,drot,pnewdt, 32 | 3 celent,dfgrd0,dfgrd1,noel,npt,layer,kspt,jstep,kinc) 33 | 34 | include 'aba_param.inc' 35 | 36 | character*8 cmname 37 | dimension stress(ntens),statev(nstatv),ddsdde(ntens,ntens), 38 | 1 ddsddt(ntens),drplde(ntens),stran(ntens),dstran(ntens), 39 | 2 time(2),predef(1),dpred(1),props(nprops),coords(3),drot(3,3), 40 | 3 dfgrd0(3,3),dfgrd1(3,3),jstep(4) 41 | 42 | dimension eelas(ntens),eplas(ntens),stress0(ntens),flow(ntens), olds(ntens),oldpl(ntens) 43 | 44 | parameter(toler=1.d-6,newton=20) 45 | 46 | ! Initialization 47 | ddsdde=0.d0 48 | E=props(1) ! Young's modulus 49 | xnu=props(2) ! Poisson's ratio 50 | Sy=props(3) ! Yield stress multiplier 51 | xn=props(4) ! Strain hardening exponent 52 | sDam=props(5) ! Lemaitre damage denominator 53 | bDam=props(6) ! Lemaitre damage exponent 54 | charLength=props(7) ! Characterisitic length 55 | damage=statev(2+2*ntens) ! Local damage 56 | damageNL=temp+dtemp ! Non-local damage 57 | damageNLOld=temp+dtemp ! Old value of the non-local damage 58 | damageOld=damage ! Old value of the local damage 59 | 60 | gd=1.d0-damageNL ! Degredation due to damage 61 | 62 | do k1=1,ntens 63 | stress0(k1)=statev(k1+2+2*ntens) !Recover undegraded stress 64 | enddo 65 | 66 | call rotsig(statev(1),drot,eelas,2,ndi,nshr) 67 | call rotsig(statev(ntens+1),drot,eplas,2,ndi,nshr) 68 | eqplas=statev(1+2*ntens) 69 | olds=stress 70 | oldpl=eplas 71 | 72 | ! Build elastic stiffness matrix 73 | eg=E/(1.d0+xnu)/2.d0 74 | elam=(E/(1.d0-2.d0*xnu)-2.d0*eg)/3.d0 75 | ek=E/(3.d0*(1.d0-2.d0*xnu)) 76 | 77 | do i=1,3 78 | do j=1,3 79 | ddsdde(j,i)=elam 80 | end do 81 | ddsdde(i,i)=2.d0*eg+elam 82 | end do 83 | do i=4,ntens 84 | ddsdde(i,i)=eg 85 | end do 86 | 87 | ! Calculate predictor stress and elastic strain 88 | stress0=stress0+matmul(ddsdde,dstran) 89 | eelas=eelas+dstran 90 | 91 | ! Calculate equivalent von Mises stress 92 | Smises=(stress0(1)-stress0(2))**2+(stress0(2)-stress0(3))**2 93 | 1 +(stress0(3)-stress0(1))**2 94 | do i=4,ntens 95 | Smises=Smises+6.d0*stress0(i)**2 96 | end do 97 | Smises=sqrt(Smises/2.d0) 98 | 99 | ! Get yield stress from the specified hardening curve 100 | Sf=Sy*(0.0001+eqplas)**xn 101 | 102 | ! Determine if active yielding 103 | if (Smises.gt.(1.d0+toler)*Sf) then 104 | 105 | ! Calculate the flow direction 106 | Sh=(stress0(1)+stress0(2)+stress0(3))/3.d0 107 | flow(1:3)=(stress0(1:3)-Sh)/Smises 108 | flow(4:ntens)=stress0(4:ntens)/Smises 109 | 110 | deqpl=0.d0 111 | Et=xn*Sy*(0.0001+eqplas)**(xn-1.d0) 112 | 113 | ! Newton loop to calculate plastic multiplier 114 | do kewton=1,newton 115 | rhs=Smises-(3.d0*eg*deqpl)/gd-Sf 116 | deqpl=deqpl+rhs/((3.d0*eg/gd)+Et) 117 | Sf=Sy*(0.0001+eqplas+deqpl)**xn 118 | Et=xn*Sy*(0.0001+eqplas+deqpl)**(xn-1.d0) 119 | 120 | if(abs(rhs).lt.toler*Sy) exit 121 | end do 122 | if (kewton.eq.newton) write(7,*)'WARNING: plasticity loop failed' 123 | 124 | if (deqpl.lt.0.d0) then 125 | deqpl=0.d0 126 | endif 127 | 128 | ! Energy release rate associated with the damage 129 | Y=-((Sf**2)/(6*eg)+(Sh**2)/(2*ek)) 130 | YStar=((-Y/sDam)**bDam) 131 | 132 | ! Update local damage 133 | damage=damageOld+YStar*deqpl/gd 134 | 135 | if (damage.GT.1.d0) then 136 | damage=0.99 137 | endif 138 | 139 | 140 | ! update stresses and strains 141 | stress0(1:3)=flow(1:3)*Sf+Sh 142 | eplas(1:3)=eplas(1:3)+3.d0/2.d0*flow(1:3)*deqpl/gd 143 | eelas(1:3)=eelas(1:3)-3.d0/2.d0*flow(1:3)*deqpl/gd 144 | stress0(4:ntens)=flow(4:ntens)*Sf 145 | eplas(4:ntens)=eplas(4:ntens)+3.d0*flow(4:ntens)*deqpl/gd 146 | eelas(4:ntens)=eelas(4:ntens)-3.d0*flow(4:ntens)*deqpl/gd 147 | eqplas=eqplas+deqpl 148 | 149 | stress=stress0 150 | 151 | 152 | ! Calculate the plastic strain energy density 153 | do i=1,ntens 154 | spd=spd+deqpl*Sf 155 | end do 156 | 157 | sse = 0.d0 158 | do k1 = 1, ntens 159 | sse=sse+stress0(k1)*eelas(k1)/2.d0 !Update specific elastic strain energy 160 | enddo 161 | 162 | ! Formulate the jacobian (material tangent) 163 | effg=eg*Sf/Smises 164 | efflam=(E/(1.d0-2.d0*xnu)-2.d0*effg)/3.d0 165 | effhrd=3.d0*eg*Et/(3.d0*eg+Et)-3.d0*effg 166 | do i=1,3 167 | do j=1,3 168 | ddsdde(j,i)=efflam 169 | end do 170 | ddsdde(i,i)=2.d0*effg+efflam 171 | end do 172 | do i=4,ntens 173 | ddsdde(i,i)=effg 174 | end do 175 | 176 | do i=1,ntens 177 | do j=1,ntens 178 | ddsdde(j,i)=ddsdde(j,i)+effhrd*flow(j)*flow(i) 179 | end do 180 | end do 181 | endif 182 | 183 | ! Degrade stress and material tangent 184 | stress=gd*stress0 185 | ddsdde=gd*ddsdde 186 | 187 | ! Update state variables 188 | statev(1:ntens)=eelas 189 | statev((ntens+1):2*ntens)=eplas 190 | statev(1+2*ntens)=eqplas 191 | statev(2+2*ntens)=damage 192 | 193 | statev(3+2*ntens:2+2*ntens+ntens)=stress0 194 | statev(3+2*ntens+ntens)=damageNLOld 195 | 196 | ! Variables for calculating of non-local damage 197 | rpl=(damage-damageNL)/charLength**2 198 | drpldt=-1.d0/charLength**2 199 | 200 | return 201 | end 202 | --------------------------------------------------------------------------------