!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| module io_types 31,16 !BOP ! ! !MODULE: io_types ! ! !DESCRIPTION: ! This module contains the declarations for all required io ! data types and several operators for those data types. It also ! contains several global parameters used by various io operations ! and an io unit manager. ! ! !REVISION HISTORY: ! SVN:$Id: io_types.F90 19531 2009-11-19 19:05:44Z njn01 $ ! !USES: use POP_KindsMod use POP_IOUnitsMod use kinds_mod use constants use communicate use broadcast use exit_mod #ifdef CCSMCOUPLED use shr_file_mod use pio #endif implicit none private save ! !PUBLIC TYPES: type, public :: io_dim integer(i4) :: id integer(i4) :: length ! 1 to n, but 0 means unlimited integer(i4) :: start, stop, stride ! For slicing and dicing logical(log_kind) :: active character(char_len) :: name character(char_len) :: units end type ! Generic IO field descriptor type, public :: io_field_desc character(char_len) :: short_name character(char_len) :: long_name character(char_len) :: units character(char_len) :: coordinates character(4) :: grid_loc real(r4) :: missing_value real(r4), dimension(2) :: valid_range integer(i4) :: id integer(i4) :: nfield_dims integer(i4) :: field_loc integer(i4) :: field_type integer(int_kind) :: missing_value_i type (io_dim), dimension(4) :: field_dim character(char_len), dimension(:), pointer :: add_attrib_cname character(char_len), dimension(:), pointer :: add_attrib_cval character(char_len), dimension(:), pointer :: add_attrib_lname logical (log_kind), dimension(:), pointer :: add_attrib_lval character(char_len), dimension(:), pointer :: add_attrib_iname integer (i4), dimension(:), pointer :: add_attrib_ival character(char_len), dimension(:), pointer :: add_attrib_rname real (r4), dimension(:), pointer :: add_attrib_rval character(char_len), dimension(:), pointer :: add_attrib_dname real (r8), dimension(:), pointer :: add_attrib_dval ! Only one of these next 12 pointers can be associated. ! The others must be nullified. For convenience in ! initialization, these declarations are the last listed ! in this type. integer(i4) :: field_i_0d integer(i4), dimension(:), pointer :: field_i_1d integer(i4), dimension(:,:,:), pointer :: field_i_2d integer(i4), dimension(:,:,:,:), pointer :: field_i_3d real(r4) :: field_r_0d real(r4), dimension(:), pointer :: field_r_1d real(r4), dimension(:,:,:), pointer :: field_r_2d real(r4), dimension(:,:,:,:), pointer :: field_r_3d real(r8) :: field_d_0d real(r8), dimension(:), pointer :: field_d_1d real(r8), dimension(:,:,:), pointer :: field_d_2d real(r8), dimension(:,:,:,:), pointer :: field_d_3d type (VAR_desc_t) :: varDesc type (IO_desc_t), pointer :: ioDesc logical :: set_ioDesc logical :: set_ioFrame end type ! Generic data file descriptor type, public :: datafile character(char_len) :: full_name character(char_len) :: data_format ! .bin or ! .nc or ! piobin or pioncd character(char_len) :: root_name character(char_len) :: file_suffix integer(i4), dimension (2) :: id ! LUN (binary) or ! NCID (netcdf) character(char_len) :: title character(char_len) :: history character(char_len) :: conventions character(char_len), dimension(:), pointer :: add_attrib_cname character(char_len), dimension(:), pointer :: add_attrib_cval character(char_len), dimension(:), pointer :: add_attrib_lname logical (log_kind), dimension(:), pointer :: add_attrib_lval character(char_len), dimension(:), pointer :: add_attrib_iname integer (i4), dimension(:), pointer :: add_attrib_ival character(char_len), dimension(:), pointer :: add_attrib_rname real (r4), dimension(:), pointer :: add_attrib_rval character(char_len), dimension(:), pointer :: add_attrib_dname real (r8), dimension(:), pointer :: add_attrib_dval integer(i4) :: num_iotasks integer(i4) :: record_length integer(i4) :: current_record ! bin logical(log_kind) :: readonly logical(log_kind) :: ldefine type (File_desc_t) :: File(2) end type ! !PUBLIC MEMBER FUNCTIONS: public :: get_unit, & release_unit, & construct_file, & destroy_file, & add_attrib_file, & extract_attrib_file, & construct_io_field, & destroy_io_field, & construct_io_dim, & add_attrib_io_field, & extract_attrib_io_field, & init_io ! !PUBLIC DATA MEMBERS: #ifndef CCSMCOUPLED integer (i4), parameter, public :: & nml_in = 10, &! reserved unit for namelist input stdin = 5, &! reserved unit for standard input stdout = 6, &! reserved unit for standard output stderr = 6 ! reserved unit for standard error #else integer (i4), public :: & nml_in ! reserved unit for namelist input integer (i4), public :: & stdout = 6, &! reserved unit for standard output stdin = 5, &! reserved unit for standard input stderr = 6 ! reserved unit for standard error #endif integer (i4), parameter, public :: & rec_type_int = -1, &! ids to use for inquiring the rec_type_real = -2, &! record length to use for binary files rec_type_dbl = -3 ! character (7), parameter, public :: & nml_filename = 'pop2_in' ! namelist input file name integer (i4), public :: & num_iotasks ! num of procs to use for parallel io ! if output format is 'netcdf'. Then it is 1. logical (log_kind), public :: & luse_pointer_files ! use files to point to location of restarts character (char_len), public :: & pointer_filename ! filename to use for pointer files !EOP !BOC !----------------------------------------------------------------------- ! ! io unit manager variables ! !----------------------------------------------------------------------- integer (i4), parameter, private :: & max_units = 99 ! maximum number of open units logical (log_kind), dimension(max_units), private :: & in_use ! flag=.true. if unit currently open !----------------------------------------------------------------------- ! ! other module variables ! !----------------------------------------------------------------------- logical (log_kind), private :: & lredirect_stdout ! redirect stdout to log file logical (log_kind), public :: & luse_nf_64bit_offset ! use 64-bit offset in netCDF files character (char_len), private :: & log_filename ! root name for log file !----------------------------------------------------------------------- ! ! generic interface definitions ! !----------------------------------------------------------------------- interface add_attrib_file 152 module procedure add_attrib_file_char add_attrib_file_log, & add_attrib_file_int, & add_attrib_file_real, & add_attrib_file_dbl end interface interface extract_attrib_file 58 module procedure extract_attrib_file_char extract_attrib_file_log, & extract_attrib_file_int, & extract_attrib_file_real, & extract_attrib_file_dbl end interface interface add_attrib_io_field 53 module procedure add_attrib_io_field_char add_attrib_io_field_log, & add_attrib_io_field_int, & add_attrib_io_field_real, & add_attrib_io_field_dbl end interface interface extract_attrib_io_field module procedure extract_attrib_io_field_char extract_attrib_io_field_log, & extract_attrib_io_field_int, & extract_attrib_io_field_real, & extract_attrib_io_field_dbl end interface !EOC !*********************************************************************** contains !*********************************************************************** !BOP ! !IROUTINE: construct_file ! !INTERFACE: function construct_file ( & 41,2 data_format, & ! Optional arguments begin here full_name, & root_name, & file_suffix, & id, & title, & history, & conventions, & record_length, & recl_words, & current_record, & input_num_iotasks & ) & result (descriptor) ! !DESCRIPTION: ! This routine constructs a file descriptor for use in io routines. ! It fills in every field to guarantee that the descriptor ! will contain no illegal field values upon exit. The data format ! is required together with either a full name or root name. ! If full name is supplied, that name will be used in all file ! operations. If root name is supplied, the full name will be ! constructed using rootname.suffix.dataformat. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character(*), intent(in) :: & data_format ! bin (binary) or nc (netCDF) character(*), intent(in), optional :: & full_name, &! name (and path) for file root_name, &! file name root file_suffix, &! suffix (eg model day, step) title, &! descriptive name for the file history, &! file history string conventions ! conventions for file integer (i4), dimension (2), intent(in), optional :: & id ! unit numbers for binary file & hdr ! netCDF id for netCDF file integer (i4), intent(in), optional :: & input_num_iotasks, &! to override default iotasks record_length, &! record length type for binary files recl_words, &! num words per record for binary files current_record ! current record number in binary file ! !OUTPUT PARAMETERS: type (datafile) :: descriptor ! data file descriptor !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n, &! loop index io_record_length ! actual record length integer (i4), dimension(:), allocatable :: work_i real (r4), dimension(:), allocatable :: work_r real (r8), dimension(:), allocatable :: work_d !----------------------------------------------------------------------- ! ! define data format ! !----------------------------------------------------------------------- descriptor%data_format = char_blank descriptor%data_format = trim(data_format) !----------------------------------------------------------------------- ! ! file naming stuff ! if full name is present, use that as filename ! if root name and suffix supplied, construct file name from those ! !----------------------------------------------------------------------- if (present(full_name)) then descriptor%full_name = char_blank descriptor%full_name = trim(full_name) else if (present(root_name)) then descriptor%root_name = char_blank descriptor%root_name = trim(root_name) descriptor%file_suffix = char_blank if (present(file_suffix)) then if (trim(data_format) == 'nc') then if (trim(file_suffix) == '') then descriptor%file_suffix = trim(file_suffix)/& &/trim(data_format) else descriptor%file_suffix = trim(file_suffix)/& &/'.'/& &/trim(data_format) endif else descriptor%file_suffix = trim(file_suffix) endif else if (trim(data_format) == 'nc') & descriptor%file_suffix = trim(data_format) end if descriptor%full_name = char_blank if (trim(descriptor%file_suffix) /= '') then descriptor%full_name = trim(descriptor%root_name)/& &/'.'/& &/trim(descriptor%file_suffix) else descriptor%full_name = trim(descriptor%root_name)/& &/'.'/& &/trim(descriptor%file_suffix) endif else call exit_POP(sigAbort, & 'construct_file: can not determine file name') endif !----------------------------------------------------------------------- ! ! parameters specific to binary files ! !----------------------------------------------------------------------- if (descriptor%data_format=='bin') then !*** assign unit numbers as file id !*** if not assigned as input, assign later during file open if (present(id)) then descriptor%id = id else descriptor%id = 0 endif !*** number of io tasks for parallel io if (present(input_num_iotasks)) then !*** override namelist input - useful if you need !*** to serial i/o for a particular file in binary mode descriptor%num_iotasks = input_num_iotasks else descriptor%num_iotasks = num_iotasks ! namelist input endif !*** compute record length if (present(record_length)) then if (.not. present(recl_words)) & call exit_POP(sigAbort, & 'construct_file: must supply recl_words') select case (record_length) case (rec_type_int) io_record_length = POP_i4*recl_words !MEMSAVE allocate (work_i(recl_words)) !MEMSAVE inquire (iolength=io_record_length) work_i !MEMSAVE deallocate (work_i) case (rec_type_real) io_record_length = POP_r4*recl_words !MEMSAVE allocate (work_r(recl_words)) !MEMSAVE inquire (iolength=io_record_length) work_r !MEMSAVE deallocate (work_r) case (rec_type_dbl) io_record_length = POP_r8*recl_words !MEMSAVE allocate (work_d(recl_words)) !MEMSAVE inquire (iolength=io_record_length) work_d !MEMSAVE deallocate (work_d) case default io_record_length = 0 end select else io_record_length = 0 endif descriptor%record_length = io_record_length !*** initialize first record if (present(current_record)) then descriptor%current_record = current_record else descriptor%current_record = 1 endif !----------------------------------------------------------------------- ! ! parameters specific to netCDF files ! !----------------------------------------------------------------------- else !*** set id if already known, otherwise defined during file open if (present(id)) then descriptor%id = id else descriptor%id = 0 ! to be defined during open endif descriptor%num_iotasks = 1 ! netCDF can only do serial i/o descriptor%record_length = 0 ! not used for netCDF descriptor%current_record = 0 ! not used for netCDF endif !----------------------------------------------------------------------- ! ! general descriptive info for files ! !----------------------------------------------------------------------- descriptor%title = char_blank if (present(title)) then descriptor%title = trim(title) else descriptor%title = 'none' endif descriptor%history = char_blank if (present(history)) then descriptor%history = trim(history) else descriptor%history = 'none' endif descriptor%conventions = char_blank if (present(conventions)) then descriptor%conventions = trim(conventions) else descriptor%conventions = 'none' endif !----------------------------------------------------------------------- ! ! initialize global file attributes - these must be set separately ! in the routine add_attrib_file. ! !----------------------------------------------------------------------- descriptor%readonly = .false. ! reset later if necessary nullify (descriptor%add_attrib_cname) nullify (descriptor%add_attrib_cval) nullify (descriptor%add_attrib_lname) nullify (descriptor%add_attrib_lval) nullify (descriptor%add_attrib_iname) nullify (descriptor%add_attrib_ival) nullify (descriptor%add_attrib_rname) nullify (descriptor%add_attrib_rval) nullify (descriptor%add_attrib_dname) nullify (descriptor%add_attrib_dval) !----------------------------------------------------------------------- !EOC end function construct_file !*********************************************************************** !BOP ! !IROUTINE: add_attrib_file_char ! !INTERFACE: subroutine add_attrib_file_char(file_descr, att_name, att_value) 1 ! !DESCRIPTION: ! This routine adds a global file attribute to an io file. This ! particular instantiation adds a character attribute, but is aliased ! to the generic routine name add\_attrib\_file. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name, &! name of attribute to be added att_value ! value of attribute to be added ! !INPUT/OUTPUT PARAMETERS: type (datafile), intent(inout) :: & file_descr ! data file descriptor !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n, &! loop index num_attribs ! current number of attributes defined character (char_len), dimension(:), allocatable :: & name_tmp, &! temp space for resizing attrib name array val_tmp ! temp space for resizing attrib value array logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! if this is the first attribute, allocate space and set the attribute ! !----------------------------------------------------------------------- if (.not. associated(file_descr%add_attrib_cval)) then allocate(file_descr%add_attrib_cval(1), & file_descr%add_attrib_cname(1)) file_descr%add_attrib_cval (1) = char_blank file_descr%add_attrib_cname(1) = char_blank file_descr%add_attrib_cval (1) = trim(att_value) file_descr%add_attrib_cname(1) = trim(att_name) !----------------------------------------------------------------------- ! ! if not the first, see if it already exists and over-write value ! if does not exist, resize the attribute array and store the ! attributes ! !----------------------------------------------------------------------- else att_exists = .false. num_attribs = size(file_descr%add_attrib_cval(:)) att_search: do n=1,num_attribs if (trim(file_descr%add_attrib_cname(n)) == trim(att_name)) then file_descr%add_attrib_cval(n) = char_blank file_descr%add_attrib_cval(n) = trim(att_value) att_exists = .true. exit att_search endif end do att_search if (.not. att_exists) then allocate(name_tmp(num_attribs), val_tmp(num_attribs)) name_tmp(:) = file_descr%add_attrib_cname(:) val_tmp (:) = file_descr%add_attrib_cval (:) deallocate(file_descr%add_attrib_cname) deallocate(file_descr%add_attrib_cval ) num_attribs = num_attribs + 1 allocate(file_descr%add_attrib_cname(num_attribs), & file_descr%add_attrib_cval (num_attribs)) file_descr%add_attrib_cname(:) = char_blank file_descr%add_attrib_cval (:) = char_blank do n=1,num_attribs-1 file_descr%add_attrib_cname(n) = trim(name_tmp(n)) file_descr%add_attrib_cval (n) = trim( val_tmp(n)) end do file_descr%add_attrib_cname(num_attribs) = trim(att_name) file_descr%add_attrib_cval (num_attribs) = trim(att_value) deallocate(name_tmp,val_tmp) endif endif !----------------------------------------------------------------------- !EOC end subroutine add_attrib_file_char !*********************************************************************** !BOP ! !IROUTINE: add_attrib_file_log ! !INTERFACE: subroutine add_attrib_file_log(file_descr, att_name, att_value) ! !DESCRIPTION: ! This routine adds a global file attribute to an io file. This ! particular instantiation adds a logical attribute, but is aliased ! to the generic routine name add\_attrib\_file. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be added logical (log_kind), intent(in) :: & att_value ! value of attribute to be added ! !INPUT/OUTPUT PARAMETERS: type (datafile), intent(inout) :: & file_descr ! data file descriptor !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n, &! loop index num_attribs ! current number of attributes defined character (char_len), dimension(:), allocatable :: & name_tmp ! temp space for resizing attrib name array logical (log_kind), dimension(:), allocatable :: & val_tmp ! temp space for resizing attrib value array logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! if this is the first attribute, allocate space and set the attribute ! !----------------------------------------------------------------------- if (.not. associated(file_descr%add_attrib_lval)) then allocate(file_descr%add_attrib_lval(1), & file_descr%add_attrib_lname(1)) file_descr%add_attrib_lval (1) = att_value file_descr%add_attrib_lname(1) = char_blank file_descr%add_attrib_lname(1) = trim(att_name) !----------------------------------------------------------------------- ! ! if not the first, see if it already exists and over-write value ! if does not exist, resize the attribute array and store the ! attributes ! !----------------------------------------------------------------------- else att_exists = .false. num_attribs = size(file_descr%add_attrib_lval(:)) att_search: do n=1,num_attribs if (trim(file_descr%add_attrib_lname(n)) == trim(att_name)) then file_descr%add_attrib_lval(n) = att_value att_exists = .true. exit att_search endif end do att_search if (.not. att_exists) then allocate(name_tmp(num_attribs), val_tmp(num_attribs)) name_tmp(:) = file_descr%add_attrib_lname(:) val_tmp (:) = file_descr%add_attrib_lval (:) deallocate(file_descr%add_attrib_lname, & file_descr%add_attrib_lval ) num_attribs = num_attribs + 1 allocate(file_descr%add_attrib_lname(num_attribs), & file_descr%add_attrib_lval (num_attribs)) file_descr%add_attrib_lname(:) = char_blank do n=1,num_attribs-1 file_descr%add_attrib_lname(n) = trim(name_tmp(n)) file_descr%add_attrib_lval (n) = val_tmp(n) end do file_descr%add_attrib_lname(num_attribs) = trim(att_name) file_descr%add_attrib_lval (num_attribs) = att_value deallocate(name_tmp,val_tmp) endif endif !----------------------------------------------------------------------- !EOC end subroutine add_attrib_file_log !*********************************************************************** !BOP ! !IROUTINE: add_attrib_file_int ! !INTERFACE: subroutine add_attrib_file_int(file_descr, att_name, att_value) ! !DESCRIPTION: ! This routine adds a global file attribute to an io file. This ! particular instantiation adds an integer attribute, but is aliased ! to the generic routine name add\_attrib\_file. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be added integer (i4), intent(in) :: & att_value ! value of attribute to be added ! !INPUT/OUTPUT PARAMETERS: type (datafile), intent(inout) :: & file_descr ! data file descriptor !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n, &! loop index num_attribs ! current number of attributes defined character (char_len), dimension(:), allocatable :: & name_tmp ! temp space for resizing attrib name array integer (i4), dimension(:), allocatable :: & val_tmp ! temp space for resizing attrib value array logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! if this is the first attribute, allocate space and set the attribute ! !----------------------------------------------------------------------- if (.not. associated(file_descr%add_attrib_ival)) then allocate(file_descr%add_attrib_ival(1), & file_descr%add_attrib_iname(1)) file_descr%add_attrib_ival (1) = att_value file_descr%add_attrib_iname(1) = char_blank file_descr%add_attrib_iname(1) = trim(att_name) !----------------------------------------------------------------------- ! ! if not the first, see if it already exists and over-write value ! if does not exist, resize the attribute array and store the ! attributes ! !----------------------------------------------------------------------- else att_exists = .false. num_attribs = size(file_descr%add_attrib_ival(:)) att_search: do n=1,num_attribs if (trim(file_descr%add_attrib_iname(n)) == trim(att_name)) then file_descr%add_attrib_ival(n) = att_value att_exists = .true. exit att_search endif end do att_search if (.not. att_exists) then allocate(name_tmp(num_attribs), val_tmp(num_attribs)) name_tmp(:) = file_descr%add_attrib_iname(:) val_tmp (:) = file_descr%add_attrib_ival (:) deallocate(file_descr%add_attrib_iname, & file_descr%add_attrib_ival ) num_attribs = num_attribs + 1 allocate(file_descr%add_attrib_iname(num_attribs), & file_descr%add_attrib_ival (num_attribs)) file_descr%add_attrib_iname(:) = char_blank do n=1,num_attribs-1 file_descr%add_attrib_iname(n) = trim(name_tmp(n)) file_descr%add_attrib_ival (n) = val_tmp(n) end do file_descr%add_attrib_iname(num_attribs) = trim(att_name) file_descr%add_attrib_ival (num_attribs) = att_value deallocate(name_tmp,val_tmp) endif endif !----------------------------------------------------------------------- !EOC end subroutine add_attrib_file_int !*********************************************************************** !BOP ! !IROUTINE: add_attrib_file_real ! !INTERFACE: subroutine add_attrib_file_real(file_descr, att_name, att_value) ! !DESCRIPTION: ! This routine adds a global file attribute to an io file. This ! particular instantiation adds a real attribute, but is aliased ! to the generic routine name add\_attrib\_file. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be added real (r4), intent(in) :: & att_value ! value of attribute to be added ! !INPUT/OUTPUT PARAMETERS: type (datafile), intent(inout) :: & file_descr ! data file descriptor !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n, &! loop index num_attribs ! current number of attributes defined character (char_len), dimension(:), allocatable :: & name_tmp ! temp space for resizing attrib name array real (r4), dimension(:), allocatable :: & val_tmp ! temp space for resizing attrib value array logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! if this is the first attribute, allocate space and set the attribute ! !----------------------------------------------------------------------- if (.not. associated(file_descr%add_attrib_rval)) then allocate(file_descr%add_attrib_rval(1), & file_descr%add_attrib_rname(1)) file_descr%add_attrib_rval (1) = att_value file_descr%add_attrib_rname(1) = char_blank file_descr%add_attrib_rname(1) = trim(att_name) !----------------------------------------------------------------------- ! ! if not the first, see if it already exists and over-write value ! if does not exist, resize the attribute array and store the ! attributes ! !----------------------------------------------------------------------- else att_exists = .false. num_attribs = size(file_descr%add_attrib_rval(:)) att_search: do n=1,num_attribs if (trim(file_descr%add_attrib_rname(n)) == trim(att_name)) then file_descr%add_attrib_rval(n) = att_value att_exists = .true. exit att_search endif end do att_search if (.not. att_exists) then allocate(name_tmp(num_attribs), val_tmp(num_attribs)) name_tmp(:) = file_descr%add_attrib_rname(:) val_tmp (:) = file_descr%add_attrib_rval (:) deallocate(file_descr%add_attrib_rname, & file_descr%add_attrib_rval ) num_attribs = num_attribs + 1 allocate(file_descr%add_attrib_rname(num_attribs), & file_descr%add_attrib_rval (num_attribs)) file_descr%add_attrib_rname(:) = char_blank do n=1,num_attribs-1 file_descr%add_attrib_rname(n) = trim(name_tmp(n)) file_descr%add_attrib_rval (n) = val_tmp(n) end do file_descr%add_attrib_rname(num_attribs) = trim(att_name) file_descr%add_attrib_rval (num_attribs) = att_value deallocate(name_tmp,val_tmp) endif endif !----------------------------------------------------------------------- !EOC end subroutine add_attrib_file_real !*********************************************************************** !BOP ! !IROUTINE: add_attrib_file_dbl ! !INTERFACE: subroutine add_attrib_file_dbl(file_descr, att_name, att_value) ! !DESCRIPTION: ! This routine adds a global file attribute to an io file. This ! particular instantiation adds a double precision attribute, but is ! aliased to the generic routine name add\_attrib\_file. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be added real (r8), intent(in) :: & att_value ! value of attribute to be added ! !INPUT/OUTPUT PARAMETERS: type (datafile), intent(inout) :: & file_descr ! data file descriptor !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n, &! loop index num_attribs ! current number of attributes defined character (char_len), dimension(:), allocatable :: & name_tmp ! temp space for resizing attrib name array real (r8), dimension(:), allocatable :: & val_tmp ! temp space for resizing attrib value array logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! if this is the first attribute, allocate space and set the attribute ! !----------------------------------------------------------------------- if (.not. associated(file_descr%add_attrib_dval)) then allocate(file_descr%add_attrib_dval(1), & file_descr%add_attrib_dname(1)) file_descr%add_attrib_dval (1) = att_value file_descr%add_attrib_dname(1) = char_blank file_descr%add_attrib_dname(1) = trim(att_name) !----------------------------------------------------------------------- ! ! if not the first, see if it already exists and over-write value ! if does not exist, resize the attribute array and store the ! attributes ! !----------------------------------------------------------------------- else att_exists = .false. num_attribs = size(file_descr%add_attrib_dval(:)) att_search: do n=1,num_attribs if (trim(file_descr%add_attrib_dname(n)) == trim(att_name)) then file_descr%add_attrib_dval(n) = att_value att_exists = .true. exit att_search endif end do att_search if (.not. att_exists) then allocate(name_tmp(num_attribs), val_tmp(num_attribs)) name_tmp(:) = file_descr%add_attrib_dname(:) val_tmp (:) = file_descr%add_attrib_dval (:) deallocate(file_descr%add_attrib_dname, & file_descr%add_attrib_dval ) num_attribs = num_attribs + 1 allocate(file_descr%add_attrib_dname(num_attribs), & file_descr%add_attrib_dval (num_attribs)) file_descr%add_attrib_dname(:) = char_blank do n=1,num_attribs-1 file_descr%add_attrib_dname(n) = trim(name_tmp(n)) file_descr%add_attrib_dval (n) = val_tmp(n) end do file_descr%add_attrib_dname(num_attribs) = trim(att_name) file_descr%add_attrib_dval (num_attribs) = att_value deallocate(name_tmp,val_tmp) endif endif !----------------------------------------------------------------------- !EOC end subroutine add_attrib_file_dbl !*********************************************************************** !BOP ! !IROUTINE: extract_attrib_file_char ! !INTERFACE: subroutine extract_attrib_file_char(file_descr, att_name, att_value) 1,1 ! !DESCRIPTION: ! This routine extracts a global file attribute from an io file ! descriptor based on the attribute name. This particular ! instantiation extracts a character attribute, but is aliased ! to the generic routine name extract\_attrib\_file. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be extracted type (datafile), intent(in) :: & file_descr ! data file descriptor ! !OUTPUT PARAMETERS: character (*), intent(out) :: & att_value ! value of attribute to be extracted !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n ! loop index logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! first check standard attributes ! !----------------------------------------------------------------------- att_exists = .false. select case(trim(att_name)) case('full_name','FULL_NAME') att_exists = .true. att_value = file_descr%full_name case('data_format','DATA_FORMAT') att_exists = .true. att_value = file_descr%data_format case('root_name','ROOT_NAME') att_exists = .true. att_value = file_descr%root_name case('file_suffix','FILE_SUFFIX') att_exists = .true. att_value = file_descr%file_suffix case('title','TITLE') att_exists = .true. att_value = file_descr%title case('history','HISTORY') att_exists = .true. att_value = file_descr%history case('conventions','CONVENTIONS') att_exists = .true. att_value = file_descr%conventions end select !----------------------------------------------------------------------- ! ! if attribute array exists, search for attribute ! !----------------------------------------------------------------------- if (.not. att_exists .and. & associated(file_descr%add_attrib_cval)) then att_search: do n=1,size(file_descr%add_attrib_cval) if (trim(file_descr%add_attrib_cname(n))==trim(att_name)) then !*** found the attribute - assign the value att_value = file_descr%add_attrib_cval(n) att_exists = .true. exit att_search endif end do att_search endif !----------------------------------------------------------------------- ! ! if attribute not found, exit with an error ! !----------------------------------------------------------------------- if (.not. att_exists) then if (my_task == master_task) then write(stdout,*) 'Attribute name: ',trim(att_name) endif call exit_POP(sigAbort,'Unknown file attribute') endif !----------------------------------------------------------------------- !EOC end subroutine extract_attrib_file_char !*********************************************************************** !BOP ! !IROUTINE: extract_attrib_file_log ! !INTERFACE: subroutine extract_attrib_file_log(file_descr, att_name, att_value),1 ! !DESCRIPTION: ! This routine extracts a global file attribute from an io file ! descriptor based on the attribute name. This particular ! instantiation extracts a logical attribute, but is aliased ! to the generic routine name extract\_attrib\_file. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be extracted type (datafile), intent(in) :: & file_descr ! data file descriptor ! !OUTPUT PARAMETERS: logical (log_kind), intent(out) :: & att_value ! value of attribute to be extracted !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n ! loop index logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! first check standard attributes ! !----------------------------------------------------------------------- att_exists = .false. select case(trim(att_name)) case('readonly','READONLY') att_exists = .true. att_value = file_descr%readonly case('ldefine','LDEFINE') att_exists = .true. att_value = file_descr%ldefine end select !----------------------------------------------------------------------- ! ! if attribute array exists, search for attribute ! !----------------------------------------------------------------------- if (.not. att_exists .and. & associated(file_descr%add_attrib_lval)) then att_search: do n=1,size(file_descr%add_attrib_lval) if (trim(file_descr%add_attrib_lname(n))==trim(att_name)) then !*** found the attribute - assign the value att_value = file_descr%add_attrib_lval(n) att_exists = .true. exit att_search endif end do att_search endif !----------------------------------------------------------------------- ! ! if attribute not found, exit with an error ! !----------------------------------------------------------------------- if (.not. att_exists) then if (my_task == master_task) then write(stdout,*) 'Attribute name: ',trim(att_name) endif call exit_POP(sigAbort,'Unknown file attribute') endif !----------------------------------------------------------------------- !EOC end subroutine extract_attrib_file_log !*********************************************************************** !BOP ! !IROUTINE: extract_attrib_file_int ! !INTERFACE: subroutine extract_attrib_file_int(file_descr, att_name, att_value),1 ! !DESCRIPTION: ! This routine extracts a global file attribute from an io file ! descriptor based on the attribute name. This particular ! instantiation extracts an integer attribute, but is aliased ! to the generic routine name extract\_attrib\_file. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be extracted type (datafile), intent(in) :: & file_descr ! data file descriptor ! !OUTPUT PARAMETERS: integer (i4), intent(out) :: & att_value ! value of attribute to be extracted !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n ! loop index logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! first check standard attributes ! !----------------------------------------------------------------------- att_exists = .false. select case(trim(att_name)) case('id','ID') att_exists = .true. att_value = file_descr%id(1) case('num_iotasks','NUM_IOTASKS') att_exists = .true. att_value = file_descr%num_iotasks case('record_length','RECORD_LENGTH') att_exists = .true. att_value = file_descr%record_length case('current_record','CURRENT_RECORD') att_exists = .true. att_value = file_descr%current_record end select !----------------------------------------------------------------------- ! ! if attribute array exists, search for attribute ! !----------------------------------------------------------------------- if (.not. att_exists .and. & associated(file_descr%add_attrib_ival)) then att_search: do n=1,size(file_descr%add_attrib_ival) if (trim(file_descr%add_attrib_iname(n))==trim(att_name)) then !*** found the attribute - assign the value att_value = file_descr%add_attrib_ival(n) att_exists = .true. exit att_search endif end do att_search endif !----------------------------------------------------------------------- ! ! if attribute not found, exit with an error ! !----------------------------------------------------------------------- if (.not. att_exists) then if (my_task == master_task) then write(stdout,*) 'Attribute name: ',trim(att_name) endif call exit_POP(sigAbort,'Unknown file attribute') endif !----------------------------------------------------------------------- !EOC end subroutine extract_attrib_file_int !*********************************************************************** !BOP ! !IROUTINE: extract_attrib_file_real ! !INTERFACE: subroutine extract_attrib_file_real(file_descr, att_name, att_value),1 ! !DESCRIPTION: ! This routine extracts a global file attribute from an io file ! descriptor based on the attribute name. This particular ! instantiation extracts a real attribute, but is aliased ! to the generic routine name extract\_attrib\_file. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be extracted type (datafile), intent(in) :: & file_descr ! data file descriptor ! !OUTPUT PARAMETERS: real (r4), intent(out) :: & att_value ! value of attribute to be extracted !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n ! loop index logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! first check standard attributes ! !----------------------------------------------------------------------- att_exists = .false. !*** no standard real attributes !----------------------------------------------------------------------- ! ! if attribute array exists, search for attribute ! !----------------------------------------------------------------------- if (.not. att_exists .and. & associated(file_descr%add_attrib_rval)) then att_search: do n=1,size(file_descr%add_attrib_rval) if (trim(file_descr%add_attrib_rname(n))==trim(att_name)) then !*** found the attribute - assign the value att_value = file_descr%add_attrib_rval(n) att_exists = .true. exit att_search endif end do att_search endif !----------------------------------------------------------------------- ! ! if attribute not found, exit with an error ! !----------------------------------------------------------------------- if (.not. att_exists) then if (my_task == master_task) then write(stdout,*) 'Attribute name: ',trim(att_name) endif call exit_POP(sigAbort,'Unknown file attribute') endif !----------------------------------------------------------------------- !EOC end subroutine extract_attrib_file_real !*********************************************************************** !BOP ! !IROUTINE: extract_attrib_file_dbl ! !INTERFACE: subroutine extract_attrib_file_dbl(file_descr, att_name, att_value),1 ! !DESCRIPTION: ! This routine extracts a global file attribute from an io file ! descriptor based on the attribute name. This particular ! instantiation extracts a double precision attribute, but is aliased ! to the generic routine name extract\_attrib\_file. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be extracted type (datafile), intent(in) :: & file_descr ! data file descriptor ! !OUTPUT PARAMETERS: real (r8), intent(out) :: & att_value ! value of attribute to be extracted !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n ! loop index logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! first check standard attributes ! !----------------------------------------------------------------------- att_exists = .false. !*** no standard real attributes !----------------------------------------------------------------------- ! ! if attribute array exists, search for attribute ! !----------------------------------------------------------------------- if (.not. att_exists .and. & associated(file_descr%add_attrib_dval)) then att_search: do n=1,size(file_descr%add_attrib_dval) if (trim(file_descr%add_attrib_dname(n))==trim(att_name)) then !*** found the attribute - assign the value att_value = file_descr%add_attrib_dval(n) att_exists = .true. exit att_search endif end do att_search endif !----------------------------------------------------------------------- ! ! if attribute not found, exit with an error ! !----------------------------------------------------------------------- if (.not. att_exists) then if (my_task == master_task) then write(stdout,*) 'Attribute name: ',trim(att_name) endif call exit_POP(sigAbort,'Unknown file attribute') endif !----------------------------------------------------------------------- !EOC end subroutine extract_attrib_file_dbl !*********************************************************************** !BOP ! !IROUTINE: destroy_file ! !INTERFACE: subroutine destroy_file(descriptor) 40,2 ! !DESCRIPTION: ! This routine destroys a file descriptor in order to free up units ! and memory. ! ! !REVISION HISTORY: ! same as module ! !INPUT/OUTPUT PARAMETERS: type (datafile), intent(inout) :: descriptor ! data file descriptor !EOP !BOC !----------------------------------------------------------------------- ! ! release units if they have been assigned ! !----------------------------------------------------------------------- if (descriptor%data_format == 'bin') then call release_unit(descriptor%id(1)) !*** if a header file was absent, the sign of the unit was changed call release_unit(abs(descriptor%id(2))) else descriptor%id = 0 endif !----------------------------------------------------------------------- ! ! clear data fields ! !----------------------------------------------------------------------- descriptor%full_name = char_blank descriptor%data_format = char_blank descriptor%root_name = char_blank descriptor%file_suffix = char_blank descriptor%num_iotasks = 0 descriptor%record_length = 0 descriptor%current_record = 0 descriptor%title = char_blank descriptor%history = char_blank descriptor%conventions = char_blank descriptor%readonly = .false. ! reset later if necessary !----------------------------------------------------------------------- ! ! free up memory in additional attribute fields ! !----------------------------------------------------------------------- if (associated(descriptor%add_attrib_cname)) & deallocate(descriptor%add_attrib_cname) if (associated(descriptor%add_attrib_cval)) & deallocate(descriptor%add_attrib_cval) if (associated(descriptor%add_attrib_lname)) & deallocate(descriptor%add_attrib_lname) if (associated(descriptor%add_attrib_lval)) & deallocate(descriptor%add_attrib_lval) if (associated(descriptor%add_attrib_iname)) & deallocate(descriptor%add_attrib_iname) if (associated(descriptor%add_attrib_ival)) & deallocate(descriptor%add_attrib_ival) if (associated(descriptor%add_attrib_rname)) & deallocate(descriptor%add_attrib_rname) if (associated(descriptor%add_attrib_rval)) & deallocate(descriptor%add_attrib_rval) if (associated(descriptor%add_attrib_dname)) & deallocate(descriptor%add_attrib_dname) if (associated(descriptor%add_attrib_dval)) & deallocate(descriptor%add_attrib_dval) nullify (descriptor%add_attrib_cname) nullify (descriptor%add_attrib_cval) nullify (descriptor%add_attrib_lname) nullify (descriptor%add_attrib_lval) nullify (descriptor%add_attrib_iname) nullify (descriptor%add_attrib_ival) nullify (descriptor%add_attrib_rname) nullify (descriptor%add_attrib_rval) nullify (descriptor%add_attrib_dname) nullify (descriptor%add_attrib_dval) !----------------------------------------------------------------------- !EOC end subroutine destroy_file !*********************************************************************** !BOP ! !IROUTINE: construct_io_field ! !INTERFACE: function construct_io_field ( & 198,7 short_name, & dim1, dim2, & dim3, & time_dim, & long_name, & units, & coordinates, & grid_loc, & missing_value, & missing_value_i, & valid_range, & field_loc, & field_id, & field_type, & i0d_array, & i1d_array, & i2d_array, & i3d_array, & r0d_array, & r1d_array, & r2d_array, & r3d_array, & d0d_array, & d1d_array, & d2d_array, & d3d_array) & result (descriptor) ! !DESCRIPTION: ! Constructs a new io\_field descriptor for a field which will ! be read/written. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character(*), intent(in) :: & short_name ! short (one word) name for field type (io_dim), intent(in), optional :: & dim1, &! dimension data type for 1st dim dim2, &! dimension data type for 2nd dim dim3, &! dimension data type for 3rd dim time_dim ! dimension data type for (unlimited) time dim character(*), intent(in), optional :: & long_name, &! longer descriptive name for field units, &! units for field coordinates ! CF-1.0 required attribute character(4), intent(in), optional :: & grid_loc ! position of field in staggered grid real (r4), intent(in), optional :: & missing_value ! value for missing points (eg land) real (r4), intent(in), dimension(2), optional :: & valid_range ! valid range (min,max) for field integer (int_kind), intent(in), optional :: & missing_value_i ! missing value for integer arrays integer (i4), intent(in), optional :: & ! for ghost cell updates field_loc, &! staggering location field_type, &! field type (scalar,vector,angle) field_id ! previously defined id !*** !*** one (and only one) of these must be present !*** the extra dimension on 2d,3d arrays corresponds to block index !*** integer (i4), intent(in), optional :: & i0d_array integer (i4), dimension(:), intent(in), optional, target :: & i1d_array integer (i4), dimension(:,:,:), intent(in), optional, target :: & i2d_array integer (i4), dimension(:,:,:,:), intent(in), optional, target :: & i3d_array real (r4), intent(in), optional :: & r0d_array real (r4), dimension(:), intent(in), optional, target :: & r1d_array real (r4), dimension(:,:,:), intent(in), optional, target :: & r2d_array real (r4), dimension(:,:,:,:), intent(in), optional, target :: & r3d_array real (r8), intent(in), optional :: & d0d_array real (r8), dimension(:), intent(in), optional, target :: & d1d_array real (r8), dimension(:,:,:), intent(in), optional, target :: & d2d_array real (r8), dimension(:,:,:,:), intent(in), optional, target :: & d3d_array ! !OUTPUT PARAMETERS: type (io_field_desc) :: descriptor ! descriptor to be created !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- logical (log_kind) :: & lactive_time_dim !----------------------------------------------------------------------- ! ! variables to describe the field ! !----------------------------------------------------------------------- descriptor%short_name = char_blank descriptor%short_name = trim(short_name) descriptor%long_name = char_blank if (present(long_name)) then descriptor%long_name = trim(long_name) endif descriptor%coordinates = char_blank if (present(coordinates)) then descriptor%coordinates = trim(coordinates) endif descriptor%units = char_blank if (present(units)) then descriptor%units = trim(units) endif descriptor%grid_loc = ' ' if (present(grid_loc)) then descriptor%grid_loc = grid_loc endif descriptor%missing_value = undefined if (present(missing_value)) then descriptor%missing_value = missing_value endif descriptor%missing_value_i = undefined if (present(missing_value_i)) then descriptor%missing_value_i = missing_value_i endif descriptor%valid_range = undefined if (present(valid_range)) then descriptor%valid_range = valid_range endif descriptor%field_loc = field_loc_unknown if (present(field_loc)) then descriptor%field_loc = field_loc endif descriptor%field_type = field_type_unknown if (present(field_type)) then descriptor%field_type = field_type endif !----------------------------------------------------------------------- ! ! initialize id and dimension info (primarily for netCDF files) ! !----------------------------------------------------------------------- if (present (time_dim)) then if (time_dim%active) then lactive_time_dim = .true. else lactive_time_dim = .false. endif else lactive_time_dim = .false. endif ! support for multiple time slices on one file if (present (field_id)) then descriptor%id = field_id descriptor%vardesc%varid = field_id else descriptor%id = 0 descriptor%vardesc%varid = 0 endif ! If true, call pio_set_ioFRAME if (lactive_time_dim) then descriptor%set_ioFrame = .true. else descriptor%set_ioFrame = .false. end if ! If true, call initdecomp descriptor%set_ioDesc = .true. if (present(i3d_array) .or. present(r3d_array) .or. & present(d3d_array)) then if (lactive_time_dim) then descriptor%nfield_dims = 4 else descriptor%nfield_dims = 3 endif if (present(dim1)) then descriptor%field_dim(1) = dim1 else call exit_POP(sigAbort, & 'construct_io_field: must supply dim1') endif if (present(dim2)) then descriptor%field_dim(2) = dim2 else call exit_POP(sigAbort, & 'construct_io_field: must supply dim2') endif if (present(dim3)) then descriptor%field_dim(3) = dim3 else call exit_POP(sigAbort, & 'construct_io_field: must supply 3d dim') endif if (lactive_time_dim) then descriptor%field_dim(4) = time_dim endif else if (present(i2d_array) .or. present(r2d_array) .or. & present(d2d_array)) then if (lactive_time_dim) then descriptor%nfield_dims = 3 else descriptor%nfield_dims = 2 endif if (present(dim1)) then descriptor%field_dim(1) = dim1 else call exit_POP(sigAbort, & 'construct_io_field: must supply dim1') endif if (present(dim2)) then descriptor%field_dim(2) = dim2 else call exit_POP(sigAbort, & 'construct_io_field: must supply dim2') endif if (lactive_time_dim) then descriptor%field_dim(3) = time_dim endif else if (present(i1d_array) .or. present(r1d_array) .or. & present(d1d_array)) then descriptor%nfield_dims = 1 if (present(dim1)) then descriptor%field_dim(1) = dim1 else call exit_POP(sigAbort, & 'construct_io_field: must supply dim1') endif else descriptor%nfield_dims = 0 ! field_dim is not used for scalars end if nullify (descriptor%field_i_1d) nullify (descriptor%field_i_2d) nullify (descriptor%field_i_3d) nullify (descriptor%field_r_1d) nullify (descriptor%field_r_2d) nullify (descriptor%field_r_3d) nullify (descriptor%field_d_1d) nullify (descriptor%field_d_2d) nullify (descriptor%field_d_3d) if (present(r0d_array)) then descriptor%field_r_0d = r0d_array else if (present(r1d_array)) then descriptor%field_r_1d => r1d_array else if (present(r2d_array)) then descriptor%field_r_2d => r2d_array else if (present(r3d_array)) then descriptor%field_r_3d => r3d_array else if (present(d0d_array)) then descriptor%field_d_0d = d0d_array else if (present(d1d_array)) then descriptor%field_d_1d => d1d_array else if (present(d2d_array)) then descriptor%field_d_2d => d2d_array else if (present(d3d_array)) then descriptor%field_d_3d => d3d_array else if (present(i0d_array)) then descriptor%field_i_0d = i0d_array else if (present(i1d_array)) then descriptor%field_i_1d => i1d_array else if (present(i2d_array)) then descriptor%field_i_2d => i2d_array else if (present(i3d_array)) then descriptor%field_i_3d => i3d_array else call exit_POP(sigAbort, & 'construct_io_field: must supply data array') end if !----------------------------------------------------------------------- ! ! nullify additional field attributes ! !----------------------------------------------------------------------- nullify (descriptor%add_attrib_cname) nullify (descriptor%add_attrib_cval) nullify (descriptor%add_attrib_lname) nullify (descriptor%add_attrib_lval) nullify (descriptor%add_attrib_iname) nullify (descriptor%add_attrib_ival) nullify (descriptor%add_attrib_rname) nullify (descriptor%add_attrib_rval) nullify (descriptor%add_attrib_dname) nullify (descriptor%add_attrib_dval) !----------------------------------------------------------------------- !EOC end function construct_io_field !*********************************************************************** !BOP ! !IROUTINE: destroy_io_field ! !INTERFACE: subroutine destroy_io_field (descriptor) 117 ! !DESCRIPTION: ! Clears all fields of an io\_field structure and dereference all ! pointers. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: type (io_field_desc), intent(inout) :: & descriptor ! descriptor to be destroyed !EOP !BOC !----------------------------------------------------------------------- ! ! clear all fields ! !----------------------------------------------------------------------- descriptor%short_name = char_blank descriptor%long_name = char_blank descriptor%units = char_blank descriptor%coordinates= char_blank descriptor%grid_loc = ' ' descriptor%missing_value = undefined descriptor%missing_value_i = undefined descriptor%valid_range = undefined descriptor%id = 0 descriptor%nfield_dims = 4 descriptor%field_loc = field_loc_unknown descriptor%field_type = field_type_unknown !----------------------------------------------------------------------- ! ! deallocate and dereference pointers ! !----------------------------------------------------------------------- nullify (descriptor%field_i_2d) nullify (descriptor%field_i_2d) nullify (descriptor%field_i_3d) nullify (descriptor%field_r_1d) nullify (descriptor%field_r_2d) nullify (descriptor%field_r_3d) nullify (descriptor%field_d_1d) nullify (descriptor%field_d_2d) nullify (descriptor%field_d_3d) if (associated(descriptor%add_attrib_cname)) then deallocate (descriptor%add_attrib_cname) deallocate (descriptor%add_attrib_cval) endif if (associated(descriptor%add_attrib_lname)) then deallocate (descriptor%add_attrib_lname) deallocate (descriptor%add_attrib_lval) endif if (associated(descriptor%add_attrib_iname)) then deallocate (descriptor%add_attrib_iname) deallocate (descriptor%add_attrib_ival) endif if (associated(descriptor%add_attrib_rname)) then deallocate (descriptor%add_attrib_rname) deallocate (descriptor%add_attrib_rval) endif if (associated(descriptor%add_attrib_dname)) then deallocate (descriptor%add_attrib_dname) deallocate (descriptor%add_attrib_dval) endif nullify (descriptor%add_attrib_cname) nullify (descriptor%add_attrib_cval) nullify (descriptor%add_attrib_iname) nullify (descriptor%add_attrib_ival) nullify (descriptor%add_attrib_rname) nullify (descriptor%add_attrib_rval) nullify (descriptor%add_attrib_dname) nullify (descriptor%add_attrib_dval) !----------------------------------------------------------------------- !EOC end subroutine destroy_io_field !*********************************************************************** !BOP ! !IROUTINE: add_attrib_io_field_char ! !INTERFACE: subroutine add_attrib_io_field_char(iofield, att_name, att_value) 1 ! !DESCRIPTION: ! This routine adds an attribute to an io field. This ! particular instantiation adds a character attribute, but is aliased ! to the generic routine name add\_attrib\_io\_field. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name, &! name of attribute to be added att_value ! value of attribute to be added ! !INPUT/OUTPUT PARAMETERS: type (io_field_desc), intent(inout) :: & iofield ! data file descriptor !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n, &! loop index num_attribs ! current number of attributes defined character (char_len), dimension(:), allocatable :: & name_tmp, &! temp space for resizing attrib name array val_tmp ! temp space for resizing attrib value array logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! if this is the first attribute, allocate space and set the attribute ! !----------------------------------------------------------------------- if (.not. associated(iofield%add_attrib_cval)) then allocate(iofield%add_attrib_cval(1), & iofield%add_attrib_cname(1)) iofield%add_attrib_cval (1) = att_value iofield%add_attrib_cname(1) = att_name !----------------------------------------------------------------------- ! ! if not the first, see if it exists and over-write value ! if does not exist, resize the attribute array and store the ! attributes ! !----------------------------------------------------------------------- else att_exists = .false. num_attribs = size(iofield%add_attrib_cval(:)) att_search: do n=1,num_attribs if (trim(iofield%add_attrib_cname(n)) == trim(att_name)) then iofield%add_attrib_cval(n) = char_blank iofield%add_attrib_cval(n) = trim(att_value) att_exists = .true. exit att_search endif end do att_search if (.not. att_exists) then allocate(name_tmp(num_attribs), val_tmp(num_attribs)) name_tmp(:) = iofield%add_attrib_cname(:) val_tmp (:) = iofield%add_attrib_cval (:) deallocate(iofield%add_attrib_cname) deallocate(iofield%add_attrib_cval ) num_attribs = num_attribs + 1 allocate(iofield%add_attrib_cname(num_attribs), & iofield%add_attrib_cval (num_attribs)) iofield%add_attrib_cname(1:num_attribs-1) = name_tmp iofield%add_attrib_cval (1:num_attribs-1) = val_tmp iofield%add_attrib_cname(num_attribs) = att_name iofield%add_attrib_cval (num_attribs) = att_value deallocate(name_tmp,val_tmp) endif endif !----------------------------------------------------------------------- !EOC end subroutine add_attrib_io_field_char !*********************************************************************** !BOP ! !IROUTINE: add_attrib_io_field_log ! !INTERFACE: subroutine add_attrib_io_field_log(iofield, att_name, att_value) ! !DESCRIPTION: ! This routine adds a field attribute to an io field. This ! particular instantiation adds a logical attribute, but is aliased ! to the generic routine name add\_attrib\_io\_field. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be added logical (log_kind), intent(in) :: & att_value ! value of attribute to be added ! !INPUT/OUTPUT PARAMETERS: type (io_field_desc), intent(inout) :: & iofield ! data file descriptor !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n, &! loop index num_attribs ! current number of attributes defined character (char_len), dimension(:), allocatable :: & name_tmp ! temp space for resizing attrib name array logical (log_kind), dimension(:), allocatable :: & val_tmp ! temp space for resizing attrib value array logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! if this is the first attribute, allocate space and set the attribute ! !----------------------------------------------------------------------- if (.not. associated(iofield%add_attrib_lval)) then allocate(iofield%add_attrib_lval(1), & iofield%add_attrib_lname(1)) iofield%add_attrib_lval (1) = att_value iofield%add_attrib_lname(1) = att_name !----------------------------------------------------------------------- ! ! otherwise, check to see if the attribute already is defined ! if yes, store the value ! if no, resize the attribute array and store the attributes ! !----------------------------------------------------------------------- else att_exists = .false. num_attribs = size(iofield%add_attrib_lval(:)) att_search: do n=1,num_attribs if (trim(iofield%add_attrib_lname(n)) == trim(att_name)) then iofield%add_attrib_lval(n) = att_value att_exists = .true. exit att_search endif end do att_search if (.not. att_exists) then allocate(name_tmp(num_attribs), val_tmp(num_attribs)) name_tmp(:) = iofield%add_attrib_lname(:) val_tmp (:) = iofield%add_attrib_lval (:) deallocate(iofield%add_attrib_lname, & iofield%add_attrib_lval ) num_attribs = num_attribs + 1 allocate(iofield%add_attrib_lname(num_attribs), & iofield%add_attrib_lval (num_attribs)) iofield%add_attrib_lname(1:num_attribs-1) = name_tmp iofield%add_attrib_lval (1:num_attribs-1) = val_tmp iofield%add_attrib_lname(num_attribs) = att_name iofield%add_attrib_lval (num_attribs) = att_value deallocate(name_tmp,val_tmp) endif endif !----------------------------------------------------------------------- !EOC end subroutine add_attrib_io_field_log !*********************************************************************** !BOP ! !IROUTINE: add_attrib_io_field_int ! !INTERFACE: subroutine add_attrib_io_field_int(iofield, att_name, att_value) ! !DESCRIPTION: ! This routine adds a field attribute to an io field. This ! particular instantiation adds an integer attribute, but is aliased ! to the generic routine name add\_attrib\_io\_field. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be added integer (i4), intent(in) :: & att_value ! value of attribute to be added ! !INPUT/OUTPUT PARAMETERS: type (io_field_desc), intent(inout) :: & iofield ! data file descriptor !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n, &! loop index num_attribs ! current number of attributes defined character (char_len), dimension(:), allocatable :: & name_tmp ! temp space for resizing attrib name array integer (i4), dimension(:), allocatable :: & val_tmp ! temp space for resizing attrib value array logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! if this is the first attribute, allocate space and set the attribute ! !----------------------------------------------------------------------- if (.not. associated(iofield%add_attrib_ival)) then allocate(iofield%add_attrib_ival(1), & iofield%add_attrib_iname(1)) iofield%add_attrib_ival (1) = att_value iofield%add_attrib_iname(1) = att_name !----------------------------------------------------------------------- ! ! otherwise, check to see if the attribute already is defined ! if yes, store the value ! if no, resize the attribute array and store the attributes ! !----------------------------------------------------------------------- else att_exists = .false. num_attribs = size(iofield%add_attrib_ival(:)) att_search: do n=1,num_attribs if (trim(iofield%add_attrib_iname(n)) == trim(att_name)) then iofield%add_attrib_ival(n) = att_value att_exists = .true. exit att_search endif end do att_search if (.not. att_exists) then allocate(name_tmp(num_attribs), val_tmp(num_attribs)) name_tmp(:) = iofield%add_attrib_iname(:) val_tmp (:) = iofield%add_attrib_ival (:) deallocate(iofield%add_attrib_iname, & iofield%add_attrib_ival ) num_attribs = num_attribs + 1 allocate(iofield%add_attrib_iname(num_attribs), & iofield%add_attrib_ival (num_attribs)) iofield%add_attrib_iname(1:num_attribs-1) = name_tmp iofield%add_attrib_ival (1:num_attribs-1) = val_tmp iofield%add_attrib_iname(num_attribs) = att_name iofield%add_attrib_ival (num_attribs) = att_value deallocate(name_tmp,val_tmp) endif endif !----------------------------------------------------------------------- !EOC end subroutine add_attrib_io_field_int !*********************************************************************** !BOP ! !IROUTINE: add_attrib_io_field_real ! !INTERFACE: subroutine add_attrib_io_field_real(iofield, att_name, att_value) ! !DESCRIPTION: ! This routine adds a field attribute to an io field. This ! particular instantiation adds a real attribute, but is aliased ! to the generic routine name add\_attrib\_io\_field. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be added real (r4), intent(in) :: & att_value ! value of attribute to be added ! !INPUT/OUTPUT PARAMETERS: type (io_field_desc), intent(inout) :: & iofield ! io field descriptor !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n, &! loop index num_attribs ! current number of attributes defined character (char_len), dimension(:), allocatable :: & name_tmp ! temp space for resizing attrib name array real (r4), dimension(:), allocatable :: & val_tmp ! temp space for resizing attrib value array logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! if this is the first attribute, allocate space and set the attribute ! !----------------------------------------------------------------------- if (.not. associated(iofield%add_attrib_rval)) then allocate(iofield%add_attrib_rval(1), & iofield%add_attrib_rname(1)) iofield%add_attrib_rval (1) = att_value iofield%add_attrib_rname(1) = att_name !----------------------------------------------------------------------- ! ! otherwise, check to see if the attribute already is defined ! if yes, store the value ! if no, resize the attribute array and store the attributes ! !----------------------------------------------------------------------- else att_exists = .false. num_attribs = size(iofield%add_attrib_rval(:)) att_search: do n=1,num_attribs if (trim(iofield%add_attrib_rname(n)) == trim(att_name)) then iofield%add_attrib_rval(n) = att_value att_exists = .true. exit att_search endif end do att_search if (.not. att_exists) then allocate(name_tmp(num_attribs), val_tmp(num_attribs)) name_tmp(:) = iofield%add_attrib_rname(:) val_tmp (:) = iofield%add_attrib_rval (:) deallocate(iofield%add_attrib_rname, & iofield%add_attrib_rval ) num_attribs = num_attribs + 1 allocate(iofield%add_attrib_rname(num_attribs), & iofield%add_attrib_rval (num_attribs)) iofield%add_attrib_rname(1:num_attribs-1) = name_tmp iofield%add_attrib_rval (1:num_attribs-1) = val_tmp iofield%add_attrib_rname(num_attribs) = att_name iofield%add_attrib_rval (num_attribs) = att_value deallocate(name_tmp,val_tmp) endif endif !----------------------------------------------------------------------- !EOC end subroutine add_attrib_io_field_real !*********************************************************************** !BOP ! !IROUTINE: add_attrib_io_field_dbl ! !INTERFACE: subroutine add_attrib_io_field_dbl(iofield, att_name, att_value) ! !DESCRIPTION: ! This routine adds a field attribute to an io field. This ! particular instantiation adds a double precision attribute, but is ! aliased to the generic routine name add\_attrib\_io\_field. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be added real (r8), intent(in) :: & att_value ! value of attribute to be added ! !INPUT/OUTPUT PARAMETERS: type (io_field_desc), intent(inout) :: & iofield ! io field descriptor !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n, &! loop index num_attribs ! current number of attributes defined character (char_len), dimension(:), allocatable :: & name_tmp ! temp space for resizing attrib name array real (r8), dimension(:), allocatable :: & val_tmp ! temp space for resizing attrib value array logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! if this is the first attribute, allocate space and set the attribute ! !----------------------------------------------------------------------- if (.not. associated(iofield%add_attrib_dval)) then allocate(iofield%add_attrib_dval(1), & iofield%add_attrib_dname(1)) iofield%add_attrib_dval (1) = att_value iofield%add_attrib_dname(1) = att_name !----------------------------------------------------------------------- ! ! otherwise, check to see if the attribute already is defined ! if yes, store the value ! if no, resize the attribute array and store the attributes ! !----------------------------------------------------------------------- else att_exists = .false. num_attribs = size(iofield%add_attrib_dval(:)) att_search: do n=1,num_attribs if (trim(iofield%add_attrib_dname(n)) == trim(att_name)) then iofield%add_attrib_dval(n) = att_value att_exists = .true. exit att_search endif end do att_search if (.not. att_exists) then allocate(name_tmp(num_attribs), val_tmp(num_attribs)) name_tmp(:) = iofield%add_attrib_dname(:) val_tmp (:) = iofield%add_attrib_dval (:) deallocate(iofield%add_attrib_dname, & iofield%add_attrib_dval ) num_attribs = num_attribs + 1 allocate(iofield%add_attrib_dname(num_attribs), & iofield%add_attrib_dval (num_attribs)) iofield%add_attrib_dname(1:num_attribs-1) = name_tmp iofield%add_attrib_dval (1:num_attribs-1) = val_tmp iofield%add_attrib_dname(num_attribs) = att_name iofield%add_attrib_dval (num_attribs) = att_value deallocate(name_tmp,val_tmp) endif endif !----------------------------------------------------------------------- !EOC end subroutine add_attrib_io_field_dbl !*********************************************************************** !BOP ! !IROUTINE: extract_attrib_io_field_char ! !INTERFACE: subroutine extract_attrib_io_field_char(iofield, att_name, att_value) 1,1 ! !DESCRIPTION: ! This routine extracts an attribute from an io field. This ! particular instantiation extracts a character attribute, but is ! aliased to the generic routine name extract\_attrib\_io\_field. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be extracted type (io_field_desc), intent(in) :: & iofield ! data file descriptor ! !OUTPUT PARAMETERS: character (*), intent(out) :: & att_value ! value of attribute to be extracted !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n ! loop index logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! first check standard attributes ! !----------------------------------------------------------------------- att_exists = .false. select case (trim(att_name)) case ('short_name','SHORT_NAME') att_value = iofield%short_name att_exists = .true. case ('long_name','LONG_NAME') att_exists = .true. att_value = iofield%long_name case ('units','UNITS') att_exists = .true. att_value = iofield%units case ('grid_loc','GRID_LOC') att_exists = .true. att_value = iofield%grid_loc case ('coordinates','COORDINATES') att_exists = .true. att_value = iofield%coordinates end select !----------------------------------------------------------------------- ! ! if not a standard attribute, check additional attributes ! !----------------------------------------------------------------------- if (.not. att_exists .and. associated(iofield%add_attrib_cval)) then att_search: do n=1,size(iofield%add_attrib_cval) if (trim(att_name) == trim(iofield%add_attrib_cname(n))) then att_value = iofield%add_attrib_cval(n) att_exists = .true. exit att_search endif end do att_search endif !----------------------------------------------------------------------- ! ! if attribute not found, exit with error ! !----------------------------------------------------------------------- if (.not. att_exists) then if (my_task == master_task) then write(stdout,*) 'Attribute name: ',trim(att_name) endif call exit_POP(sigAbort,'Unknown iofield attribute') endif !----------------------------------------------------------------------- !EOC end subroutine extract_attrib_io_field_char !*********************************************************************** !BOP ! !IROUTINE: extract_attrib_io_field_log ! !INTERFACE: subroutine extract_attrib_io_field_log(iofield, att_name, att_value),1 ! !DESCRIPTION: ! This routine extracts an attribute from an io field. This ! particular instantiation extracts a logical attribute, but is ! aliased to the generic routine name extract\_attrib\_io\_field. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be extracted type (io_field_desc), intent(in) :: & iofield ! data file descriptor ! !OUTPUT PARAMETERS: logical (log_kind), intent(out) :: & att_value ! value of attribute to be extracted !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n ! loop index logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! first check standard attributes ! !----------------------------------------------------------------------- att_exists = .false. !*** no standard logical attributes !----------------------------------------------------------------------- ! ! if not a standard attribute, check additional attributes ! !----------------------------------------------------------------------- if (.not. att_exists .and. associated(iofield%add_attrib_lval)) then att_search: do n=1,size(iofield%add_attrib_lval) if (trim(att_name) == trim(iofield%add_attrib_lname(n))) then att_value = iofield%add_attrib_lval(n) att_exists = .true. exit att_search endif end do att_search endif !----------------------------------------------------------------------- ! ! if attribute not found, exit with error ! !----------------------------------------------------------------------- if (.not. att_exists) then if (my_task == master_task) then write(stdout,*) 'Attribute name: ',trim(att_name) endif call exit_POP(sigAbort,'Unknown iofield attribute') endif !----------------------------------------------------------------------- !EOC end subroutine extract_attrib_io_field_log !*********************************************************************** !BOP ! !IROUTINE: extract_attrib_io_field_int ! !INTERFACE: subroutine extract_attrib_io_field_int(iofield, att_name, att_value),1 ! !DESCRIPTION: ! This routine extracts an attribute from an io field. This ! particular instantiation extracts an integer attribute, but is ! aliased to the generic routine name extract\_attrib\_io\_field. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be extracted type (io_field_desc), intent(in) :: & iofield ! data file descriptor ! !OUTPUT PARAMETERS: integer (i4), intent(out) :: & att_value ! value of attribute to be extracted !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n ! loop index logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! first check standard attributes ! !----------------------------------------------------------------------- att_exists = .false. select case (trim(att_name)) case ('id','ID') att_exists = .true. att_value = iofield%id case ('nfield_dims','NFIELD_DIMS') att_exists = .true. att_value = iofield%nfield_dims end select !----------------------------------------------------------------------- ! ! if not a standard attribute, check additional attributes ! !----------------------------------------------------------------------- if (.not. att_exists .and. associated(iofield%add_attrib_ival)) then att_search: do n=1,size(iofield%add_attrib_ival) if (trim(att_name) == trim(iofield%add_attrib_iname(n))) then att_value = iofield%add_attrib_ival(n) att_exists = .true. exit att_search endif end do att_search endif !----------------------------------------------------------------------- ! ! if attribute not found, exit with error ! !----------------------------------------------------------------------- if (.not. att_exists) then if (my_task == master_task) then write(stdout,*) 'Attribute name: ',trim(att_name) endif call exit_POP(sigAbort,'Unknown iofield attribute') endif !----------------------------------------------------------------------- !EOC end subroutine extract_attrib_io_field_int !*********************************************************************** !BOP ! !IROUTINE: extract_attrib_io_field_real ! !INTERFACE: subroutine extract_attrib_io_field_real(iofield, att_name, att_value),1 ! !DESCRIPTION: ! This routine extracts an attribute from an io field. This ! particular instantiation extracts a real attribute, but is ! aliased to the generic routine name extract\_attrib\_io\_field. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be extracted type (io_field_desc), intent(in) :: & iofield ! data file descriptor ! !OUTPUT PARAMETERS: real (r4), intent(out) :: & att_value ! value of attribute to be extracted !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n ! loop index logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! first check standard attributes ! !----------------------------------------------------------------------- att_exists = .false. select case (trim(att_name)) case ('missing_value','MISSING_VALUE') att_value = iofield%missing_value att_exists = .true. case ('missing_value_i','MISSING_VALUE_I') att_value = iofield%missing_value_i att_exists = .true. case ('valid_range','VALID_RANGE') att_exists = .true. !att_value = iofield%valid_range end select !----------------------------------------------------------------------- ! ! if not a standard attribute, check additional attributes ! !----------------------------------------------------------------------- if (.not. att_exists .and. associated(iofield%add_attrib_rval)) then att_search: do n=1,size(iofield%add_attrib_rval) if (trim(att_name) == trim(iofield%add_attrib_rname(n))) then att_value = iofield%add_attrib_rval(n) att_exists = .true. exit att_search endif end do att_search endif !----------------------------------------------------------------------- ! ! if attribute not found, exit with error ! !----------------------------------------------------------------------- if (.not. att_exists) then if (my_task == master_task) then write(stdout,*) 'Attribute name: ',trim(att_name) endif call exit_POP(sigAbort,'Unknown iofield attribute') endif !----------------------------------------------------------------------- !EOC end subroutine extract_attrib_io_field_real !*********************************************************************** !BOP ! !IROUTINE: extract_attrib_io_field_dbl ! !INTERFACE: subroutine extract_attrib_io_field_dbl(iofield, att_name, att_value),1 ! !DESCRIPTION: ! This routine extracts an attribute from an io field. This ! particular instantiation extracts a double precision attribute, but ! is aliased to the generic routine name extract\_attrib\_io\_field. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character (*), intent(in) :: & att_name ! name of attribute to be extracted type (io_field_desc), intent(in) :: & iofield ! data file descriptor ! !OUTPUT PARAMETERS: real (r8), intent(out) :: & att_value ! value of attribute to be extracted !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & n ! loop index logical (log_kind) :: & att_exists ! attribute already defined !----------------------------------------------------------------------- ! ! first check standard attributes ! !----------------------------------------------------------------------- att_exists = .false. !*** no standard dbl attributes !----------------------------------------------------------------------- ! ! if not a standard attribute, check additional attributes ! !----------------------------------------------------------------------- if (.not. att_exists .and. associated(iofield%add_attrib_dval)) then att_search: do n=1,size(iofield%add_attrib_dval) if (trim(att_name) == trim(iofield%add_attrib_dname(n))) then att_value = iofield%add_attrib_dval(n) att_exists = .true. exit att_search endif end do att_search endif !----------------------------------------------------------------------- ! ! if attribute not found, exit with error ! !----------------------------------------------------------------------- if (.not. att_exists) then if (my_task == master_task) then write(stdout,*) 'Attribute name: ',trim(att_name) endif call exit_POP(sigAbort,'Unknown iofield attribute') endif !----------------------------------------------------------------------- !EOC end subroutine extract_attrib_io_field_dbl !*********************************************************************** !BOP ! !IROUTINE: construct_io_dim ! !INTERFACE: function construct_io_dim(name, length, start, stop, stride, active) 122 ! !DESCRIPTION: ! Constructs a dimension for use in defining fields for io. ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETERS: character(*), intent(in) :: & name ! name of dimension integer(i4), intent(in) :: & length ! size of dimension (1 to n, but 0 means unlimited) integer(i4), intent(in), optional :: & start, stop, stride ! For slicing and dicing logical(log_kind),intent(in), optional :: & active ! !OUTPUT PARAMETERS: type (io_dim) :: construct_io_dim !EOP !BOC !----------------------------------------------------------------------- ! ! build data structure using input values ! !----------------------------------------------------------------------- construct_io_dim%name = char_blank construct_io_dim%name = trim(name) construct_io_dim%id = 0 ! will be set later using netCDF routine construct_io_dim%length = length if (present(start)) then construct_io_dim%start = start else construct_io_dim%start = 1 endif if (present(stop)) then construct_io_dim%stop = stop else construct_io_dim%stop = length endif if (present(stride)) then construct_io_dim%stride = stride else construct_io_dim%stride = 1 endif if (present(active)) then construct_io_dim%active = active else construct_io_dim%active = .true. endif !----------------------------------------------------------------------- !EOC end function construct_io_dim !*********************************************************************** !BOP ! !IROUTINE: init_io ! !INTERFACE: subroutine init_io 1,13 ! !DESCRIPTION: ! This routine initializes some i/o arrays and checks the validity ! of the i/o processor number. It also sets up netcdf datasets. ! ! !REVISION HISTORY: ! same as module !EOP !BOC !----------------------------------------------------------------------- ! ! local variables ! !----------------------------------------------------------------------- integer (i4) :: & nml_error ! namelist i/o error flag character (8) :: & logdate ! actual date at model startup ! (not simulation date) character (10) :: & logtime ! wallclock time at model startup character (char_len) :: & char_tmp ! temp character string for filenames namelist /io_nml/ num_iotasks, & lredirect_stdout, log_filename, & luse_pointer_files, pointer_filename, & luse_nf_64bit_offset !----------------------------------------------------------------------- ! ! initialize io unit manager ! !----------------------------------------------------------------------- in_use = .false. ! no unit in use in_use(stdin) = .true. ! reserved units in_use(stdout) = .true. in_use(stderr) = .true. #ifndef CCSMCOUPLED in_use(nml_in) = .true. #endif !----------------------------------------------------------------------- ! ! read and define namelist inputs ! !----------------------------------------------------------------------- luse_nf_64bit_offset = .false. lredirect_stdout = .false. log_filename = 'pop.out' luse_pointer_files = .false. pointer_filename = 'pop2_pointer' num_iotasks = 1 ! set default num io tasks if (my_task == master_task) then #ifdef CCSMCOUPLED call get_unit(nml_in) #endif open (nml_in, file=nml_filename, status='old',iostat=nml_error) if (nml_error /= 0) then nml_error = -1 else nml_error = 1 endif do while (nml_error > 0) read(nml_in, nml=io_nml,iostat=nml_error) end do if (nml_error == 0) close(nml_in) endif call broadcast_scalar(nml_error, master_task) if (nml_error /= 0) then call exit_POP(sigAbort,'ERROR reading io_nml') endif call broadcast_scalar(num_iotasks, master_task) call broadcast_scalar(lredirect_stdout, master_task) call broadcast_scalar(log_filename, master_task) call broadcast_scalar(luse_pointer_files, master_task) call broadcast_scalar(luse_nf_64bit_offset, master_task) call broadcast_scalar(pointer_filename, master_task) !----------------------------------------------------------------------- ! ! redirect stdout to a log file if requested ! !----------------------------------------------------------------------- #ifndef CCSMCOUPLED if (lredirect_stdout .and. my_task == master_task) then open (stdout,file=trim(log_filename),form='formatted',position='append') end if #else if (my_task == master_task) then stdout = shr_file_getUnit() call shr_file_setIO('ocn_modelio.nml',stdout) end if #endif !----------------------------------------------------------------------- ! ! document namelist after stdout redirection ! !----------------------------------------------------------------------- if (my_task == master_task) then write(stdout,blank_fmt) write(stdout,ndelim_fmt) write(stdout,blank_fmt) write(stdout,*)' I/O:' write(stdout,blank_fmt) write(stdout,*) 'io_nml namelist settings:' write(stdout,blank_fmt) write(stdout,io_nml) write(stdout,blank_fmt) call POP_IOUnitsFlush(stdout) endif !----------------------------------------------------------------------- !EOC call flushm (stdout) end subroutine init_io !*********************************************************************** !BOP ! !IROUTINE: get_unit ! !INTERFACE: subroutine get_unit(iunit) 43,1 ! !DESCRIPTION: ! This routine returns the next available i/o unit. ! Note that {\em all} processors must call get\_unit (even if only ! the master task is doing the i/o) to insure that ! the in\_use array remains synchronized. ! ! !REVISION HISTORY: ! same as module ! !OUTPUT PARAMETERS: integer (i4), intent(out) :: & iunit ! next free i/o unit !EOP !BOC !----------------------------------------------------------------------- integer (i4) :: n ! dummy loop index !----------------------------------------------------------------------- ! ! find next free unit ! !----------------------------------------------------------------------- #ifdef CCSMCOUPLED iunit = shr_file_getUnit() #else srch_units: do n=1,max_units if (.not. in_use(n)) then ! I found one, I found one iunit = n exit srch_units endif end do srch_units in_use(iunit) = .true. ! mark iunit as being in use #endif !----------------------------------------------------------------------- !EOC end subroutine get_unit !*********************************************************************** !BOP ! !IROUTINE: release_unit ! !INTERFACE: subroutine release_unit(iunit) 35,1 ! !DESCRIPTION: ! This routine releases an i/o unit (marks it as available). ! ! !REVISION HISTORY: ! same as module ! !INPUT PARAMETER: integer (i4), intent(in) :: & iunit ! i/o unit to be released !EOP !BOC !----------------------------------------------------------------------- ! ! mark the unit as not in use ! !----------------------------------------------------------------------- #ifdef CCSMCOUPLED call shr_file_freeUnit(iunit) #else in_use(iunit) = .false. ! that was easy... #endif !----------------------------------------------------------------------- !EOC end subroutine release_unit !*********************************************************************** end module io_types !|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||