subroutine clone_chunk(in,ou,doheader,error)
  use mrtcal_interfaces, except_this=>clone_chunk
  use mrtcal_calib_types
  !---------------------------------------------------------------------
  ! @ private
  !  Clone a chunk structure.
  !
  !  Nothing is done for the data and headers (not copied, not
  ! initialized e.g. to 0).
  !---------------------------------------------------------------------
  type(chunk_t), intent(in)    :: in        !
  type(chunk_t), intent(inout) :: ou        !
  logical,       intent(in)    :: doheader  ! Also clone the headers?
  logical,       intent(inout) :: error     !
  !
  call reallocate_chunk(in%ndata,ou,error)
  if (error)  return
  !
  if (doheader) then
    call mrtcal_chunk_copy_header(in,ou,error)
    if (error)  return
  endif
  !
end subroutine clone_chunk
!
subroutine clone_chunkset(in,ou,doheader,error)
  use mrtcal_interfaces, except_this=>clone_chunkset
  use mrtcal_calib_types
  !---------------------------------------------------------------------
  ! @ private
  !  Clone a chunkset structure.
  !
  !  The chunks in the chunkset are ALLOCATED so that the full structure
  ! clones exactly the input one.
  !  Nothing is done for the data and headers (not copied, not
  ! initialized e.g. to 0).
  !---------------------------------------------------------------------
  type(chunkset_t), intent(in)    :: in        !
  type(chunkset_t), intent(inout) :: ou        !
  logical,          intent(in)    :: doheader  ! Also clone the headers?
  logical,          intent(inout) :: error     !
  ! Local
  integer(kind=4) :: ichunk
  !
  call reallocate_chunkset(in%n,ou,error)
  if (error) return
  !
  do ichunk=1,in%n
    call clone_chunk(in%chunks(ichunk),ou%chunks(ichunk),doheader,error)
    if (error) return
  enddo
  !
end subroutine clone_chunkset
!
subroutine clone_chunkset_2d_from_2d(in2d,ou2d,doheader,error)
  use mrtcal_interfaces, except_this=>clone_chunkset_2d_from_2d
  use mrtcal_calib_types
  !---------------------------------------------------------------------
  ! @ private-generic clone_chunkset_2d
  !  Clone a chunkset_2d structure.
  !
  !  The chunksets and chunks in the chunksets are ALLOCATED so that
  ! the full structure clones exactly in2d(:,:).
  !  Nothing is done for the data and headers (not copied, not
  ! initialized e.g. to 0).
  !---------------------------------------------------------------------
  type(chunkset_2d_t), intent(in)    :: in2d
  type(chunkset_2d_t), intent(inout) :: ou2d
  logical,             intent(in)    :: doheader  ! Also clone the headers?
  logical,             intent(inout) :: error
  ! Local
  integer(kind=4) :: iset,ipix
  !
  call reallocate_chunkset_2d(in2d%nset,in2d%npix,ou2d,error)
  if (error)  return
  !
  do ipix=1,in2d%npix
    do iset=1,in2d%nset
      call clone_chunkset(in2d%chunkset(iset,ipix),  &
                          ou2d%chunkset(iset,ipix),  &
                          doheader,error)
      if (error)  return
    enddo ! iset
  enddo ! ipix
  !
  if (doheader) then
    ! NB: npix and nset are copied at reallocation time, so that the
    !     structure remains consistent
    ou2d%mjd  = in2d%mjd
    ou2d%corr = in2d%corr
    ou2d%isub = in2d%isub
  endif
  !
