!=======================================================================
!BOP
!
! !MODULE: ice_read_write
!
! !DESCRIPTION:
!
! Routines for opening, reading and writing external files
!
! !REVISION HISTORY:
! SVN:$Id$
!
! author: Tony Craig, NCAR
!
! 2004: Block structure added by William Lipscomb, LANL
! 2006: Converted to free source form (F90) by Elizabeth Hunke
! 2007: netcdf versions added by Alison McLaren & Ann Keen, Met Office
!
! !INTERFACE:
!
module ice_read_write 16,9
!
! !USES:
!
use ice_kinds_mod
use ice_constants
use ice_communicate
, only: my_task, master_task
use ice_broadcast
use ice_domain_size
use ice_blocks
use ice_fileunits
#ifdef ncdf
use netcdf
#endif
!
!EOP
implicit none
public :: ice_read_global_nc
interface ice_read_global_nc 8
module procedure ice_read_global_nc_dbl
ice_read_global_nc_r4
end interface
!=======================================================================
contains
!=======================================================================
!
!BOP
!
! !IROUTINE: ice_open - opens an unformatted file for reading
!
! !INTERFACE:
!
subroutine ice_open(nu, filename, nbits) 28
!
! !DESCRIPTION:
!
! Opens an unformatted file for reading \\
! nbits indicates whether the file is sequential or direct access
!
! !REVISION HISTORY:
!
! author: Tony Craig, NCAR
!
! !USES:
!
! !INPUT/OUTPUT PARAMETERS:
!
integer (kind=int_kind), intent(in) :: &
nu , & ! unit number
nbits ! no. of bits per variable (0 for sequential access)
character (*) :: filename
!
!EOP
!
if (my_task == master_task) then
if (nbits == 0) then ! sequential access
open(nu,file=filename,form='unformatted')
else ! direct access
open(nu,file=filename,recl=nx_global*ny_global*nbits/8, &
form='unformatted',access='direct')
endif ! nbits = 0
endif ! my_task = master_task
end subroutine ice_open
!=======================================================================
!BOP
!
! !IROUTINE: ice_read - read and scatter an unformatted file
!
! !INTERFACE:
!
subroutine ice_read(nu, nrec, work, atype, diag, & 44,6
field_loc, field_type, &
ignore_eof, hit_eof)
!
! !DESCRIPTION:
!
! Read an unformatted file and scatter to processors\\
! work is a real array, atype indicates the format of the data\\
! If the optional variables field_loc and field_type are present \\
! the ghost cells are filled using values from the global array.\\
! This prevents them from being filled with zeroes in land cells \\
! (subroutine ice_HaloUpdate need not be called).
!
! !REVISION HISTORY:
!
! author: Tony Craig, NCAR
!
! !USES:
!
use ice_domain
use ice_gather_scatter
use ice_work
, only: work_g1, work_gr, work_gi4, work_gi8
!
! !INPUT/OUTPUT PARAMETERS:
!
integer (kind=int_kind), intent(in) :: &
nu , & ! unit number
nrec ! record number (0 for sequential access)
real (kind=dbl_kind), dimension(nx_block,ny_block,max_blocks), &
intent(out) :: &
work ! output array (real, 8-byte)
character (len=4), intent(in) :: &
atype ! format for input array
! (real/integer, 4-byte/8-byte)
logical (kind=log_kind), intent(in) :: &
diag ! if true, write diagnostic output
integer (kind=int_kind), optional, intent(in) :: &
field_loc, & ! location of field on staggered grid
field_type ! type of field (scalar, vector, angle)
logical (kind=log_kind), optional, intent(in) :: ignore_eof
logical (kind=log_kind), optional, intent(out) :: hit_eof
!
!EOP
!
integer (kind=int_kind) :: i, j, ios
real (kind=dbl_kind) :: &
amin, amax ! min and max values of input array
logical (kind=log_kind) :: ignore_eof_use
if (my_task == master_task) then
allocate(work_g1(nx_global,ny_global))
else
allocate(work_g1(1,1)) ! to save memory
endif
if (my_task == master_task) then
!-------------------------------------------------------------------
! Read global array according to format atype
!-------------------------------------------------------------------
if (present(hit_eof)) hit_eof = .false.
if (atype == 'ida4') then
allocate(work_gi4(nx_global,ny_global))
read(nu,rec=nrec) work_gi4
work_g1 = real(work_gi4,kind=dbl_kind)
deallocate(work_gi4)
elseif (atype == 'ida8') then
allocate(work_gi8(nx_global,ny_global))
read(nu,rec=nrec) work_gi8
work_g1 = real(work_gi8,kind=dbl_kind)
deallocate(work_gi8)
elseif (atype == 'rda4') then
allocate(work_gr(nx_global,ny_global))
read(nu,rec=nrec) work_gr
work_g1 = work_gr
deallocate(work_gr)
elseif (atype == 'rda8') then
read(nu,rec=nrec) work_g1
elseif (atype == 'ruf8') then
if (present(ignore_eof)) then
ignore_eof_use = ignore_eof
else
ignore_eof_use = .false.
endif
if (ignore_eof_use) then
! Read line from file, checking for end-of-file
read(nu, iostat=ios) ((work_g1(i,j),i=1,nx_global), &
j=1,ny_global)
if (present(hit_eof)) hit_eof = ios < 0
else
read(nu) ((work_g1(i,j),i=1,nx_global),j=1,ny_global)
endif
else
write(nu_diag,*) ' ERROR: reading unknown atype ',atype
endif
endif ! my_task = master_task
if (present(hit_eof)) then
call broadcast_scalar
(hit_eof,master_task)
if (hit_eof) then
deallocate(work_g1)
return
endif
endif
!-------------------------------------------------------------------
! optional diagnostics
!-------------------------------------------------------------------
if (my_task==master_task .and. diag) then
amin = minval(work_g1)
amax = maxval(work_g1, mask = work_g1 /= spval_dbl)
write(nu_diag,*) ' read_global ',nu, nrec, amin, amax
endif
!-------------------------------------------------------------------
! Scatter data to individual processors.
! NOTE: Ghost cells are not updated unless field_loc is present.
!-------------------------------------------------------------------
if (present(field_loc)) then
call scatter_global
(work, work_g1, master_task, distrb_info, &
field_loc, field_type)
else
call scatter_global
(work, work_g1, master_task, distrb_info, &
field_loc_noupdate, field_type_noupdate)
endif
deallocate(work_g1)
end subroutine ice_read
!=======================================================================
!BOP
!
! !IROUTINE: ice_read_global - read an unformatted file
!
! !INTERFACE:
!
subroutine ice_read_global (nu, nrec, work_g, atype, diag, & 26,2
ignore_eof, hit_eof)
!
! !DESCRIPTION:
!
! Read an unformatted file \\
! Just like ice_read except that it returns a global array \\
! work_g is a real array, atype indicates the format of the data
!
! !REVISION HISTORY:
! Adapted by William Lipscomb, LANL, from ice_read
!
! !USES:
!
use ice_work
, only: work_gr, work_gi4, work_gi8
!
! !INPUT/OUTPUT PARAMETERS:
!
integer (kind=int_kind), intent(in) :: &
nu , & ! unit number
nrec ! record number (0 for sequential access)
real (kind=dbl_kind), dimension(:,:), &
intent(out) :: &
work_g ! output array (real, 8-byte)
character (len=4) :: &
atype ! format for input array
! (real/integer, 4-byte/8-byte)
logical (kind=log_kind) :: &
diag ! if true, write diagnostic output
logical (kind=log_kind), optional, intent(in) :: ignore_eof
logical (kind=log_kind), optional, intent(out) :: hit_eof
!
!EOP
!
integer (kind=int_kind) :: i, j, ios
real (kind=dbl_kind) :: &
amin, amax ! min and max values of input array
logical (kind=log_kind) :: ignore_eof_use
work_g(:,:) = c0
if (my_task == master_task) then
!-------------------------------------------------------------------
! Read global array according to format atype
!-------------------------------------------------------------------
if (present(hit_eof)) hit_eof = .false.
if (atype == 'ida4') then
allocate(work_gi4(nx_global,ny_global))
read(nu,rec=nrec) work_gi4
work_g = real(work_gi4,kind=dbl_kind)
deallocate(work_gi4)
elseif (atype == 'ida8') then
allocate(work_gi8(nx_global,ny_global))
read(nu,rec=nrec) work_gi8
work_g = real(work_gi8,kind=dbl_kind)
deallocate(work_gi8)
elseif (atype == 'rda4') then
allocate(work_gr(nx_global,ny_global))
read(nu,rec=nrec) work_gr
work_g = work_gr
deallocate(work_gr)
elseif (atype == 'rda8') then
read(nu,rec=nrec) work_g
elseif (atype == 'ruf8') then
if (present(ignore_eof)) then
ignore_eof_use = ignore_eof
else
ignore_eof_use = .false.
endif
if (ignore_eof_use) then
! Read line from file, checking for end-of-file
read(nu, iostat=ios) ((work_g(i,j),i=1,nx_global), &
j=1,ny_global)
if (present(hit_eof)) hit_eof = ios < 0
else
read(nu) ((work_g(i,j),i=1,nx_global),j=1,ny_global)
endif
else
write(nu_diag,*) ' ERROR: reading unknown atype ',atype
endif
endif ! my_task = master_task
if (present(hit_eof)) then
call broadcast_scalar
(hit_eof,master_task)
if (hit_eof) return
endif
!-------------------------------------------------------------------
! optional diagnostics
!-------------------------------------------------------------------
if (my_task == master_task .and. diag) then
amin = minval(work_g)
amax = maxval(work_g, mask = work_g /= spval_dbl)
write(nu_diag,*) ' read_global ',nu, nrec, amin, amax
endif
end subroutine ice_read_global
!=======================================================================
!BOP
!
! !IROUTINE: ice_write - writes an unformatted file
!
! !INTERFACE:
!
subroutine ice_write(nu, nrec, work, atype, diag) 43,4
!
! !DESCRIPTION:
!
! Writes an unformatted file \\
! work is a real array, atype indicates the format of the data
!
! !REVISION HISTORY:
!
! author: Tony Craig, NCAR
!
! !USES:
!
use ice_gather_scatter
use ice_domain
use ice_work
, only: work_g1, work_gr, work_gi4, work_gi8
!
! !INPUT/OUTPUT PARAMETERS:
!
integer (kind=int_kind), intent(in) :: &
nu , & ! unit number
nrec ! record number (0 for sequential access)
real (kind=dbl_kind), dimension(nx_block,ny_block,max_blocks), &
intent(in) :: &
work ! input array (real, 8-byte)
character (len=4) :: &
atype ! format for output array
! (real/integer, 4-byte/8-byte)
logical (kind=log_kind) :: &
diag ! if true, write diagnostic output
!
!EOP
!
integer (kind=int_kind) :: i, j
real (kind=dbl_kind) :: &
amin, amax ! min and max values of ouput array
!-------------------------------------------------------------------
! Gather data from individual processors
!-------------------------------------------------------------------
if (my_task == master_task) then
allocate(work_g1(nx_global,ny_global))
else
allocate(work_g1(1,1)) ! to save memory
endif
call gather_global
(work_g1, work, master_task, distrb_info)
if (my_task == master_task) then
!-------------------------------------------------------------------
! Write global array according to format atype
!-------------------------------------------------------------------
if (atype == 'ida4') then
allocate(work_gi4(nx_global,ny_global))
work_gi4 = nint(work_g1)
write(nu,rec=nrec) work_gi4
deallocate(work_gi4)
elseif (atype == 'ida8') then
allocate(work_gi8(nx_global,ny_global))
work_gi8 = nint(work_g1)
write(nu,rec=nrec) work_gi8
deallocate(work_gi8)
elseif (atype == 'rda4') then
allocate(work_gr(nx_global,ny_global))
work_gr = work_g1
write(nu,rec=nrec) work_gr
deallocate(work_gr)
elseif (atype == 'rda8') then
write(nu,rec=nrec) work_g1
elseif (atype == 'ruf8') then
write(nu) ((work_g1(i,j),i=1,nx_global),j=1,ny_global)
else
write(nu_diag,*) ' ERROR: writing unknown atype ',atype
endif
!-------------------------------------------------------------------
! diagnostics
!-------------------------------------------------------------------
if (diag) then
amin = minval(work_g1)
amax = maxval(work_g1, mask = work_g1 /= spval_dbl)
write(nu_diag,*) ' write_global ', nu, nrec, amin, amax
endif
endif ! my_task = master_task
deallocate(work_g1)
end subroutine ice_write
!=======================================================================
!BOP
!
! !IROUTINE: ice_write_nc - writes a field to a netcdf file
!
! !INTERFACE:
!
subroutine ice_write_nc(fid, nrec, varname, work, atype, diag),7
!
! !DESCRIPTION:
!
! Writes a field to a netcdf file \\
! work is a real array, atype indicates the format of the data
!
! !REVISION HISTORY:
!
! author: David A Bailey, NCAR
!
! !USES:
!
use ice_gather_scatter
use ice_domain
use ice_work
, only: work_g1, work_gr, work_gi4, work_gi8
use ice_exit
!
! !INPUT/OUTPUT PARAMETERS:
!
integer (kind=int_kind), intent(in) :: &
fid ,& ! netcdf file id
nrec ! record number
character (len=*), intent(in) :: varname
real (kind=dbl_kind), dimension(nx_block,ny_block,max_blocks), &
intent(in) :: &
work ! input array (real, 8-byte)
character (len=4), intent(in) :: &
atype ! format for output array
! (real/integer, 4-byte/8-byte)
logical (kind=log_kind), intent(in) :: &
diag ! if true, write diagnostic output
!
!EOP
!
integer (kind=int_kind) :: i, j, varid, numDims
integer (kind=int_kind) :: &
status ! status variable from netCDF routine
real (kind=dbl_kind) :: &
amin, amax ! min and max values of ouput array
integer (kind=int_kind), allocatable :: &
start_arr(:), count_arr(:)
!-------------------------------------------------------------------
! Gather data from individual processors
!-------------------------------------------------------------------
if (my_task == master_task) then
allocate(work_g1(nx_global,ny_global))
else
allocate(work_g1(1,1)) ! to save memory
endif
call gather_global
(work_g1, work, master_task, distrb_info)
if (my_task == master_task) then
status = nf90_inq_varid(fid, trim(varname), varid)
if (status /= nf90_noerr) then
call abort_ice
( &
'ice_write_nc: Cannot find variable '//trim(varname) )
endif
status = nf90_inquire_variable(fid, varid, ndims = numDims)
if (status /= nf90_noerr) then
call abort_ice
( &
'ice_write_nc: Cannot find dimensions for '//trim(varname) )
endif
allocate(start_arr(numDims))
allocate(count_arr(numDims))
if (numDims > 2) then
start_arr(1) = 1
start_arr(2) = 1
start_arr(3) = nrec
count_arr(1) = nx_global
count_arr(2) = ny_global
count_arr(3) = 1
else
start_arr(1) = 1
start_arr(2) = 1
count_arr(1) = nx_global
count_arr(2) = ny_global
endif
!-------------------------------------------------------------------
! Write global array according to format atype
!-------------------------------------------------------------------
if (atype == 'ida4') then
allocate(work_gi4(nx_global,ny_global))
work_gi4 = nint(work_g1)
status = nf90_put_var(fid,varid,work_gi4, &
start=start_arr, &
count=count_arr)
deallocate(work_gi4)
elseif (atype == 'ida8') then
allocate(work_gi8(nx_global,ny_global))
work_gi8 = nint(work_g1)
status = nf90_put_var(fid,varid,work_gi8, &
start=start_arr, &
count=count_arr)
deallocate(work_gi8)
elseif (atype == 'rda4') then
allocate(work_gr(nx_global,ny_global))
work_gr = work_g1
status = nf90_put_var(fid,varid,work_gr, &
start=start_arr, &
count=count_arr)
deallocate(work_gr)
elseif (atype == 'rda8') then
status = nf90_put_var(fid,varid,work_g1, &
start=start_arr, &
count=count_arr)
else
write(nu_diag,*) ' ERROR: writing unknown atype ',atype
endif
!-------------------------------------------------------------------
! diagnostics
!-------------------------------------------------------------------
if (diag) then
amin = minval(work_g1)
amax = maxval(work_g1, mask = work_g1 /= spval_dbl)
write(nu_diag,*) ' write_global ', fid, varid, nrec, amin, amax
endif
deallocate(start_arr)
deallocate(count_arr)
endif ! my_task = master_task
deallocate(work_g1)
end subroutine ice_write_nc
!=======================================================================
!
!BOP
!
! !IROUTINE: ice_open_nc - opens a netCDF file for reading
!
! !INTERFACE:
!
subroutine ice_open_nc(filename, fid) 12,2
!
! !DESCRIPTION:
!
! Opens a netCDF file for reading
!
! !REVISION HISTORY:
!
! Adapted by Alison McLaren, Met Office from ice_open
!
! !USES:
use ice_exit
!
! !INPUT/OUTPUT PARAMETERS:
!
character (char_len_long), intent(in) :: &
filename ! netCDF filename
integer (kind=int_kind), intent(out) :: &
fid ! unit number
!
!EOP
!
#ifdef ncdf
integer (kind=int_kind) :: &
status ! status variable from netCDF routine
if (my_task == master_task) then
status = nf90_open(filename, NF90_NOWRITE, fid)
if (status /= nf90_noerr) then
call abort_ice
( &
'ice_open_nc: Cannot open '//trim(filename) )
endif
endif ! my_task = master_task
#else
fid = -999 ! to satisfy intent(out) attribute
#endif
end subroutine ice_open_nc
!=======================================================================
!BOP
!
! !IROUTINE: ice_read_nc - read and scatter one field from a netCDF file
!
! !INTERFACE:
!
subroutine ice_read_nc(fid, nrec, varname, work, diag, & 12,8
field_loc, field_type)
!
! !DESCRIPTION:
!
! Read a netCDF file and scatter to processors\\
! If the optional variables field_loc and field_type are present \\
! the ghost cells are filled using values from the global array.\\
! This prevents them from being filled with zeroes in land cells \\
! (subroutine ice_HaloUpdate need not be called).
!
! !REVISION HISTORY:
!
! Adapted by Alison McLaren, Met Office from ice_read
!
! !USES:
!
use ice_domain
use ice_gather_scatter
#ifdef ORCA_GRID
use ice_work
, only: work_g1, work_g2
#else
use ice_work
, only: work_g1
#endif
use ice_exit
!
! !INPUT/OUTPUT PARAMETERS:
!
integer (kind=int_kind), intent(in) :: &
fid , & ! file id
nrec ! record number
logical (kind=log_kind), intent(in) :: &
diag ! if true, write diagnostic output
character (len=*), intent(in) :: &
varname ! field name in netcdf file
real (kind=dbl_kind), dimension(nx_block,ny_block,max_blocks), &
intent(out) :: &
work ! output array (real, 8-byte)
integer (kind=int_kind), optional, intent(in) :: &
field_loc, & ! location of field on staggered grid
field_type ! type of field (scalar, vector, angle)
!
!EOP
!
#ifdef ncdf
! netCDF file diagnostics:
integer (kind=int_kind) :: &
varid, & ! netcdf id for field
status, & ! status output from netcdf routines
ndim, nvar, & ! sizes of netcdf file
id, & ! dimension index
dimlen ! size of dimension
real (kind=dbl_kind) :: &
amin, amax ! min and max values of input array
character (char_len) :: &
dimname ! dimension name
!
if (my_task == master_task) then
allocate(work_g1(nx_global,ny_global))
else
allocate(work_g1(1,1)) ! to save memory
endif
#ifdef ORCA_GRID
if (my_task == master_task) then
allocate(work_g2(nx_global+2,ny_global+1))
else
allocate(work_g2(1,1)) ! to save memory
endif
#endif
if (my_task == master_task) then
!-------------------------------------------------------------
! Find out ID of required variable
!-------------------------------------------------------------
status = nf90_inq_varid(fid, trim(varname), varid)
if (status /= nf90_noerr) then
call abort_ice
( &
'ice_read_nc: Cannot find variable '//trim(varname) )
endif
!--------------------------------------------------------------
! Read global array
!--------------------------------------------------------------
#ifndef ORCA_GRID
status = nf90_get_var( fid, varid, work_g1, &
start=(/1,1,nrec/), &
count=(/nx_global,ny_global,1/) )
#else
status = nf90_get_var( fid, varid, work_g2, &
start=(/1,1,nrec/), &
count=(/nx_global+2,ny_global+1,1/) )
work_g1=work_g2(2:nx_global+1,1:ny_global)
#endif
endif ! my_task = master_task
!-------------------------------------------------------------------
! optional diagnostics
!-------------------------------------------------------------------
if (my_task==master_task .and. diag) then
! write(nu_diag,*) &
! 'ice_read_nc, fid= ',fid, ', nrec = ',nrec, &
! ', varname = ',trim(varname)
status = nf90_inquire(fid, nDimensions=ndim, nVariables=nvar)
! write(nu_diag,*) 'ndim= ',ndim,', nvar= ',nvar
do id=1,ndim
status = nf90_inquire_dimension(fid,id,name=dimname,len=dimlen)
! write(nu_diag,*) 'Dim name = ',trim(dimname),', size = ',dimlen
enddo
amin = minval(work_g1)
amax = maxval(work_g1, mask = work_g1 /= spval_dbl)
write(nu_diag,*) ' read_global ',fid, varid, nrec, amin, amax
endif
!-------------------------------------------------------------------
! Scatter data to individual processors.
! NOTE: Ghost cells are not updated unless field_loc is present.
!-------------------------------------------------------------------
if (present(field_loc)) then
call scatter_global
(work, work_g1, master_task, distrb_info, &
field_loc, field_type)
else
call scatter_global
(work, work_g1, master_task, distrb_info, &
field_loc_noupdate, field_type_noupdate)
endif
deallocate(work_g1)
#ifdef ORCA_GRID
deallocate(work_g2)
#endif
#else
work = c0 ! to satisfy intent(out) attribute
#endif
end subroutine ice_read_nc
!
!=======================================================================
!BOP
!
! !IROUTINE: ice_read_global_nc - read one field from a netcdf file
!
! !INTERFACE:
!
subroutine ice_read_global_nc_dbl (fid, nrec, varname, work_g, diag) 1,3
!
! !DESCRIPTION:
!
! Read a netcdf file \\
! Just like ice_read_nc except that it returns a global array \\
! work_g is a real array
!
! !REVISION HISTORY:
! Adapted by William Lipscomb, LANL, from ice_read
! Adapted by Ann Keen, Met Office, to read from a netcdf file
!
! !USES:
!
use ice_exit
#ifdef ORCA_GRID
use ice_work
, only: work_g3
#endif
!
! !INPUT/OUTPUT PARAMETERS:
!
integer (kind=int_kind), intent(in) :: &
fid , & ! file id
nrec ! record number
character (len=*), intent(in) :: &
varname ! field name in netcdf file
real (kind=dbl_kind), dimension(:,:), &
intent(out) :: &
work_g ! output array (real, 8-byte)
logical (kind=log_kind) :: &
diag ! if true, write diagnostic output
!
!EOP
!
#ifdef ncdf
! netCDF file diagnostics:
integer (kind=int_kind) :: &
varid, & ! netcdf id for field
status, & ! status output from netcdf routines
ndim, nvar, & ! sizes of netcdf file
id, & ! dimension index
dimlen ! size of dimension
real (kind=dbl_kind) :: &
amin, amax ! min and max values of input array
character (char_len) :: &
dimname ! dimension name
!
#ifdef ORCA_GRID
if (my_task == master_task) then
allocate(work_g3(nx_global+2,ny_global+1))
else
allocate(work_g3(1,1)) ! to save memory
endif
work_g3(:,:) = c0
#endif
work_g(:,:) = c0
if (my_task == master_task) then
!-------------------------------------------------------------
! Find out ID of required variable
!-------------------------------------------------------------
status = nf90_inq_varid(fid, trim(varname), varid)
if (status /= nf90_noerr) then
call abort_ice
( &
'ice_read_global_nc: Cannot find variable '//trim(varname) )
endif
!--------------------------------------------------------------
! Read global array
!--------------------------------------------------------------
#ifndef ORCA_GRID
status = nf90_get_var( fid, varid, work_g, &
start=(/1,1,nrec/), &
count=(/nx_global,ny_global,1/) )
#else
status = nf90_get_var( fid, varid, work_g3, &
start=(/1,1,nrec/), &
count=(/nx_global+2,ny_global+1,1/) )
work_g=work_g3(2:nx_global+1,1:ny_global)
#endif
endif ! my_task = master_task
!-------------------------------------------------------------------
! optional diagnostics
!-------------------------------------------------------------------
if (my_task == master_task .and. diag) then
! write(nu_diag,*) &
! 'ice_read_global_nc, fid= ',fid, ', nrec = ',nrec, &
! ', varname = ',trim(varname)
status = nf90_inquire(fid, nDimensions=ndim, nVariables=nvar)
! write(nu_diag,*) 'ndim= ',ndim,', nvar= ',nvar
do id=1,ndim
status = nf90_inquire_dimension(fid,id,name=dimname,len=dimlen)
! write(nu_diag,*) 'Dim name = ',trim(dimname),', size = ',dimlen
enddo
amin = minval(work_g)
amax = maxval(work_g, mask = work_g /= spval_dbl)
! write(nu_diag,*) 'min and max = ', amin, amax
! write(nu_diag,*) ''
write(nu_diag,*) ' read_global ',fid, varid, nrec, amin, amax
endif
#ifdef ORCA_GRID
deallocate(work_g3)
#endif
#else
work_g = c0 ! to satisfy intent(out) attribute
#endif
end subroutine ice_read_global_nc_dbl
!=======================================================================
!BOP
!
! !IROUTINE: ice_read_global_nc - read one field from a netcdf file
!
! !INTERFACE:
!
subroutine ice_read_global_nc_r4 (fid, nrec, varname, work_g, diag),3
!
! !DESCRIPTION:
!
! Read a netcdf file \\
! Just like ice_read_nc except that it returns a global array \\
! work_g is a real array
!
! !REVISION HISTORY:
! Adapted by William Lipscomb, LANL, from ice_read
! Adapted by Ann Keen, Met Office, to read from a netcdf file
!
! !USES:
!
use ice_exit
#ifdef ORCA_GRID
use ice_work
, only: work_g3
#endif
!
! !INPUT/OUTPUT PARAMETERS:
!
integer (kind=int_kind), intent(in) :: &
fid , & ! file id
nrec ! record number
character (len=*), intent(in) :: &
varname ! field name in netcdf file
real (kind=real_kind), dimension(:,:), &
intent(out) :: &
work_g ! output array (real, 8-byte)
logical (kind=log_kind) :: &
diag ! if true, write diagnostic output
!
!EOP
!
#ifdef ncdf
! netCDF file diagnostics:
integer (kind=int_kind) :: &
varid, & ! netcdf id for field
status, & ! status output from netcdf routines
ndim, nvar, & ! sizes of netcdf file
id, & ! dimension index
dimlen ! size of dimension
real (kind=dbl_kind) :: &
amin, amax ! min and max values of input array
character (char_len) :: &
dimname ! dimension name
!
#ifdef ORCA_GRID
if (my_task == master_task) then
allocate(work_g3(nx_global+2,ny_global+1))
else
allocate(work_g3(1,1)) ! to save memory
endif
work_g3(:,:) = c0
#endif
work_g(:,:) = c0
if (my_task == master_task) then
!-------------------------------------------------------------
! Find out ID of required variable
!-------------------------------------------------------------
status = nf90_inq_varid(fid, trim(varname), varid)
if (status /= nf90_noerr) then
call abort_ice
( &
'ice_read_global_nc: Cannot find variable '//trim(varname) )
endif
!--------------------------------------------------------------
! Read global array
!--------------------------------------------------------------
#ifndef ORCA_GRID
status = nf90_get_var( fid, varid, work_g, &
start=(/1,1,nrec/), &
count=(/nx_global,ny_global,1/) )
#else
status = nf90_get_var( fid, varid, work_g3, &
start=(/1,1,nrec/), &
count=(/nx_global+2,ny_global+1,1/) )
work_g=work_g3(2:nx_global+1,1:ny_global)
#endif
endif ! my_task = master_task
!-------------------------------------------------------------------
! optional diagnostics
!-------------------------------------------------------------------
if (my_task == master_task .and. diag) then
! write(nu_diag,*) &
! 'ice_read_global_nc, fid= ',fid, ', nrec = ',nrec, &
! ', varname = ',trim(varname)
status = nf90_inquire(fid, nDimensions=ndim, nVariables=nvar)
! write(nu_diag,*) 'ndim= ',ndim,', nvar= ',nvar
do id=1,ndim
status = nf90_inquire_dimension(fid,id,name=dimname,len=dimlen)
! write(nu_diag,*) 'Dim name = ',trim(dimname),', size = ',dimlen
enddo
amin = minval(work_g)
amax = maxval(work_g, mask = work_g /= spval_dbl)
! write(nu_diag,*) 'min and max = ', amin, amax
! write(nu_diag,*) ''
write(nu_diag,*) ' read_global ',fid, varid, nrec, amin, amax
endif
#ifdef ORCA_GRID
deallocate(work_g3)
#endif
#else
work_g = c0 ! to satisfy intent(out) attribute
#endif
end subroutine ice_read_global_nc_r4
!=======================================================================
!BOP
!
! !IROUTINE: ice_close_nc - closes a netCDF file
!
! !INTERFACE:
!
subroutine ice_close_nc(fid) 11
!
! !DESCRIPTION:
!
! Closes a netCDF file
!
! !REVISION HISTORY:
!
! author: Alison McLaren, Met Office
!
! !USES:
!
! !INPUT/OUTPUT PARAMETERS:
!
integer (kind=int_kind), intent(in) :: &
fid ! unit number
!
!EOP
!
#ifdef ncdf
integer (kind=int_kind) :: &
status ! status variable from netCDF routine
if (my_task == master_task) then
status = nf90_close(fid)
endif
#endif
end subroutine ice_close_nc
!=======================================================================
end module ice_read_write
!=======================================================================