├── 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 |
--------------------------------------------------------------------------------