!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
module passive_tracer_tools 5,13
!BOP
! !MODULE: passive_tracer_tools
! !DESCRIPTION:
! This module provides support for passive tracers.
! Subroutines in this module can be called by individual tracer modules.
! !REVISION HISTORY:
! SVN:$Id:$
! !USES:
use kinds_mod
use constants
, only: c0, c1, char_blank, blank_fmt
use domain_size, only: nx_global, ny_global
use domain
, only: nblocks_clinic
use exit_mod
, only: sigAbort, exit_POP
use communicate
, only: my_task, master_task
use constants
, only: char_blank, field_loc_center, field_type_scalar
use prognostic
, only: tracer_field
use io_tools
, only: document
use io
, only: data_set
use io_types
, only: datafile, io_dim, io_field_desc, rec_type_dbl, &
construct_file, construct_io_dim, construct_io_field, &
destroy_file, destroy_io_field, stdout
use prognostic
, only: curtime, oldtime
implicit none
private
save
! !PUBLIC TYPES:
type, public :: ind_name_pair
integer(int_kind) :: ind
character(char_len) :: name
end type
!-----------------------------------------------------------------------
! derived type for reading tracers from a file
!-----------------------------------------------------------------------
type, public :: tracer_read
character(char_len) :: mod_varname, filename, file_varname, file_fmt
real(r8) :: scale_factor, default_val
end type
!-----------------------------------------------------------------------
! monthly forcing variables
!-----------------------------------------------------------------------
type, public :: forcing_monthly_every_ts
type(tracer_read) :: input
logical(log_kind) :: has_data
real(r8), dimension(:,:,:,:,:), pointer :: DATA
character(char_len) :: &
interp_type, & ! = 'linear'
data_type, & ! = 'monthly-calendar'
interp_freq, & ! = 'every-timestep'
filename, & ! = 'not-used-for-monthly'
data_label ! = 'not-used-for-monthly'
real(r8), dimension(12) :: &
data_time ! times where DATA is given
real(r8), dimension(20) :: &
data_renorm ! not used for monthly
real(r8) :: &
data_inc, & ! not used for monthly data
data_next, & ! time that will be used for the next
! value of forcing data that is needed
data_update, & ! time when the a new forcing value
! needs to be added to interpolation set
interp_inc, & ! not used for 'every-timestep' interp
interp_next, & ! not used for 'every-timestep' interp
interp_last ! not used for 'every-timestep' interp
integer(int_kind) :: &
data_time_min_loc ! index of the third dimension of data_time
! containing the minimum forcing time
end type forcing_monthly_every_ts
! !PUBLIC MEMBER FUNCTIONS:
public :: &
init_forcing_monthly_every_ts, &
file_read_tracer_block, &
rest_read_tracer_block, &
read_field
!EOP
!BOC
interface read_field 21
module procedure read_field_2D
read_field_3D
end interface
!EOC
!***********************************************************************
contains
!***********************************************************************
!BOP
! !IROUTINE: init_forcing_monthly_every_ts(var)
! !INTERFACE:
subroutine init_forcing_monthly_every_ts(var) 13
! !DESCRIPTION:
! initialize fields of a variable of type forcing_monthly_every_ts
!
! !REVISION HISTORY:
! same as module
! !OUTPUT PARAMETERS:
type(forcing_monthly_every_ts), intent(out) :: var
!EOP
!BOC
!-----------------------------------------------------------------------
var%interp_type = 'linear'
var%data_type = 'monthly-calendar'
var%interp_freq = 'every-timestep'
var%filename = 'not-used-for-monthly'
var%data_label = 'not-used-for-monthly'
!-----------------------------------------------------------------------
!EOC
end subroutine init_forcing_monthly_every_ts
!***********************************************************************
!BOP
! !IROUTINE: name2ind
! !INTERFACE:
function name_to_ind(name, ind_name_table) 1
! !DESCRIPTION:
! translate string into a tracer index
!
! !REVISION HISTORY:
! same as module
! !INPUT PARAMETERS:
character(char_len), intent(in) :: name
type(ind_name_pair), dimension(:), intent(in) :: ind_name_table
! !OUTPUT PARAMETERS:
integer(int_kind) :: name_to_ind
!EOP
!BOC
!-----------------------------------------------------------------------
! local variables
!-----------------------------------------------------------------------
integer(int_kind) :: i
!-----------------------------------------------------------------------
do i = 1,size(ind_name_table)
if (trim(name) == trim(ind_name_table(i)%name)) then
name_to_ind = ind_name_table(i)%ind
return
end if
end do
name_to_ind = 0
!-----------------------------------------------------------------------
!EOC
end function name_to_ind
!***********************************************************************
!BOP
! !IROUTINE: rest_read_tracer_block
! !INTERFACE:
subroutine rest_read_tracer_block(fmt, filename, tracer_d_module, & 4,3
TRACER_MODULE)
! !DESCRIPTION:
! read from a restart file all tracers for a tracer module
!
! !REVISION HISTORY:
! same as module
! !INPUT PARAMETERS:
character (*), intent(in) :: &
fmt, & ! format (bin or nc)
filename ! file name for restart file
type (tracer_field), dimension(:), intent(in) :: &
tracer_d_module ! descriptors for each tracer
! !INPUT/OUTPUT PARAMETERS:
real(r8), dimension(:,:,:,:,:,:), intent(inout) :: &
TRACER_MODULE ! tracers to be read in
!EOP
!BOC
!-----------------------------------------------------------------------
! local variables
!-----------------------------------------------------------------------
character(*), parameter :: &
subname = 'passive_tracer_tools:rest_read_tracer_block'
integer (int_kind) :: &
n ! tracer index
character (char_len) :: &
fieldname ! tracer name temporaries
!-----------------------------------------------------------------------
call document
(subname, 'reading tracer block from ' /&
&/ trim(filename))
do n=1,size(tracer_d_module)
fieldname = char_blank
fieldname = trim(tracer_d_module(n)%short_name) /&
&/ '_CUR'
call read_field
(fmt, filename, fieldname, TRACER_MODULE(:,:,:,n,curtime,:))
fieldname = char_blank
fieldname = trim(tracer_d_module(n)%short_name) /&
&/ '_OLD'
call read_field
(fmt, filename, fieldname, TRACER_MODULE(:,:,:,n,oldtime,:))
end do
!-----------------------------------------------------------------------
!EOC
end subroutine rest_read_tracer_block
!***********************************************************************
!BOP
! !IROUTINE: file_read_tracer_block
! !INTERFACE:
subroutine file_read_tracer_block(init_filename_fmt, init_filename, & 4,6
tracer_d_module, ind_name_table, tracer_init_ext, TRACER_MODULE)
! !DESCRIPTION:
! read from a file all tracers for a tracer module
!
! !REVISION HISTORY:
! same as module
! !INPUT PARAMETERS:
character (*), intent(in) :: &
init_filename_fmt, & ! format (bin or nc)
init_filename ! default filename
type (tracer_field), dimension(:), intent(in) :: &
tracer_d_module ! descriptors for each tracer
type(tracer_read), dimension(:), intent(in) :: &
tracer_init_ext ! namelist variable for initializing tracers
type(ind_name_pair), dimension(:) :: &
ind_name_table
! !INPUT/OUTPUT PARAMETERS:
real(r8), dimension(:,:,:,:,:,:), intent(inout) :: &
TRACER_MODULE ! tracers to be read in
!EOP
!BOC
!-----------------------------------------------------------------------
! local variables
!-----------------------------------------------------------------------
character(*), parameter :: &
subname = 'passive_tracer_tools:file_read_tracer_block'
integer (int_kind) :: &
tracer_cnt, & ! number of tracers in module
ind, & ! tracer index for tracer name from namelist
iblock, & ! index for looping over blocks
n ! tracer index
type(tracer_read), dimension(:), allocatable :: &
tracer_init_int ! namelist variable for initializing tracers
type (datafile) :: &
in_file ! data file type for init ts file
!-----------------------------------------------------------------------
tracer_cnt = size(tracer_d_module)
!-----------------------------------------------------------------------
! initialize internal tracer_init array
!-----------------------------------------------------------------------
allocate(tracer_init_int(tracer_cnt))
do n = 1,tracer_cnt
tracer_init_int(n)%mod_varname = tracer_d_module(n)%short_name
tracer_init_int(n)%filename = init_filename
tracer_init_int(n)%file_varname = tracer_d_module(n)%short_name
tracer_init_int(n)%scale_factor = c1
tracer_init_int(n)%default_val = c0
tracer_init_int(n)%file_fmt = init_filename_fmt
end do
!-----------------------------------------------------------------------
! copy non-default values from external tracer_init array
!-----------------------------------------------------------------------
do n = 1,tracer_cnt
if (trim(tracer_init_ext(n)%mod_varname) /= 'unknown') then
ind = name_to_ind
(tracer_init_ext(n)%mod_varname, ind_name_table)
if (ind == 0) then
call document
(subname, 'unknown external varname = ', &
trim(tracer_init_ext(n)%mod_varname))
call exit_POP
(sigAbort, 'stopping in ' /&
&/ subname)
end if
if (trim(tracer_init_ext(n)%filename) /= 'unknown') &
tracer_init_int(ind)%filename = &
tracer_init_ext(n)%filename
if (trim(tracer_init_ext(n)%file_varname) /= 'unknown') &
tracer_init_int(ind)%file_varname = &
tracer_init_ext(n)%file_varname
if (tracer_init_ext(n)%scale_factor /= c1) &
tracer_init_int(ind)%scale_factor = &
tracer_init_ext(n)%scale_factor
if (tracer_init_ext(n)%default_val /= c1) &
tracer_init_int(ind)%default_val = &
tracer_init_ext(n)%default_val
end if
end do
!-----------------------------------------------------------------------
! process internal tracer_init array
!-----------------------------------------------------------------------
do n = 1,tracer_cnt
if (trim(tracer_init_int(n)%filename) == 'none' .or. &
trim(tracer_init_int(n)%filename) == 'unknown') then
call document
(subname, 'initializing ' /&
&/ trim(tracer_init_int(n)%mod_varname) /&
&/ ' to default_val')
do iblock = 1,nblocks_clinic
TRACER_MODULE(:,:,:,n,curtime,iblock) = &
tracer_init_int(n)%default_val
enddo
else
call document
(subname, 'initializing ' /&
&/ trim(tracer_init_int(n)%mod_varname) /&
&/ ' with ' /&
&/ trim(tracer_init_int(n)%file_varname) /&
&/ ' from ' /&
&/ trim(tracer_init_int(n)%filename))
call read_field
(tracer_init_int(n)%file_fmt, &
tracer_init_int(n)%filename, &
tracer_init_int(n)%file_varname, &
TRACER_MODULE(:,:,:,n,curtime,:))
do iblock=1,nblocks_clinic
TRACER_MODULE(:,:,:,n,curtime,iblock) = &
TRACER_MODULE(:,:,:,n,curtime,iblock)*tracer_init_int(n)%scale_factor
where (TRACER_MODULE(:,:,:,n,curtime,iblock) < c0) &
TRACER_MODULE(:,:,:,n,curtime,iblock) = c0
end do
if (my_task == master_task) then
write(stdout,blank_fmt)
write(stdout,'(a12,a)') ' file read: ', &
trim(tracer_init_int(n)%filename)
endif
end if
do iblock=1,nblocks_clinic
TRACER_MODULE(:,:,:,n,oldtime,iblock) = &
TRACER_MODULE(:,:,:,n,curtime,iblock)
enddo
end do
deallocate(tracer_init_int)
!-----------------------------------------------------------------------
!EOC
end subroutine file_read_tracer_block
!***********************************************************************
!BOP
! !IROUTINE: read_field_2D
! !INTERFACE:
subroutine read_field_2D(fmt, filename, fieldname, FIELD, record_length) 1,11
! !DESCRIPTION:
! read 2D field from a file
! Assumes the field is (nx_global,ny_global), cell centered, and scalar.
! For binary files, the default external precision is double precision.
! This can be overridden by passing the desired precision into record_length.
!
! !REVISION HISTORY:
! same as module
! !INPUT PARAMETERS:
character (*), intent(in) :: &
fmt, & ! format (bin or nc)
filename, & ! file to read from
fieldname ! field to be read
integer(int_kind), intent(in), optional :: &
record_length ! record length type for binary files
! !INPUT/OUTPUT PARAMETERS:
real(r8), dimension(:,:,:), intent(inout), target :: &
FIELD ! field to be read in
!EOP
!BOC
!-----------------------------------------------------------------------
! local variables
!-----------------------------------------------------------------------
character(*), parameter :: &
subname = 'passive_tracer_tools:read_field_2D'
integer(int_kind) :: &
record_length_loc ! record length type for binary files
type (io_field_desc) :: &
FIELD_DESC ! IO field descriptors for FIELD
type (datafile) :: &
restart_file ! io file descriptor
type (io_dim) :: &
i_dim, j_dim ! dimension descriptors
!-----------------------------------------------------------------------
call document
(subname, 'reading ' /&
&/ trim(fieldname) /&
&/ ' from ' /&
&/ trim(filename))
if (present(record_length)) then
record_length_loc = record_length
else
record_length_loc = rec_type_dbl
endif
restart_file = &
construct_file
(fmt, &
full_name=trim(filename), &
record_length=record_length_loc, &
recl_words=nx_global*ny_global)
call data_set
(restart_file, 'open_read')
i_dim = construct_io_dim
('i', nx_global)
j_dim = construct_io_dim
('j', ny_global)
FIELD_DESC = &
construct_io_field
(trim(fieldname), &
dim1=i_dim, &
dim2=j_dim, &
d2d_array = FIELD)
call data_set
(restart_file, 'define', FIELD_DESC)
call data_set
(restart_file, 'read', FIELD_DESC)
call destroy_io_field
(FIELD_DESC)
call data_set
(restart_file, 'close')
call destroy_file
(restart_file)
!-----------------------------------------------------------------------
!EOC
end subroutine read_field_2D
!***********************************************************************
!BOP
! !IROUTINE: read_field_3D
! !INTERFACE:
subroutine read_field_3D(fmt, filename, fieldname, FIELD, record_length),12
! !DESCRIPTION:
! read 3D field from a file
! Assumes the field is (nx_global,ny_global), cell centered, and scalar.
! The length of the 3rd dimension is determined by the dimension of FIELD.
! For binary files, the default external precision is double precision.
! This can be overridden by passing the desired precision into record_length.
!
! !REVISION HISTORY:
! same as module
! !INPUT PARAMETERS:
character (*), intent(in) :: &
fmt, & ! format (bin or nc)
filename, & ! file to read from
fieldname ! field to be read
integer(int_kind), intent(in), optional :: &
record_length ! record length type for binary files
! !INPUT/OUTPUT PARAMETERS:
real(r8), dimension(:,:,:,:), intent(inout), target :: &
FIELD ! field to be read in
!EOP
!BOC
!-----------------------------------------------------------------------
! local variables
!-----------------------------------------------------------------------
character(*), parameter :: &
subname = 'passive_tracer_tools:read_field_3D'
integer(int_kind) :: &
record_length_loc ! record length type for binary files
type (io_field_desc) :: &
FIELD_DESC ! IO field descriptors for FIELD
type (datafile) :: &
restart_file ! io file descriptor
type (io_dim) :: &
i_dim, j_dim, k_dim ! dimension descriptors
!-----------------------------------------------------------------------
call document
(subname, 'reading ' /&
&/ trim(fieldname) /&
&/ ' from ' /&
&/ trim(filename))
if (present(record_length)) then
record_length_loc = record_length
else
record_length_loc = rec_type_dbl
endif
restart_file = &
construct_file
(fmt, &
full_name=trim(filename), &
record_length=record_length_loc, &
recl_words=nx_global*ny_global)
call data_set
(restart_file, 'open_read')
i_dim = construct_io_dim
('i', nx_global)
j_dim = construct_io_dim
('j', ny_global)
k_dim = construct_io_dim
('k', size(FIELD,3))
FIELD_DESC = &
construct_io_field
(trim(fieldname), &
dim1=i_dim, &
dim2=j_dim, &
dim3=k_dim, &
d3d_array = FIELD)
call data_set
(restart_file, 'define', FIELD_DESC)
call data_set
(restart_file, 'read', FIELD_DESC)
call destroy_io_field
(FIELD_DESC)
call data_set
(restart_file, 'close')
call destroy_file
(restart_file)
!-----------------------------------------------------------------------
!EOC
end subroutine read_field_3D
!***********************************************************************
end module passive_tracer_tools
!|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||