FrontISTR  6.0.0
Large-scale structural analysis program with finit element method
Elastoplastic.f90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
2 ! Copyright (c) 2019 FrontISTR Commons
3 ! This software is released under the MIT License, see LICENSE.txt
4 !-------------------------------------------------------------------------------
7  use hecmw_util
8  use mmaterial
10  use muyield
11  use, intrinsic :: ieee_arithmetic, only: ieee_is_finite
12 
13  implicit none
14 
15  private
16  public :: calelastoplasticmatrix
17  public :: backwardeuler
18  public :: updateepstate
19  public :: update_planestressj2
20  public :: planestressj2tangent
22  integer, parameter, public :: j2_unsupported=1, j2_bad_state=2, j2_bad_property=3
23  integer, parameter, public :: j2_singular=4, j2_no_convergence=5, j2_nonfinite=6, j2_temperature=7
24 
25  real(kind=kreal), parameter :: id(6,6) = reshape( &
26  & (/ 2.d0/3.d0, -1.d0/3.d0, -1.d0/3.d0, 0.d0, 0.d0, 0.d0, &
27  & -1.d0/3.d0, 2.d0/3.d0, -1.d0/3.d0, 0.d0, 0.d0, 0.d0, &
28  & -1.d0/3.d0, -1.d0/3.d0, 2.d0/3.d0, 0.d0, 0.d0, 0.d0, &
29  & 0.d0, 0.d0, 0.d0, 0.5d0, 0.d0, 0.d0, &
30  & 0.d0, 0.d0, 0.d0, 0.d0, 0.5d0, 0.d0, &
31  & 0.d0, 0.d0, 0.d0, 0.d0, 0.d0, 0.5d0/), &
32  & (/6, 6/))
33  real(kind=kreal), parameter :: i2(6) = (/ 1.d0, 1.d0, 1.d0, 0.d0, 0.d0, 0.d0 /)
34 
35  integer, parameter :: vm_elastic = 0
36  integer, parameter :: vm_plastic = 1
37 
38  integer, parameter :: mc_elastic = 0
39  integer, parameter :: mc_plastic_surf = 1
40  integer, parameter :: mc_plastic_right = 2
41  integer, parameter :: mc_plastic_left = 3
42  integer, parameter :: mc_plastic_apex = 4
43 
44  integer, parameter :: dp_elastic = 0
45  integer, parameter :: dp_plastic_surf = 1
46  integer, parameter :: dp_plastic_apex = 2
47 
48  real(kind=kreal), parameter :: shell_shear_correction = 5.0d0/6.0d0
49  integer, parameter :: plane_stress_components(3) = (/ 1, 2, 4 /)
50 
51 contains
52 
53  logical function isplanestressj2perfectplasticity( matl )
54  type(tmaterial), intent(in) :: matl
55 
56  isplanestressj2perfectplasticity = .false.
57  if( .not. iselastoplastic(matl%mtype) ) return
58  if( getelastictype(matl%mtype) /= 0 ) return
59  if( getyieldfunction(matl%mtype) /= 0 ) return
60  if( gethardentype(matl%mtype) /= 0 ) return
61  if( abs(matl%variables(m_plconst2)) > tiny(1.0d0) ) return
62  isplanestressj2perfectplasticity = .true.
63  end function isplanestressj2perfectplasticity
64 
65  subroutine checkplanestressj2material(matl, ierr)
66  type(tmaterial), intent(in) :: matl
67  integer(kind=kint), intent(out) :: ierr
68  type(ttable), pointer :: table
69  real(kind=kreal) :: constants(4), elastic(2)
70  logical :: missing
71 
72  ierr = j2_unsupported
73  if( .not. isplanestressj2perfectplasticity(matl) ) return
74  if( associated(matl%shell_var) ) then
75  if( any(matl%shell_var%ortho /= 0) ) return
76  endif
77  call fetch_table(mc_isoelastic, matl%dict, table, missing)
78  if( .not. missing ) then
79  if( table%ndepends /= 0 ) then
80  ierr = j2_temperature
81  return
82  endif
83  endif
84  call fetch_tabledata(mc_isoelastic, matl%dict, elastic, missing)
85  ierr = j2_bad_property
86  if( missing ) return
87  constants = (/ elastic, matl%variables(m_plconst1), matl%variables(m_plconst2) /)
88  if( .not. all(ieee_is_finite(constants)) ) return
89  if( constants(1) <= 0.0d0 .or. constants(2) <= -1.0d0 .or. constants(2) >= 0.5d0 ) return
90  if( constants(3) <= 0.0d0 ) return
91  ierr = 0
92  end subroutine checkplanestressj2material
93 
94  function planestressj2errormessage(ierr) result(message)
95  integer(kind=kint), intent(in) :: ierr
96  character(len=128) :: message
97 
98  select case(ierr)
99  case(j2_unsupported)
100  message = 'Plane-stress J2 requires isotropic elasticity and perfect plasticity'
101  case(j2_bad_state)
102  message = 'Invalid plane-stress J2 history state'
103  case(j2_bad_property)
104  message = 'Invalid or missing plane-stress J2 properties: require E > 0, -1 < nu < 0.5, yield stress > 0'
105  case(j2_singular)
106  message = 'Singular thickness tangent in plane-stress J2 condensation'
107  case(j2_no_convergence)
108  message = 'Plane-stress J2 local iteration did not converge'
109  case(j2_nonfinite)
110  message = 'Non-finite value in plane-stress J2 material update'
111  case(j2_temperature)
112  message = 'Temperature-dependent elasticity is not supported by plane-stress J2 shells'
113  case default
114  message = 'Unknown plane-stress J2 error'
115  end select
116  end function planestressj2errormessage
117 
118  subroutine condenseplanestressj2tangent( tangent3d, shear_stiffness, tangent, ierr )
119  real(kind=kreal), intent(in) :: tangent3d(6,6)
120  real(kind=kreal), intent(in) :: shear_stiffness
121  real(kind=kreal), intent(out) :: tangent(5,5)
122  integer(kind=kint), intent(out) :: ierr
123 
124  integer :: i, j, ii, jj
125 
126  ierr = 0
127  tangent = 0.0d0
128  if( .not. all(ieee_is_finite(tangent3d)) ) then
129  ierr = j2_nonfinite
130  return
131  endif
132  if( abs(tangent3d(3,3)) <= 100.0d0*epsilon(1.0d0)*maxval(abs(tangent3d)) ) then
133  ierr = j2_singular
134  return
135  endif
136 
137  do i = 1, 3
138  ii = plane_stress_components(i)
139  do j = 1, 3
140  jj = plane_stress_components(j)
141  tangent(i,j) = tangent3d(ii,jj)-tangent3d(ii,3)*tangent3d(3,jj)/tangent3d(3,3)
142  enddo
143  enddo
144  tangent(4,4) = shear_stiffness
145  tangent(5,5) = shear_stiffness
146  end subroutine condenseplanestressj2tangent
147 
152  subroutine update_planestressj2( matl, strain_increment, stress_bak, plstrain, &
153  fstatus, stress, strain_increment_out, tangent, istat, fstatus_out, plpotential, energy_increment, ierr )
154  type(tmaterial), intent(in) :: matl
155  real(kind=kreal), intent(in) :: strain_increment(6), stress_bak(6)
156  real(kind=kreal), intent(in) :: plstrain, fstatus(:)
157  real(kind=kreal), intent(out) :: stress(6), strain_increment_out(6), tangent(5,5)
158  integer, intent(out) :: istat
159  real(kind=kreal), intent(out) :: fstatus_out(:), plpotential, energy_increment
160  integer(kind=kint), intent(out) :: ierr
161 
162  integer, parameter :: maxiter = 25
163  integer :: iter
164  real(kind=kreal) :: elastic(6,6), tangent3d(6,6)
165  real(kind=kreal) :: strain_increment_work(6)
166  real(kind=kreal) :: stress_work(6), stress_bak_work(6)
167  real(kind=kreal) :: shear_stiffness, residual, tolerance
168 
169  ierr = 0
170  stress = 0.0d0
171  strain_increment_out = strain_increment
172  tangent = 0.0d0
173  istat = 0
174  fstatus_out = 0.0d0
175  plpotential = 0.0d0
176  energy_increment = 0.0d0
177 
178  call checkplanestressj2material(matl, ierr)
179  if( ierr /= 0 ) return
180  if( size(fstatus) /= size(fstatus_out) .or. size(fstatus) < 1 ) then
181  ierr = j2_bad_state
182  return
183  endif
184  if( .not. all(ieee_is_finite(strain_increment)) .or. .not. all(ieee_is_finite(stress_bak)) .or. &
185  .not. all(ieee_is_finite(fstatus)) .or. .not. ieee_is_finite(plstrain) ) then
186  ierr = j2_nonfinite
187  return
188  endif
189  fstatus_out = fstatus
190 
191  ! Only the in-plane response enters the three-dimensional J2 update.
192  strain_increment_work = strain_increment
193  strain_increment_work(5:6) = 0.0d0
194  stress_bak_work = stress_bak
195  stress_bak_work(5:6) = 0.0d0
196  strain_increment_work(3) = 0.0d0
197  call calelasticmatrix( matl, d3, elastic, 0.0d0 )
198  shear_stiffness = shell_shear_correction*elastic(5,5)
199 
200  do iter = 1, maxiter
201  ! Each plane-stress iteration starts from the committed J2 state.
202  fstatus_out = fstatus
203  fstatus_out(1) = plstrain
204  stress_work = stress_bak_work+matmul(elastic, strain_increment_work)
205  call backwardeuler( matl, stress_work, plstrain, istat, fstatus_out, plpotential, 0.0d0 )
206  call calelastoplasticmatrix( matl, d3, stress_work, istat, fstatus_out, plstrain, tangent3d, 0.0d0 )
207 
208  if( .not. all(ieee_is_finite(stress_work)) .or. .not. all(ieee_is_finite(tangent3d)) .or. &
209  .not. all(ieee_is_finite(fstatus_out)) ) then
210  ierr = j2_nonfinite
211  return
212  endif
213 
214  residual = stress_work(3)
215  tolerance = 1.0d-10*max(matl%variables(m_plconst1), maxval(abs(stress_work)))
216  if( abs(residual) <= tolerance ) exit
217  if( abs(tangent3d(3,3)) <= 100.0d0*epsilon(1.0d0)*maxval(abs(tangent3d)) ) then
218  ierr = j2_singular
219  return
220  endif
221  strain_increment_work(3) = strain_increment_work(3)-residual/tangent3d(3,3)
222  enddo
223  if( iter > maxiter ) then
224  ierr = j2_no_convergence
225  return
226  endif
227 
228  call condenseplanestressj2tangent(tangent3d, shear_stiffness, tangent, ierr)
229  if( ierr /= 0 ) return
230 
231  stress = stress_work
232  stress(3) = 0.0d0
233  stress(5:6) = stress_bak(5:6)+shear_stiffness*strain_increment(5:6)
234  strain_increment_out = strain_increment_work
235  strain_increment_out(5:6) = strain_increment(5:6)
236  ! Use the elastic predictor work before applying the plastic correction.
237  energy_increment = dot_product(stress_bak_work, strain_increment_work) &
238  +0.5d0*dot_product(matmul(elastic, strain_increment_work), strain_increment_work)+plpotential &
239  +dot_product(stress_bak(5:6)+0.5d0*shear_stiffness*strain_increment(5:6), strain_increment(5:6))
240  if( .not. ieee_is_finite(energy_increment) ) ierr = j2_nonfinite
241  end subroutine update_planestressj2
242 
244  subroutine planestressj2tangent( matl, stress, istat, fstatus, plstrain, tangent, ierr )
245  type(tmaterial), intent(in) :: matl
246  real(kind=kreal), intent(in) :: stress(6), fstatus(:), plstrain
247  integer, intent(in) :: istat
248  real(kind=kreal), intent(out) :: tangent(5,5)
249  integer(kind=kint), intent(out) :: ierr
250 
251  real(kind=kreal) :: tangent3d(6,6), stress_work(6), elastic(6,6)
252 
253  ierr = 0
254  tangent = 0.0d0
255  call checkplanestressj2material(matl, ierr)
256  if( ierr /= 0 ) return
257  if( size(fstatus) < 1 ) then
258  ierr = j2_bad_state
259  return
260  endif
261  if( .not. all(ieee_is_finite(stress)) .or. .not. all(ieee_is_finite(fstatus)) .or. &
262  .not. ieee_is_finite(plstrain) ) then
263  ierr = j2_nonfinite
264  return
265  endif
266  stress_work = stress
267  stress_work(5:6) = 0.0d0
268  call calelasticmatrix( matl, d3, elastic, 0.0d0 )
269  call calelastoplasticmatrix( matl, d3, stress_work, istat, fstatus, plstrain, tangent3d, 0.0d0 )
270  call condenseplanestressj2tangent(tangent3d, shell_shear_correction*elastic(5,5), tangent, ierr)
271  end subroutine planestressj2tangent
272 
274  subroutine calelastoplasticmatrix( matl, sectType, stress, istat, extval, plstrain, D, temperature, hdflag )
275  type( tmaterial ), intent(in) :: matl
276  integer, intent(in) :: secttype
277  real(kind=kreal), intent(in) :: stress(6)
278  real(kind=kreal), intent(in) :: extval(:)
279  real(kind=kreal), intent(in) :: plstrain
280  integer, intent(in) :: istat
281  real(kind=kreal), intent(out) :: d(:,:)
282  real(kind=kreal), intent(in) :: temperature
283  integer(kind=kint), intent(in), optional :: hdflag
284 
285  integer :: ytype,hdflag_in
286 
287  hdflag_in = 0
288  if( present(hdflag) ) hdflag_in = hdflag
289 
290  ytype = getyieldfunction( matl%mtype )
291  select case (ytype)
292  case (0)
293  call calelastoplasticmatrix_vm( matl, secttype, stress, istat, extval, plstrain, d, temperature, hdflag_in )
294  case (1)
295  call calelastoplasticmatrix_mc( matl, secttype, stress, istat, extval, plstrain, d, temperature, hdflag_in )
296  case (2)
297  call calelastoplasticmatrix_dp( matl, secttype, stress, istat, extval, plstrain, d, temperature, hdflag_in )
298  case (3)
299  call uelastoplasticmatrix( matl%variables, stress, istat, extval, plstrain, d, temperature, hdflag_in )
300  end select
301  end subroutine calelastoplasticmatrix
302 
304  subroutine calelastoplasticmatrix_vm( matl, sectType, stress, istat, extval, plstrain, D, temperature, hdflag )
305  type( tmaterial ), intent(in) :: matl
306  integer, intent(in) :: secttype
307  real(kind=kreal), intent(in) :: stress(6)
308  real(kind=kreal), intent(in) :: extval(:)
309  real(kind=kreal), intent(in) :: plstrain
310  integer, intent(in) :: istat
311  real(kind=kreal), intent(out) :: d(:,:)
312  real(kind=kreal), intent(in) :: temperature
313  integer(kind=kint), intent(in) :: hdflag
314 
315  integer :: i,j
316  logical :: kinematic
317  real(kind=kreal) :: dum, a(6), g, dlambda
318  real(kind=kreal) :: c1,c2,c3, back(6)
319  real(kind=kreal) :: j1,j2, harden, khard, devia(6)
320 
321  if( secttype /=d3 ) stop "Elastoplastic calculation support only Solid element currently"
322 
323  call calelasticmatrix( matl, secttype, d, temperature, hdflag=hdflag )
324  if( istat == vm_elastic ) return
325  if( hdflag == 2 ) return
326 
327  harden = calhardencoeff( matl, extval(1), temperature )
328 
329  kinematic = iskinematicharden( matl%mtype )
330  khard = 0.d0
331  if( kinematic ) then
332  back(1:6) = extval(2:7)
333  khard = calkinematicharden( matl, extval(1) )
334  endif
335 
336  j1 = (stress(1)+stress(2)+stress(3))
337  devia(1:3) = stress(1:3)-j1/3.d0
338  devia(4:6) = stress(4:6)
339  if( kinematic ) devia = devia-back
340  j2 = 0.5d0* dot_product( devia(1:3), devia(1:3) ) + &
341  dot_product( devia(4:6), devia(4:6) )
342 
343  a(1:6) = devia(1:6)/sqrt(2.d0*j2)
344  g = d(4,4)
345  dlambda = extval(1)-plstrain
346  c3 = sqrt(3.d0*j2)+3.d0*g*dlambda !trial mises stress
347  c1 = 6.d0*dlambda*g*g/c3
348  dum = 3.d0*g+khard+harden
349  c2 = 6.d0*g*g*(dlambda/c3-1.d0/dum)
350 
351  do i=1,6
352  do j=1,6
353  d(i,j) = d(i,j) - c1*id(i,j) + c2*a(i)*a(j)
354  enddo
355  enddo
356  end subroutine calelastoplasticmatrix_vm
357 
359  subroutine calelastoplasticmatrix_mc( matl, sectType, stress, istat, extval, plstrain, D, temperature, hdflag )
361  type( tmaterial ), intent(in) :: matl
362  integer, intent(in) :: secttype
363  real(kind=kreal), intent(in) :: stress(6)
364  real(kind=kreal), intent(in) :: extval(:)
365  real(kind=kreal), intent(in) :: plstrain
366  integer, intent(in) :: istat
367  real(kind=kreal), intent(out) :: d(:,:)
368  real(kind=kreal), intent(in) :: temperature
369  integer(kind=kint), intent(in) :: hdflag
370 
371  real(kind=kreal) :: g, k, harden, r2g, r2gd3, r4gd3, r2k, youngs, poisson
372  real(kind=kreal) :: phi, psi, cosphi, sinphi, cotphi, sinpsi, sphsps, r2cosphi, r4cos2phi
373  real(kind=kreal) :: prnstre(3), prnprj(3,3), prnstra(3)
374  integer(kind=kint) :: m1, m2, m3
375  real(kind=kreal) :: c1,c2, ca1, ca2, ca3, cam, cap, cd1, cd2, cd3, cdiag, coffd
376  real(kind=kreal) :: ck1, ck2, ck3
377  real(kind=kreal) :: dum, da, db, dc, dd, detinv
378  real(kind=kreal) :: dpsdpe(3,3)
379 
380  if( secttype /=d3 ) stop "Elastoplastic calculation support only Solid element currently"
381 
382  call calelasticmatrix( matl, secttype, d, temperature, hdflag=hdflag )
383  if( istat == mc_elastic ) return
384  if( hdflag == 2 ) return
385 
386  harden = calhardencoeff( matl, extval(1), temperature )
387  g = d(4,4)
388  k = d(1,1)-(4.d0/3.d0)*g
389  r2g = 2.d0*g
390  r2k = 2.d0*k
391  r2gd3 = r2g/3.d0
392  r4gd3 = 2.d0*r2gd3
393  youngs = 9.d0*k*g/(3.d0*k+g)
394  poisson = (3.d0*k-r2g)/(6.d0*k+r2g)
395 
396  phi = matl%variables(m_plconst3)
397  psi = matl%variables(m_plconst4)
398  sinphi = sin(phi)
399  cosphi = cos(phi)
400  sinpsi = sin(psi)
401  sphsps = sinphi*sinpsi
402  r2cosphi = 2.d0*cosphi
403  r4cos2phi = r2cosphi*r2cosphi
404 
405  call eigen3( stress, prnstre, prnprj )
406  m1 = maxloc( prnstre, 1 )
407  m3 = minloc( prnstre, 1 )
408  if( m1 == m3 ) then
409  m1 = 1; m2 = 2; m3 = 3
410  else
411  m2 = 6 - (m1 + m3)
412  endif
413 
414  c1 = 4.d0*(g*(1.d0+sphsps/3.d0)+k*sphsps)
415  if( istat==mc_plastic_surf ) then
416  dd= c1 + r4cos2phi*harden
417  cd1 = (r2g*(1.d0+sinpsi/3.d0) + r2k*sinpsi)/dd
418  cd2 = (r4gd3-r2k)*sinpsi/dd
419  cd3 = (r2g*(1.d0-sinpsi/3.d0) - r2k*sinpsi)/dd
420  cap = 1.d0+sinphi/3.d0
421  cam = 1.d0-sinphi/3.d0
422  ck1 = 1.d0-2.d0*cd1*sinphi
423  ck2 = 1.d0+2.d0*cd2*sinphi
424  ck3 = 1.d0+2.d0*cd3*sinphi
425  dpsdpe(m1,m1) = r2g*( 2.d0/3.d0-cd1*cap)+k*ck1
426  dpsdpe(m1,m2) = (k-r2gd3)*ck1
427  dpsdpe(m1,m3) = r2g*(-1.d0/3.d0+cd1*cam)+k*ck1
428  dpsdpe(m2,m1) = r2g*(-1.d0/3.d0+cd2*cap)+k*ck2
429  dpsdpe(m2,m2) = r4gd3*( 1.d0-cd2*sinphi)+k*ck2
430  dpsdpe(m2,m3) = r2g*(-1.d0/3.d0-cd2*cam)+k*ck2
431  dpsdpe(m3,m1) = r2g*(-1.d0/3.d0+cd3*cap)+k*ck3
432  dpsdpe(m3,m2) = (k-r2gd3)*ck3
433  dpsdpe(m3,m3) = r2g*( 2.d0/3.d0-cd3*cam)+k*ck3
434  else if( istat==mc_plastic_apex ) then
435  cotphi = cosphi/sinphi
436  dpsdpe(:,:) = k*(1.d0-(k/(k+harden*cotphi*cosphi/sinpsi)))
437  else ! EDGE
438  if( istat==mc_plastic_right ) then
439  c2 = r2g*(1.d0+sinphi+sinpsi-sphsps/3.d0) + 4.d0*k*sphsps
440  else if( istat==mc_plastic_left ) then
441  c2 = r2g*(1.d0-sinphi-sinpsi-sphsps/3.d0) + 4.d0*k*sphsps
442  endif
443  dum = r4cos2phi*harden
444  da = c1 + dum
445  db = c2 + dum
446  dc = db
447  dd = da
448  detinv = 1.d0/(da*dd-db*dc)
449  ca1 = r2g*(1.d0+sinpsi/3.d0)+r2k*sinpsi
450  ca2 = (r4gd3-r2k)*sinpsi
451  ca3 = r2g*(1.d0-sinpsi/3.d0)-r2k*sinpsi
452  cdiag = k+r4gd3
453  coffd = k-r2gd3
454  if( istat==mc_plastic_right ) then
455  dpsdpe(m1,m1) = cdiag+ca1*(db-dd-da+dc)*(r2g+(r2k+r2gd3)*sinphi)*detinv
456  dpsdpe(m1,m2) = coffd+ca1*(r2g*(da-db)+((db-dd-da+dc)*(r2k+r2gd3)+(dd-dc)*r2g)*sinphi)*detinv
457  dpsdpe(m1,m3) = coffd+ca1*(r2g*(dd-dc)+((db-dd-da+dc)*(r2k+r2gd3)+(da-db)*r2g)*sinphi)*detinv
458  dpsdpe(m2,m1) = coffd+(ca2*(dd-db)+ca3*(da-dc))*(r2g+(r2k+r2gd3)*sinphi)*detinv
459  dpsdpe(m2,m2) = cdiag+(ca2*((r2k*(dd-db)-(db*r2gd3+dd*r4gd3))*sinphi+db*r2g) &
460  & +ca3*((r2k*(da-dc)+(da*r2gd3+dc*r4gd3))*sinphi-da*r2g))*detinv
461  dpsdpe(m2,m3) = coffd+(ca2*((r2k*(dd-db)+(db*r4gd3+dd*r2gd3))*sinphi-dd*r2g) &
462  & +ca3*((r2k*(da-dc)-(da*r4gd3+dc*r2gd3))*sinphi+dc*r2g))*detinv
463  dpsdpe(m3,m1) = coffd+(ca2*(da-dc)+ca3*(dd-db))*(r2g+(r2k+r2gd3)*sinphi)*detinv
464  dpsdpe(m3,m2) = coffd+(ca2*((r2k*(da-dc)+(da*r2gd3+dc*r4gd3))*sinphi-da*r2g) &
465  & +ca3*((r2k*(dd-db)-(db*r2gd3+dd*r4gd3))*sinphi+db*r2g))*detinv
466  dpsdpe(m3,m3) = cdiag+(ca2*((r2k*(da-dc)-(da*r4gd3+dc*r2gd3))*sinphi+dc*r2g) &
467  & +ca3*((r2k*(dd-db)+(db*r4gd3+dd*r2gd3))*sinphi-dd*r2g))*detinv
468  else if( istat==mc_plastic_left ) then
469  dpsdpe(m1,m1) = cdiag+(ca1*((r2k*(db-dd)-(db*r4gd3+dd*r2gd3))*sinphi-dd*r2g) &
470  & +ca2*((r2k*(da-dc)-(da*r4gd3+dc*r2gd3))*sinphi-dc*r2g))*detinv
471  dpsdpe(m1,m2) = coffd+(ca1*((r2k*(db-dd)+(db*r2gd3+dd*r4gd3))*sinphi+db*r2g) &
472  & +ca2*((r2k*(da-dc)+(da*r2gd3+dc*r4gd3))*sinphi+da*r2g))*detinv
473  dpsdpe(m1,m3) = coffd+(ca1*(db-dd)+ca2*(da-dc))*(-r2g+(r2k+r2gd3)*sinphi)*detinv
474  dpsdpe(m2,m1) = coffd+(ca1*((r2k*(dc-da)+(da*r4gd3+dc*r2gd3))*sinphi+dc*r2g) &
475  & +ca2*((r2k*(dd-db)+(db*r4gd3+dd*r2gd3))*sinphi+dd*r2g))*detinv
476  dpsdpe(m2,m2) = cdiag+(ca1*((r2k*(dc-da)-(da*r2gd3+dc*r4gd3))*sinphi-da*r2g) &
477  & +ca2*((r2k*(dd-db)-(db*r2gd3+dd*r4gd3))*sinphi-db*r2g))*detinv
478  dpsdpe(m2,m3) = coffd+(ca1*(dc-da)+ca2*(dd-db))*(-r2g+(r2k+r2gd3)*sinphi)*detinv
479  dpsdpe(m3,m1) = coffd+ca3*((r2k*(-db+dd+da-dc)+(db-da)*r4gd3+(dd-dc)*r2gd3)*sinphi+(dd-dc)*r2g)*detinv
480  dpsdpe(m3,m2) = coffd+ca3*((r2k*(-db+dd+da-dc)+(da-db)*r2gd3+(dc-dd)*r4gd3)*sinphi+(da-db)*r2g)*detinv
481  dpsdpe(m3,m3) = cdiag+ca3*(-db+dd+da-dc)*(-r2g+(r2k+r2gd3)*sinphi)*detinv
482  endif
483  endif
484  ! compute principal elastic strain from principal stress
485  prnstra(1) = (prnstre(1)-poisson*(prnstre(2)+prnstre(3)))/youngs
486  prnstra(2) = (prnstre(2)-poisson*(prnstre(1)+prnstre(3)))/youngs
487  prnstra(3) = (prnstre(3)-poisson*(prnstre(1)+prnstre(2)))/youngs
488  call deriv_general_iso_tensor_func_3d(dpsdpe, d, prnprj, prnstra, prnstre)
489  end subroutine calelastoplasticmatrix_mc
490 
492  subroutine calelastoplasticmatrix_dp( matl, sectType, stress, istat, extval, plstrain, D, temperature, hdflag )
493  type( tmaterial ), intent(in) :: matl
494  integer, intent(in) :: secttype
495  real(kind=kreal), intent(in) :: stress(6)
496  real(kind=kreal), intent(in) :: extval(:)
497  real(kind=kreal), intent(in) :: plstrain
498  integer, intent(in) :: istat
499  real(kind=kreal), intent(out) :: d(:,:)
500  real(kind=kreal), intent(in) :: temperature
501  integer(kind=kint), intent(in) :: hdflag
502 
503  integer :: i,j
504  real(kind=kreal) :: dum, a(6), dlambda, g, k
505  real(kind=kreal) :: j1,j2, eta, xi, etabar, harden, devia(6)
506  real(kind=kreal) :: alpha, beta, c1, c2, c3, c4, ca, devia_norm
507 
508  if( secttype /=d3 ) stop "Elastoplastic calculation support only Solid element currently"
509 
510  call calelasticmatrix( matl, secttype, d, temperature, hdflag=hdflag )
511  if( istat == dp_elastic ) return ! elastic state
512  if( hdflag == 2 ) return
513 
514  harden = calhardencoeff( matl, extval(1), temperature )
515 
516  g = d(4,4)
517  k = d(1,1)-(4.d0/3.d0)*g
518 
519  eta = matl%variables(m_plconst3)
520  xi = matl%variables(m_plconst4)
521  etabar = matl%variables(m_plconst5)
522 
523  if( istat==dp_plastic_surf ) then
524  j1 = (stress(1)+stress(2)+stress(3))
525  devia(1:3) = stress(1:3)-j1/3.d0
526  devia(4:6) = stress(4:6)
527  j2 = 0.5d0* dot_product( devia(1:3), devia(1:3) ) + &
528  dot_product( devia(4:6), devia(4:6) )
529 
530  devia_norm = sqrt(2.d0*j2)
531  a(1:6) = devia(1:6)/devia_norm
532  dlambda = extval(1)-plstrain
533  ca = 1.d0 / (g + k*eta*etabar + xi*xi*harden)
534  dum = sqrt(2.d0)*devia_norm
535  c1 = 4.d0*g*g*dlambda/dum
536  c2 = 2.d0*g*(2.d0*g*dlambda/dum - g*ca)
537  c3 = sqrt(2.d0)*g*ca*k
538  c4 = k*k*eta*etabar*ca
539  do j=1,6
540  do i=1,6
541  d(i,j) = d(i,j) - c1*id(i,j) + c2*a(i)*a(j) &
542  - c3*(eta*a(i)*i2(j) + etabar*i2(i)*a(j)) &
543  - c4*i2(i)*i2(j)
544  enddo
545  enddo
546  else ! istat==DP_PLASTIC_APEX
547  alpha = xi/etabar
548  beta = xi/eta
549  c1 = k*(1.d0 - k/(k + alpha*beta*harden))
550  do j=1,6
551  do i=1,6
552  d(i,j) = c1*i2(i)*i2(j)
553  enddo
554  enddo
555  endif
556  end subroutine calelastoplasticmatrix_dp
557 
559  real(kind=kreal) function calhardencoeff( matl, pstrain, temp )
560  type( tmaterial ), intent(in) :: matl
561  real(kind=kreal), intent(in) :: pstrain
562  real(kind=kreal), intent(in) :: temp
563 
564  integer :: htype
565  logical :: ierr
566  real(kind=kreal) :: s0, s1,s2, ef, ina(2)
567 
568  calhardencoeff = -1.d0
569  htype = gethardentype( matl%mtype )
570  select case (htype)
571  case (0) ! Linear hardening
572  calhardencoeff = matl%variables(m_plconst2)
573  case (1) ! Multilinear approximation
574  ina(1) = temp; ina(2)=pstrain
575  call fetch_tablegrad( mc_yield, ina, matl%dict, calhardencoeff, ierr )
576  case (2) ! Swift
577  s0= matl%variables(m_plconst1)
578  s1= matl%variables(m_plconst2)
579  s2= matl%variables(m_plconst3)
580  calhardencoeff = s1*s2*( s0+pstrain )**(s2-1)
581  case (3) ! Ramberg-Osgood
582  s0= matl%variables(m_plconst1)
583  s1= matl%variables(m_plconst2)
584  s2= matl%variables(m_plconst3)
585  ef = calcurryield( matl, pstrain, temp )
586  calhardencoeff = s1*(ef/s1)**(1.d0-s2) /(s0*s2)
587  case(4) ! Prager
588  calhardencoeff = 0.d0
589  case(5) ! Prager+linear
590  calhardencoeff = matl%variables(m_plconst2)
591  end select
592  end function
593 
595  real(kind=kreal) function calkinematicharden( matl, pstrain )
596  type( tmaterial ), intent(in) :: matl
597  real(kind=kreal), intent(in) :: pstrain
598 
599  integer :: htype
600  htype = gethardentype( matl%mtype )
601  select case (htype)
602  case(4, 5) ! Prager
603  calkinematicharden = matl%variables(m_plconst3)
604  case default
605  calkinematicharden = 0.d0
606  end select
607  end function
608 
610  real(kind=kreal) function calcurrkinematic( matl, pstrain )
611  type( tmaterial ), intent(in) :: matl
612  real(kind=kreal), intent(in) :: pstrain
613 
614  integer :: htype
615  htype = gethardentype( matl%mtype )
616  select case (htype)
617  case(4, 5) ! Prager
618  calcurrkinematic = matl%variables(m_plconst3)*pstrain
619  case default
620  calcurrkinematic = 0.d0
621  end select
622  end function
623 
625  real(kind=kreal) function calcurryield( matl, pstrain, temp )
626  type( tmaterial ), intent(in) :: matl
627  real(kind=kreal), intent(in) :: pstrain
628  real(kind=kreal), intent(in) :: temp
629 
630  integer :: htype
631  real(kind=kreal) :: s0, s1,s2, ina(2), outa(1)
632  logical :: ierr
633  calcurryield = -1.d0
634  htype = gethardentype( matl%mtype )
635 
636  select case (htype)
637  case (0, 5) ! Linear hardening, Linear+Parger hardening
638  calcurryield = matl%variables(m_plconst1)+matl%variables(m_plconst2)*pstrain
639  case (1) ! Multilinear approximation
640  ina(1) = temp; ina(2)=pstrain
641  call fetch_tabledata(mc_yield, matl%dict, outa, ierr, ina)
642  if( ierr ) stop "Fail to get yield stress!"
643  calcurryield = outa(1)
644  case (2) ! Swift
645  s0= matl%variables(m_plconst1)
646  s1= matl%variables(m_plconst2)
647  s2= matl%variables(m_plconst3)
648  calcurryield = s1*( s0+pstrain )**s2
649  case (3) ! Ramberg-Osgood
650  s0= matl%variables(m_plconst1)
651  s1= matl%variables(m_plconst2)
652  s2= matl%variables(m_plconst3)
653  if( pstrain<=s0 ) then
654  calcurryield = s1
655  else
656  calcurryield = s1*( pstrain/s0 )**(1.d0/s2)
657  endif
658  case (4) ! Parger hardening
659  calcurryield = matl%variables(m_plconst1)
660  end select
661  end function
662 
664  subroutine backwardeuler( matl, stress, plstrain, istat, fstat, plpotential, temp, hdflag )
665  type( tmaterial ), intent(in) :: matl
666  real(kind=kreal), intent(inout) :: stress(6)
667  real(kind=kreal), intent(in) :: plstrain
668  integer, intent(inout) :: istat
669  real(kind=kreal), intent(inout) :: fstat(:)
670  real(kind=kreal), intent(inout) :: plpotential
671  real(kind=kreal), intent(in) :: temp
672  integer(kind=kint), intent(in), optional :: hdflag
673 
674  integer :: ytype, hdflag_in
675 
676  hdflag_in = 0
677  if( present(hdflag) ) hdflag_in = hdflag
678 
679  ytype = getyieldfunction( matl%mtype )
680  ! The return mappings leave the trial state untouched when the trial stress is elastic.
681  if( ytype /= 3 ) then
682  fstat(1) = plstrain
683  if( iskinematicharden( matl%mtype ) ) fstat(2:7) = fstat(8:13)
684  endif
685  select case (ytype)
686  case (0)
687  call backwardeuler_vm( matl, stress, plstrain, istat, fstat, plpotential, temp, hdflag_in )
688  case (1)
689  call backwardeuler_mc( matl, stress, plstrain, istat, fstat, temp, hdflag_in )
690  case (2)
691  call backwardeuler_dp( matl, stress, plstrain, istat, fstat, temp, hdflag_in )
692  case (3)
693  call ubackwardeuler( matl%variables, stress, plstrain, istat, fstat, temp, hdflag_in )
694  end select
695  end subroutine backwardeuler
696 
698  subroutine backwardeuler_vm( matl, stress, plstrain, istat, fstat, plpotential, temp, hdflag )
699  type( tmaterial ), intent(in) :: matl
700  real(kind=kreal), intent(inout) :: stress(6)
701  real(kind=kreal), intent(in) :: plstrain
702  integer, intent(inout) :: istat
703  real(kind=kreal), intent(inout) :: fstat(:)
704  real(kind=kreal), intent(inout) :: plpotential
705  real(kind=kreal), intent(in) :: temp
706  integer(kind=kint), intent(in) :: hdflag
707 
708  real(kind=kreal), parameter :: tol =1.d-8
709  integer, parameter :: maxiter = 10
710  real(kind=kreal) :: dlambda, f
711  integer :: i
712  real(kind=kreal) :: youngs, poisson, pstrain, ina(1), ee(2)
713  real(kind=kreal) :: j1, j2, h, kh, kk, dd, eqvs, yd, g, k, devia(6)
714  logical :: kinematic, ierr
715  real(kind=kreal) :: betan, back(6)
716 
717  plpotential = 0.d0
718  kinematic = iskinematicharden( matl%mtype )
719  if( kinematic ) back(1:6) = fstat(8:13)
720 
721  j1 = (stress(1)+stress(2)+stress(3))
722  devia(1:3) = stress(1:3)-j1/3.d0
723  devia(4:6) = stress(4:6)
724  if( kinematic ) devia = devia-back
725  j2 = 0.5d0* dot_product( devia(1:3), devia(1:3) ) + &
726  dot_product( devia(4:6), devia(4:6) )
727 
728  eqvs = dsqrt( 3.d0*j2 )
729  yd = calcurryield( matl, plstrain, temp )
730  f = eqvs - yd
731 
732  if( abs(f/yd)<tol ) then ! yielded
733  istat = vm_plastic
734  return
735  elseif( f<0.d0 ) then ! not yielded or unloading
736  istat = vm_elastic
737  return
738  endif
739  if( hdflag == 2 ) return
740 
741  istat = vm_plastic ! yielded
742  kh = 0.d0; kk=0.d0; betan=0.d0
743  if( kinematic ) then
744  betan = calcurrkinematic( matl, plstrain ) ! keep back = alpha_n (loaded above) so it accumulates at fstat update and is restored into stress
745  else
746  back(:)=0.d0
747  endif
748 
749  ina(1) = temp
750  call fetch_tabledata(mc_isoelastic, matl%dict, ee, ierr, ina)
751  if( ierr ) then
752  stop " fail to fetch young's modulus in elastoplastic calculation"
753  else
754  youngs = ee(1)
755  poisson = ee(2)
756  endif
757  if( youngs==0.d0 ) stop "YOUNG's ratio==0"
758  g = youngs/ ( 2.d0*(1.d0+poisson) )
759  k = youngs/ ( 3.d0*(1.d0-2.d0*poisson) )
760 
761  dlambda = 0.d0
762  pstrain = plstrain
763 
764  do i=1,maxiter
765  h= calhardencoeff( matl, pstrain, temp )
766  if( kinematic ) then
767  kh = calkinematicharden( matl, pstrain )
768  endif
769  dd= 3.d0*g+h+kh
770  dlambda = dlambda+f/dd
771  if( dlambda<0.d0 ) then
772  dlambda = 0.d0
773  pstrain = plstrain
774  istat=vm_elastic; exit
775  endif
776  pstrain = plstrain+dlambda
777  yd = calcurryield( matl, pstrain, temp )
778  if( kinematic ) then
779  kk = calcurrkinematic( matl, pstrain )
780  endif
781  f = eqvs-3.d0*g*dlambda-yd -(kk-betan)
782  if( abs(f/yd)<tol ) exit
783  ! if( i==MAXITER ) then
784  ! stop 'ERROR: BackwardEuler_VM: convergence failure'
785  ! endif
786  enddo
787  if( kinematic ) then
788  kk = calcurrkinematic( matl, pstrain )
789  fstat(2:7) = back(:)+(kk-betan)*devia(:)/eqvs
790  endif
791  devia(:) = (1.d0-3.d0*dlambda*g/eqvs)*devia(:)
792  stress(1:3) = devia(1:3)+j1/3.d0
793  stress(4:6) = devia(4:6)
794  stress(:)= stress(:)+back(:)
795 
796  fstat(1) = pstrain
797 
798  h= calhardencoeff( matl, pstrain, temp ) !a
799  yd = calcurryield( matl, plstrain, temp ) !b
800  plpotential = -0.5d0*(eqvs-yd)*(eqvs-yd)/(h+3.d0*g)
801 
802  end subroutine backwardeuler_vm
803 
805  subroutine backwardeuler_mc( matl, stress, plstrain, istat, fstat, temp, hdflag )
806  use m_utilities, only : eigen3
807  type( tmaterial ), intent(in) :: matl
808  real(kind=kreal), intent(inout) :: stress(6)
809  real(kind=kreal), intent(in) :: plstrain
810  integer, intent(inout) :: istat
811  real(kind=kreal), intent(inout) :: fstat(:)
812  real(kind=kreal), intent(in) :: temp
813  integer(kind=kint), intent(in) :: hdflag
814 
815  real(kind=kreal), parameter :: tol =1.d-8
816  integer, parameter :: maxiter = 10
817  real(kind=kreal) :: dlambda, f, mat(3,3)
818  integer :: i, m1, m2, m3
819  real(kind=kreal) :: youngs, poisson, pstrain, ina(1), ee(2)
820  real(kind=kreal) :: h, dd, eqvs, cohe, g, k
821  real(kind=kreal) :: prnstre(3), prnprj(3,3), tstre(3,3)
822  real(kind=kreal) :: phi, psi, trialprn(3)
823  logical :: ierr
824  real(kind=kreal) :: c1, c2, cs1, cs2, cs3
825  real(kind=kreal) :: sinphi, cosphi, sinpsi, sphsps, r2cosphi, r4cos2phi, cotphi
826  real(kind=kreal) :: da, db, dc, depv, detinv, dlambdb, dum, eps, eqvsb, fb
827  real(kind=kreal) :: pt, p, resid
828 
829  phi = matl%variables(m_plconst3)
830  psi = matl%variables(m_plconst4)
831  sinphi = sin(phi)
832  cosphi = cos(phi)
833  r2cosphi = 2.d0*cosphi
834 
835  call eigen3( stress, prnstre, prnprj )
836  trialprn = prnstre
837  m1 = maxloc( prnstre, 1 )
838  m3 = minloc( prnstre, 1 )
839  if( m1 == m3 ) then
840  m1 = 1; m2 = 2; m3 = 3
841  else
842  m2 = 6 - (m1 + m3)
843  endif
844 
845  eqvs = prnstre(m1)-prnstre(m3) + (prnstre(m1)+prnstre(m3))*sinphi
846  cohe = calcurryield( matl, plstrain, temp )
847  f = eqvs - r2cosphi*cohe
848 
849  if( abs(f/cohe)<tol ) then ! yielded
850  istat = mc_plastic_surf
851  return
852  elseif( f<0.d0 ) then ! not yielded or unloading
853  istat = mc_elastic
854  return
855  endif
856  if( hdflag == 2 ) return
857 
858  istat = mc_plastic_surf ! yielded
859 
860  ina(1) = temp
861  call fetch_tabledata(mc_isoelastic, matl%dict, ee, ierr, ina)
862  if( ierr ) then
863  stop " fail to fetch young's modulus in elastoplastic calculation"
864  else
865  youngs = ee(1)
866  poisson = ee(2)
867  endif
868  if( youngs==0.d0 ) stop "YOUNG's ratio==0"
869  g = youngs/ ( 2.d0*(1.d0+poisson) )
870  k = youngs/ ( 3.d0*(1.d0-2.d0*poisson) )
871 
872  dlambda = 0.d0
873  pstrain = plstrain
874 
875  sinpsi = sin(psi)
876  sphsps = sinphi*sinpsi
877  r4cos2phi = r2cosphi*r2cosphi
878  c1 = 4.d0*(g*(1.d0+sphsps/3.d0)+k*sphsps)
879  do i=1,maxiter
880  h= calhardencoeff( matl, pstrain, temp )
881  dd= c1 + r4cos2phi*h
882  dlambda = dlambda+f/dd
883  if( r2cosphi*dlambda<0.d0 ) then
884  if( cosphi==0.d0 ) stop "Math error in return mapping"
885  dlambda = 0.d0
886  pstrain = plstrain
887  istat = mc_elastic; exit
888  endif
889  pstrain = plstrain + r2cosphi*dlambda
890  cohe = calcurryield( matl, pstrain, temp )
891  f = eqvs - c1*dlambda - r2cosphi*cohe
892  if( abs(f/cohe)<tol ) exit
893  ! if( i==MAXITER ) then
894  ! stop 'ERROR: BackwardEuler_MC: convergence failure'
895  ! endif
896  enddo
897  cs1 =2.d0*g*(1.d0+sinpsi/3.d0) + 2.d0*k*sinpsi
898  cs2 =(4.d0*g/3.d0-2.d0*k)*sinpsi
899  cs3 =2.d0*g*(1.d0-sinpsi/3.d0) - 2.d0*k*sinpsi
900  prnstre(m1) = prnstre(m1)-cs1*dlambda
901  prnstre(m2) = prnstre(m2)+cs2*dlambda
902  prnstre(m3) = prnstre(m3)+cs3*dlambda
903  eps = (abs(prnstre(m1))+abs(prnstre(m2))+abs(prnstre(m3)))*tol
904  if( prnstre(m1) < prnstre(m2)-eps .or. prnstre(m2) < prnstre(m3)-eps ) then
905  ! return mapping to EDGE
906  prnstre = trialprn
907  dlambda = 0.d0
908  dlambdb = 0.d0
909  if( (1.d0-sinpsi)*prnstre(m1) - 2*prnstre(m2) + (1.d0+sinpsi)*prnstre(m3) > 0) then
910  istat = mc_plastic_right
911  eqvsb = prnstre(m1)-prnstre(m2) + (prnstre(m1)+prnstre(m2))*sinphi
912  c2 = 2.d0*g*(1.d0+sinphi+sinpsi-sphsps/3.d0) + 4.d0*k*sphsps
913  else
914  istat = mc_plastic_left
915  eqvsb = prnstre(m2)-prnstre(m3) + (prnstre(m2)+prnstre(m3))*sinphi
916  c2 = 2.d0*g*(1.d0-sinphi-sinpsi-sphsps/3.d0) + 4.d0*k*sphsps
917  endif
918  cohe = calcurryield( matl, plstrain, temp )
919  f = eqvs - r2cosphi*cohe
920  fb = eqvsb - r2cosphi*cohe
921  pstrain = plstrain
922  do i=1,maxiter
923  h= calhardencoeff( matl, pstrain, temp )
924  dum = r4cos2phi*h
925  da = c1 + dum
926  db = c2 + dum
927  dc = db
928  dd = da
929  detinv = 1.d0/(da*dd-db*dc)
930  dlambda = dlambda + detinv*( dd*f - db*fb)
931  dlambdb = dlambdb + detinv*(-dc*f + da*fb)
932  pstrain = plstrain + r2cosphi*(dlambda+dlambdb)
933  cohe = calcurryield( matl, pstrain, temp )
934  f = eqvs - c1*dlambda - c2*dlambdb - r2cosphi*cohe
935  fb = eqvsb - c2*dlambda - c1*dlambdb - r2cosphi*cohe
936  if( (abs(f)+abs(fb))/(abs(eqvs)+abs(eqvsb)) < tol ) exit
937  ! if( i==MAXITER ) then
938  ! stop 'ERROR: BackwardEuler_MC: convergence failure(2)'
939  ! endif
940  enddo
941  if( istat==mc_plastic_right ) then
942  prnstre(m1) = prnstre(m1)-cs1*(dlambda+dlambdb)
943  prnstre(m2) = prnstre(m2)+cs2*dlambda+cs3*dlambdb
944  prnstre(m3) = prnstre(m3)+cs3*dlambda+cs2*dlambdb
945  else
946  prnstre(m1) = prnstre(m1)-cs1*dlambda+cs2*dlambdb
947  prnstre(m2) = prnstre(m2)+cs2*dlambda-cs1*dlambdb
948  prnstre(m3) = prnstre(m3)+cs3*(dlambda+dlambdb)
949  endif
950  eps = (abs(prnstre(m1))+abs(prnstre(m2))+abs(prnstre(m3)))*tol
951  if( prnstre(m1) < prnstre(m2)-eps .or. prnstre(m2) < prnstre(m3)-eps ) then
952  ! return mapping to APEX
953  prnstre = trialprn
954  istat = mc_plastic_apex
955  if( sinphi==0.d0 ) stop 'ERROR: BackwardEuler_MC: phi==0.0'
956  if( sinpsi==0.d0 ) stop 'ERROR: BackwardEuler_MC: psi==0.0'
957  depv = 0.d0
958  cohe = calcurryield( matl, plstrain, temp )
959  cotphi = cosphi/sinphi
960  pt = (stress(1)+stress(2)+stress(3))/3.d0
961  resid = cotphi*cohe - pt
962  pstrain = plstrain
963  do i=1,maxiter
964  h= calhardencoeff( matl, pstrain, temp )
965  dd= cosphi*cotphi*h/sinpsi + k
966  depv = depv - resid/dd
967  pstrain = plstrain + cosphi*depv/sinpsi
968  cohe = calcurryield( matl, pstrain,temp )
969  p = pt-k*depv
970  resid = cotphi*cohe-p
971  if( abs(resid/cohe)<tol ) exit
972  ! if( i==MAXITER ) then
973  ! stop 'ERROR: BackwardEuler_MC: convergence failure(3)'
974  ! endif
975  enddo
976  prnstre(m1) = p
977  prnstre(m2) = p
978  prnstre(m3) = p
979  endif
980  endif
981  tstre(:,:) = 0.d0
982  tstre(1,1)= prnstre(1); tstre(2,2)=prnstre(2); tstre(3,3)=prnstre(3)
983  mat= matmul( prnprj, tstre )
984  mat= matmul( mat, transpose(prnprj) )
985  stress(1) = mat(1,1)
986  stress(2) = mat(2,2)
987  stress(3) = mat(3,3)
988  stress(4) = mat(1,2)
989  stress(5) = mat(2,3)
990  stress(6) = mat(3,1)
991 
992  fstat(1) = pstrain
993  end subroutine backwardeuler_mc
994 
996  subroutine backwardeuler_dp( matl, stress, plstrain, istat, fstat, temp, hdflag )
997  type( tmaterial ), intent(in) :: matl
998  real(kind=kreal), intent(inout) :: stress(6)
999  real(kind=kreal), intent(in) :: plstrain
1000  integer, intent(inout) :: istat
1001  real(kind=kreal), intent(inout) :: fstat(:)
1002  real(kind=kreal), intent(in) :: temp
1003  integer(kind=kint), intent(in) :: hdflag
1004 
1005  real(kind=kreal), parameter :: tol =1.d-8
1006  integer, parameter :: maxiter = 10
1007  real(kind=kreal) :: dlambda, f
1008  integer :: i
1009  real(kind=kreal) :: youngs, poisson, pstrain, xi, ina(1), ee(2)
1010  real(kind=kreal) :: j1,j2,h, dd, eqvst, eqvs, cohe, g, k, devia(6), eta, etabar, pt, p
1011  logical :: ierr
1012  real(kind=kreal) :: alpha, beta, depv, factor, resid
1013 
1014  eta = matl%variables(m_plconst3)
1015  xi = matl%variables(m_plconst4)
1016  etabar = matl%variables(m_plconst5)
1017 
1018  j1 = (stress(1)+stress(2)+stress(3))
1019  pt = j1/3.d0
1020  devia(1:3) = stress(1:3)-pt
1021  devia(4:6) = stress(4:6)
1022  j2 = 0.5d0* dot_product( devia(1:3), devia(1:3) ) + &
1023  dot_product( devia(4:6), devia(4:6) )
1024 
1025  eqvst = sqrt(j2)
1026  cohe = calcurryield( matl, plstrain, temp )
1027  f = eqvst + eta*pt - xi*cohe
1028 
1029  if( abs(f/cohe)<tol ) then ! yielded
1030  istat = dp_plastic_surf
1031  return
1032  elseif( f<0.d0 ) then ! not yielded or unloading
1033  istat = dp_elastic
1034  return
1035  endif
1036  if( hdflag == 2 ) return
1037 
1038  istat = dp_plastic_surf
1039 
1040  ina(1) = temp
1041  call fetch_tabledata(mc_isoelastic, matl%dict, ee, ierr, ina)
1042  if( ierr ) then
1043  stop " fail to fetch young's modulus in elastoplastic calculation"
1044  else
1045  youngs = ee(1)
1046  poisson = ee(2)
1047  endif
1048  if( youngs==0.d0 ) stop "YOUNG's ratio==0"
1049  g = youngs/ ( 2.d0*(1.d0+poisson) )
1050  k = youngs/ ( 3.d0*(1.d0-2.d0*poisson) )
1051 
1052  dlambda = 0.d0
1053  pstrain = plstrain
1054 
1055  do i=1,maxiter
1056  h= calhardencoeff( matl, pstrain, temp )
1057  dd= g+k*etabar*eta+h*xi*xi
1058  dlambda = dlambda+f/dd
1059  if( xi*dlambda<0.d0 ) then
1060  if( xi==0.d0 ) stop "Math error in return mapping"
1061  dlambda = 0.d0
1062  pstrain = plstrain
1063  istat=0; exit
1064  endif
1065  pstrain = plstrain+xi*dlambda
1066  cohe = calcurryield( matl, pstrain, temp )
1067  eqvs = eqvst-g*dlambda
1068  p = pt-k*etabar*dlambda
1069  f = eqvs + eta*p- xi*cohe
1070  if( abs(f/cohe)<tol ) exit
1071  ! if( i==MAXITER ) then
1072  ! stop 'ERROR: BackwardEuler_DP: convergence failure'
1073  ! endif
1074  enddo
1075  if( eqvs>=0.d0 ) then ! converged
1076  factor = 1.d0-g*dlambda/eqvst
1077  else ! return mapping to APEX
1078  istat = dp_plastic_apex
1079  if( eta==0.d0 ) stop 'ERROR: BackwardEuler_DP: eta==0.0'
1080  if( etabar==0.d0 ) stop 'ERROR: BackwardEuler_DP: etabar==0.0'
1081  alpha = xi/etabar
1082  beta = xi/eta
1083  depv=0.d0
1084  pstrain = plstrain
1085  cohe = calcurryield( matl, pstrain, temp )
1086  resid = beta*cohe - pt
1087  do i=1,maxiter
1088  h= calhardencoeff( matl, pstrain, temp )
1089  dd= alpha*beta*h + k
1090  depv = depv - resid/dd
1091  pstrain = plstrain+alpha*depv
1092  cohe = calcurryield( matl, pstrain, temp )
1093  p = pt-k*depv
1094  resid = beta*cohe - p
1095  if( abs(resid/cohe)<tol ) then
1096  dlambda=depv/etabar
1097  factor=0.d0
1098  exit
1099  endif
1100  ! if( i==MAXITER ) then
1101  ! stop 'ERROR: BackwardEuler_DP: convergence failure(2)'
1102  ! endif
1103  enddo
1104  endif
1105  devia(:) = factor*devia(:)
1106  stress(1:3) = devia(1:3)+p
1107  stress(4:6) = devia(4:6)
1108 
1109  fstat(1) = pstrain
1110  end subroutine backwardeuler_dp
1111 
1113  subroutine updateepstate( gauss )
1114  use mmechgauss
1115  type(tgaussstatus), intent(inout) :: gauss ! status of curr gauss point
1116  gauss%plstrain= gauss%fstatus(1)
1117  if(iskinematicharden(gauss%pMaterial%mtype)) then
1118  gauss%fstatus(8:13) =gauss%fstatus(2:7)
1119  endif
1120  end subroutine
1121 
1122 end module m_elastoplastic
I/O and Utility.
Definition: hecmw_util_f.F90:7
integer(kind=4), parameter kreal
This module provides functions for elastic material.
subroutine calelasticmatrix(matl, sectType, D, temp, hdflag)
Calculate isotropic elastic matrix hdflag: 0=full, 1=deviatoric only (edge-smoothed,...
This module provide functions for elastoplastic calculation.
subroutine calelastoplasticmatrix_dp(matl, sectType, stress, istat, extval, plstrain, D, temperature, hdflag)
This subroutine calculates elastoplastic constitutive relation.
subroutine, public planestressj2tangent(matl, stress, istat, fstatus, plstrain, tangent, ierr)
Condense the in-plane J2 tangent and retain the elastic transverse-shear stiffness.
integer, parameter, public j2_no_convergence
integer, parameter, public j2_singular
subroutine, public backwardeuler(matl, stress, plstrain, istat, fstat, plpotential, temp, hdflag)
This subroutine does backward-Euler return calculation.
subroutine backwardeuler_dp(matl, stress, plstrain, istat, fstat, temp, hdflag)
This subroutine does backward-Euler return calculation for Drucker-Prager.
integer, parameter, public j2_bad_state
subroutine, public calelastoplasticmatrix(matl, sectType, stress, istat, extval, plstrain, D, temperature, hdflag)
This subroutine calculates elastoplastic constitutive relation.
character(len=128) function, public planestressj2errormessage(ierr)
subroutine, public update_planestressj2(matl, strain_increment, stress_bak, plstrain, fstatus, stress, strain_increment_out, tangent, istat, fstatus_out, plpotential, energy_increment, ierr)
Return the plane-stress response of the existing three-dimensional J2 perfect-plastic material update...
integer, parameter, public j2_temperature
integer, parameter, public j2_nonfinite
integer, parameter, public j2_bad_property
integer, parameter, public j2_unsupported
subroutine, public checkplanestressj2material(matl, ierr)
subroutine, public updateepstate(gauss)
Clear elatoplastic state.
This module provides aux functions.
Definition: utilities.f90:6
subroutine eigen3(tensor, eigval, princ)
Compute eigenvalue and eigenvetor for symmetric 3*3 tensor using Jacobi iteration adapted from numeri...
Definition: utilities.f90:118
subroutine deriv_general_iso_tensor_func_3d(dpydpx, dydx, eigv, px, py)
Compute derivative of a general isotropic tensor function of one tensor.
Definition: utilities.f90:605
This module summarizes all information of material properties.
Definition: material.f90:6
integer function getyieldfunction(mtype)
Get type of yield function.
Definition: material.f90:294
integer(kind=kint), parameter m_plconst5
Definition: material.f90:104
integer(kind=kint), parameter m_plconst4
Definition: material.f90:103
integer function getelastictype(mtype)
Get elastic type.
Definition: material.f90:282
integer(kind=kint), parameter m_plconst1
Definition: material.f90:100
integer function gethardentype(mtype)
Get type of hardening.
Definition: material.f90:306
integer(kind=kint), parameter d3
Definition: material.f90:87
integer(kind=kint), parameter elastic
Definition: material.f90:68
integer(kind=kint), parameter m_plconst2
Definition: material.f90:101
character(len=dict_key_length) mc_yield
Definition: material.f90:144
logical function iskinematicharden(mtype)
If it is a kinematic hardening material?
Definition: material.f90:318
character(len=dict_key_length) mc_isoelastic
Definition: material.f90:142
integer(kind=kint), parameter m_plconst3
Definition: material.f90:102
logical function iselastoplastic(mtype)
If it is an elastoplastic material?
Definition: material.f90:336
This modules defines a structure to record history dependent parameter in static analysis.
Definition: mechgauss.f90:6
This subroutine read in used-defined material properties tangent.
Definition: uyield.f90:7
subroutine, public uelastoplasticmatrix(matl, stress, istat, fstat, plstrain, D, temp, hdflag)
This subroutine calculates elastoplastic constitutive relation.
Definition: uyield.f90:32
subroutine, public ubackwardeuler(matl, stress, plstrain, istat, fstat, temp, hdflag)
This subroutine does backward-Euler return calculation.
Definition: uyield.f90:45
Structure to manage all material related data.
Definition: material.f90:169
All data should be recorded in every quadrature points.
Definition: mechgauss.f90:15