!
subroutine hogbom_cycle(rname,pflux, beam,mx,my,resid,nx,ny,               &
     &    ixbeam,iybeam, box, fracres, absres, miter, piter, niter,          &
     &    gainloop, converge, cct_list, start_iter, msk, list, nl, np, primary, weight, wtrun, &
     &    cflux, jcode, next_flux)
  use gkernel_interfaces
  use imager_interfaces, except_this=>hogbom_cycle
  use clean_def
  use clean_default
  use gbl_message
  use omp_control
  !$ use omp_lib
  !----------------------------------------------------------------------
  ! @ private-mandatory
  !*
  ! IMAGER  -- CLEAN Method HOGBOM  
  !     Deconvolve map into residual map and source list
  !-----------------------------------------------------------------------
  external :: next_flux                         !! Cumulative flux display
  character(len=*), intent(in) :: rname         !! Calling command
  logical, intent(in) :: pflux                  !! Plot cumulative flux ?
  integer, intent(in) :: mx                     !! X size of beam
  integer, intent(in) :: my                     !! Y size of beam
  integer, intent(in) :: nx                     !! X size of image
  integer, intent(in) :: ny                     !! Y size of image
  integer, intent(in) :: np                     !! Number of fields
  real, intent(in) :: beam(mx,my,np)            !! Primary beam(s)
  real, intent(inout) :: resid(nx,ny)           !! residual image
  real, intent(in) :: fracres                   !! Fractional residual
  real, intent(in) :: absres                    !! Absolute residual
  integer, intent(inout) :: miter               !! Maximum number of clean components
  integer, intent(in) :: ixbeam, iybeam         !! Beam maximum position
  integer, intent(in) :: box(4)                 !! Cleaning box
  real, intent(in) :: gainloop                  !! Clean loop gain
  integer, intent(in) :: converge               !! Convergence iteration number 
  integer, intent(out) :: niter                 !! Resulting number of Iterations
  integer, intent(in) :: piter                  !! Positive Iterations
  logical, intent(in) :: msk(nx,ny)             !! Mask for clean search
  integer, intent(in) :: nl                     !! Size of search list
  integer, intent(in) :: list(nl)               !! Search list
  real, intent(in) :: primary(np,nx,ny)         !! Primary beams
  real, intent(in) :: weight(nx,ny)             !! Weight function
  real, intent(in) :: wtrun                     !! Safety threshold on primary beams
  type(cct_lst), intent(inout) :: cct_list      !! Clean Component List
  integer, intent(in) :: start_iter             !! Starting Component Number
  integer, intent(out) :: jcode                 !! Stopping code
  real, intent(out) :: cflux                    !! Cleaned Flux
  !
  ! Local ---
  logical :: ok
  integer :: dimcum
  real, allocatable :: oldcum(:)
  real :: cum, conv, sign
  real :: valmax, valmin, f, vnew, borne, gain
  integer :: i, j, ix, iy, ip, imax, jmax, imin, jmin, k, l
  character(len=message_length) :: chain
  integer, allocatable :: imax_it(:), jmax_it(:)
  real, allocatable :: vnew_it(:)
  integer :: it, ier, nthread, mthread, ithread
  integer :: max_iter ! Maximum number of Clean Components
  !
  ! Code ----
  dimcum = converge
  allocate(oldcum(max(1,dimcum)),stat=ier)
  if (ier.ne.0) then
    call map_message(seve%e,rname,'Memory allocation error')
    return
  endif
  !
  oldcum = 0.0
  !
  ! Find highest point in region to be searched
  call maxlst (resid,nx,ny,list,nl,valmax,imax,jmax,   &
     &    valmin,imin,jmin)
  write(chain,'(A,1PG10.3,A,I6,I6,A,1PG10.3,A,I6,I6)') &
    &   'Map max. ',valmax,' at ',imax,jmax,  &
    &   ', Min. ',valmin,' at ',imin,jmin
  call map_message(seve%d,rname,chain)
  !
  ! Subtract +ve and -ve peaks
  niter = 0
  if (niter.lt.piter) then
    vnew = valmax
    ix = imax
    iy = jmax
    sign = 1.0
  elseif (abs(valmin) .gt. abs(valmax)) then
    vnew = valmin
    ix = imin
    iy = jmin
    sign = -1.0
  else
    vnew = valmax
    ix = imax
    iy = jmax
    sign = 1.0
  endif
  !
  ! Setup Subtraction loop
  cum    = 0.
  niter  = 0
  conv   = 0.
  borne = max(absres,fracres*abs(vnew))
  if (np.le.1) then
    gain = gainloop / beam(ixbeam,iybeam,1)
  else
    gain = gainloop
  endif
  !
  ! Main subtraction loop
  mthread = 1
  !$  mthread = omp_get_max_threads()
  !$  if (omp_in_parallel()) then
  !$    if (omp_get_nested()) then
  !$      ! Further optimisation requires to know the number of Outer Threads
  !$      mthread = omp_inner_thread
  !$      if (omp_debug) Print *,'Already in parallel mode, Outer THREAD ',omp_outer_thread,' Inner ',omp_inner_thread
  !$    else
  !$      mthread = 1
  !$      if (omp_debug) Print *,'Already in parallel mode, Outer THREAD ',omp_outer_thread,' No Inner threads'
  !$    endif
  !$  else
  !$    mthread = omp_inner_thread
  !$    if (omp_get_nested()) then
  !$      if (omp_debug) Print *,'Activating nesting ',omp_get_max_threads(),' possible, used ',mthread
  !$    else
  !$      if (omp_debug) Print *,'No parallel, and No nesting either, ',mthread
  !$    endif
  !$  endif
  allocate(vnew_it(mthread),imax_it(mthread),jmax_it(mthread),stat=ier)
  if (ier.ne.0) then
    write(chain,'(A,I4)') 'Memory allocation error for Mthread ',mthread
    call map_message(seve%e,rname,chain)
    return
  endif
  !
  if (miter.eq.0) then
    max_iter = 2**30  ! A Large  number
  else
    max_iter = miter
  endif
  !
  niter = start_iter-1 ! Could use the cct_list%cur_iter instead.
  ok = niter.lt.max_iter .and. abs(vnew).gt.borne
  !
  ! !Print *,'VNEW at start ',vnew
  do while (ok)
    !
    ! Get the component flux
    niter = niter+1
    f = vnew * gain
    if (np.gt.1) then
      f = f * weight(ix,iy)    ! Convert to Clean component
    endif
    if (niter.gt.cct_list%max_size) then
      ! !Print *,'Re-allocting CCT list  in HOGBOM_CYCLE'
      call cct_list%reallocate()
    endif
    !
    cct_list%cc(niter)%value = f       ! Store as fractions of beam max
    cct_list%cc(niter)%ix = ix
    cct_list%cc(niter)%iy = iy
    cct_list%cc(niter)%size = 0
    cct_list%cur_size = niter          ! That one was missing...
    ! !Print *,'Niter ',niter,cct_list%cc(niter)
    !
    cum = cum + f
    if (dimcum.ne.0) then
      !
      ! Keep last DIMCUM cumulative fluxes to test convergence
      oldcum(mod(niter,dimcum)+1) = cum
      conv = sign * (cum - oldcum(mod(niter+1,dimcum)+1))
    endif
    !
    ! Plot the new point
    if (pflux) call next_flux(niter,cum,0)
    !
    ! Subtract previous component from residual map
    nthread = 1
    !
    ! Parallel programming comment:
    ! Note that the gain is significant only in case of enough primary beams.
    ! It may slow down the method quite significantly otherwise, unless
    ! the number of inner threads has been properly evaluated.
    !
    !$OMP PARALLEL DEFAULT(none) NUM_THREADS(mthread) &
    !$OMP   &   SHARED(beam,resid,primary,weight,msk) &
    !$OMP   &   SHARED(nx,ny,mx,my,np,box,niter,piter,wtrun) &
    !$OMP   &   SHARED(vnew_it,imax_it,jmax_it) &
    !$OMP   &   SHARED(ixbeam,iybeam,f)  SHARED(ix,iy) &
    !$OMP   &   PRIVATE(j,l,i,k,ip,ithread) SHARED(nthread,omp_debug)
    !
    ithread = 1
    !$  nthread = omp_get_num_threads()
    !$  ithread = omp_get_thread_num()+1
    !$  if (omp_debug.and.niter.eq.1) Print *,'Inner Hogbom Nthread ',nthread,' Ithread ',ithread
    !
    vnew_it(ithread)  = 0
    !$OMP DO SCHEDULE(STATIC,1) 
    !$ ! The type of Scheduling does not seem to affect the timing
    !$ ! significantly.  DYNAMIC may be slightly better.
    do j=1,ny
      !
      ! Proceed Row by Row
      l = j-iy+iybeam
      if (l.ge.1 .and. l.le.my) then
        !
        ! Along that row, subtract clean component if in beam
        do i = 1,nx
          k = i-ix+ixbeam
          if (k.ge.1 .and. k.le.mx) then
            if (np.le.1) then
              resid(i,j) = resid(i,j) - f*beam(k,l,1)
            else
              if (resid(i,j).ne.0) then
                do ip = 1,np
                  !
                  ! Beware of truncating the primary beam.
                  if (primary(ip,i,j).gt.wtrun) then
                    resid(i,j) = resid(i,j) -   &
     &                      f*beam(k,l,ip)*primary(ip,i,j)   &
     &                      *primary(ip,ix,iy)*weight(i,j)
                  endif
                enddo
              endif
            endif
          endif
        enddo
      endif
      !
      ! Find new maximum inside cleaning box in residual map for this row
      if ((j.ge.box(2)).and.(j.le.box(4))) then
        if (niter.lt.piter) then
          ! Force positive components
          do i = box(1), box(3)
            if (msk(i,j)) then
              if (vnew_it(ithread).lt.resid(i,j)) then
                vnew_it(ithread)=resid(i,j)
                imax_it(ithread)=i
                jmax_it(ithread)=j
              endif
            endif
          enddo
        else
          ! Do not force positivity
          do i = box(1), box(3)
            if (msk(i,j)) then
              if (abs(vnew_it(ithread)).lt.abs(resid(i,j))) then
                vnew_it(ithread)=resid(i,j)
                imax_it(ithread)=i
                jmax_it(ithread)=j
              endif
            endif
          enddo
        endif
      endif
      !
      ! Loop for next row
    enddo
    !$OMP END DO
    !$OMP END PARALLEL
    !
    ! Compute VNEW and Position for next iteration
    vnew = vnew_it(1) 
    it = 1
    do i=2,nthread
      if (abs(vnew).lt.abs(vnew_it(i))) then
        it = i
        vnew = vnew_it(i)
      endif
    enddo
    vnew = vnew_it(it)
    ix = imax_it(it)
    iy = jmax_it(it)
    !
    ! !Print *,'Niter ',niter,' < ',max_iter,niter.lt.miter
    ! !Print *,'Converge ',converge, ' > 0',(converge.gt.0)
    ! !Print *,'Vnew = ',vnew,' > Borne = ',borne,abs(vnew).gt.borne
    !
    jcode = 0
    if (sic_ctrlc()) exit
    !
    if (niter.ge.max_iter) then
      jcode = 1
      exit
    endif
    if ((converge.gt.0).and.(conv.le.0)) then
      jcode = 2
      exit
    endif
    if (abs(vnew) .le. borne) then
      jcode = 3
      exit
    endif
  enddo
  !
  cflux = cum
  deallocate(vnew_it,imax_it,jmax_it,stat=ier)
end subroutine hogbom_cycle
