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:
parent
a0ef3ce5ef
commit
81531097f1
|
@ -77,7 +77,8 @@ module DAMASK_spectral_solverAL
|
|||
F_aimDot, & !< assumed rate of average deformation gradient
|
||||
F_aim = math_I3, & !< current prescribed 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
|
||||
real(pReal), private, dimension(3,3,3,3) :: &
|
||||
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
|
||||
logical, private :: ForwardData
|
||||
integer(pInt), private :: &
|
||||
currIter = 0_pInt, & !< helper to count total iteration correctly
|
||||
totalIter = 0_pInt !< total iteration in current increment
|
||||
|
||||
public :: &
|
||||
|
@ -277,10 +277,7 @@ end subroutine AL_init
|
|||
type(tSolutionState) function &
|
||||
AL_solution(incInfoIn,guess,timeinc,timeinc_old,loadCaseTime,P_BC,F_BC,temperature_bc,rotation_BC,density)
|
||||
use numerics, only: &
|
||||
update_gamma, &
|
||||
itmax, &
|
||||
err_stress_tolrel, &
|
||||
err_stress_tolabs
|
||||
update_gamma
|
||||
use math, only: &
|
||||
math_mul33x33 ,&
|
||||
math_mul3333xx33, &
|
||||
|
@ -314,7 +311,8 @@ use mesh, only: &
|
|||
timeinc, & !< increment in time for current solution
|
||||
timeinc_old, & !< increment in time of last increment
|
||||
loadCaseTime, & !< remaining time of current load case
|
||||
temperature_bc
|
||||
temperature_bc, &
|
||||
density
|
||||
logical, intent(in) :: &
|
||||
guess
|
||||
type(tBoundaryCondition), intent(in) :: &
|
||||
|
@ -323,8 +321,7 @@ use mesh, only: &
|
|||
character(len=*), intent(in) :: &
|
||||
incInfoIn
|
||||
real(pReal), dimension(3,3), intent(in) :: rotation_BC
|
||||
real(pReal), intent(in) :: density
|
||||
real(pReal) :: err_stress_tol
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! PETSc Data
|
||||
PetscScalar, dimension(:,:,:,:), pointer :: xx_psc, F, F_lambda
|
||||
|
@ -424,35 +421,20 @@ use mesh, only: &
|
|||
params%temperature = temperature_bc
|
||||
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
|
||||
call SNESSolve(snes,PETSC_NULL_OBJECT,solution_vec,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
|
||||
call SNESGetConvergedReason(snes,reason,ierr)
|
||||
CHKERRQ(ierr)
|
||||
|
||||
AL_solution%termIll = terminallyIll
|
||||
terminallyIll = .false.
|
||||
AL_solution%converged = .true.
|
||||
if (reason < 1 ) AL_solution%converged = .false.
|
||||
AL_solution%iterationsNeeded = totalIter
|
||||
end do
|
||||
AL_solution%converged = .true.
|
||||
if (reason < 1 ) AL_solution%converged = .false.
|
||||
AL_solution%iterationsNeeded = totalIter
|
||||
|
||||
end function AL_solution
|
||||
|
||||
|
@ -465,14 +447,20 @@ subroutine AL_formResidual(in,x_scal,f_scal,dummy,ierr)
|
|||
itmax, &
|
||||
itmin, &
|
||||
polarAlpha, &
|
||||
polarBeta
|
||||
polarBeta, &
|
||||
err_stress_tolrel, &
|
||||
err_stress_tolabs, &
|
||||
err_f_tol, &
|
||||
err_p_tol, &
|
||||
err_stress_tolabs
|
||||
use IO, only: &
|
||||
IO_intOut
|
||||
use math, only: &
|
||||
math_rotate_backward33, &
|
||||
math_transpose33, &
|
||||
math_mul3333xx33, &
|
||||
math_invSym3333
|
||||
math_invSym3333, &
|
||||
PI
|
||||
use DAMASK_spectral_Utilities, only: &
|
||||
grid, &
|
||||
geomSize, &
|
||||
|
@ -516,6 +504,7 @@ subroutine AL_formResidual(in,x_scal,f_scal,dummy,ierr)
|
|||
PetscErrorCode :: ierr
|
||||
integer(pInt) :: &
|
||||
i, j, k
|
||||
real(pReal) :: correctionFactor
|
||||
|
||||
F => x_scal(1:3,1:3,1,&
|
||||
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 SNESGetIterationNumber(snes,PETScIter,ierr); CHKERRQ(ierr)
|
||||
|
||||
if(nfuncs== 0 .and. PETScIter == 0) currIter = -1_pInt ! new increment
|
||||
|
||||
if (PETScIter == currIter .or. currIter == -1 ) then ! new iteration
|
||||
if(nfuncs== 0 .and. PETScIter == 0) totalIter = -1_pInt ! new increment
|
||||
if (totalIter <= PETScIter) then ! new iteration
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! report begin of new iteration
|
||||
currIter = currIter + 1_pInt
|
||||
totalIter = totalIter + 1_pInt
|
||||
write(6,'(1x,a,3(a,'//IO_intOut(itmax)//'))') trim(incInfo), &
|
||||
' @ Iteration ', itmin, '≤',totalIter, '≤', itmax
|
||||
|
@ -546,10 +533,11 @@ subroutine AL_formResidual(in,x_scal,f_scal,dummy,ierr)
|
|||
flush(6)
|
||||
endif
|
||||
|
||||
if (params%density > 0.0_pReal) then
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! 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
|
||||
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],&
|
||||
|
@ -557,9 +545,9 @@ subroutine AL_formResidual(in,x_scal,f_scal,dummy,ierr)
|
|||
call Utilities_FFTforward()
|
||||
call Utilities_inverseLaplace()
|
||||
inertiaField_fourier = field_fourier
|
||||
else
|
||||
else dynamic
|
||||
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)
|
||||
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
|
||||
err_p = 0.0_pReal
|
||||
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)) - &
|
||||
F_lambda(1:3,1:3,i,j,k))**2.0_pReal)
|
||||
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)
|
||||
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) &
|
||||
+ residual_F_lambda(1:3,1:3,i,j,k)
|
||||
|
@ -611,13 +606,13 @@ end subroutine AL_formResidual
|
|||
!> @brief convergence check
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
subroutine AL_converged(snes_local,PETScIter,xnorm,snorm,fnorm,reason,dummy,ierr)
|
||||
use numerics, only: &
|
||||
use numerics, only: &
|
||||
itmax, &
|
||||
itmin, &
|
||||
err_f_tol, &
|
||||
err_p_tol, &
|
||||
err_stress_tolrel, &
|
||||
err_stress_tolabs
|
||||
err_stress_tolabs, &
|
||||
err_stress_tolrel
|
||||
use FEsolving, only: &
|
||||
terminallyIll
|
||||
|
||||
|
@ -631,27 +626,38 @@ subroutine AL_converged(snes_local,PETScIter,xnorm,snorm,fnorm,reason,dummy,ierr
|
|||
SNESConvergedReason :: reason
|
||||
PetscObject :: dummy
|
||||
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,'(/,a,f8.2,a,es11.5,a,es11.4,a)') ' mismatch F = ', &
|
||||
err_f/err_f_tol, &
|
||||
' (',err_f,' -, tol =',err_f_tol,')'
|
||||
err_f/mismatch_f_tol, &
|
||||
' (',err_f,' -, tol =',mismatch_f_tol,')'
|
||||
write(6,'(a,f8.2,a,es11.5,a,es11.4,a)') ' mismatch P = ', &
|
||||
err_p/err_p_tol, &
|
||||
' (',err_p,' -, tol =',err_p_tol,')'
|
||||
err_p/mismatch_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. &
|
||||
all([ err_f/err_f_tol, &
|
||||
err_p/err_p_tol ] < 1.0_pReal)) &
|
||||
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
|
||||
elseif (totalIter >= itmax) then converged
|
||||
reason = -1
|
||||
write(6,'(/,a)') ' ===========================================================================' ! if leaving, write line for end of iteration (otherwise stress BC check will be done)
|
||||
else converged
|
||||
reason = 0
|
||||
write(6,'(/,a)') ' ===========================================================================' ! if leaving, write line for end of iteration (otherwise stress BC check will be done)
|
||||
endif converged
|
||||
flush(6)
|
||||
|
||||
end subroutine AL_converged
|
||||
|
||||
|
|
|
@ -427,10 +427,10 @@ subroutine BasicPETSC_formResidual(in,x_scal,f_scal,dummy,ierr)
|
|||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! 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
|
||||
endif
|
||||
if (reportIter <= iter) then ! new iteration
|
||||
if (reportIter <= iter) then ! new iteration
|
||||
reportIter = reportIter + 1_pInt
|
||||
write(6,'(1x,a,3(a,'//IO_intOut(itmax)//'))') trim(incInfo), &
|
||||
' @ Iteration ', itmin, '≤',reportIter, '≤', itmax
|
||||
|
@ -442,14 +442,15 @@ subroutine BasicPETSC_formResidual(in,x_scal,f_scal,dummy,ierr)
|
|||
flush(6)
|
||||
endif
|
||||
|
||||
if (params%density > 0.0_pReal) then
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! 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
|
||||
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],&
|
||||
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_inverseLaplace()
|
||||
inertiaField_fourier = field_fourier
|
||||
|
|
|
@ -77,7 +77,8 @@ module DAMASK_spectral_solverPolarisation
|
|||
F_aimDot, & !< assumed rate of average deformation gradient
|
||||
F_aim = math_I3, & !< current prescribed 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
|
||||
real(pReal), private, dimension(3,3,3,3) :: &
|
||||
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
|
||||
logical, private :: ForwardData
|
||||
integer(pInt), private :: &
|
||||
currIter = 0_pInt, & !< helper to count total iteration correctly
|
||||
totalIter = 0_pInt !< total iteration in current increment
|
||||
|
||||
public :: &
|
||||
|
@ -208,9 +208,9 @@ subroutine Polarisation_init(temperature)
|
|||
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_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_tau = F
|
||||
F_tau = 2.0_pReal* F
|
||||
elseif (restartInc > 1_pInt) then
|
||||
if (iand(debug_level(debug_spectral),debug_spectralRestart)/= 0) &
|
||||
write(6,'(/,a,'//IO_intOut(restartInc-1_pInt)//',a)') &
|
||||
|
@ -277,10 +277,7 @@ end subroutine Polarisation_init
|
|||
type(tSolutionState) function &
|
||||
Polarisation_solution(incInfoIn,guess,timeinc,timeinc_old,loadCaseTime,P_BC,F_BC,temperature_bc,rotation_BC,density)
|
||||
use numerics, only: &
|
||||
update_gamma, &
|
||||
itmax, &
|
||||
err_stress_tolrel, &
|
||||
err_stress_tolabs
|
||||
update_gamma
|
||||
use math, only: &
|
||||
math_mul33x33 ,&
|
||||
math_mul3333xx33, &
|
||||
|
@ -310,11 +307,12 @@ type(tSolutionState) function &
|
|||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! input data for solution
|
||||
real(pReal), intent(in) :: &
|
||||
real(pReal), intent(in) :: &
|
||||
timeinc, & !< increment in time for current solution
|
||||
timeinc_old, & !< increment in time of last increment
|
||||
loadCaseTime, & !< remaining time of current load case
|
||||
temperature_bc
|
||||
temperature_bc, &
|
||||
density
|
||||
logical, intent(in) :: &
|
||||
guess
|
||||
type(tBoundaryCondition), intent(in) :: &
|
||||
|
@ -323,8 +321,7 @@ type(tSolutionState) function &
|
|||
character(len=*), intent(in) :: &
|
||||
incInfoIn
|
||||
real(pReal), dimension(3,3), intent(in) :: rotation_BC
|
||||
real(pReal), intent(in) :: density
|
||||
real(pReal) :: err_stress_tol
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! PETSc Data
|
||||
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)])
|
||||
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)]))
|
||||
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)]))
|
||||
F_lastInc2 = F_lastInc
|
||||
F_lastInc = reshape(F, [3,3,grid(1),grid(2),grid(3)])
|
||||
|
@ -400,7 +397,7 @@ type(tSolutionState) function &
|
|||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! 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)])
|
||||
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)
|
||||
|
@ -424,36 +421,20 @@ type(tSolutionState) function &
|
|||
params%temperature = temperature_bc
|
||||
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
|
||||
call SNESSolve(snes,PETSC_NULL_OBJECT,solution_vec,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)') ' ==========================================================================='
|
||||
call SNESSolve(snes,PETSC_NULL_OBJECT,solution_vec,ierr)
|
||||
CHKERRQ(ierr)
|
||||
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! check convergence
|
||||
call SNESGetConvergedReason(snes,reason,ierr)
|
||||
CHKERRQ(ierr)
|
||||
|
||||
Polarisation_solution%termIll = terminallyIll
|
||||
terminallyIll = .false.
|
||||
Polarisation_solution%converged = .true.
|
||||
if (reason < 1 ) Polarisation_solution%converged = .false.
|
||||
Polarisation_solution%iterationsNeeded = totalIter
|
||||
end do
|
||||
call SNESGetConvergedReason(snes,reason,ierr)
|
||||
CHKERRQ(ierr)
|
||||
Polarisation_solution%termIll = terminallyIll
|
||||
terminallyIll = .false.
|
||||
Polarisation_solution%converged = .true.
|
||||
if (reason < 1 ) Polarisation_solution%converged = .false.
|
||||
Polarisation_solution%iterationsNeeded = totalIter
|
||||
|
||||
end function Polarisation_solution
|
||||
|
||||
|
@ -466,14 +447,20 @@ subroutine Polarisation_formResidual(in,x_scal,f_scal,dummy,ierr)
|
|||
itmax, &
|
||||
itmin, &
|
||||
polarAlpha, &
|
||||
polarBeta
|
||||
polarBeta, &
|
||||
err_stress_tolrel, &
|
||||
err_stress_tolabs, &
|
||||
err_f_tol, &
|
||||
err_p_tol, &
|
||||
err_stress_tolabs
|
||||
use IO, only: &
|
||||
IO_intOut
|
||||
use math, only: &
|
||||
math_rotate_backward33, &
|
||||
math_transpose33, &
|
||||
math_mul3333xx33, &
|
||||
math_invSym3333
|
||||
math_invSym3333, &
|
||||
PI
|
||||
use DAMASK_spectral_Utilities, only: &
|
||||
grid, &
|
||||
geomSize, &
|
||||
|
@ -517,7 +504,8 @@ subroutine Polarisation_formResidual(in,x_scal,f_scal,dummy,ierr)
|
|||
PetscErrorCode :: ierr
|
||||
integer(pInt) :: &
|
||||
i, j, k, e
|
||||
|
||||
real(pReal) :: correctionFactor
|
||||
|
||||
F => x_scal(1:3,1:3,1,&
|
||||
XG_RANGE,YG_RANGE,ZG_RANGE)
|
||||
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 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
|
||||
currIter = currIter + 1_pInt
|
||||
totalIter = totalIter + 1_pInt
|
||||
write(6,'(1x,a,3(a,'//IO_intOut(itmax)//'))') trim(incInfo), &
|
||||
' @ Iteration ', itmin, '≤',totalIter, '≤', itmax
|
||||
|
@ -547,20 +534,21 @@ subroutine Polarisation_formResidual(in,x_scal,f_scal,dummy,ierr)
|
|||
flush(6)
|
||||
endif
|
||||
|
||||
if (params%density > 0.0_pReal) then
|
||||
!--------------------------------------------------------------------------------------------------
|
||||
! 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
|
||||
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],&
|
||||
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_inverseLaplace()
|
||||
inertiaField_fourier = field_fourier
|
||||
else
|
||||
else dynamic
|
||||
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
|
||||
P_avLastEval = P_av
|
||||
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)
|
||||
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
|
||||
e = 0_pInt
|
||||
err_p = 0.0_pReal
|
||||
do k = 1_pInt, grid(3); do j = 1_pInt, grid(2); do i = 1_pInt, grid(1)
|
||||
e = e + 1_pInt
|
||||
err_p = err_p + sum((math_mul3333xx33(S_scale,residual_F(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))**2.0_pReal)
|
||||
err_p = err_p + sum((math_mul3333xx33(C_scale,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 -&
|
||||
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(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)
|
||||
enddo; enddo; enddo
|
||||
|
||||
|
@ -607,7 +606,7 @@ subroutine Polarisation_formResidual(in,x_scal,f_scal,dummy,ierr)
|
|||
! calculating errors
|
||||
err_f = wgt*sqrt(sum(residual_F_tau**2.0_pReal))/polarBeta
|
||||
err_p = wgt*sqrt(err_p)
|
||||
|
||||
|
||||
end subroutine Polarisation_formResidual
|
||||
|
||||
|
||||
|
@ -620,8 +619,8 @@ subroutine Polarisation_converged(snes_local,PETScIter,xnorm,snorm,fnorm,reason,
|
|||
itmin, &
|
||||
err_f_tol, &
|
||||
err_p_tol, &
|
||||
err_stress_tolrel, &
|
||||
err_stress_tolabs
|
||||
err_stress_tolabs, &
|
||||
err_stress_tolrel
|
||||
use FEsolving, only: &
|
||||
terminallyIll
|
||||
|
||||
|
@ -635,29 +634,39 @@ subroutine Polarisation_converged(snes_local,PETScIter,xnorm,snorm,fnorm,reason,
|
|||
SNESConvergedReason :: reason
|
||||
PetscObject :: dummy
|
||||
PetscErrorCode ::ierr
|
||||
logical :: Converged
|
||||
Converged = (totalIter >= itmin .and. &
|
||||
all([ err_f/err_f_tol, &
|
||||
err_p/err_p_tol ] < 1.0_pReal)) &
|
||||
.or. terminallyIll
|
||||
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)
|
||||
|
||||
if (Converged) then
|
||||
reason = 1
|
||||
elseif (totalIter >= itmax) then
|
||||
reason = -1
|
||||
else
|
||||
reason = 0
|
||||
endif
|
||||
write(6,'(1/,a)') ' ... reporting .............................................................'
|
||||
write(6,'(/,a,f8.2,a,es11.5,a,es11.4,a)') ' mismatch F = ', &
|
||||
err_f/err_f_tol, &
|
||||
' (',err_f,' -, tol =',err_f_tol,')'
|
||||
err_f/mismatch_f_tol, &
|
||||
' (',err_f,' -, tol =',mismatch_f_tol,')'
|
||||
write(6,'(a,f8.2,a,es11.5,a,es11.4,a)') ' mismatch P = ', &
|
||||
err_p/err_p_tol, &
|
||||
' (',err_p,' -, tol =',err_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)') ' ==========================================================================='
|
||||
flush(6)
|
||||
err_p/mismatch_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. &
|
||||
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
|
||||
|
||||
|
|
|
@ -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
|
||||
do j = 1_pInt, grid(2)
|
||||
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
|
||||
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)/&
|
||||
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
|
||||
if (any(k_s /= 0_pInt)) field_fourier(i,j,k, 1:3,1:3) = &
|
||||
field_fourier(i,j,k, 1:3,1:3)/ &
|
||||
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
|
||||
field_fourier(1,1,1,1:3,1:3) = cmplx(0.0_pReal,0.0_pReal,pReal)
|
||||
|
||||
|
|
|
@ -86,10 +86,10 @@ module numerics
|
|||
#ifdef Spectral
|
||||
real(pReal), protected, public :: &
|
||||
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_tolabs = 1.0e3_pReal, & !< absolute tolerance for fullfillment of stress BC
|
||||
err_f_tol = 1.0e-7_pReal, &
|
||||
err_p_tol = 1.0e-7_pReal, &
|
||||
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_f_tol = 1.0e-7_pReal, & !< absolute tolerance mismatch F
|
||||
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
|
||||
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
|
||||
|
@ -338,7 +338,7 @@ subroutine numerics_init
|
|||
|
||||
#ifdef Spectral
|
||||
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
|
||||
case('measure','fftw_measure')
|
||||
fftw_planner_flag = 0_pInt
|
||||
|
|
Loading…
Reference in New Issue