Test residuals to determine if the current processor has converged, adapted to optimal control. Can probably be removed, when pf_pfasst_block_oc is changed to use pf_check_convergence of pf_check_convergence_old.
Note that if the previous processor hasn't converged yet (pstatus), the current processor hasn't converged yet either, regardless of the residual.
Check to see if tolerances are met
Until I hear the previous processor is done, recieve it's status
Check to see if I am converged Assign status and send it forward ! old code below
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
type(pf_pfasst_t), | intent(inout) | :: | pf | |||
integer, | intent(in) | :: | send_tag | |||
integer, | intent(in), | optional | :: | flags |
subroutine pf_check_convergence_oc(pf, send_tag, flags)
type(pf_pfasst_t), intent(inout) :: pf
integer, intent(in) :: send_tag
! real(pfdp), intent(inout) :: residual
! integer, intent(in) :: k
! logical, intent(out) :: converged !! True if this processor is done
integer, optional, intent(in) :: flags
! real(pfdp) :: residual1
integer :: dir, which
logical :: residual_converged, converged
converged = .false.
! shortcut for fixed block mode
if (pf%abs_res_tol == 0 .and. pf%rel_res_tol == 0) then
pf%state%pstatus = PF_STATUS_ITERATING
pf%state%status = PF_STATUS_ITERATING
return
end if
! in first sweep: always continue
if (pf%state%iter == 1) then
pf%state%pstatus = PF_STATUS_ITERATING
pf%state%status = PF_STATUS_ITERATING
return
end if
which = 1
if (present(flags)) which = flags
! send forward by default, even if sweeping on both components; send backwards if sweeping on p only
dir = 1
if(which == 2) dir = 2
call call_hooks(pf, 1, PF_PRE_CONVERGENCE)
!> Check to see if tolerances are met
call pf_check_residual_oc(pf, residual_converged)
!> Until I hear the previous processor is done, recieve it's status
if (pf%state%pstatus /= PF_STATUS_CONVERGED) call pf_recv_status(pf, send_tag, dir)
!> Check to see if I am converged
converged = .false.
if (residual_converged) then
if (pf%rank == 0 .and. dir==1) then
converged = .true.
elseif (pf%rank == pf%comm%nproc-1 .and. dir==2) then
converged = .true.
else ! I am not the first/last processor, so I need to check the previous one
if (pf%state%pstatus == PF_STATUS_CONVERGED) converged = .true.
end if
end if ! (residual_converged)
!> Assign status and send it forward
if (converged) then
if (pf%state%status == PF_STATUS_ITERATING) then
! If I am converged for the first time
! then flip my flag and send the last status update
pf%state%status = PF_STATUS_CONVERGED
call pf_send_status(pf, send_tag, dir)
end if
else
! I am not converged, send the news
pf%state%status = PF_STATUS_ITERATING
call pf_send_status(pf, send_tag, dir)
end if
call call_hooks(pf, 1, PF_POST_CONVERGENCE)
!!! old code below
! Check to see if tolerances are met
! residual1 = pf%levels(pf%nlevels)%residual
! if (pf%state%status == PF_STATUS_ITERATING .and. residual > 0.0d0) then
! if ( (abs(1.0_pfdp - abs(residual1/residual)) < pf%rel_res_tol) .or. &
! (abs(residual1) < pf%abs_res_tol) ) then
! pf%state%status = PF_STATUS_CONVERGED
! end if
! end if
!
! !->why? how to do that more cleanly?
! if (pf%state%status == PF_STATUS_ITERATING .and. residual >= 0.0d0) then
! ! if do_mixed, adjoint on last time step will be constant zero, so residual will be zero
! ! need to stop in that case as well, but not in the very first iteration
! if( abs(residual1) < pf%abs_res_tol ) then
! pf%state%status = PF_STATUS_CONVERGED
! end if
! end if
! !!-
!
! residual = residual1
!
! call call_hooks(pf, 1, PF_PRE_CONVERGENCE)
! if (pf%state%pstatus /= PF_STATUS_CONVERGED) call pf_recv_status(pf, 1+k, dir)
!
! if (pf%rank /= 0 .and. pf%state%pstatus == PF_STATUS_ITERATING .and. dir == 1) &
! pf%state%status = PF_STATUS_ITERATING
! if (pf%rank /= pf%comm%nproc-1 .and. pf%state%pstatus == PF_STATUS_ITERATING .and. dir == 2) &
! pf%state%status = PF_STATUS_ITERATING
!
! ! if (pf%state%status .ne. PF_STATUS_CONVERGED)
! call pf_send_status(pf, 1+k, dir)
! call call_hooks(pf, 1, PF_POST_CONVERGENCE)
!
! ! XXX: this ain't so pretty, perhaps we should use the
! ! 'nmoved' thinger to break this cycle if everyone is
! ! done...
!
! if (pf%state%status == PF_STATUS_CONVERGED) then
! converged = .true.
! return
! end if
!
! if (0 == pf%comm%nproc) then
! pf%state%status = PF_STATUS_PREDICTOR
! converged = .true.
! return
! end if
end subroutine pf_check_convergence_oc