check_nonlin_convergence Subroutine

private subroutine check_nonlin_convergence(istep, heat_flux, exit)

Uses

Trinity convergence condition - simple and experimental look for the averaged differential of the summed averaged heat flux to drop below a threshold

Arguments

Type IntentOptional Attributes Name
integer, intent(in) :: istep
real, intent(in) :: heat_flux
logical, intent(inout) :: exit

Contents


Source Code

  subroutine check_nonlin_convergence(istep, heat_flux, exit)
    use gs2_time, only: user_time
    use mp, only: proc0, broadcast, job
    logical, intent(inout) :: exit
    integer, intent(in) :: istep
    real, intent(in) :: heat_flux

    real :: heat_av_new, heat_av_diff
    integer :: place, iwrite, nwrite_av
    logical :: debug = .false.

    if(proc0 .and. .not. (trin_istep .ne. 0 .and. istep .eq. 0)) then
       if(istep .gt. 0) trin_istep = trin_istep + nwrite ! Total number of steps including restarted trinity runs
       iwrite = trin_istep/nwrite ! Number of diagnostic write steps written
       nwrite_av = conv_nstep_av/nwrite ! Number of diagnostic write steps to average over        

       heat_sum_av = (heat_sum_av * iwrite + heat_flux) / (iwrite+1) ! Cumulative average of heat flux

       place = mod(trin_istep,conv_nstep_av)/nwrite
       conv_heat(place) = heat_flux

       if (debug) write(6,'(A,I5,A,e11.4,A,I6,I6)') 'Job ',job, &
            ' time = ',user_time, ' step = ',trin_istep
       if (debug) write(6,'(A,I5,A,e11.4,A,e11.4)') 'Job ',job, &
            ' heat = ',heat_flux, ' heatsumav = ',heat_av

       if (trin_istep .ge. conv_nstep_av) then
          heat_av_new = sum(conv_heat) / nwrite_av
          heat_av_diff = heat_av_new - heat_av
          if(debug) write(6,'(A,I5,A,e11.4,A,e11.4)') 'Job ',job, &
               ' heat_sum_av_diff = ',heat_sum_av
          heat_av = heat_av_new
          ! Convergence test - needs to be met conv_nsteps_converged/nwrite times in succession
          if (abs(heat_av_diff) .lt. heat_av_test) then
             conv_isteps_converged = conv_isteps_converged + 1
          else
             conv_isteps_converged = 0
             heat_av_test = heat_sum_av * conv_test_multiplier
          endif

          if ((conv_isteps_converged .ge. conv_nsteps_converged/nwrite) .and. &
               (trin_istep .ge. conv_min_step)) then
             if (debug) write(6,'(A,I5,A,I6,I3)')'Job ',job, &
                  ' Reached convergence condition after step ',trin_istep
             exit = .true. .and. exit_when_converged
          endif

          if(trin_istep .gt. conv_max_step) then
             write(6,'(A,I5,A,I7)') '*** Warning. Job ',job, &
                  ' did not meet the convergence condition after ',trin_istep
             exit = .true. .and. exit_when_converged
          endif
       endif
    endif

    call broadcast(exit)

  end subroutine check_nonlin_convergence