program data_ocn
  !****************************************************************
  !--- OCN main for testing
  !****************************************************************

  use mpi

  !--- com_cpl defines: impi, com_mpi_init, nlon_a, nlat_a, nlon_o, nlat_o
  use com_cpl

!xxx  !--- Store and retrieve cccma logical records
!xxx  use com_ccdata

  implicit none

  !--- The mpi communicator assigned to the ocn
  integer(kind=impi) :: ocn_comm

  !--- Integer parameters passed to mpi routines
  integer(kind=impi) :: ierr, rank, nproc, mynode

  !--- misc
  integer :: ix, iy, iz, nwrds, idx, ntime, verbose=1
  integer :: curr_size, curr_tag
  integer(kind=8) :: curr_time
  character(len=32) :: name
  type(cpl_vinfo_t) :: cpl_vinfo

  !--- Buffer and work space used by CCCma io routines
  integer, parameter :: maxx=8392704  !---2049x4096
  real               :: wrk(maxx)
  integer            :: ibuf(8)

  !--- Start MPI
  call mpi_init( ierr )

  !--- Initialize groups for coupler, atm and ocn
  call define_group('ocn', ocn_comm)

  call mpi_comm_rank( ocn_comm, rank, ierr )
  call mpi_comm_size( ocn_comm, nproc, ierr )
  write(6,'(a,4i8)')'data_ocn: ocn_comm, rank, size, ocn_master ',ocn_comm,rank,nproc,ocn_master

  !--- Determine rank in MPI_COMM_WORLD
  call mpi_comm_rank( MPI_COMM_WORLD, mynode, ierr )

  !--- IMPORTANT ---
  !--- ocn_master is the rank in MPI_COMM_WORLD not the rank in ocn_comm
  !--- IMPORTANT ---

  !--- Initialize ibuf and wrk
  ibuf(1:8) = (/ transfer("GRID",ix), 0, 0, 1, nlon_a+1, nlat_a, 1, 1 /)
  wrk(:) = 0.0

  !--- Loop over time
  do ntime=1,2

    curr_time = ntime

    if ( mynode == ocn_master ) then
      !--- Send MSG data to the coupler
      cpl_vinfo = find_cpl_vinfo( name="MSG" )
      curr_size = cpl_vinfo%size
      curr_tag  = cpl_vinfo%tag
      ibuf(1:8) = (/ transfer(" MSG",ix), curr_time, curr_tag, 1, 8, 1, 0, 1 /)
      wrk(1:curr_size) = 0.0
      wrk(1) = 1
      call send_data_rec(wrk, ibuf, cpl_master, curr_size, curr_tag)
    endif

!xxx    if ( mynode == ocn_master ) then
!xxx      !--- Send data to the coupler, but only from the master node
!xxx      do idx=1,n_ocn_to_atm_list
!xxx        name = trim( ocn_to_atm_list(idx)%name )
!xxx        curr_size = ocn_to_atm_list(idx)%size
!xxx        curr_tag  = ocn_to_atm_list(idx)%tag
!xxx
!xxx        !--- Read data at curr_time for the current variable
!xxx        call read_ocn_data( trim(name), curr_time, curr_tag, curr_size, ibuf, wrk )
!xxx
!xxx        !--- Send to coupler
!xxx        if (verbose>1) then
!xxx          write(6,'(3a)')'data_ocn: SEND ',trim(name),' to coupler.'
!xxx          call flush(6)
!xxx        endif
!xxx        call send_data_rec(wrk, ibuf, cpl_master, curr_size, curr_tag)
!xxx      enddo

!xxx#ifdef coupler_ctem
!xxx      call ctem_ocn2cpl()
!xxx#endif

      !--- XSFX_atm is transferred after ctem data so is added here explictly
      cpl_vinfo = find_cpl_vinfo( name="XSFX_atm" )
      curr_size = cpl_vinfo%size
      curr_tag  = cpl_vinfo%tag
      call send_data_rec(wrk, ibuf, atm_master, curr_size, curr_tag)
    endif

!xxx    if ( mynode == ocn_master ) then
!xxx      !--- Receive data from the coupler, but only from the master node
!xxx      do idx=1,n_atm_to_ocn_list
!xxx        name = trim( atm_to_ocn_list(idx)%name )
!xxx        curr_size = atm_to_ocn_list(idx)%size
!xxx        curr_tag  = atm_to_ocn_list(idx)%tag
!xxx
!xxx        !--- Receive from the coupler
!xxx        if (verbose>1) then
!xxx          write(6,'(3a)')'data_ocn: RECV ',trim(name),' from coupler.'
!xxx          call flush(6)
!xxx        endif
!xxx        call recv_data_rec(wrk, ibuf, cpl_master, curr_size, curr_tag)
!xxx      enddo
!xxx    endif

    if ( mynode == ocn_master ) then
      !--- Receive MSG data from the coupler
      cpl_vinfo = find_cpl_vinfo( name="MSG" )
      curr_size = cpl_vinfo%size
      curr_tag  = cpl_vinfo%tag
      call recv_data_rec(wrk, ibuf, cpl_master, curr_size, curr_tag)
    endif

  enddo

  if (verbose>0) then
    write(6,'(a,i4,a)')'data_ocn:  Node ',mynode,' is DONE.'
    call flush(6)
  endif

  !--- Stop MPI
  call mpi_finalize( ierr )

