changes on convergence tolerances of AL and Polarisation, switched back to immediate correction of stress bc but only when last two average stresses are close to each other (cosine decay)

This commit is contained in:
Martin Diehl 2013-07-30 15:32:55 +00:00
parent a0ef3ce5ef
commit 81531097f1
5 changed files with 161 additions and 144 deletions

View File

@ -77,7 +77,8 @@ module DAMASK_spectral_solverAL
F_aimDot, & !< assumed rate of average deformation gradient F_aimDot, & !< assumed rate of average deformation gradient
F_aim = math_I3, & !< current prescribed deformation gradient F_aim = math_I3, & !< current prescribed deformation gradient
F_aim_lastInc = math_I3, & !< previous average deformation gradient F_aim_lastInc = math_I3, & !< previous average deformation gradient
P_av = 0.0_pReal !< average 1st Piola--Kirchhoff stress P_av = 0.0_pReal, & !< average 1st Piola--Kirchhoff stress
P_avLastEval = 0.0_pReal !< average 1st Piola--Kirchhoff stress last call of CPFEM_general
character(len=1024), private :: incInfo !< time and increment information character(len=1024), private :: incInfo !< time and increment information
real(pReal), private, dimension(3,3,3,3) :: & real(pReal), private, dimension(3,3,3,3) :: &
C_volAvg = 0.0_pReal, & !< current volume average stiffness C_volAvg = 0.0_pReal, & !< current volume average stiffness
@ -93,7 +94,6 @@ module DAMASK_spectral_solverAL
err_p !< difference of stress resulting from compatible and incompatible F err_p !< difference of stress resulting from compatible and incompatible F
logical, private :: ForwardData logical, private :: ForwardData
integer(pInt), private :: & integer(pInt), private :: &
currIter = 0_pInt, & !< helper to count total iteration correctly
totalIter = 0_pInt !< total iteration in current increment totalIter = 0_pInt !< total iteration in current increment
public :: & public :: &
@ -277,10 +277,7 @@ end subroutine AL_init
type(tSolutionState) function & type(tSolutionState) function &
AL_solution(incInfoIn,guess,timeinc,timeinc_old,loadCaseTime,P_BC,F_BC,temperature_bc,rotation_BC,density) AL_solution(incInfoIn,guess,timeinc,timeinc_old,loadCaseTime,P_BC,F_BC,temperature_bc,rotation_BC,density)
use numerics, only: & use numerics, only: &
update_gamma, & update_gamma
itmax, &
err_stress_tolrel, &
err_stress_tolabs
use math, only: & use math, only: &
math_mul33x33 ,& math_mul33x33 ,&
math_mul3333xx33, & math_mul3333xx33, &
@ -314,7 +311,8 @@ use mesh, only: &
timeinc, & !< increment in time for current solution timeinc, & !< increment in time for current solution
timeinc_old, & !< increment in time of last increment timeinc_old, & !< increment in time of last increment
loadCaseTime, & !< remaining time of current load case loadCaseTime, & !< remaining time of current load case
temperature_bc temperature_bc, &
density
logical, intent(in) :: & logical, intent(in) :: &
guess guess
type(tBoundaryCondition), intent(in) :: & type(tBoundaryCondition), intent(in) :: &
@ -323,8 +321,7 @@ use mesh, only: &
character(len=*), intent(in) :: & character(len=*), intent(in) :: &
incInfoIn incInfoIn
real(pReal), dimension(3,3), intent(in) :: rotation_BC real(pReal), dimension(3,3), intent(in) :: rotation_BC
real(pReal), intent(in) :: density
real(pReal) :: err_stress_tol
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! PETSc Data ! PETSc Data
PetscScalar, dimension(:,:,:,:), pointer :: xx_psc, F, F_lambda PetscScalar, dimension(:,:,:,:), pointer :: xx_psc, F, F_lambda
@ -424,35 +421,20 @@ use mesh, only: &
params%temperature = temperature_bc params%temperature = temperature_bc
params%density = density params%density = density
err_stress_tol = 1.0_pReal; err_stress = 2.0_pReal * err_stress_tol ! ensure to start loop
totalIter = -1_pInt
do while(err_stress/err_stress_tol > 1.0_pReal) ! solve BVP and Stress RB
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! solve BVP ! solve BVP
call SNESSolve(snes,PETSC_NULL_OBJECT,solution_vec,ierr) call SNESSolve(snes,PETSC_NULL_OBJECT,solution_vec,ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
!--------------------------------------------------------------------------------------------------
! stress BC handling
err_stress = maxval(abs(mask_stress * (P_av - params%P_BC))) ! mask = 0.0 for no bc
err_stress_tol = max(maxval(abs(P_av))*err_stress_tolrel,err_stress_tolabs)
F_aim = F_aim - math_mul3333xx33(S, ((P_av - params%P_BC))) ! S = 0.0 for no bc
write(6,'(1/,a)') ' ... correcting stress boundary condition .................................'
write(6,'(1/,a,f8.2,a,es11.5,a,es11.4,a)') ' error stress BC = ', &
err_stress/err_stress_tol, ' (',err_stress, ' Pa, tol =',err_stress_tol,')'
write(6,'(/,a)') ' ==========================================================================='
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! check convergence ! check convergence
call SNESGetConvergedReason(snes,reason,ierr) call SNESGetConvergedReason(snes,reason,ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
AL_solution%termIll = terminallyIll AL_solution%termIll = terminallyIll
terminallyIll = .false. terminallyIll = .false.
AL_solution%converged = .true. AL_solution%converged = .true.
if (reason < 1 ) AL_solution%converged = .false. if (reason < 1 ) AL_solution%converged = .false.
AL_solution%iterationsNeeded = totalIter AL_solution%iterationsNeeded = totalIter
end do
end function AL_solution end function AL_solution
@ -465,14 +447,20 @@ subroutine AL_formResidual(in,x_scal,f_scal,dummy,ierr)
itmax, & itmax, &
itmin, & itmin, &
polarAlpha, & polarAlpha, &
polarBeta polarBeta, &
err_stress_tolrel, &
err_stress_tolabs, &
err_f_tol, &
err_p_tol, &
err_stress_tolabs
use IO, only: & use IO, only: &
IO_intOut IO_intOut
use math, only: & use math, only: &
math_rotate_backward33, & math_rotate_backward33, &
math_transpose33, & math_transpose33, &
math_mul3333xx33, & math_mul3333xx33, &
math_invSym3333 math_invSym3333, &
PI
use DAMASK_spectral_Utilities, only: & use DAMASK_spectral_Utilities, only: &
grid, & grid, &
geomSize, & geomSize, &
@ -516,6 +504,7 @@ subroutine AL_formResidual(in,x_scal,f_scal,dummy,ierr)
PetscErrorCode :: ierr PetscErrorCode :: ierr
integer(pInt) :: & integer(pInt) :: &
i, j, k i, j, k
real(pReal) :: correctionFactor
F => x_scal(1:3,1:3,1,& F => x_scal(1:3,1:3,1,&
XG_RANGE,YG_RANGE,ZG_RANGE) XG_RANGE,YG_RANGE,ZG_RANGE)
@ -529,12 +518,10 @@ subroutine AL_formResidual(in,x_scal,f_scal,dummy,ierr)
call SNESGetNumberFunctionEvals(snes,nfuncs,ierr); CHKERRQ(ierr) call SNESGetNumberFunctionEvals(snes,nfuncs,ierr); CHKERRQ(ierr)
call SNESGetIterationNumber(snes,PETScIter,ierr); CHKERRQ(ierr) call SNESGetIterationNumber(snes,PETScIter,ierr); CHKERRQ(ierr)
if(nfuncs== 0 .and. PETScIter == 0) currIter = -1_pInt ! new increment if(nfuncs== 0 .and. PETScIter == 0) totalIter = -1_pInt ! new increment
if (totalIter <= PETScIter) then ! new iteration
if (PETScIter == currIter .or. currIter == -1 ) then ! new iteration
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! report begin of new iteration ! report begin of new iteration
currIter = currIter + 1_pInt
totalIter = totalIter + 1_pInt totalIter = totalIter + 1_pInt
write(6,'(1x,a,3(a,'//IO_intOut(itmax)//'))') trim(incInfo), & write(6,'(1x,a,3(a,'//IO_intOut(itmax)//'))') trim(incInfo), &
' @ Iteration ', itmin, '≤',totalIter, '≤', itmax ' @ Iteration ', itmin, '≤',totalIter, '≤', itmax
@ -546,10 +533,11 @@ subroutine AL_formResidual(in,x_scal,f_scal,dummy,ierr)
flush(6) flush(6)
endif endif
if (params%density > 0.0_pReal) then
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! evaluate inertia ! evaluate inertia
residual_F = ((F - F_lastInc)/params%timeinc - (F_lastInc - F_lastInc2)/params%timeincOld)/((params%timeinc + params%timeincOld)/2.0_pReal) dynamic: if (params%density > 0.0_pReal) then
residual_F = ((F - F_lastInc)/params%timeinc - (F_lastInc - F_lastInc2)/params%timeincOld)/&
((params%timeinc + params%timeincOld)/2.0_pReal)
residual_F = params%density*product(geomSize/grid)*residual_F residual_F = params%density*product(geomSize/grid)*residual_F
field_real = 0.0_pReal field_real = 0.0_pReal
field_real(1:grid(1),1:grid(2),1:grid(3),1:3,1:3) = reshape(residual_F,[grid(1),grid(2),grid(3),3,3],& field_real(1:grid(1),1:grid(2),1:grid(3),1:3,1:3) = reshape(residual_F,[grid(1),grid(2),grid(3),3,3],&
@ -557,9 +545,9 @@ subroutine AL_formResidual(in,x_scal,f_scal,dummy,ierr)
call Utilities_FFTforward() call Utilities_FFTforward()
call Utilities_inverseLaplace() call Utilities_inverseLaplace()
inertiaField_fourier = field_fourier inertiaField_fourier = field_fourier
else else dynamic
inertiaField_fourier = cmplx(0.0_pReal,0.0_pReal,pReal) inertiaField_fourier = cmplx(0.0_pReal,0.0_pReal,pReal)
endif endif dynamic
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! !
@ -587,13 +575,20 @@ subroutine AL_formResidual(in,x_scal,f_scal,dummy,ierr)
residual_F,C_volAvg,C_minMaxAvg,P_av,ForwardData,params%rotation_BC) residual_F,C_volAvg,C_minMaxAvg,P_av,ForwardData,params%rotation_BC)
ForwardData = .False. ForwardData = .False.
!--------------------------------------------------------------------------------------------------
! stress BC handling
write(6,'(/,a)') ' ... correcting F to fullfill stress BC ....................................'
correctionFactor = (cos((1.0-500.0_pReal**(-sum((P_av-P_avLastEval)**2.0_pReal)/& ! only correct when averages stress of last two calls is close
sum(P_av**2.0_pReal)))*PI)+1.0)/2.0_pReal
write(6,'(/,a,f8.2)') ' stress BC correction factor = ', correctionFactor
F_aim = F_aim - correctionFactor *math_mul3333xx33(S, ((P_av - params%P_BC))) ! S = 0.0 for no bc
err_stress = maxval(abs(mask_stress * (P_av - params%P_BC))) ! mask = 0.0 for no bc
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! constructing residual ! constructing residual
err_p = 0.0_pReal err_p = 0.0_pReal
do k = 1_pInt, grid(3); do j = 1_pInt, grid(2); do i = 1_pInt, grid(1) do k = 1_pInt, grid(3); do j = 1_pInt, grid(2); do i = 1_pInt, grid(1)
err_p = err_p + sum((math_I3 + math_mul3333xx33(S_scale,residual_F(1:3,1:3,i,j,k)) - & err_p = err_p + sum((math_mul3333xx33(C_scale,F_lambda(1:3,1:3,i,j,k) - math_I3) - residual_F(1:3,1:3,i,j,k))**2.0_pReal)
F_lambda(1:3,1:3,i,j,k))**2.0_pReal)
residual_F(1:3,1:3,i,j,k) = math_I3 + math_mul3333xx33(S_scale,residual_F(1:3,1:3,i,j,k)) - & residual_F(1:3,1:3,i,j,k) = math_I3 + math_mul3333xx33(S_scale,residual_F(1:3,1:3,i,j,k)) - &
F_lambda(1:3,1:3,i,j,k) & F_lambda(1:3,1:3,i,j,k) &
+ residual_F_lambda(1:3,1:3,i,j,k) + residual_F_lambda(1:3,1:3,i,j,k)
@ -611,13 +606,13 @@ end subroutine AL_formResidual
!> @brief convergence check !> @brief convergence check
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
subroutine AL_converged(snes_local,PETScIter,xnorm,snorm,fnorm,reason,dummy,ierr) subroutine AL_converged(snes_local,PETScIter,xnorm,snorm,fnorm,reason,dummy,ierr)
use numerics, only: & use numerics, only: &
itmax, & itmax, &
itmin, & itmin, &
err_f_tol, & err_f_tol, &
err_p_tol, & err_p_tol, &
err_stress_tolrel, & err_stress_tolabs, &
err_stress_tolabs err_stress_tolrel
use FEsolving, only: & use FEsolving, only: &
terminallyIll terminallyIll
@ -631,27 +626,38 @@ subroutine AL_converged(snes_local,PETScIter,xnorm,snorm,fnorm,reason,dummy,ierr
SNESConvergedReason :: reason SNESConvergedReason :: reason
PetscObject :: dummy PetscObject :: dummy
PetscErrorCode ::ierr PetscErrorCode ::ierr
real(pReal) :: &
mismatch_f_tol, &
mismatch_p_tol, &
stressBC_tol
mismatch_f_tol = max(maxval(abs(F_aim-math_I3))*err_stress_tolrel,err_f_tol)
mismatch_p_tol = max(maxval(abs(P_av)) *err_stress_tolrel,err_p_tol)
stressBC_tol = max(maxval(abs(P_av)) *err_stress_tolrel,err_stress_tolabs)
write(6,'(1/,a)') ' ... reporting .............................................................' write(6,'(1/,a)') ' ... reporting .............................................................'
write(6,'(/,a,f8.2,a,es11.5,a,es11.4,a)') ' mismatch F = ', & write(6,'(/,a,f8.2,a,es11.5,a,es11.4,a)') ' mismatch F = ', &
err_f/err_f_tol, & err_f/mismatch_f_tol, &
' (',err_f,' -, tol =',err_f_tol,')' ' (',err_f,' -, tol =',mismatch_f_tol,')'
write(6,'(a,f8.2,a,es11.5,a,es11.4,a)') ' mismatch P = ', & write(6,'(a,f8.2,a,es11.5,a,es11.4,a)') ' mismatch P = ', &
err_p/err_p_tol, & err_p/mismatch_p_tol, &
' (',err_p,' -, tol =',err_p_tol,')' ' (',err_p,' -, tol =',mismatch_p_tol,')'
write(6,'(a,f8.2,a,es11.5,a,es11.4,a)') ' error stress BC = ', &
err_stress/stressBC_tol, ' (',err_stress, ' Pa, tol =',stressBC_tol,')'
write(6,'(/,a)') ' ==========================================================================='
flush(6)
converged: if ((totalIter >= itmin .and. & converged: if ((totalIter >= itmin .and. &
all([ err_f/err_f_tol, & all([ err_f/mismatch_f_tol, &
err_p/err_p_tol ] < 1.0_pReal)) & err_p/mismatch_p_tol, &
err_stress/stressBC_tol] < 1.0_pReal)) &
.or. terminallyIll) then .or. terminallyIll) then
reason = 1 reason = 1
elseif (totalIter >= itmax) then converged elseif (totalIter >= itmax) then converged
reason = -1 reason = -1
write(6,'(/,a)') ' ===========================================================================' ! if leaving, write line for end of iteration (otherwise stress BC check will be done)
else converged else converged
reason = 0 reason = 0
write(6,'(/,a)') ' ===========================================================================' ! if leaving, write line for end of iteration (otherwise stress BC check will be done)
endif converged endif converged
flush(6)
end subroutine AL_converged end subroutine AL_converged

View File

@ -427,10 +427,10 @@ subroutine BasicPETSC_formResidual(in,x_scal,f_scal,dummy,ierr)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! report begin of new iteration ! report begin of new iteration
if (iter == 0 .and. nfuncs == 0) then ! new increment if (iter == 0 .and. nfuncs == 0) then ! new increment
reportIter = -1_pInt reportIter = -1_pInt
endif endif
if (reportIter <= iter) then ! new iteration if (reportIter <= iter) then ! new iteration
reportIter = reportIter + 1_pInt reportIter = reportIter + 1_pInt
write(6,'(1x,a,3(a,'//IO_intOut(itmax)//'))') trim(incInfo), & write(6,'(1x,a,3(a,'//IO_intOut(itmax)//'))') trim(incInfo), &
' @ Iteration ', itmin, '≤',reportIter, '≤', itmax ' @ Iteration ', itmin, '≤',reportIter, '≤', itmax
@ -442,14 +442,15 @@ subroutine BasicPETSC_formResidual(in,x_scal,f_scal,dummy,ierr)
flush(6) flush(6)
endif endif
if (params%density > 0.0_pReal) then
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! evaluate inertia ! evaluate inertia
f_scal = ((x_scal - F_lastInc)/params%timeinc - (F_lastInc - F_lastInc2)/params%timeincOld)/((params%timeinc + params%timeincOld)/2.0_pReal) if (params%density > 0.0_pReal) then
f_scal = ((x_scal - F_lastInc)/params%timeinc - (F_lastInc - F_lastInc2)/params%timeincOld)/&
((params%timeinc + params%timeincOld)/2.0_pReal)
f_scal = params%density*product(geomSize/grid)*f_scal f_scal = params%density*product(geomSize/grid)*f_scal
field_real = 0.0_pReal field_real = 0.0_pReal
field_real(1:grid(1),1:grid(2),1:grid(3),1:3,1:3) = reshape(f_scal,[grid(1),grid(2),grid(3),3,3],& field_real(1:grid(1),1:grid(2),1:grid(3),1:3,1:3) = reshape(f_scal,[grid(1),grid(2),grid(3),3,3],&
order=[4,5,1,2,3]) ! field real has a different order order=[4,5,1,2,3]) ! field real has a different order
call Utilities_FFTforward() call Utilities_FFTforward()
call Utilities_inverseLaplace() call Utilities_inverseLaplace()
inertiaField_fourier = field_fourier inertiaField_fourier = field_fourier

View File

@ -77,7 +77,8 @@ module DAMASK_spectral_solverPolarisation
F_aimDot, & !< assumed rate of average deformation gradient F_aimDot, & !< assumed rate of average deformation gradient
F_aim = math_I3, & !< current prescribed deformation gradient F_aim = math_I3, & !< current prescribed deformation gradient
F_aim_lastInc = math_I3, & !< previous average deformation gradient F_aim_lastInc = math_I3, & !< previous average deformation gradient
P_av = 0.0_pReal !< average 1st Piola--Kirchhoff stress P_av = 0.0_pReal, & !< average 1st Piola--Kirchhoff stress
P_avLastEval = 0.0_pReal !< average 1st Piola--Kirchhoff stress last call of CPFEM_general
character(len=1024), private :: incInfo !< time and increment information character(len=1024), private :: incInfo !< time and increment information
real(pReal), private, dimension(3,3,3,3) :: & real(pReal), private, dimension(3,3,3,3) :: &
C_volAvg = 0.0_pReal, & !< current volume average stiffness C_volAvg = 0.0_pReal, & !< current volume average stiffness
@ -93,7 +94,6 @@ module DAMASK_spectral_solverPolarisation
err_p !< difference of stress resulting from compatible and incompatible F err_p !< difference of stress resulting from compatible and incompatible F
logical, private :: ForwardData logical, private :: ForwardData
integer(pInt), private :: & integer(pInt), private :: &
currIter = 0_pInt, & !< helper to count total iteration correctly
totalIter = 0_pInt !< total iteration in current increment totalIter = 0_pInt !< total iteration in current increment
public :: & public :: &
@ -208,9 +208,9 @@ subroutine Polarisation_init(temperature)
if (restartInc == 1_pInt) then ! no deformation (no restart) if (restartInc == 1_pInt) then ! no deformation (no restart)
F_lastInc = spread(spread(spread(math_I3,3,grid(1)),4,grid(2)),5,grid(3)) ! initialize to identity F_lastInc = spread(spread(spread(math_I3,3,grid(1)),4,grid(2)),5,grid(3)) ! initialize to identity
F_lastInc2 = F_lastInc F_lastInc2 = F_lastInc
F_tau_lastInc = F_lastInc F_tau_lastInc = 2.0_pReal*F_lastInc
F = reshape(F_lastInc,[9,grid(1),grid(2),grid(3)]) F = reshape(F_lastInc,[9,grid(1),grid(2),grid(3)])
F_tau = F F_tau = 2.0_pReal* F
elseif (restartInc > 1_pInt) then elseif (restartInc > 1_pInt) then
if (iand(debug_level(debug_spectral),debug_spectralRestart)/= 0) & if (iand(debug_level(debug_spectral),debug_spectralRestart)/= 0) &
write(6,'(/,a,'//IO_intOut(restartInc-1_pInt)//',a)') & write(6,'(/,a,'//IO_intOut(restartInc-1_pInt)//',a)') &
@ -277,10 +277,7 @@ end subroutine Polarisation_init
type(tSolutionState) function & type(tSolutionState) function &
Polarisation_solution(incInfoIn,guess,timeinc,timeinc_old,loadCaseTime,P_BC,F_BC,temperature_bc,rotation_BC,density) Polarisation_solution(incInfoIn,guess,timeinc,timeinc_old,loadCaseTime,P_BC,F_BC,temperature_bc,rotation_BC,density)
use numerics, only: & use numerics, only: &
update_gamma, & update_gamma
itmax, &
err_stress_tolrel, &
err_stress_tolabs
use math, only: & use math, only: &
math_mul33x33 ,& math_mul33x33 ,&
math_mul3333xx33, & math_mul3333xx33, &
@ -310,11 +307,12 @@ type(tSolutionState) function &
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! input data for solution ! input data for solution
real(pReal), intent(in) :: & real(pReal), intent(in) :: &
timeinc, & !< increment in time for current solution timeinc, & !< increment in time for current solution
timeinc_old, & !< increment in time of last increment timeinc_old, & !< increment in time of last increment
loadCaseTime, & !< remaining time of current load case loadCaseTime, & !< remaining time of current load case
temperature_bc temperature_bc, &
density
logical, intent(in) :: & logical, intent(in) :: &
guess guess
type(tBoundaryCondition), intent(in) :: & type(tBoundaryCondition), intent(in) :: &
@ -323,8 +321,7 @@ type(tSolutionState) function &
character(len=*), intent(in) :: & character(len=*), intent(in) :: &
incInfoIn incInfoIn
real(pReal), dimension(3,3), intent(in) :: rotation_BC real(pReal), dimension(3,3), intent(in) :: rotation_BC
real(pReal), intent(in) :: density
real(pReal) :: err_stress_tol
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! PETSc Data ! PETSc Data
PetscScalar, dimension(:,:,:,:), pointer :: xx_psc, F, F_tau PetscScalar, dimension(:,:,:,:), pointer :: xx_psc, F, F_tau
@ -390,7 +387,7 @@ type(tSolutionState) function &
F,[3,3,grid(1),grid(2),grid(3)])),[3,1,product(grid)]) F,[3,3,grid(1),grid(2),grid(3)])),[3,1,product(grid)])
Fdot = Utilities_calculateRate(math_rotate_backward33(f_aimDot,rotation_BC), & Fdot = Utilities_calculateRate(math_rotate_backward33(f_aimDot,rotation_BC), &
timeinc_old,guess,F_lastInc,reshape(F,[3,3,grid(1),grid(2),grid(3)])) timeinc_old,guess,F_lastInc,reshape(F,[3,3,grid(1),grid(2),grid(3)]))
F_tauDot = Utilities_calculateRate(math_rotate_backward33(f_aimDot,rotation_BC), & F_tauDot = Utilities_calculateRate(math_rotate_backward33(2.0_pReal*f_aimDot,rotation_BC), &
timeinc_old,guess,F_tau_lastInc,reshape(F_tau,[3,3,grid(1),grid(2),grid(3)])) timeinc_old,guess,F_tau_lastInc,reshape(F_tau,[3,3,grid(1),grid(2),grid(3)]))
F_lastInc2 = F_lastInc F_lastInc2 = F_lastInc
F_lastInc = reshape(F, [3,3,grid(1),grid(2),grid(3)]) F_lastInc = reshape(F, [3,3,grid(1),grid(2),grid(3)])
@ -400,7 +397,7 @@ type(tSolutionState) function &
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! update local deformation gradient ! update local deformation gradient
F = reshape(Utilities_forwardField(timeinc,F_lastInc,Fdot, & ! ensure that it matches rotated F_aim F = reshape(Utilities_forwardField(timeinc,F_lastInc,Fdot, & ! ensure that it matches rotated F_aim
math_rotate_backward33(F_aim,rotation_BC)),[9,grid(1),grid(2),grid(3)]) math_rotate_backward33(F_aim,rotation_BC)),[9,grid(1),grid(2),grid(3)])
F_tau = reshape(Utilities_forwardField(timeinc,F_tau_lastInc,F_taudot), [9,grid(1),grid(2),grid(3)]) ! does not have any average value as boundary condition F_tau = reshape(Utilities_forwardField(timeinc,F_tau_lastInc,F_taudot), [9,grid(1),grid(2),grid(3)]) ! does not have any average value as boundary condition
call DMDAVecRestoreArrayF90(da,solution_vec,xx_psc,ierr) call DMDAVecRestoreArrayF90(da,solution_vec,xx_psc,ierr)
@ -424,36 +421,20 @@ type(tSolutionState) function &
params%temperature = temperature_bc params%temperature = temperature_bc
params%density = density params%density = density
err_stress_tol = 1.0_pReal; err_stress = 2.0_pReal * err_stress_tol ! ensure to start loop
totalIter = -1_pInt
do while(err_stress/err_stress_tol > 1.0_pReal) ! solve BVP and Stress RB
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! solve BVP ! solve BVP
call SNESSolve(snes,PETSC_NULL_OBJECT,solution_vec,ierr) call SNESSolve(snes,PETSC_NULL_OBJECT,solution_vec,ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
!--------------------------------------------------------------------------------------------------
! stress BC handling
err_stress = maxval(abs(mask_stress * (P_av - params%P_BC))) ! mask = 0.0 for no bc
err_stress_tol = max(maxval(abs(P_av))*err_stress_tolrel,err_stress_tolabs)
F_aim = F_aim - math_mul3333xx33(S, ((P_av - params%P_BC))) ! S = 0.0 for no bc
write(6,'(1/,a)') ' ... correcting stress boundary condition .................................'
write(6,'(1/,a,f8.2,a,es11.5,a,es11.4,a)') ' error stress BC = ', &
err_stress/err_stress_tol, ' (',err_stress, ' Pa, tol =',err_stress_tol,')'
write(6,'(/,a)') ' ==========================================================================='
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! check convergence ! check convergence
call SNESGetConvergedReason(snes,reason,ierr) call SNESGetConvergedReason(snes,reason,ierr)
CHKERRQ(ierr) CHKERRQ(ierr)
Polarisation_solution%termIll = terminallyIll
Polarisation_solution%termIll = terminallyIll terminallyIll = .false.
terminallyIll = .false. Polarisation_solution%converged = .true.
Polarisation_solution%converged = .true. if (reason < 1 ) Polarisation_solution%converged = .false.
if (reason < 1 ) Polarisation_solution%converged = .false. Polarisation_solution%iterationsNeeded = totalIter
Polarisation_solution%iterationsNeeded = totalIter
end do
end function Polarisation_solution end function Polarisation_solution
@ -466,14 +447,20 @@ subroutine Polarisation_formResidual(in,x_scal,f_scal,dummy,ierr)
itmax, & itmax, &
itmin, & itmin, &
polarAlpha, & polarAlpha, &
polarBeta polarBeta, &
err_stress_tolrel, &
err_stress_tolabs, &
err_f_tol, &
err_p_tol, &
err_stress_tolabs
use IO, only: & use IO, only: &
IO_intOut IO_intOut
use math, only: & use math, only: &
math_rotate_backward33, & math_rotate_backward33, &
math_transpose33, & math_transpose33, &
math_mul3333xx33, & math_mul3333xx33, &
math_invSym3333 math_invSym3333, &
PI
use DAMASK_spectral_Utilities, only: & use DAMASK_spectral_Utilities, only: &
grid, & grid, &
geomSize, & geomSize, &
@ -517,7 +504,8 @@ subroutine Polarisation_formResidual(in,x_scal,f_scal,dummy,ierr)
PetscErrorCode :: ierr PetscErrorCode :: ierr
integer(pInt) :: & integer(pInt) :: &
i, j, k, e i, j, k, e
real(pReal) :: correctionFactor
F => x_scal(1:3,1:3,1,& F => x_scal(1:3,1:3,1,&
XG_RANGE,YG_RANGE,ZG_RANGE) XG_RANGE,YG_RANGE,ZG_RANGE)
F_tau => x_scal(1:3,1:3,2,& F_tau => x_scal(1:3,1:3,2,&
@ -530,12 +518,11 @@ subroutine Polarisation_formResidual(in,x_scal,f_scal,dummy,ierr)
call SNESGetNumberFunctionEvals(snes,nfuncs,ierr); CHKERRQ(ierr) call SNESGetNumberFunctionEvals(snes,nfuncs,ierr); CHKERRQ(ierr)
call SNESGetIterationNumber(snes,PETScIter,ierr); CHKERRQ(ierr) call SNESGetIterationNumber(snes,PETScIter,ierr); CHKERRQ(ierr)
if(nfuncs== 0 .and. PETScIter == 0) currIter = -1_pInt ! new increment if(nfuncs== 0 .and. PETScIter == 0) totalIter = -1_pInt ! new increment
if (PETScIter == currIter .or. currIter == -1 ) then ! new iteration if (totalIter <= PETScIter) then ! new iteration
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! report begin of new iteration ! report begin of new iteration
currIter = currIter + 1_pInt
totalIter = totalIter + 1_pInt totalIter = totalIter + 1_pInt
write(6,'(1x,a,3(a,'//IO_intOut(itmax)//'))') trim(incInfo), & write(6,'(1x,a,3(a,'//IO_intOut(itmax)//'))') trim(incInfo), &
' @ Iteration ', itmin, '≤',totalIter, '≤', itmax ' @ Iteration ', itmin, '≤',totalIter, '≤', itmax
@ -547,20 +534,21 @@ subroutine Polarisation_formResidual(in,x_scal,f_scal,dummy,ierr)
flush(6) flush(6)
endif endif
if (params%density > 0.0_pReal) then
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! evaluate inertia ! evaluate inertia
residual_F = ((F - F_lastInc)/params%timeinc - (F_lastInc - F_lastInc2)/params%timeincOld)/((params%timeinc + params%timeincOld)/2.0_pReal) dynamic: if (params%density > 0.0_pReal) then
residual_F = ((F - F_lastInc)/params%timeinc - (F_lastInc - F_lastInc2)/params%timeincOld)/&
((params%timeinc + params%timeincOld)/2.0_pReal)
residual_F = params%density*product(geomSize/grid)*residual_F residual_F = params%density*product(geomSize/grid)*residual_F
field_real = 0.0_pReal field_real = 0.0_pReal
field_real(1:grid(1),1:grid(2),1:grid(3),1:3,1:3) = reshape(residual_F,[grid(1),grid(2),grid(3),3,3],& field_real(1:grid(1),1:grid(2),1:grid(3),1:3,1:3) = reshape(residual_F,[grid(1),grid(2),grid(3),3,3],&
order=[4,5,1,2,3]) ! field real has a different order order=[4,5,1,2,3]) ! field real has a different order
call Utilities_FFTforward() call Utilities_FFTforward()
call Utilities_inverseLaplace() call Utilities_inverseLaplace()
inertiaField_fourier = field_fourier inertiaField_fourier = field_fourier
else else dynamic
inertiaField_fourier = cmplx(0.0_pReal,0.0_pReal,pReal) inertiaField_fourier = cmplx(0.0_pReal,0.0_pReal,pReal)
endif endif dynamic
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! !
@ -584,22 +572,33 @@ subroutine Polarisation_formResidual(in,x_scal,f_scal,dummy,ierr)
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! evaluate constitutive response ! evaluate constitutive response
P_avLastEval = P_av
call Utilities_constitutiveResponse(F_lastInc,F - residual_F_tau/polarBeta,params%temperature,params%timeinc, & call Utilities_constitutiveResponse(F_lastInc,F - residual_F_tau/polarBeta,params%temperature,params%timeinc, &
residual_F,C_volAvg,C_minMaxAvg,P_av,ForwardData,params%rotation_BC) residual_F,C_volAvg,C_minMaxAvg,P_av,ForwardData,params%rotation_BC)
ForwardData = .False. ForwardData = .False.
!--------------------------------------------------------------------------------------------------
! stress BC handling
write(6,'(/,a)') ' ... correcting F to fullfill stress BC ....................................'
correctionFactor = (cos((1.0-500.0_pReal**(-sum((P_av-P_avLastEval)**2.0_pReal)/& ! only correct when averages stress of last two calls is close
sum(P_av**2.0_pReal)))*PI)+1.0)/2.0_pReal
write(6,'(/,a,f8.2)') ' stress BC correction factor = ', correctionFactor
F_aim = F_aim - correctionFactor *math_mul3333xx33(S, ((P_av - params%P_BC))) ! S = 0.0 for no bc
err_stress = maxval(abs(mask_stress * (P_av - params%P_BC))) ! mask = 0.0 for no bc
!-------------------------------------------------------------------------------------------------- !--------------------------------------------------------------------------------------------------
! constructing residual ! constructing residual
e = 0_pInt e = 0_pInt
err_p = 0.0_pReal err_p = 0.0_pReal
do k = 1_pInt, grid(3); do j = 1_pInt, grid(2); do i = 1_pInt, grid(1) do k = 1_pInt, grid(3); do j = 1_pInt, grid(2); do i = 1_pInt, grid(1)
e = e + 1_pInt e = e + 1_pInt
err_p = err_p + sum((math_mul3333xx33(S_scale,residual_F(1:3,1:3,i,j,k)) - & err_p = err_p + sum((math_mul3333xx33(C_scale,F_tau(1:3,1:3,i,j,k) -&
(F_tau(1:3,1:3,i,j,k) - & F(1:3,1:3,i,j,k) - residual_F_tau(1:3,1:3,i,j,k)/polarBeta -&
F(1:3,1:3,i,j,k) + residual_F_tau(1:3,1:3,i,j,k)/polarBeta))**2.0_pReal) math_I3) - &
residual_F(1:3,1:3,i,j,k))**2.0_pReal)
residual_F(1:3,1:3,i,j,k) = math_mul3333xx33(math_invSym3333(materialpoint_dPdF(:,:,:,:,1,e) + C_scale), & residual_F(1:3,1:3,i,j,k) = math_mul3333xx33(math_invSym3333(materialpoint_dPdF(:,:,:,:,1,e) + C_scale), &
residual_F(1:3,1:3,i,j,k) - & residual_F(1:3,1:3,i,j,k) - &
math_mul3333xx33(C_scale,F_tau(1:3,1:3,i,j,k) - F(1:3,1:3,i,j,k))) & math_mul3333xx33(C_scale,F_tau(1:3,1:3,i,j,k) - F(1:3,1:3,i,j,k) - math_I3)) &
+ residual_F_tau(1:3,1:3,i,j,k) + residual_F_tau(1:3,1:3,i,j,k)
enddo; enddo; enddo enddo; enddo; enddo
@ -607,7 +606,7 @@ subroutine Polarisation_formResidual(in,x_scal,f_scal,dummy,ierr)
! calculating errors ! calculating errors
err_f = wgt*sqrt(sum(residual_F_tau**2.0_pReal))/polarBeta err_f = wgt*sqrt(sum(residual_F_tau**2.0_pReal))/polarBeta
err_p = wgt*sqrt(err_p) err_p = wgt*sqrt(err_p)
end subroutine Polarisation_formResidual end subroutine Polarisation_formResidual
@ -620,8 +619,8 @@ subroutine Polarisation_converged(snes_local,PETScIter,xnorm,snorm,fnorm,reason,
itmin, & itmin, &
err_f_tol, & err_f_tol, &
err_p_tol, & err_p_tol, &
err_stress_tolrel, & err_stress_tolabs, &
err_stress_tolabs err_stress_tolrel
use FEsolving, only: & use FEsolving, only: &
terminallyIll terminallyIll
@ -635,29 +634,39 @@ subroutine Polarisation_converged(snes_local,PETScIter,xnorm,snorm,fnorm,reason,
SNESConvergedReason :: reason SNESConvergedReason :: reason
PetscObject :: dummy PetscObject :: dummy
PetscErrorCode ::ierr PetscErrorCode ::ierr
logical :: Converged real(pReal) :: &
Converged = (totalIter >= itmin .and. & mismatch_f_tol, &
all([ err_f/err_f_tol, & mismatch_p_tol, &
err_p/err_p_tol ] < 1.0_pReal)) & stressBC_tol
.or. terminallyIll
mismatch_f_tol = max(maxval(abs(F_aim-math_I3))*err_stress_tolrel,err_f_tol)
mismatch_p_tol = max(maxval(abs(P_av)) *err_stress_tolrel,err_p_tol)
stressBC_tol = max(maxval(abs(P_av)) *err_stress_tolrel,err_stress_tolabs)
if (Converged) then
reason = 1
elseif (totalIter >= itmax) then
reason = -1
else
reason = 0
endif
write(6,'(1/,a)') ' ... reporting .............................................................' write(6,'(1/,a)') ' ... reporting .............................................................'
write(6,'(/,a,f8.2,a,es11.5,a,es11.4,a)') ' mismatch F = ', & write(6,'(/,a,f8.2,a,es11.5,a,es11.4,a)') ' mismatch F = ', &
err_f/err_f_tol, & err_f/mismatch_f_tol, &
' (',err_f,' -, tol =',err_f_tol,')' ' (',err_f,' -, tol =',mismatch_f_tol,')'
write(6,'(a,f8.2,a,es11.5,a,es11.4,a)') ' mismatch P = ', & write(6,'(a,f8.2,a,es11.5,a,es11.4,a)') ' mismatch P = ', &
err_p/err_p_tol, & err_p/mismatch_p_tol, &
' (',err_p,' -, tol =',err_p_tol,')' ' (',err_p,' -, tol =',mismatch_p_tol,')'
if(err_p/err_p_tol>1.0_pReal .or. err_f/err_f_tol>1.0_pReal) & ! if not converged, write line for end of iteration (otherwise stress BC check will be done) write(6,'(a,f8.2,a,es11.5,a,es11.4,a)') ' error stress BC = ', &
write(6,'(/,a)') ' ===========================================================================' err_stress/stressBC_tol, ' (',err_stress, ' Pa, tol =',stressBC_tol,')'
flush(6) write(6,'(/,a)') ' ==========================================================================='
flush(6)
converged: if ((totalIter >= itmin .and. &
all([ err_f/mismatch_f_tol, &
err_p/mismatch_p_tol, &
err_stress/stressBC_tol] < 1.0_pReal)) &
.or. terminallyIll) then
reason = 1
elseif (totalIter >= itmax) then converged
reason = -1
else converged
reason = 0
endif converged
end subroutine Polarisation_converged end subroutine Polarisation_converged

View File

@ -508,12 +508,13 @@ subroutine utilities_inverseLaplace()
if(k > grid(3)/2_pInt + 1_pInt) k_s(3) = k_s(3) - grid(3) ! running from 0,1,...,N/2,N/2+1,-N/2,-N/2+1,...,-1 if(k > grid(3)/2_pInt + 1_pInt) k_s(3) = k_s(3) - grid(3) ! running from 0,1,...,N/2,N/2+1,-N/2,-N/2+1,...,-1
do j = 1_pInt, grid(2) do j = 1_pInt, grid(2)
k_s(2) = j - 1_pInt k_s(2) = j - 1_pInt
if(j > grid(2)/2_pInt + 1_pInt) k_s(2) = k_s(2) - grid(2) ! running from 0,1,...,N/2,N/2+1,-N/2,-N/2+1,...,-1 if(j > grid(2)/2_pInt + 1_pInt) k_s(2) = k_s(2) - grid(2) ! running from 0,1,...,N/2,N/2+1,-N/2,-N/2+1,...,-1
do i = 1_pInt, grid1Red do i = 1_pInt, grid1Red
k_s(1) = i - 1_pInt k_s(1) = i - 1_pInt
if (any(k_s /= 0_pInt)) field_fourier(i,j,k, 1:3,1:3) = field_fourier(i,j,k, 1:3,1:3)/& if (any(k_s /= 0_pInt)) field_fourier(i,j,k, 1:3,1:3) = &
cmplx(-sum((2.0_pReal*PI*k_s/geomSize)*& field_fourier(i,j,k, 1:3,1:3)/ &
(2.0_pReal*PI*k_s/geomSize)),0.0_pReal,pReal) ! symmetry, junst running from 0,1,...,N/2,N/2+1 cmplx(-sum((2.0_pReal*PI*k_s/geomSize)*&
(2.0_pReal*PI*k_s/geomSize)),0.0_pReal,pReal) ! symmetry, junst running from 0,1,...,N/2,N/2+1
enddo; enddo; enddo enddo; enddo; enddo
field_fourier(1,1,1,1:3,1:3) = cmplx(0.0_pReal,0.0_pReal,pReal) field_fourier(1,1,1,1:3,1:3) = cmplx(0.0_pReal,0.0_pReal,pReal)

View File

@ -86,10 +86,10 @@ module numerics
#ifdef Spectral #ifdef Spectral
real(pReal), protected, public :: & real(pReal), protected, public :: &
err_div_tol = 5.0e-4_pReal, & !< Div(P)/avg(P)*meter err_div_tol = 5.0e-4_pReal, & !< Div(P)/avg(P)*meter
err_stress_tolrel = 0.01_pReal, & !< relative tolerance for fullfillment of stress BC in percent err_stress_tolrel = 0.01_pReal, & !< relative tolerance for fullfillment of stress BC and of mismatch F and P in percent
err_stress_tolabs = 1.0e3_pReal, & !< absolute tolerance for fullfillment of stress BC err_stress_tolabs = 1.0e3_pReal, & !< absolute tolerance for fullfillment of stress BC
err_f_tol = 1.0e-7_pReal, & err_f_tol = 1.0e-7_pReal, & !< absolute tolerance mismatch F
err_p_tol = 1.0e-7_pReal, & err_p_tol = 1.0e3_pReal, & !< absolute tolerance mismatch P
fftw_timelimit = -1.0_pReal, & !< sets the timelimit of plan creation for FFTW, see manual on www.fftw.org, Default -1.0: disable timelimit fftw_timelimit = -1.0_pReal, & !< sets the timelimit of plan creation for FFTW, see manual on www.fftw.org, Default -1.0: disable timelimit
rotation_tol = 1.0e-12_pReal, & !< tolerance of rotation specified in loadcase, Default 1.0e-12: first guess rotation_tol = 1.0e-12_pReal, & !< tolerance of rotation specified in loadcase, Default 1.0e-12: first guess
polarAlpha = 1.0_pReal, & !< polarization scheme parameter 0.0 < alpha < 2.0. alpha = 1.0 ==> AL scheme, alpha = 2.0 ==> accelerated scheme polarAlpha = 1.0_pReal, & !< polarization scheme parameter 0.0 < alpha < 2.0. alpha = 1.0 ==> AL scheme, alpha = 2.0 ==> accelerated scheme
@ -338,7 +338,7 @@ subroutine numerics_init
#ifdef Spectral #ifdef Spectral
select case(IO_lc(fftw_plan_mode)) ! setting parameters for the plan creation of FFTW. Basically a translation from fftw3.f select case(IO_lc(fftw_plan_mode)) ! setting parameters for the plan creation of FFTW. Basically a translation from fftw3.f
case('estimate','fftw_estimate') ! ordered from slow execution (but fast plan creation) to fast execution case('estimate','fftw_estimate') ! ordered from slow execution (but fast plan creation) to fast execution
fftw_planner_flag = 64_pInt fftw_planner_flag = 64_pInt
case('measure','fftw_measure') case('measure','fftw_measure')
fftw_planner_flag = 0_pInt fftw_planner_flag = 0_pInt