module solver_tiny_brad
use sep
! 0 = F m - d with a jniter writes of progress on model 
  implicit none
  integer     :: time_array(8)
  real:: blocks
  contains
    subroutine solver_init(blck)
      real:: blck
      blocks=blck
    end subroutine solver_init
    subroutine solver( m,d, Fop, stepper, add,niter,jniter,resd)
      optional ::                                          resd
      !----------------------------------------------------------------
      interface
         integer function Fop(adj,add,m,d)
           real,dimension(:) :: m,d
           logical,intent(in):: adj,add
         end function Fop
         integer function stepper(forget,m,g,rr,gg)
           real,dimension(:) ::          m,g,rr,gg
           logical           ::   forget
         end function stepper
      end interface
      !----------------------------------------------------------------
      real, dimension(:),    intent(in)  :: d
      real, dimension(:),    intent(inout):: m
      integer,               intent(in)  :: niter,jniter
      real, dimension(size( m))          :: g
      real, dimension(size( d)),target   :: rr
      real, dimension(:),       pointer  :: rd
      real, dimension(size( d)),target   :: gg
      real, dimension(:),       pointer  :: gd
      integer                            :: stat,done,nter,iter
      real, dimension(:),    intent(out) :: resd
      real         :: start, finish,startg, finishg
      logical :: add

      finish=0.;      finishg=0.

      rd => rr(1:size( d))
      gd => gg(1:size( d))
      rd = -d      

      if (add) then
         call start_timer(start)
         stat = Fop(.false.,.true.,m,rd)
         call end_timer(finish,start)
      end if

      done=0
      do 
         if(done.ne.0)call sseek("OUT",0,0)
         nter=min(niter-done,jniter)
         do iter=1,nter
            call start_timer(start)
            stat = Fop( .true.,.false.,g,rd)
            stat = Fop(.false.,.false.,g,gd)
            call end_timer(finish,start)
            call start_timer(startg)
            stat = stepper(.false., m,g, rr,gg)
            call end_timer(finishg,startg)
            write(0,*) "Iterations complete:",done+iter          
         end do
            done=done+nter
            write(0,*) 'Writing iteration :',done
            call to_history("iterations",done,'OUT')
            if(blocks.gt.1.) call srite('OUT',m,size(m)*4)
         if(done.eq.niter) exit
      end do
      if (present( resd)) then
         resd = rd
      end if
      write(0,'(8x,a,f10.2,a)') 'Time spent in linear operator:',finish/60.,' (m)'
      write(0,'(8x,a,f8.2,a)') 'Time spent in gradient calculation:',finishg,' (s)'
    end subroutine solver
!----------------------------------------------------------------
  subroutine end_timer(ftime,stime)
    real::ftime,stime
    call date_and_time(values=time_array)
    ftime = ftime + (-stime+( time_array (5) * 3600 + time_array (6) * 60 &
                  + time_array (7) + 0.001 * time_array (8)))
  end subroutine end_timer
!----------------------------------------------------------------
  subroutine start_timer(time)
    real        ::time
    call date_and_time(values=time_array)
    time = time_array (5) * 3600 + time_array (6) * 60 &
         + time_array (7) + 0.001 * time_array (8)
  end subroutine start_timer
!----------------------------------------------------------------
end module solver_tiny_brad