contains

!xxx  subroutine ctem_ocn2cpl()
!xxx    implicit none
!xxx
!xxx    !--- CTEM related dimension sizes
!xxx    integer, parameter :: ictem=9 ! number of CTEM PFTs
!xxx    integer, parameter ::  ignd=3 ! number of SOIL LAYERS
!xxx    integer, parameter ::  ican=4 ! number of CLASS PFTs
!xxx
!xxx    integer :: k,l,m
!xxx
!xxx    integer, save :: ntile=1
!xxx
!xxx    cpl_vinfo = find_cpl_vinfo( name="FCANM_atm" )
!xxx    curr_size = cpl_vinfo%size
!xxx    curr_tag  = cpl_vinfo%tag
!xxx    call read_ocn_data( "FCANM_atm", curr_time, curr_tag, curr_size, ibuf, wrk )
!xxx    do k = 1, ican+1
!xxx      do m = 1, ntile
!xxx        call send_data_rec(wrk, ibuf, cpl_master, curr_size, curr_tag)
!xxx      enddo
!xxx    enddo
!xxx
!xxx    cpl_vinfo = find_cpl_vinfo( name="ZOLN_atm" )
!xxx    curr_size = cpl_vinfo%size
!xxx    curr_tag  = cpl_vinfo%tag
!xxx    call read_ocn_data( "ZOLN_atm", curr_time, curr_tag, curr_size, ibuf, wrk )
!xxx    do k = 1, ican
!xxx      do m = 1, ntile
!xxx        call send_data_rec(wrk, ibuf, cpl_master, curr_size, curr_tag)
!xxx      enddo
!xxx    enddo
!xxx
!xxx    cpl_vinfo = find_cpl_vinfo( name="AIL_atm" )
!xxx    curr_size = cpl_vinfo%size
!xxx    curr_tag  = cpl_vinfo%tag
!xxx    call read_ocn_data( "AIL_atm", curr_time, curr_tag, curr_size, ibuf, wrk )
!xxx    do k = 1, ican
!xxx      do m = 1, ntile
!xxx        call send_data_rec(wrk, ibuf, cpl_master, curr_size, curr_tag)
!xxx      enddo
!xxx    enddo
!xxx
!xxx    cpl_vinfo = find_cpl_vinfo( name="CMASV_atm" )
!xxx    curr_size = cpl_vinfo%size
!xxx    curr_tag  = cpl_vinfo%tag
!xxx    call read_ocn_data( "CMASV_atm", curr_time, curr_tag, curr_size, ibuf, wrk )
!xxx    do k = 1, ican
!xxx      do m = 1, ntile
!xxx        call send_data_rec(wrk, ibuf, cpl_master, curr_size, curr_tag)
!xxx      enddo
!xxx    enddo
!xxx
!xxx    cpl_vinfo = find_cpl_vinfo( name="ALVIS_atm" )
!xxx    curr_size = cpl_vinfo%size
!xxx    curr_tag  = cpl_vinfo%tag
!xxx    call read_ocn_data( "ALVIS_atm", curr_time, curr_tag, curr_size, ibuf, wrk )
!xxx    do k = 1, ican+1
!xxx      do m = 1, ntile
!xxx        call send_data_rec(wrk, ibuf, cpl_master, curr_size, curr_tag)
!xxx      enddo
!xxx    enddo
!xxx
!xxx    cpl_vinfo = find_cpl_vinfo( name="ALNIR_atm" )
!xxx    curr_size = cpl_vinfo%size
!xxx    curr_tag  = cpl_vinfo%tag
!xxx    call read_ocn_data( "ALNIR_atm", curr_time, curr_tag, curr_size, ibuf, wrk )
!xxx    do k = 1, ican+1
!xxx      do m = 1, ntile
!xxx        call send_data_rec(wrk, ibuf, cpl_master, curr_size, curr_tag)
!xxx      enddo
!xxx    enddo
!xxx
!xxx    cpl_vinfo = find_cpl_vinfo( name="CURF_atm" )
!xxx    curr_size = cpl_vinfo%size
!xxx    curr_tag  = cpl_vinfo%tag
!xxx    call read_ocn_data( "CURF_atm", curr_time, curr_tag, curr_size, ibuf, wrk )
!xxx    do k = 1, ictem
!xxx      do m = 1, ntile
!xxx        call send_data_rec(wrk, ibuf, cpl_master, curr_size, curr_tag)
!xxx      enddo
!xxx    enddo
!xxx
!xxx    cpl_vinfo = find_cpl_vinfo( name="AILC_atm" )
!xxx    curr_size = cpl_vinfo%size
!xxx    curr_tag  = cpl_vinfo%tag
!xxx    call read_ocn_data( "AILC_atm", curr_time, curr_tag, curr_size, ibuf, wrk )
!xxx    do k = 1, ictem
!xxx      do m = 1, ntile
!xxx        call send_data_rec(wrk, ibuf, cpl_master, curr_size, curr_tag)
!xxx      enddo
!xxx    enddo
!xxx
!xxx    cpl_vinfo = find_cpl_vinfo( name="SLAI_atm" )
!xxx    curr_size = cpl_vinfo%size
!xxx    curr_tag  = cpl_vinfo%tag
!xxx    call read_ocn_data( "SLAI_atm", curr_time, curr_tag, curr_size, ibuf, wrk )
!xxx    do k = 1, ictem
!xxx      do m = 1, ntile
!xxx        call send_data_rec(wrk, ibuf, cpl_master, curr_size, curr_tag)
!xxx      enddo
!xxx    enddo
!xxx
!xxx    cpl_vinfo = find_cpl_vinfo( name="RMAT_atm" )
!xxx    curr_size = cpl_vinfo%size
!xxx    curr_tag  = cpl_vinfo%tag
!xxx    call read_ocn_data( "RMAT_atm", curr_time, curr_tag, curr_size, ibuf, wrk )
!xxx    do l = 1, ignd
!xxx      do k = 1, ican
!xxx        do m = 1, ntile
!xxx          call send_data_rec(wrk, ibuf, cpl_master, curr_size, curr_tag)
!xxx        enddo
!xxx      enddo
!xxx    enddo
!xxx
!xxx    cpl_vinfo = find_cpl_vinfo( name="RMATCT_atm" )
!xxx    curr_size = cpl_vinfo%size
!xxx    curr_tag  = cpl_vinfo%tag
!xxx    call read_ocn_data( "RMATCT_atm", curr_time, curr_tag, curr_size, ibuf, wrk )
!xxx    do l = 1, ignd
!xxx      do k = 1, ictem
!xxx        do m = 1, ntile
!xxx          call send_data_rec(wrk, ibuf, cpl_master, curr_size, curr_tag)
!xxx        enddo
!xxx      enddo
!xxx    enddo
!xxx
!xxx    cpl_vinfo = find_cpl_vinfo( name="PAIC_atm" )
!xxx    curr_size = cpl_vinfo%size
!xxx    curr_tag  = cpl_vinfo%tag
!xxx    call read_ocn_data( "PAIC_atm", curr_time, curr_tag, curr_size, ibuf, wrk )
!xxx    do k = 1, ican
!xxx      do m = 1, ntile
!xxx        call send_data_rec(wrk, ibuf, cpl_master, curr_size, curr_tag)
!xxx      enddo
!xxx    enddo
!xxx
!xxx    cpl_vinfo = find_cpl_vinfo( name="SLAIC_atm" )
!xxx    curr_size = cpl_vinfo%size
!xxx    curr_tag  = cpl_vinfo%tag
!xxx    call read_ocn_data( "SLAIC_atm", curr_time, curr_tag, curr_size, ibuf, wrk )
!xxx    do k = 1, ican
!xxx      do m = 1, ntile
!xxx        call send_data_rec(wrk, ibuf, cpl_master, curr_size, curr_tag)
!xxx      enddo
!xxx    enddo
!xxx
!xxx  end subroutine ctem_ocn2cpl
!xxx
!xxxend program data_ocn

subroutine read_ocn_data( name, curr_time, curr_tag, curr_size, ibuf, wrk )

  use mpi
  use com_cpl

  implicit none

  integer, parameter :: maxx=8392704  !---2049x4096

  character(len=*), intent(in) :: name
  integer(kind=8), intent(in) :: curr_time
  integer, intent(out) :: ibuf(8)
  real,    intent(out) :: wrk(maxx)
  integer, intent(in) :: curr_size, curr_tag

  !--- local
  integer :: ix, nwrds

  !--- Initialize ibuf and wrk
  ibuf(1:8) = (/ transfer("GRID",ix), curr_time, curr_tag, 1, nlon_a+1, nlat_a, 1, 1 /)
  nwrds = ibuf(5) * ibuf(6)
  wrk(1:nwrds) = (/ (ix, ix=1,nwrds) /)
  wrk(1) = curr_tag

end subroutine read_ocn_data
