module helicon_mod  
! Convolution, inverse to deconvolution.
! Requires the filter be causal with an implicit "1." at the onset.
  use adj_mod
  use helix_mod
  use regrid_mod
  use createhelix_mod
  use cartesian_mod
  implicit none
  type( filter), private :: aa 
  contains
  subroutine helicon_init ( aa_in )
    type( filter)    :: aa_in
    aa = aa_in
  end subroutine
  function helicon_lop ( adj, add, xx, yy,opt) result(stat)
    integer            :: stat 
    logical,intent(in) :: adj,add 
    real,dimension(:)  :: xx,yy 
    logical              :: opt
    optional             :: opt
    call adjnull (adj,add,xx,yy )
    if(present(opt))then
    call helicon_lop2(adj,add,xx,yy,opt)
    else
    call helicon_lop2(adj,add,xx,yy)
    endif
    stat=0
  end function 
  subroutine helicon_lop2(adj,add,xx,yy,opt)
    logical,intent(in) :: adj,add 
    real, dimension (:)  :: xx 
    real, dimension (:)  :: yy 
    logical              :: opt
    optional             :: opt
    integer iy, ix, ia
    if ( adj) then  !zero lag
      xx =xx + yy
    else
      yy =yy + xx
    end if

    if(present(opt))then
    endif
    do ia = 1, size( aa%lag)
        do iy = 1  + aa%lag( ia), size( yy)
                if ( associated( aa%mis)) then; if ( aa%mis( iy)) cycle; end if; 
                ix = iy - aa%lag( ia)
                if ( adj) then
                        xx(ix)=xx(ix)+yy(iy)*aa%flt(ia)
                else
                        yy(iy)=yy(iy)+xx(ix)*aa%flt(ia)
                end if
        end do
    end do
  end subroutine 
  subroutine helicon_close()
  end subroutine 

        subroutine boundn1 ( nold, nd, na, aa)
                integer, dimension( :), intent( in) :: nold, nd, na     ! (ndim)
                type( filter)                       :: aa
                integer, dimension( size( nd))      :: nb, ii
                real,    dimension( :), allocatable :: xx, yy
                integer                             :: iy, my, ib, mb, stat
                        nb = nd + 2*na
                        mb = product( nb)                               ! nb is a bigger space to pad into.
                        allocate( xx( mb), yy( mb))                     ! two large spaces, equal size
                        xx = 0.                                         ! zeros
                        do ib = 1, mb                                   ! surround the zeros with many ones
                                call line2cart1( nb, ib, ii)             ! ii( ib)
                                if ( any( ii <= na  .or.  ii > nb-na)) xx( ib) = 1. 
                        end do 
                        call helicon_init( aa)                          ! give aa pointer to helicon.lop
                        call regridn( nold, nb, aa)
                        aa%flt = 1.                                     ! put all 1's in filter
                        stat = helicon_lop( .false., .false., xx, yy)   ! apply filter
                        call regridn(   nb, nd, aa)
                        aa%flt = 0.                                     ! remake filter for orig data.
                        my = product( nd)
                        allocate( aa%mis( my))                          ! attach missing designation to y_filter
                        do iy = 1, my                                   ! map from unpadded to padded space
                                call line2cart1( nd, iy, ii )
                                call cart2line1( nb,     ii+na, ib )     ! ib( iy)
                                aa%mis( iy) = ( yy( ib) > 0.)           ! true where inputs missing
                        end do 
                deallocate( xx, yy)
        end subroutine 
!#####################################################  conv or deconv
  end module
