program WEIdtm_main  
  use sep 
  use mpi_sep 
  use wei_util 
  use wei_par 
  use wei_pro 
  use wei_tag 
  use wei_dtm

  use oc_global_mod 
  use oc_utils_mod 
  use oc_mpi_dottest_mod 

  use weiop_cig 
  use weiop_mwc 
  use weiop_sll 
  use weiop_slo
  use weiop_ssf 
  use weiop_wem 

  implicit none
  character(len=3) :: operation
  integer :: stat 
  integer :: mpierr 
  real    :: ocmaxmem
  integer :: order
  !----------------------------------------------------------------
  call MPI_INIT(mpierr)
  call sep_init()
  !----------------------------------------------------------------
  !! init params for MPI and OMP
  call weipar_init()
  call weipar_report()

  if(wpar%impi==0) then
     call MPI_SEP_SEND_ARGS(wpar%nmpi,1,0)
  else
     call MPI_SEP_RECEIVE_ARGS()
  end if

  !! init tag names on all nodes
  call weitag_init()

  !! init process parameters on the MASTER
  if(wpar%impi==0) call weipro_init()
  !! broadcast parameters from MASTER to NODES
  if(wpar%nmpi >0) call weipro_bcast()

  if(wpar%impi==0) call from_param("operation",operation,'dtm')
  if(wpar%nmpi >0) call MPI_BCAST(operation, 3,MPI_CHARACTER,0,MPI_COMM_WORLD,mpierr) 
  !----------------------------------------------------------------
  if(wpar%impi==0) call from_param("ocmaxmem",ocmaxmem,     0.)
  ocmaxmem = ocmaxmem * 1024*1024
  if(wpar%nmpi >0) call MPI_BCAST(ocmaxmem, 1,MPI_REAL,0,MPI_COMM_WORLD,mpierr)
  !----------------------------------------------------------------
  if(wpar%impi==0) call from_param("order",order,1)
  if(wpar%nmpi >0) call MPI_BCAST(order, 1,MPI_INTEGER,0,MPI_COMM_WORLD,mpierr)
  !----------------------------------------------------------------
  if(wpro%nfk==1) then
     call weidtm_init(SLin=weiop_slo1_init &
     ,                WCin=weiop_mwc1_init &
     ,                FKin=weiop_wem3_init &
     ,                FXin=weiop_ssf3_init )
  else
     call weidtm_init(SLin=weiop_sllN_init &
     ,                WCin=weiop_mwcN_init &
     ,                FKin=weiop_wem3_init &
     ,                FXin=weiop_ssf3_init )
  end if
  !----------------------------------------------------------------
  if(wpar%impi==0) call weipro_report()
  !----------------------------------------------------------------
  !! select an operation
  select case(operation(1:3))
  case('dot')
     if(wpar%impi==0 .and. wpro%verb) call weimessage("start dottest")
     call oc_mpi_dottest_init(wpar%impi,maxmem=nint(ocmaxmem))
     if(wpro%nfk==1) then
        call oc_mpi_dottest(weidtm,wtag%D,wtag%U &
        ,           op1=weiop_slo1 &
        ,           op2=weiop_mwc1 &
        ,           op3=weiop_wem3 &
        ,           op4=weiop_ssf3 )
     else
        call oc_mpi_dottest(weidtm,wtag%D,wtag%U &
        ,           op1=weiop_sllN &
        ,           op2=weiop_mwcN &
        ,           op3=weiop_wem3 &
        ,           op4=weiop_ssf3 )
     end if
     if(wpar%impi==0 .and. wpro%verb) call weimessage("OK")
  case('dtm')
     if(wpar%impi==0 .and. wpro%verb) then
        if(wpro%adj) then
           call weimessage("start adjoint operator")
        else
           call weimessage("start forward operator")
        end if
     end if
     if(wpro%nfk==1) then
        stat = weidtm(wpro%adj,wpro%add,wtag%D,wtag%U &
        ,              SLop=weiop_slo1 &
        ,              WCop=weiop_mwc1 &
        ,              FKop=weiop_wem3 &
        ,              FXop=weiop_ssf3 )
     else
        stat = weidtm(wpro%adj,wpro%add,wtag%D,wtag%U &
        ,              SLop=weiop_sllN &
        ,              WCop=weiop_mwcN &
        ,              FKop=weiop_wem3 &
        ,              FXop=weiop_ssf3 )
     end if
     if(wpar%impi==0 .and. wpro%verb) call weimessage("OK")
  case default
     call seperr('unknown operation')
  end select
  !----------------------------------------------------------------  
  !! shutdown MPI
  call MPI_FINALIZE(mpierr) 
  !----------------------------------------------------------------
  call exit(0)
end program WEIdtm_main
