!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
module cubecompute_one2one_template
  !----------------------------------------------------------------------
  ! Commands that take one input cube and produce one output cube
  !
  ! Syntax: "COMMAND cubeid"
  !----------------------------------------------------------------------
  use cubetools_parameters
  use cubetools_structure
  use cube_types
  use cubeadm_cubeid_types
  use cubecompute_messaging
  !
  public :: one2one_comm_t,one2one_user_t,one2one_prog_t
  private
  !
  type :: one2one_comm_t
     type(option_t), pointer :: comm
   contains
     procedure, private :: parse   => cubecompute_one2one_parse
     procedure, public  :: command => cubecompute_one2one_command
     procedure, private :: main    => cubecompute_one2one_main
  end type one2one_comm_t
  !
  integer(kind=4), parameter :: icube = 1
  type one2one_user_t
     type(cubeid_user_t)   :: cubeids
   contains
     procedure, private :: toprog => cubecompute_one2one_user_toprog
  end type one2one_user_t
  !
  type one2one_prog_t
     type(cube_t), pointer :: incube
     type(cube_t), pointer :: oucube
   contains
     procedure, public  :: header => cubecompute_one2one_prog_header
     procedure, private :: data   => cubecompute_one2one_prog_data
     procedure, private :: loop   => cubecompute_one2one_prog_loop
  end type one2one_prog_t
  !
contains
  !
  !----------------------------------------------------------------------
  !
  subroutine cubecompute_one2one_parse(one2one,line,user,error)
    use cubetools_parse
    !----------------------------------------------------------------------
    ! COMMAND cubeid
    !----------------------------------------------------------------------
    class(one2one_comm_t), intent(in)    :: one2one
    character(len=*),      intent(in)    :: line
    type(one2one_user_t),  intent(out)   :: user
    logical,               intent(inout) :: error
    !
    character(len=*), parameter :: rname='ONE2ONE>PARSE'
    !
    call cubecompute_message(computeseve%trace,rname,'Welcome')
    !
    call cubeadm_cubeid_parse(line,one2one%comm,user%cubeids,error)
    if (error) return
  end subroutine cubecompute_one2one_parse
  !
  subroutine cubecompute_one2one_command(comm,line,error)
    use cubeadm_timing
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(one2one_comm_t), intent(in)    :: comm
    character(len=*),      intent(in)    :: line
    logical,               intent(inout) :: error
    !
    type(one2one_user_t) :: user
    character(len=*), parameter :: rname='ONE2ONE>MAIN'
    !
    call cubecompute_message(computeseve%trace,rname,'Welcome')
    !
    call comm%parse(line,user,error)
    if (error) return
    call comm%main(user,error)
    if (error) continue
  end subroutine cubecompute_one2one_command
  !
  subroutine cubecompute_one2one_main(comm,user,error)
    use cubeadm_timing
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(one2one_comm_t), intent(in)    :: comm
    type(one2one_user_t),  intent(in)    :: user
    logical,               intent(inout) :: error
    !
    type(one2one_prog_t) :: prog
    character(len=*), parameter :: rname='ONE2ONE>MAIN'
    !
    call cubecompute_message(computeseve%trace,rname,'Welcome')
    !
    call user%toprog(comm,prog,error)
    if (error) return
    call prog%header(error)
    if (error) return
    call cubeadm_timing_prepro2process()
    call prog%data(error)
    if (error) return
    call cubeadm_timing_process2postpro()
  end subroutine cubecompute_one2one_main
  !
  !----------------------------------------------------------------------
  !
  subroutine cubecompute_one2one_user_toprog(user,comm,prog,error)
    use cubeadm_get
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(one2one_user_t), intent(in)    :: user
    type(one2one_comm_t),  intent(in)    :: comm
    type(one2one_prog_t),  intent(out)   :: prog
    logical,               intent(inout) :: error
    !
    character(len=*), parameter :: rname='ONE2ONE>USER>TOPROG'
    !
    call cubecompute_message(computeseve%trace,rname,'Welcome')
    !
    call cubeadm_cubeid_get_header(comm%comm,icube,user%cubeids,&
         code_access_imaset,code_read,prog%incube,error)
    if (error) return
  end subroutine cubecompute_one2one_user_toprog
  !
  !----------------------------------------------------------------------
  !
  subroutine cubecompute_one2one_prog_header(prog,error)
    use cubedag_allflags
    use cubeadm_clone
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(one2one_prog_t), intent(inout) :: prog
    logical,               intent(inout) :: error
    !
    character(len=*), parameter :: rname='ONE2ONE>PROG>HEADER'
    !
    call cubecompute_message(computeseve%trace,rname,'Welcome')
    !
    call cubeadm_clone_header(prog%incube,flag_any,prog%oucube,error)
    if (error) return
  end subroutine cubecompute_one2one_prog_header
  !
  subroutine cubecompute_one2one_prog_data(prog,error)
    use cubeadm_opened
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(one2one_prog_t), intent(inout) :: prog
    logical,               intent(inout) :: error
    !
    type(cubeadm_iterator_t) :: iter
    character(len=*), parameter :: rname='ONE2ONE>PROG>DATA'
    !
    call cubecompute_message(computeseve%trace,rname,'Welcome')
    !
    call cubeadm_datainit_all(iter,error)
    if (error) return
    !
    !$OMP PARALLEL DEFAULT(none) SHARED(prog,error) FIRSTPRIVATE(iter)
    !$OMP SINGLE
    do while (cubeadm_dataiterate_all(iter,error))
       if (error)  exit
       !$OMP TASK SHARED(prog) FIRSTPRIVATE(iter,error)
       if (.not.error) call prog%loop(iter%first,iter%last,error)
       !$OMP END TASK
    enddo ! ie
    !$OMP END SINGLE
    !$OMP END PARALLEL
  end subroutine cubecompute_one2one_prog_data
  !
  subroutine cubecompute_one2one_prog_loop(prog,first,last,error)
    !----------------------------------------------------------------------
    !
    !----------------------------------------------------------------------
    class(one2one_prog_t), intent(inout) :: prog
    integer(kind=entr_k),  intent(in)    :: first
    integer(kind=entr_k),  intent(in)    :: last    
    logical,               intent(inout) :: error
    !
    character(len=*), parameter :: rname='ONE2ONE>PROG>LOOP'
    !
    call cubecompute_message(computeseve%trace,rname,'Welcome')
  end subroutine cubecompute_one2one_prog_loop
end module cubecompute_one2one_template
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