end subroutine clone_chunkset_2d_from_2d
!
subroutine clone_chunkset_2d_from_3d(in3d,ou2d,doheader,error)
  use mrtcal_interfaces, except_this=>clone_chunkset_2d_from_3d
  use mrtcal_calib_types
  !---------------------------------------------------------------------
  ! @ private-generic clone_chunkset_2d
  !  Clone a chunkset_2d structure.
  !
  !  The chunksets and chunks in the chunksets are ALLOCATED so that
  ! the full structure clones exactly in3d(:,:,itime=1).
  !  Nothing is done for the data and headers (not copied, not
  ! initialized e.g. to 0).
  !---------------------------------------------------------------------
  type(chunkset_3d_t), intent(in)    :: in3d
  type(chunkset_2d_t), intent(inout) :: ou2d
  logical,             intent(in)    :: doheader  ! Also clone the headers?
  logical,             intent(inout) :: error
  ! Local
  type(chunkset_2d_t) :: in2d
  !
  ! Create a chunkset_2d_t pointer to 1st time dump (marginal cost), and
  ! build the output chunkset_2d from that pointer
  call reassociate_chunkset_2d(1,in3d,in2d,error)
  if (error)  return
  !
  call clone_chunkset_2d_from_2d(in2d,ou2d,doheader,error)
  if (error)  return
  !
end subroutine clone_chunkset_2d_from_3d
!
subroutine clone_chunkset_3d_from_3d(in3d,ou3d,doheader,error)
  use mrtcal_interfaces, except_this=>clone_chunkset_3d_from_3d
  use mrtcal_calib_types
  !---------------------------------------------------------------------
  ! @ private-generic clone_chunkset_3d
  !  Clone a chunkset_3d structure.
  !---------------------------------------------------------------------
  type(chunkset_3d_t), intent(in)    :: in3d
  type(chunkset_3d_t), intent(inout) :: ou3d
  logical,             intent(in)    :: doheader  ! Also clone the headers?
  logical,             intent(inout) :: error
  ! Local
  integer(kind=4) :: iset,ipix,itime
  !
  call reallocate_chunkset_3d(in3d%nset,in3d%npix,in3d%ntime,ou3d,error)
  if (error)  return
  !
  do itime=1,in3d%ntime
    do ipix=1,in3d%npix
      do iset=1,in3d%nset
        call clone_chunkset(in3d%chunkset(iset,ipix,itime),  &
                            ou3d%chunkset(iset,ipix,itime),  &
                            doheader,error)
        if (error)  return
      enddo ! iset
    enddo ! ipix
  enddo ! itime
  !
  if (doheader) then
    ! NB: ntime, npix and nset are copied at reallocation time, so that
    !     the structure remains consistent
    ou3d%kind = in3d%kind  ! ZZZ Unclear if this is generic
    ou3d%mjd  = in3d%mjd
    ou3d%corr = in3d%corr
    ou3d%isub = in3d%isub
  endif
  !
end subroutine clone_chunkset_3d_from_3d
!
subroutine clone_chunkset_3d_from_2d(in2d,ntime,ou3d,doheader,error)
  use mrtcal_interfaces, except_this=>clone_chunkset_3d_from_2d
  use mrtcal_calib_types
  !---------------------------------------------------------------------
  ! @ private-generic clone_chunkset_3d
  !  Create a chunkset_3d by cloning a chunkset_2d structure + extra
  ! "time" dimension.
  !---------------------------------------------------------------------
  type(chunkset_2d_t), intent(in)    :: in2d      !
  integer(kind=4),     intent(in)    :: ntime     ! Time dimension to be added
  type(chunkset_3d_t), intent(inout) :: ou3d      !
  logical,             intent(in)    :: doheader  ! Also clone the headers?
  logical,             intent(inout) :: error     !
  ! Local
  integer(kind=4) :: iset,ipix,itime
  !
  call reallocate_chunkset_3d(in2d%nset,in2d%npix,ntime,ou3d,error)
  if (error)  return
  !
  do itime=1,ntime
    do ipix=1,in2d%npix
      do iset=1,in2d%nset
        call clone_chunkset(in2d%chunkset(iset,ipix),        &
                            ou3d%chunkset(iset,ipix,itime),  &
                            doheader,error)
        if (error)  return
      enddo ! iset
    enddo ! ipix
  enddo ! itime
  !
  if (doheader) then
    ou3d%mjd  = in2d%mjd
    ou3d%corr = in2d%corr
    ou3d%isub = in2d%isub
  endif
  !
end subroutine clone_chunkset_3d_from_2d
