Stress integration now uses Armijo rule to find an appropriate correction of Lp: decreases step in case that residuum does not improve significantly, accelerates as usual in case of good convergence. This turned out to improve convergence behavior.
This commit is contained in:
parent
6f859e99de
commit
ef7405fe21
|
@ -661,7 +661,7 @@ do while (any(crystallite_subStep(:,:,FEsolving_execELem(1):FEsolving_execElem(2
|
||||||
enddo
|
enddo
|
||||||
!$OMP END PARALLEL DO
|
!$OMP END PARALLEL DO
|
||||||
|
|
||||||
! --- integrate ---
|
! --- integrate --- requires fully defined state array (basic + dependent state)
|
||||||
|
|
||||||
if (any(crystallite_todo)) then
|
if (any(crystallite_todo)) then
|
||||||
select case(numerics_integrator(numerics_integrationMode))
|
select case(numerics_integrator(numerics_integrationMode))
|
||||||
|
@ -2533,6 +2533,7 @@ use math, only: math_mul33x33, &
|
||||||
math_invert3x3, &
|
math_invert3x3, &
|
||||||
math_invert, &
|
math_invert, &
|
||||||
math_det3x3, &
|
math_det3x3, &
|
||||||
|
math_norm33, &
|
||||||
math_I3, &
|
math_I3, &
|
||||||
math_identity2nd, &
|
math_identity2nd, &
|
||||||
math_Mandel66to3333, &
|
math_Mandel66to3333, &
|
||||||
|
@ -2562,22 +2563,25 @@ real(pReal), dimension(3,3):: Fg_new, & ! deformation
|
||||||
Lp_constitutive, & ! plastic velocity gradient resulting from constitutive law
|
Lp_constitutive, & ! plastic velocity gradient resulting from constitutive law
|
||||||
residuum, & ! current residuum of plastic velocity gradient
|
residuum, & ! current residuum of plastic velocity gradient
|
||||||
residuum_old, & ! last residuum of plastic velocity gradient
|
residuum_old, & ! last residuum of plastic velocity gradient
|
||||||
|
deltaLp, &
|
||||||
|
expectedImprovement, &
|
||||||
A, &
|
A, &
|
||||||
B, &
|
B, &
|
||||||
BT, &
|
BT, &
|
||||||
AB, &
|
AB, &
|
||||||
BTA
|
BTA
|
||||||
real(pReal), dimension(6):: Tstar_v ! 2nd Piola-Kirchhoff Stress in Mandel-Notation
|
real(pReal), dimension(6):: Tstar_v ! 2nd Piola-Kirchhoff Stress in Mandel-Notation
|
||||||
real(pReal), dimension(9,9):: dLpdT_constitutive, & ! partial derivative of plastic velocity gradient calculated by constitutive law
|
real(pReal), dimension(9,9):: dLp_dT_constitutive, & ! partial derivative of plastic velocity gradient calculated by constitutive law
|
||||||
dTdLp, & ! partial derivative of 2nd Piola-Kirchhoff stress
|
dT_dLp, & ! partial derivative of 2nd Piola-Kirchhoff stress
|
||||||
dRdLp, & ! partial derivative of residuum (Jacobian for NEwton-Raphson scheme)
|
dR_dLp, & ! partial derivative of residuum (Jacobian for NEwton-Raphson scheme)
|
||||||
invdRdLp ! inverse of dRdLp
|
inv_dR_dLp ! inverse of dRdLp
|
||||||
real(pReal), dimension(3,3,3,3):: C ! 4th rank elasticity tensor
|
real(pReal), dimension(3,3,3,3):: C ! 4th rank elasticity tensor
|
||||||
real(pReal), dimension(6,6):: C_66 ! simplified 2nd rank elasticity tensor
|
real(pReal), dimension(6,6):: C_66 ! simplified 2nd rank elasticity tensor
|
||||||
real(pReal) p_hydro, & ! volumetric part of 2nd Piola-Kirchhoff Stress
|
real(pReal) p_hydro, & ! volumetric part of 2nd Piola-Kirchhoff Stress
|
||||||
det, & ! determinant
|
det, & ! determinant
|
||||||
leapfrog, & ! acceleration factor for Newton-Raphson scheme
|
steplength0, &
|
||||||
maxleap, & ! maximum acceleration factor
|
steplength, &
|
||||||
|
steplength_max, &
|
||||||
dt ! time increment
|
dt ! time increment
|
||||||
logical error ! flag indicating an error
|
logical error ! flag indicating an error
|
||||||
integer(pInt) NiterationStress, & ! number of stress integrations
|
integer(pInt) NiterationStress, & ! number of stress integrations
|
||||||
|
@ -2594,6 +2598,7 @@ integer(pLongInt) tick, &
|
||||||
tickrate, &
|
tickrate, &
|
||||||
maxticks
|
maxticks
|
||||||
|
|
||||||
|
|
||||||
!* be pessimistic
|
!* be pessimistic
|
||||||
|
|
||||||
crystallite_integrateStress = .false.
|
crystallite_integrateStress = .false.
|
||||||
|
@ -2647,11 +2652,12 @@ C_66 = constitutive_homogenizedC(g,i,e)
|
||||||
C = math_Mandel66to3333(C_66)
|
C = math_Mandel66to3333(C_66)
|
||||||
|
|
||||||
|
|
||||||
!* start LpLoop with no acceleration
|
!* start LpLoop with normal step length
|
||||||
|
|
||||||
NiterationStress = 0_pInt
|
NiterationStress = 0_pInt
|
||||||
leapfrog = 1.0_pReal
|
steplength0 = 1.0_pReal
|
||||||
maxleap = 16.0_pReal
|
steplength = steplength0
|
||||||
|
steplength_max = 16.0_pReal
|
||||||
jacoCounter = 0_pInt
|
jacoCounter = 0_pInt
|
||||||
|
|
||||||
LpLoop: do
|
LpLoop: do
|
||||||
|
@ -2688,7 +2694,7 @@ LpLoop: do
|
||||||
if (debug_verbosity > 0) then
|
if (debug_verbosity > 0) then
|
||||||
call system_clock(count=tick,count_rate=tickrate,count_max=maxticks)
|
call system_clock(count=tick,count_rate=tickrate,count_max=maxticks)
|
||||||
endif
|
endif
|
||||||
call constitutive_LpAndItsTangent(Lp_constitutive, dLpdT_constitutive, Tstar_v, crystallite_Temperature(g,i,e), g, i, e)
|
call constitutive_LpAndItsTangent(Lp_constitutive, dLp_dT_constitutive, Tstar_v, crystallite_Temperature(g,i,e), g, i, e)
|
||||||
if (debug_verbosity > 4) then
|
if (debug_verbosity > 4) then
|
||||||
call system_clock(count=tock,count_rate=tickrate,count_max=maxticks)
|
call system_clock(count=tock,count_rate=tickrate,count_max=maxticks)
|
||||||
!$OMP CRITICAL (debugTimingLpTangent)
|
!$OMP CRITICAL (debugTimingLpTangent)
|
||||||
|
@ -2713,10 +2719,10 @@ LpLoop: do
|
||||||
!* update current residuum and check for convergence of loop
|
!* update current residuum and check for convergence of loop
|
||||||
|
|
||||||
residuum = Lpguess - Lp_constitutive
|
residuum = Lpguess - Lp_constitutive
|
||||||
if (.not.(any(residuum/=residuum)) .and. & ! exclude any NaN in residuum
|
if (.not.(any(residuum /= residuum)) .and. & ! exclude any NaN in residuum
|
||||||
( maxval(abs(residuum)) < aTol_crystalliteStress .or. & ! below absolute tolerance .or.
|
( maxval(abs(residuum)) < aTol_crystalliteStress .or. & ! below absolute tolerance .or.
|
||||||
( any(abs(dt*Lpguess) > relevantStrain) .and. & ! worth checking? .and.
|
( any(abs(dt * Lpguess) > relevantStrain) .and. & ! worth checking? .and.
|
||||||
maxval(abs(residuum/Lpguess), abs(dt*Lpguess) > relevantStrain) < rTol_crystalliteStress & ! below relative tolerance
|
maxval(abs(residuum / Lpguess), abs(dt*Lpguess) > relevantStrain) < rTol_crystalliteStress & ! below relative tolerance
|
||||||
) &
|
) &
|
||||||
) &
|
) &
|
||||||
) then
|
) then
|
||||||
|
@ -2724,9 +2730,8 @@ LpLoop: do
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
!* NaN occured at regular speed? -> return
|
!* NaN occured at regular speed -> return
|
||||||
|
if (steplength >= steplength0 .and. any(residuum /= residuum)) then
|
||||||
if (any(residuum/=residuum) .and. leapfrog == 1.0) then
|
|
||||||
#ifndef _OPENMP
|
#ifndef _OPENMP
|
||||||
if (debug_verbosity > 4) then
|
if (debug_verbosity > 4) then
|
||||||
write(6,'(a,i8,x,i2,x,i3,a,i3,a)') '<< CRYST >> integrateStress encountered NaN at el ip g ',e,i,g,&
|
write(6,'(a,i8,x,i2,x,i3,a,i3,a)') '<< CRYST >> integrateStress encountered NaN at el ip g ',e,i,g,&
|
||||||
|
@ -2735,82 +2740,116 @@ LpLoop: do
|
||||||
endif
|
endif
|
||||||
#endif
|
#endif
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
!* something went wrong at accelerated speed? -> restore old residuum and Lp
|
|
||||||
|
|
||||||
elseif (leapfrog > 1.0_pReal .and. & ! at fast pace .and.
|
|
||||||
( sum(residuum*residuum) > sum(residuum_old*residuum_old) .or. & ! worse residuum .or.
|
|
||||||
sum(residuum*residuum_old) < 0.0_pReal .or. & ! residuum changed sign (overshoot) .or.
|
|
||||||
any(residuum/=residuum) & ! NaN occured
|
|
||||||
) &
|
|
||||||
) then
|
|
||||||
#ifndef _OPENMP
|
|
||||||
if (debug_verbosity > 5) then
|
|
||||||
write(6,'(a,i8,x,i2,x,i3,x,a,i3)') '<< CRYST >> integrateStress encountered high-speed crash at el ip g ',e,i,g,&
|
|
||||||
'; iteration ', NiterationStress
|
|
||||||
endif
|
|
||||||
#endif
|
|
||||||
maxleap = 0.5_pReal * leapfrog ! limit next acceleration
|
|
||||||
leapfrog = 1.0_pReal ! grinding halt
|
|
||||||
jacoCounter = 0_pInt ! reset counter for Jacobian update (we want to do an update next time!)
|
|
||||||
Lpguess = Lpguess_old
|
|
||||||
residuum = residuum_old
|
|
||||||
if (debug_verbosity > 4) then
|
|
||||||
!$OMP CRITICAL (distributionLeapfrogBreak)
|
|
||||||
debug_LeapfrogBreakDistribution(NiterationStress,numerics_integrationMode) = &
|
|
||||||
debug_LeapfrogBreakDistribution(NiterationStress,numerics_integrationMode) + 1
|
|
||||||
!$OMP END CRITICAL (distributionLeapfrogBreak)
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
!* residuum got better? -> calculate Jacobian for correction term and remember current residuum and Lpguess
|
|
||||||
|
|
||||||
else
|
|
||||||
if (mod(jacoCounter, iJacoLpresiduum) == 0_pInt) then
|
|
||||||
dTdLp = 0.0_pReal
|
|
||||||
do h=1,3; do j=1,3; do k=1,3; do l=1,3; do m=1,3
|
|
||||||
dTdLp(3*(h-1)+j,3*(k-1)+l) = dTdLp(3*(h-1)+j,3*(k-1)+l) + C(h,j,l,m)*AB(k,m)+C(h,j,m,l)*BTA(m,k)
|
|
||||||
enddo; enddo; enddo; enddo; enddo
|
|
||||||
dTdLp = -0.5_pReal*dt*dTdLp
|
|
||||||
dRdLp = math_identity2nd(9) - math_mul99x99(dLpdT_constitutive,dTdLp)
|
|
||||||
invdRdLp = 0.0_pReal
|
|
||||||
call math_invert(9,dRdLp,invdRdLp,dummy,error) ! invert dR/dLp --> dLp/dR
|
|
||||||
if (error) then
|
|
||||||
#ifndef _OPENMP
|
|
||||||
if (debug_verbosity > 4) then
|
|
||||||
write(6,'(a,i8,x,i2,x,i3,a,i3)') '<< CRYST >> integrateStress failed on dR/dLp inversion at el ip g ',e,i,g,&
|
|
||||||
' ; iteration ', NiterationStress
|
|
||||||
if (debug_verbosity > 5 &
|
|
||||||
.and. ((e == debug_e .and. i == debug_i .and. g == debug_g) .or. .not. debug_selectiveDebugger)) then
|
|
||||||
write(6,*)
|
|
||||||
write(6,'(a,/,9(12(x),9(e15.3,x)/))') '<< CRYST >> dRdLp',transpose(dRdLp)
|
|
||||||
write(6,'(a,/,9(12(x),9(e15.3,x)/))') '<< CRYST >> dLpdT_constitutive',transpose(dLpdT_constitutive)
|
|
||||||
write(6,'(a,/,3(12(x),3(e20.7,x)/))') '<< CRYST >> Lp_constitutive',math_transpose3x3(Lp_constitutive)
|
|
||||||
write(6,'(a,/,3(12(x),3(e20.7,x)/))') '<< CRYST >> Lpguess',math_transpose3x3(Lpguess)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
#endif
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
jacoCounter = jacoCounter + 1_pInt ! increase counter for jaco update
|
|
||||||
residuum_old = residuum
|
|
||||||
Lpguess_old = Lpguess
|
|
||||||
|
|
||||||
|
|
||||||
!* accelerate?
|
|
||||||
|
|
||||||
if (NiterationStress > 1 .and. leapfrog+1.0_pReal <= maxleap) leapfrog = leapfrog + 1.0_pReal
|
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
||||||
!* leapfrog to updated Lp
|
if (NiterationStress > 1_pInt) then
|
||||||
|
|
||||||
do k=1,3; do l=1,3; do m=1,3; do n=1,3
|
!* not at regular speed
|
||||||
Lpguess(k,l) = Lpguess(k,l) - leapfrog * invdRdLp(3*(k-1)+l,3*(m-1)+n) * residuum(m,n)
|
if (steplength <= steplength0) then
|
||||||
enddo; enddo; enddo; enddo
|
|
||||||
|
!* Armijo rule is fullfilled (norm of residuum was reduced by at least 0.01 of what was expected)
|
||||||
|
if (math_norm33(residuum) <= math_norm33(residuum_old + 0.01_pReal * steplength * expectedImprovement)) then
|
||||||
|
|
||||||
|
!* reduced step length -> return to normal step length
|
||||||
|
if (steplength < steplength0) then
|
||||||
|
steplength = steplength0
|
||||||
|
|
||||||
|
!* normal step length without change in sign of residuum -> accelerate if not yet at maximum speed
|
||||||
|
elseif (sum(residuum * residuum_old) >= 0.0_pReal .and. steplength + 1_pInt <= steplength_max) then
|
||||||
|
steplength = steplength + 1.0_pReal
|
||||||
|
endif
|
||||||
|
|
||||||
|
!* Armijo rule not fullfilled -> try smaller step size in same direction
|
||||||
|
else
|
||||||
|
steplength = 0.5_pReal * steplength
|
||||||
|
Lpguess = Lpguess_old + steplength * deltaLp
|
||||||
|
cycle LpLoop
|
||||||
|
endif
|
||||||
|
|
||||||
|
!* at high-speed
|
||||||
|
else
|
||||||
|
|
||||||
|
!* no NaN, Armijo rule fullfilled, and sign of residuum did not change -> accelerate if not yet at maximum speed
|
||||||
|
if (.not. any(residuum /= residuum) &
|
||||||
|
.and. math_norm33(residuum) <= math_norm33(residuum_old + 0.01_pReal * steplength * expectedImprovement) &
|
||||||
|
.and. sum(residuum * residuum_old) >= 0.0_pReal) then
|
||||||
|
if (steplength + 1_pInt <= steplength_max) then
|
||||||
|
steplength = steplength + 1.0_pReal
|
||||||
|
endif
|
||||||
|
|
||||||
|
!* something went wrong at accelerated speed? -> return to regular speed and try again
|
||||||
|
else
|
||||||
|
#ifndef _OPENMP
|
||||||
|
if (debug_verbosity > 5) then
|
||||||
|
write(6,'(a,i8,x,i2,x,i3,x,a,i3)') '<< CRYST >> integrateStress encountered high-speed crash at el ip g ',e,i,g,&
|
||||||
|
'; iteration ', NiterationStress
|
||||||
|
endif
|
||||||
|
#endif
|
||||||
|
!* NaN occured -> use old guess and residuum
|
||||||
|
if (any(residuum /= residuum)) then
|
||||||
|
Lpguess = Lpguess_old
|
||||||
|
residuum = residuum_old
|
||||||
|
endif
|
||||||
|
steplength_max = steplength - 1.0_pReal ! limit acceleration
|
||||||
|
steplength = steplength0 ! grinding halt
|
||||||
|
jacoCounter = 0_pInt ! reset counter for Jacobian update (we want to do an update next time!)
|
||||||
|
if (debug_verbosity > 4) then
|
||||||
|
!$OMP CRITICAL (distributionLeapfrogBreak)
|
||||||
|
debug_LeapfrogBreakDistribution(NiterationStress,numerics_integrationMode) = &
|
||||||
|
debug_LeapfrogBreakDistribution(NiterationStress,numerics_integrationMode) + 1
|
||||||
|
!$OMP END CRITICAL (distributionLeapfrogBreak)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
!* calculate Jacobian for correction term and remember current residuum and Lpguess
|
||||||
|
|
||||||
|
if (mod(jacoCounter, iJacoLpresiduum) == 0_pInt) then
|
||||||
|
dT_dLp = 0.0_pReal
|
||||||
|
do h=1,3; do j=1,3; do k=1,3; do l=1,3; do m=1,3
|
||||||
|
dT_dLp(3*(h-1)+j,3*(k-1)+l) = dT_dLp(3*(h-1)+j,3*(k-1)+l) + C(h,j,l,m) * AB(k,m) + C(h,j,m,l) * BTA(m,k)
|
||||||
|
enddo; enddo; enddo; enddo; enddo
|
||||||
|
dT_dLp = -0.5_pReal * dt * dT_dLp
|
||||||
|
dR_dLp = math_identity2nd(9) - math_mul99x99(dLp_dT_constitutive, dT_dLp)
|
||||||
|
inv_dR_dLp = 0.0_pReal
|
||||||
|
call math_invert(9,dR_dLp,inv_dR_dLp,dummy,error) ! invert dR/dLp --> dLp/dR
|
||||||
|
if (error) then
|
||||||
|
#ifndef _OPENMP
|
||||||
|
if (debug_verbosity > 4) then
|
||||||
|
write(6,'(a,i8,x,i2,x,i3,a,i3)') '<< CRYST >> integrateStress failed on dR/dLp inversion at el ip g ',e,i,g
|
||||||
|
if (debug_verbosity > 5 &
|
||||||
|
.and. ((e == debug_e .and. i == debug_i .and. g == debug_g) .or. .not. debug_selectiveDebugger)) then
|
||||||
|
write(6,*)
|
||||||
|
write(6,'(a,/,9(12(x),9(e15.3,x)/))') '<< CRYST >> dR_dLp',transpose(dR_dLp)
|
||||||
|
write(6,'(a,/,9(12(x),9(e15.3,x)/))') '<< CRYST >> dT_dLp',transpose(dT_dLp)
|
||||||
|
write(6,'(a,/,9(12(x),9(e15.3,x)/))') '<< CRYST >> dLp_dT_constitutive',transpose(dLp_dT_constitutive)
|
||||||
|
write(6,'(a,/,3(12(x),3(e20.7,x)/))') '<< CRYST >> AB',math_transpose3x3(AB)
|
||||||
|
write(6,'(a,/,3(12(x),3(e20.7,x)/))') '<< CRYST >> BTA',math_transpose3x3(BTA)
|
||||||
|
write(6,'(a,/,3(12(x),3(e20.7,x)/))') '<< CRYST >> Lp_constitutive',math_transpose3x3(Lp_constitutive)
|
||||||
|
write(6,'(a,/,3(12(x),3(e20.7,x)/))') '<< CRYST >> Lpguess',math_transpose3x3(Lpguess)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
#endif
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
deltaLp = 0.0_pReal
|
||||||
|
do k=1,3; do l=1,3; do m=1,3; do n=1,3
|
||||||
|
deltaLp(k,l) = deltaLp(k,l) - inv_dR_dLp(3*(k-1)+l,3*(m-1)+n) * residuum(m,n)
|
||||||
|
enddo; enddo; enddo; enddo
|
||||||
|
|
||||||
|
expectedImprovement = 0.0_pReal
|
||||||
|
do k=1,3; do l=1,3; do m=1,3; do n=1,3
|
||||||
|
expectedImprovement(k,l) = expectedImprovement(k,l) - dR_dLp(3*(k-1)+l,3*(m-1)+n) * deltaLp(m,n)
|
||||||
|
enddo; enddo; enddo; enddo
|
||||||
|
endif
|
||||||
|
|
||||||
|
jacoCounter = jacoCounter + 1_pInt ! increase counter for jaco update
|
||||||
|
residuum_old = residuum
|
||||||
|
Lpguess_old = Lpguess
|
||||||
|
Lpguess = Lpguess + steplength * deltaLp
|
||||||
|
|
||||||
enddo LpLoop
|
enddo LpLoop
|
||||||
|
|
||||||
|
@ -2861,7 +2900,7 @@ if (debug_verbosity > 5 .and. ((e == debug_e .and. i == debug_i .and. g == debug
|
||||||
write(6,'(a,/,3(12(x),3(f12.7,x)/))') '<< CRYST >> Cauchy / MPa', &
|
write(6,'(a,/,3(12(x),3(f12.7,x)/))') '<< CRYST >> Cauchy / MPa', &
|
||||||
math_mul33x33(crystallite_P(1:3,1:3,g,i,e), math_transpose3x3(Fg_new)) / 1e6 / math_det3x3(Fg_new)
|
math_mul33x33(crystallite_P(1:3,1:3,g,i,e), math_transpose3x3(Fg_new)) / 1e6 / math_det3x3(Fg_new)
|
||||||
write(6,'(a,/,3(12(x),3(f12.7,x)/))') '<< CRYST >> Fe Lp Fe^-1', &
|
write(6,'(a,/,3(12(x),3(f12.7,x)/))') '<< CRYST >> Fe Lp Fe^-1', &
|
||||||
math_transpose3x3(math_mul33x33(Fe_new, math_mul33x33(crystallite_Lp(1:3,1:3,g,i,e), math_inv3x3(Fe_new)))) ! transpose to get correct print out order
|
math_transpose3x3(math_mul33x33(Fe_new, math_mul33x33(crystallite_Lp(1:3,1:3,g,i,e), math_inv3x3(Fe_new)))) ! transpose to get correct print out order
|
||||||
write(6,'(a,/,3(12(x),3(f12.7,x)/))') '<< CRYST >> Fp',math_transpose3x3(crystallite_Fp(1:3,1:3,g,i,e))
|
write(6,'(a,/,3(12(x),3(f12.7,x)/))') '<< CRYST >> Fp',math_transpose3x3(crystallite_Fp(1:3,1:3,g,i,e))
|
||||||
endif
|
endif
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue