LCOV - code coverage report
Current view: top level - control - cam_history.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1964 3059 64.2 %
Date: 2025-03-13 18:42:46 Functions: 43 64 67.2 %

          Line data    Source code
       1             : module cam_history
       2             :   !-------------------------------------------------------------------------------------------
       3             :   !
       4             :   ! The cam_history module provides the user interface for CAM's history output capabilities.
       5             :   ! It maintains the lists of fields that are written to each history file, and the associated
       6             :   ! metadata for those fields such as descriptive names, physical units, time axis properties,
       7             :   ! etc.  It also contains the programmer interface which provides routines that are called from
       8             :   ! the physics and dynamics initialization routines to define the fields that are produced by
       9             :   ! the model and are available for output, and the routine that is called from the corresponding
      10             :   ! run method to add the field values into a history buffer so that they may be output to disk.
      11             :   !
      12             :   ! There are two special history files.  The initial file and the satellite track file.
      13             :   !
      14             :   ! Public functions/subroutines:
      15             :   !   addfld, add_default
      16             :   !   intht
      17             :   !   history_initialized
      18             :   !   write_restart_history
      19             :   !   read_restart_history
      20             :   !   outfld
      21             :   !   wshist
      22             :   !-----------------------------------------------------------------------
      23             : 
      24             :    use shr_kind_mod,    only: r8 => shr_kind_r8, r4 => shr_kind_r4
      25             :    use shr_kind_mod,    only: cl=>SHR_KIND_CL
      26             :    use shr_sys_mod,     only: shr_sys_flush
      27             :    use spmd_utils,      only: masterproc
      28             :    use ppgrid,          only: pcols, psubcols
      29             :    use cam_instance,    only: inst_suffix
      30             :    use cam_control_mod, only: caseid, ctitle
      31             :    use filenames,       only: interpret_filename_spec
      32             :    use cam_initfiles,   only: ncdata, bnd_topo
      33             :    use cam_abortutils,  only: endrun
      34             : 
      35             :    use pio,          only: file_desc_t, var_desc_t, pio_setframe, pio_write,  &
      36             :                            pio_noerr, pio_bcast_error, pio_internal_error,    &
      37             :                            pio_seterrorhandling, pio_get_var, pio_clobber,    &
      38             :                            pio_int, pio_real, pio_double, pio_char,           &
      39             :                            pio_offset_kind, pio_unlimited, pio_global,        &
      40             :                            pio_inq_dimlen, pio_def_var, pio_enddef,           &
      41             :                            pio_put_att, pio_put_var, pio_get_att,             &
      42             :                            pio_file_is_open
      43             : 
      44             : 
      45             :    use perf_mod,            only: t_startf, t_stopf
      46             :    use cam_logfile,         only: iulog
      47             :    use cam_history_support, only: max_fieldname_len, fieldname_suffix_len,    &
      48             :                                   max_chars, ptapes, fieldname_len,           &
      49             :                                   max_string_len, pflds, fieldname_lenp2,     &
      50             :                                   field_info, active_entry, hentry,           &
      51             :                                   horiz_only, write_hist_coord_attrs,         &
      52             :                                   write_hist_coord_vars, interp_info_t,       &
      53             :                                   lookup_hist_coord_indices, get_hist_coord_index, &
      54             :                                   field_op_len
      55             :    use string_utils,        only: date2yyyymmdd, sec2hms
      56             :    use sat_hist,            only: is_satfile
      57             :    use solar_parms_data,    only: solar_parms_on, kp=>solar_parms_kp, ap=>solar_parms_ap
      58             :    use solar_parms_data,    only: f107=>solar_parms_f107, f107a=>solar_parms_f107a, f107p=>solar_parms_f107p
      59             :    use solar_wind_data,     only: solar_wind_on, byimf=>solar_wind_byimf, bzimf=>solar_wind_bzimf
      60             :    use solar_wind_data,     only: swvel=>solar_wind_swvel, swden=>solar_wind_swden
      61             :    use epotential_params,   only: epot_active, epot_crit_colats
      62             :    use cam_grid_support,    only: maxsplitfiles
      63             : 
      64             :   implicit none
      65             :   private
      66             :   save
      67             : 
      68             :   ! Forward common parameters to present unified interface to cam_history
      69             :   public :: fieldname_len, horiz_only
      70             :   public :: get_field_properties
      71             :   public :: cam_history_snapshot_deactivate
      72             :   public :: cam_history_snapshot_activate
      73             : 
      74             :   type grid_area_entry
      75             :      integer                         :: decomp_type = -1         ! type of decomposition (e.g., physics or dynamics)
      76             :      real(r8), allocatable           :: wbuf(:,:)                ! for area weights
      77             :   end type grid_area_entry
      78             :   type (grid_area_entry), target, allocatable:: grid_wts(:)      ! area wts for each decomp type
      79             :   type (grid_area_entry), pointer    :: allgrids_wt(:) => null() ! area wts for each decomp type
      80             :   !
      81             :   ! master_entry: elements of an entry in the master field list
      82             :   !
      83             :   type master_entry
      84             :     type (field_info)                :: field            ! field information
      85             :     character(len=max_fieldname_len) :: meridional_field = '' ! for vector fields
      86             :     character(len=max_fieldname_len) :: zonal_field = '' ! for vector fields
      87             :     character(len=1)                 :: avgflag(ptapes)  ! averaging flag
      88             :     character(len=max_chars)         :: time_op(ptapes)  ! time operator (e.g. max, min, avg)
      89             :     character(len=field_op_len)      :: field_op  = ''   ! field derived from sum or dif of field1 and field2
      90             :     character(len=max_fieldname_len) :: op_field1 = ''   ! first field name to be operated on
      91             :     character(len=max_fieldname_len) :: op_field2 = ''   ! second field name to be operated on
      92             :     logical                          :: act_sometape     ! Field is active on some tape
      93             :     logical                          :: actflag(ptapes)  ! Per tape active/inactive flag
      94             :     integer                          :: htapeindx(ptapes)! This field's index on particular history tape
      95             :     type(master_entry), pointer      :: next_entry => null() ! The next master entry
      96             :   end type master_entry
      97             : 
      98             :   type (master_entry), pointer :: masterlinkedlist => null()   ! master field linkedlist top
      99             : 
     100             :   type master_list
     101             :     type(master_entry), pointer :: thisentry => null()
     102             :   end type master_list
     103             : 
     104             :   type (master_list), pointer :: masterlist(:) => null() ! master field array for hash lookup of field
     105             : 
     106             :   ! history tape info
     107             :   type (active_entry), pointer :: tape(:) => null()          ! history tapes
     108             :   type (active_entry), target,allocatable :: history_tape(:) ! history tapes
     109             :   type (active_entry), target, allocatable :: restarthistory_tape(:) ! restart history tapes
     110             : 
     111             :   type rvar_id
     112             :     type(var_desc_t), pointer      :: vdesc => null()
     113             :     integer                        :: type
     114             :     integer                        :: ndims
     115             :     integer                        :: dims(4)
     116             :     character(len=fieldname_lenp2) :: name
     117             :     logical                        :: fillset = .false.
     118             :     integer                        :: ifill
     119             :     real(r4)                       :: rfill
     120             :     real(r8)                       :: dfill
     121             :   end type rvar_id
     122             :   type rdim_id
     123             :     integer                        :: len
     124             :     integer                        :: dimid
     125             :     character(len=fieldname_lenp2) :: name
     126             :   end type rdim_id
     127             :   !
     128             :   !   The size of these parameters should match the assignments in restart_vars_setnames and restart_dims_setnames below
     129             :   !
     130             :   integer, parameter :: restartvarcnt              = 45
     131             :   integer, parameter :: restartdimcnt              = 11
     132             :   type(rvar_id)      :: restartvars(restartvarcnt)
     133             :   type(rdim_id)      :: restartdims(restartdimcnt)
     134             :   integer, parameter :: ptapes_dim_ind             =  1
     135             :   integer, parameter :: max_string_len_dim_ind     =  2
     136             :   integer, parameter :: fieldname_lenp2_dim_ind    =  3
     137             :   integer, parameter :: pflds_dim_ind              =  4
     138             :   integer, parameter :: max_chars_dim_ind          =  5
     139             :   integer, parameter :: max_fieldname_len_dim_ind  =  6
     140             :   integer, parameter :: maxnflds_dim_ind           =  7
     141             :   integer, parameter :: maxvarmdims_dim_ind        =  8
     142             :   integer, parameter :: registeredmdims_dim_ind    =  9
     143             :   integer, parameter :: max_hcoordname_len_dim_ind = 10
     144             :   integer, parameter :: max_num_split_files        = 11
     145             : 
     146             :   ! Indices for split history files; must be 1 and 2
     147             :   integer, parameter :: instantaneous_file_index   =  1
     148             :   integer, parameter :: accumulated_file_index     =  2
     149             :   ! Indices for non-split history files; must be 1 or 2
     150             :   integer, parameter :: sat_file_index             =  1
     151             :   integer, parameter :: restart_file_index         =  1
     152             :   integer, parameter :: init_file_index            =  1
     153             : 
     154             :   integer :: nfmaster = 0             ! number of fields in master field list
     155             :   integer :: nflds(ptapes)            ! number of fields per tape
     156             : 
     157             :   ! per tape sampling frequency (0=monthly avg)
     158             : 
     159             :   integer :: idx                      ! index for nhtfrq initialization
     160             :   integer :: nhtfrq(ptapes) = (/0, (-24, idx=2,ptapes)/)  ! history write frequency (0 = monthly)
     161             :   integer :: mfilt(ptapes) = 30       ! number of time samples per tape
     162             :   integer :: nfils(ptapes)            ! Array of no. of files on current h-file
     163             :   integer :: ndens(ptapes) = 2        ! packing density (double (1) or real (2))
     164             :   integer :: ncprec(ptapes) = -999    ! netcdf packing parameter based on ndens
     165             :   real(r8) :: beg_time(ptapes)        ! time at beginning of an averaging interval
     166             : 
     167             :   logical :: rgnht(ptapes) = .false.  ! flag array indicating regeneration volumes
     168             :   logical :: hstwr(ptapes) = .false.  ! Flag for history writes
     169             :   logical :: empty_htapes  = .false.  ! Namelist flag indicates no default history fields
     170             :   logical :: write_nstep0  = .false.  ! write nstep==0 time sample to history files (except monthly)
     171             :   logical :: htapes_defined = .false. ! flag indicates history contents have been defined
     172             : 
     173             :   character(len=cl) :: model_doi_url = '' ! Model DOI
     174             :   ! NB: This name must match the group name in namelist_definition.xml
     175             :   character(len=*), parameter   :: history_namelist = 'cam_history_nl'
     176             :   character(len=max_string_len) :: hrestpath(ptapes) = (/(' ',idx=1,ptapes)/) ! Full history restart pathnames
     177             :   character(len=max_string_len) :: nfpath(ptapes) = (/(' ',idx=1,ptapes)/) ! Array of first pathnames, for header
     178             :   character(len=max_string_len) :: cpath(ptapes,maxsplitfiles)     ! Array of current pathnames
     179             :   character(len=max_string_len) :: nhfil(ptapes,maxsplitfiles)     ! Array of current file names
     180             :   character(len=1)  :: avgflag_pertape(ptapes) = (/(' ',idx=1,ptapes)/) ! per tape averaging flag
     181             :   character(len=16)  :: logname             ! user name
     182             :   character(len=16)  :: host                ! host name
     183             :   character(len=8)   :: inithist = 'YEARLY' ! If set to '6-HOURLY, 'DAILY', 'MONTHLY' or
     184             :   ! 'YEARLY' then write IC file
     185             :   logical            :: inithist_all = .false. ! Flag to indicate set of fields to be
     186             :                                           ! included on IC file
     187             :                                           !  .false.  include only required fields
     188             :                                           !  .true.   include required *and* optional fields
     189             :   character(len=fieldname_lenp2) :: fincl(pflds,ptapes) ! List of fields to add to primary h-file
     190             :   character(len=max_chars)       :: fincllonlat(pflds,ptapes) ! List of fields to add to primary h-file
     191             :   character(len=fieldname_lenp2) :: fexcl(pflds,ptapes) ! List of fields to rm from primary h-file
     192             :   character(len=fieldname_lenp2) :: fwrtpr(pflds,ptapes) ! List of fields to change default history output prec
     193             :   character(len=fieldname_suffix_len ) :: fieldname_suffix = '&IC' ! Suffix appended to field names for IC file
     194             : 
     195             :   ! Parameters for interpolated output tapes
     196             :   logical, public       :: interpolate_output(ptapes) = .false.
     197             :   ! The last two history files are not supported for interpolation
     198             :   type(interp_info_t)   :: interpolate_info(ptapes - 2)
     199             : 
     200             :   ! Allowed history averaging flags
     201             :   ! This should match namelist_definition.xml => avgflag_pertape (+ ' ')
     202             :   character(len=9), parameter    :: HIST_AVG_FLAGS = ' ABILMNSX'
     203             :   character(len=22) ,parameter   :: LT_DESC = 'mean (over local time)' ! local time description
     204             :   logical :: collect_column_output(ptapes)
     205             : 
     206             :   integer :: maxvarmdims=1
     207             :   !
     208             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     209             :   !
     210             :   !  Hashing.
     211             :   !
     212             :   !  Accelerate outfld processing by using a hash function of the field name
     213             :   !  to index masterlist and determine whehter the particular field is to
     214             :   !  be written to any history tape.
     215             :   !
     216             :   !
     217             :   !  Note: the outfld hashing logic will fail if any of the following are true:
     218             :   !
     219             :   !         1) The lower bound on the dimension of 'masterlist' is less than 1.
     220             :   !
     221             :   !         2) 'outfld' is called with field names that are not defined on
     222             :   !            masterlist.  This applies to both initial/branch and restart
     223             :   !            runs.
     224             :   !
     225             :   !         3) An inconsistency between a field's tape active flag
     226             :   !            'masterlist(ff)%actflag(t)' and active fields read from
     227             :   !            restart files.
     228             :   !
     229             :   !         4) Invoking function 'gen_hash_key' before the primary and secondary
     230             :   !            hash tables have been created (routine bld_outfld_hash_tbls).
     231             :   !
     232             : !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     233             : 
     234             :   !
     235             :   !  User definable constants for hash and overflow tables.
     236             :   !  Define size of primary hash table (specified as 2**size).
     237             :   !
     238             :   integer, parameter :: tbl_hash_pri_sz_lg2 = 16
     239             :   !
     240             :   !  Define size of overflow hash table % of primary hash table.
     241             :   !
     242             :   integer, parameter :: tbl_hash_oflow_percent = 20
     243             :   !
     244             :   !  Do *not* modify the parameters below.
     245             :   !
     246             :   integer, parameter :: tbl_hash_pri_sz = 2**tbl_hash_pri_sz_lg2
     247             :   integer, parameter :: tbl_hash_oflow_sz = int(tbl_hash_pri_sz *             &
     248             :        (tbl_hash_oflow_percent / 100.0_r8))
     249             :   !
     250             :   !  The primary and overflow tables are organized to mimimize space (read:
     251             :   !  try to maximimze cache line usage).
     252             :   !
     253             :   !  gen_hash_key(fieldname) will return an index on the interval
     254             :   !  [0 ... tbl_hash_pri_sz-1].
     255             :   !
     256             :   !
     257             :   !  Primary:
     258             :   !  gen_hash_key(fieldname)-------+     +----------+
     259             :   !                                |     |   -ii    | 1 ------>tbl_hash_oflow(ii)
     260             :   !                                |     +----------+
     261             :   !                                +-->  |    ff    | 2 ------>masterlist(ff)
     262             :   !                                      +----------+
     263             :   !                                      |          | ...
     264             :   !                                      +----------+
     265             :   !                                      |          | tbl_hash_pri_sz
     266             :   !                                      +----------+
     267             :   !
     268             :   !  Overflow (if tbl_hash_pri() < 0):
     269             :   !  tbl_hash_pri(gen_hash_key(fieldname))
     270             :   !                         |
     271             :   !                         |            +----------+
     272             :   !                         |            |     1    | 1  (one entry on O.F. chain)
     273             :   !                         |            +----------+
     274             :   !                         |            |    ff_m  | 2
     275             :   !                         |            +----------+
     276             :   !                         +--------->  |     3    | 3  (three entries on chain)
     277             :   !                                      +----------+
     278             :   !                                      |    ff_x  | 4
     279             :   !                                      +----------+
     280             :   !                                      |    ff_y  | 5
     281             :   !                                      +----------+
     282             :   !                                      |    ff_z  | 6
     283             :   !                                      +----------+
     284             :   !                                      |          | ...
     285             :   !                                      +----------+
     286             :   !                                      |          | tbl_hash_oflow_sz
     287             :   !                                      +----------+
     288             :   !
     289             :   !
     290             :   integer, dimension(0:tbl_hash_pri_sz-1) :: tbl_hash_pri ! Primary hash table
     291             :   integer, dimension(tbl_hash_oflow_sz) :: tbl_hash_oflow ! Overflow hash table
     292             :   !
     293             :   !  Constants used in hashing function gen_hash_key.
     294             :   !  Note: if the constants in table 'tbl_gen_hash_key' below are modified,
     295             :   !        changes are required to routine 'gen_hash_key' because of specific
     296             :   !        logic in the routine that optimizes character strings of length 8.
     297             :   !
     298             : 
     299             :   integer, parameter :: gen_hash_key_offset = z'000053db'
     300             : 
     301             :   integer, parameter :: tbl_max_idx = 15  ! 2**N - 1
     302             :   integer, dimension(0:tbl_max_idx) :: tbl_gen_hash_key = &
     303             :        (/61,59,53,47,43,41,37,31,29,23,17,13,11,7,3,1/)
     304             : 
     305             :   !
     306             :   ! Filename specifiers for history, initial files and restart history files
     307             :   ! (%c = caseid, $y = year, $m = month, $d = day, $s = seconds in day, %t = tape number)
     308             :   !
     309             :   character(len=max_string_len) :: rhfilename_spec = '%c.cam.rh%t.%y-%m-%d-%s.nc' ! history restart
     310             :   character(len=max_string_len) :: hfilename_spec(ptapes) = (/ (' ', idx=1, ptapes) /) ! filename specifyer
     311             :   ! Flag for if there are accumulated fields specified for a given tape
     312             :   logical                       :: hfile_accum(ptapes) = .false.
     313             : 
     314             : 
     315             :   interface addfld
     316             :     module procedure addfld_1d
     317             :     module procedure addfld_nd
     318             :   end interface
     319             : 
     320             :   ! Needed by cam_diagnostics
     321             :   public :: inithist_all
     322             : 
     323             :   integer :: lcltod_start(ptapes) ! start time of day for local time averaging (sec)
     324             :   integer :: lcltod_stop(ptapes)  ! stop time of day for local time averaging, stop > start is wrap around (sec)
     325             : 
     326             :   ! Needed by stepon and cam_restart
     327             :   public :: hstwr
     328             :   public :: nfils, mfilt
     329             : 
     330             :   ! Functions
     331             :   public :: history_readnl            ! Namelist reader for CAM history
     332             :   public :: init_restart_history      ! Write restart history data
     333             :   public :: write_restart_history     ! Write restart history data
     334             :   public :: read_restart_history      ! Read restart history data
     335             :   public :: wshist                    ! Write files out
     336             :   public :: outfld                    ! Output a field
     337             :   public :: intht                     ! Initialization
     338             :   public :: history_initialized       ! .true. iff cam history initialized
     339             :   public :: wrapup                    ! process history files at end of run
     340             :   public :: write_inithist            ! logical flag to allow dump of IC history buffer to IC file
     341             :   public :: addfld                    ! Add a field to history file
     342             :   public :: add_default               ! Add the default fields
     343             :   public :: register_vector_field     ! Register vector field set for interpolated output
     344             :   public :: get_hfilepath             ! Return history filename
     345             :   public :: get_ptapes                ! Return the number of tapes being used
     346             :   public :: get_hist_restart_filepath ! Return the full filepath to the history restart file
     347             :   public :: hist_fld_active           ! Determine if a field is active on any history file
     348             :   public :: hist_fld_col_active       ! Determine if a field is active on any history file at
     349             :   ! each column in a chunk
     350             : 
     351             : CONTAINS
     352             : 
     353           0 :   subroutine intht (model_doi_url_in)
     354             :     !
     355             :     !-----------------------------------------------------------------------
     356             :     !
     357             :     ! Purpose: Initialize history file handler for initial or continuation run.
     358             :     !          For example, on an initial run, this routine initializes "ptapes"
     359             :     !          history files.  On a restart or regeneration  run, this routine
     360             :     !          only initializes history files declared beyond what existed on the
     361             :     !          previous run.  Files which already existed on the previous run have
     362             :     !          already been initialized (i.e. named and opened) in routine RESTRT.
     363             :     !
     364             :     ! Method: Loop over tapes and fields per tape setting appropriate variables and
     365             :     !         calling appropriate routines
     366             :     !
     367             :     ! Author: CCM Core Group
     368             :     !
     369             :     !-----------------------------------------------------------------------
     370             :     use shr_sys_mod,      only: shr_sys_getenv
     371             :     use time_manager,     only: get_prev_time, get_curr_time
     372             :     use cam_control_mod,  only: restart_run, branch_run
     373             :     use sat_hist,         only: sat_hist_init
     374             :     use spmd_utils,       only: mpicom, masterprocid, mpi_character
     375             :     use cam_grid_support, only: cam_grid_get_areawt
     376             :     use cam_history_support, only: dim_index_2d
     377             :     !
     378             :     !-----------------------------------------------------------------------
     379             :     !
     380             :     ! Dummy argument
     381             :     !
     382             :     character(len=cl), intent(in) :: model_doi_url_in
     383             :     !
     384             :     ! Local workspace
     385             :     !
     386             :     integer :: t, fld            ! tape, field indices
     387             :     integer :: begdim1           ! on-node dim1 start index
     388             :     integer :: enddim1           ! on-node dim1 end index
     389             :     integer :: begdim2           ! on-node dim2 start index
     390             :     integer :: enddim2           ! on-node dim2 end index
     391             :     integer :: begdim3           ! on-node chunk or lat start index
     392             :     integer :: enddim3           ! on-node chunk or lat end index
     393             :     integer :: day, sec          ! day and seconds from base date
     394             :     integer :: rcode             ! shr_sys_getenv return code
     395             :     integer :: wtidx(1)          ! area weight index
     396             :     integer :: i,k,c,ib,ie,jb,je,count ! index
     397             :     integer :: fdecomp           ! field decomp
     398             :     type(dim_index_2d)          :: dimind    ! 2-D dimension index
     399        1536 :     real(r8), pointer           :: areawt(:)  ! pointer to areawt values for attribute
     400             :     type(master_entry), pointer :: listentry
     401             :     character(len=32)           :: fldname ! temp variable used to produce a left justified field name
     402             :     ! in the formatted logfile output
     403             : 
     404             :     !
     405             :     ! Save the DOI
     406             :     !
     407        1536 :     model_doi_url = trim(model_doi_url_in)
     408             : 
     409             :     !
     410             :     ! Print master field list
     411             :     !
     412             : 
     413        1536 :     if (masterproc) then
     414           2 :       write(iulog,*) ' '
     415           2 :       write(iulog,*)' ******* MASTER FIELD LIST *******'
     416             :     end if
     417        1536 :     listentry=>masterlinkedlist
     418        1536 :     fld=0
     419     4497408 :     do while(associated(listentry))
     420     4495872 :       fld=fld+1
     421     4495872 :       if(masterproc) then
     422        5854 :         fldname = listentry%field%name
     423        5854 :         write(iulog,9000) fld, fldname, listentry%field%units, listentry%field%numlev, &
     424       11708 :              listentry%avgflag(1), trim(listentry%field%long_name)
     425             : 9000    format(i5, 1x, a32, 1x, a16, 1x, i4, 1x, a1, 2x, a)
     426             :       end if
     427     4495872 :       listentry=>listentry%next_entry
     428             :     end do
     429        1536 :     nfmaster = fld
     430        1536 :     if(masterproc) write(iulog,*)'intht:nfmaster=',nfmaster
     431             : 
     432             :     !
     433             :     !  Now that masterlinkedlist is defined and we are performing a restart run
     434             :     !  (after all addfld calls), construct primary and secondary hashing tables.
     435             :     !
     436        1536 :     if (restart_run) then
     437         768 :        call print_active_fldlst()
     438         768 :        call bld_outfld_hash_tbls()
     439         768 :        call bld_htapefld_indices()
     440         768 :        return
     441             :     end if
     442             :     !
     443             :     ! Get users logname and machine hostname
     444             :     !
     445         768 :     if ( masterproc )then
     446           1 :       logname = ' '
     447           1 :       call shr_sys_getenv ('LOGNAME',logname,rcode)
     448           1 :       host = ' '
     449           1 :       call shr_sys_getenv ('HOST',host,rcode)
     450             :     end if
     451             :     ! PIO requires netcdf attributes have consistant values on all tasks
     452         768 :     call mpi_bcast(logname, len(logname), mpi_character, masterprocid, mpicom, rcode)
     453         768 :     call mpi_bcast(host,    len(host),    mpi_character, masterprocid, mpicom, rcode)
     454             :     !
     455             :     ! Override averaging flag for all fields on a particular tape if namelist input so specifies
     456             :     !
     457        9984 :     do t=1,ptapes
     458        9984 :       if (avgflag_pertape(t) /= ' ') then
     459           0 :         call h_override (t)
     460             :       end if
     461             :     end do
     462             :     !
     463             :     ! Define field list information for all history files.
     464             :     !
     465         768 :     call fldlst ()
     466             :     !
     467             :     ! Loop over max. no. of history files permitted
     468             :     !
     469         768 :     if (branch_run) then
     470           0 :       call get_prev_time(day, sec)  ! elapased time since reference date
     471             :     else
     472         768 :       call get_curr_time(day, sec)  ! elapased time since reference date
     473             :     end if
     474        9984 :     do t=1,ptapes
     475        9216 :       nfils(t) = 0            ! no. of time samples in hist. file no. t
     476             : 
     477             :       ! Time at beginning of current averaging interval.
     478             : 
     479        9984 :       beg_time(t) = day + sec/86400._r8
     480             :     end do
     481             : 
     482             :     !
     483             :     ! Initialize history variables
     484             :     !
     485        9984 :     do t=1,ptapes
     486      313344 :       do fld=1,nflds(t)
     487      303360 :         if (nhtfrq(t) == 1) then
     488             :            ! Override any non-I flags if nhtfrq equals 1
     489           0 :            tape(t)%hlist(fld)%avgflag = 'I'
     490             :         end if
     491      303360 :         if (tape(t)%hlist(fld)%avgflag .ne. 'I') then
     492      268032 :            hfile_accum(t) = .true.
     493             :         end if
     494      303360 :         begdim1  = tape(t)%hlist(fld)%field%begdim1
     495      303360 :         enddim1  = tape(t)%hlist(fld)%field%enddim1
     496      303360 :         begdim2  = tape(t)%hlist(fld)%field%begdim2
     497      303360 :         enddim2  = tape(t)%hlist(fld)%field%enddim2
     498      303360 :         begdim3  = tape(t)%hlist(fld)%field%begdim3
     499      303360 :         enddim3  = tape(t)%hlist(fld)%field%enddim3
     500     1516800 :         allocate(tape(t)%hlist(fld)%hbuf(begdim1:enddim1,begdim2:enddim2,begdim3:enddim3))
     501  1064741280 :         tape(t)%hlist(fld)%hbuf = 0._r8
     502      303360 :         if (tape(t)%hlist(fld)%avgflag .eq. 'S') then ! allocate the variance buffer for standard dev
     503           0 :            allocate(tape(t)%hlist(fld)%sbuf(begdim1:enddim1,begdim2:enddim2,begdim3:enddim3))
     504           0 :            tape(t)%hlist(fld)%sbuf = 0._r8
     505             :         endif
     506      303360 :         if (tape(t)%hlist(fld)%avgflag .eq. 'N') then ! set up areawt weight buffer
     507           0 :            fdecomp = tape(t)%hlist(fld)%field%decomp_type
     508           0 :            if (any(allgrids_wt(:)%decomp_type == fdecomp)) then
     509           0 :               wtidx=MAXLOC(allgrids_wt(:)%decomp_type, MASK = allgrids_wt(:)%decomp_type .EQ. fdecomp)
     510           0 :               tape(t)%hlist(fld)%wbuf => allgrids_wt(wtidx(1))%wbuf
     511             :            else
     512             :               ! area weights not found for this grid, then create them
     513             :               ! first check for an available spot in the array
     514           0 :               if (any(allgrids_wt(:)%decomp_type == -1)) then
     515           0 :                  wtidx=MINLOC(allgrids_wt(:)%decomp_type)
     516             :               else
     517           0 :                  call endrun('cam_history:intht: Error initializing allgrids_wt with area weights')
     518             :               end if
     519           0 :               allgrids_wt(wtidx)%decomp_type=fdecomp
     520           0 :               areawt => cam_grid_get_areawt(fdecomp)
     521           0 :               allocate(allgrids_wt(wtidx(1))%wbuf(begdim1:enddim1,begdim3:enddim3))
     522           0 :               allgrids_wt(wtidx(1))%wbuf(begdim1:enddim1,begdim3:enddim3)=0._r8
     523           0 :               count=0
     524           0 :               do c=begdim3,enddim3
     525           0 :                  dimind = tape(t)%hlist(fld)%field%get_dims(c)
     526           0 :                  ib=dimind%beg1
     527           0 :                  ie=dimind%end1
     528           0 :                  do i=ib,ie
     529           0 :                     count=count+1
     530           0 :                     allgrids_wt(wtidx(1))%wbuf(i,c)=areawt(count)
     531             :                  end do
     532             :               end do
     533           0 :               tape(t)%hlist(fld)%wbuf => allgrids_wt(wtidx(1))%wbuf
     534             :            endif
     535             :         endif
     536      303360 :         if(tape(t)%hlist(fld)%field%flag_xyfill .or. (avgflag_pertape(t) .eq. 'L')) then
     537       15360 :           allocate (tape(t)%hlist(fld)%nacs(begdim1:enddim1,begdim3:enddim3))
     538             :         else
     539      898560 :           allocate (tape(t)%hlist(fld)%nacs(1,begdim3:enddim3))
     540             :         end if
     541     3188760 :         tape(t)%hlist(fld)%nacs(:,:) = 0
     542      303360 :         tape(t)%hlist(fld)%beg_nstep = 0
     543      303360 :         tape(t)%hlist(fld)%field%meridional_complement = -1
     544      312576 :         tape(t)%hlist(fld)%field%zonal_complement = -1
     545             :       end do
     546             :     end do
     547             :     ! Setup vector pairs for unstructured grid interpolation
     548         768 :     call setup_interpolation_and_define_vector_complements()
     549             :     !  Initialize the sat following history subsystem
     550         768 :     call sat_hist_init()
     551             : 
     552         768 :     return
     553        3072 :   end subroutine intht
     554             : 
     555        1536 :   logical function history_initialized()
     556        1536 :     history_initialized = associated(masterlist)
     557        1536 :   end function history_initialized
     558             : 
     559        1536 :   subroutine history_readnl(nlfile)
     560             : 
     561             :     use namelist_utils, only: find_group_name
     562             :     use units,          only: getunit, freeunit
     563             :     use spmd_utils,     only: masterproc, masterprocid, mpicom
     564             :     use spmd_utils,     only: mpi_integer, mpi_logical, mpi_character
     565             :     use shr_string_mod, only: shr_string_toUpper
     566             :     use time_manager,   only: get_step_size
     567             :     use sat_hist,       only: sat_hist_readnl
     568             : 
     569             :     ! Dummy argument
     570             :     character(len=*), intent(in)   :: nlfile  ! filepath of namelist input file
     571             : 
     572             :     !
     573             :     ! Local variables
     574             :     integer                        :: dtime   ! Step time in seconds
     575             :     integer                        :: unitn, ierr, f, t
     576             :     character(len=8)               :: ctemp      ! Temporary character string
     577             :     integer                        :: filename_len
     578             : 
     579             :     character(len=fieldname_lenp2) :: fincl1(pflds)
     580             :     character(len=fieldname_lenp2) :: fincl2(pflds)
     581             :     character(len=fieldname_lenp2) :: fincl3(pflds)
     582             :     character(len=fieldname_lenp2) :: fincl4(pflds)
     583             :     character(len=fieldname_lenp2) :: fincl5(pflds)
     584             :     character(len=fieldname_lenp2) :: fincl6(pflds)
     585             :     character(len=fieldname_lenp2) :: fincl7(pflds)
     586             :     character(len=fieldname_lenp2) :: fincl8(pflds)
     587             :     character(len=fieldname_lenp2) :: fincl9(pflds)
     588             :     character(len=fieldname_lenp2) :: fincl10(pflds)
     589             : 
     590             :     character(len=max_chars)       :: fincl1lonlat(pflds)
     591             :     character(len=max_chars)       :: fincl2lonlat(pflds)
     592             :     character(len=max_chars)       :: fincl3lonlat(pflds)
     593             :     character(len=max_chars)       :: fincl4lonlat(pflds)
     594             :     character(len=max_chars)       :: fincl5lonlat(pflds)
     595             :     character(len=max_chars)       :: fincl6lonlat(pflds)
     596             :     character(len=max_chars)       :: fincl7lonlat(pflds)
     597             :     character(len=max_chars)       :: fincl8lonlat(pflds)
     598             :     character(len=max_chars)       :: fincl9lonlat(pflds)
     599             :     character(len=max_chars)       :: fincl10lonlat(pflds)
     600             : 
     601             :     character(len=fieldname_len)   :: fexcl1(pflds)
     602             :     character(len=fieldname_len)   :: fexcl2(pflds)
     603             :     character(len=fieldname_len)   :: fexcl3(pflds)
     604             :     character(len=fieldname_len)   :: fexcl4(pflds)
     605             :     character(len=fieldname_len)   :: fexcl5(pflds)
     606             :     character(len=fieldname_len)   :: fexcl6(pflds)
     607             :     character(len=fieldname_len)   :: fexcl7(pflds)
     608             :     character(len=fieldname_len)   :: fexcl8(pflds)
     609             :     character(len=fieldname_len)   :: fexcl9(pflds)
     610             :     character(len=fieldname_len)   :: fexcl10(pflds)
     611             : 
     612             :     character(len=fieldname_lenp2) :: fwrtpr1(pflds)
     613             :     character(len=fieldname_lenp2) :: fwrtpr2(pflds)
     614             :     character(len=fieldname_lenp2) :: fwrtpr3(pflds)
     615             :     character(len=fieldname_lenp2) :: fwrtpr4(pflds)
     616             :     character(len=fieldname_lenp2) :: fwrtpr5(pflds)
     617             :     character(len=fieldname_lenp2) :: fwrtpr6(pflds)
     618             :     character(len=fieldname_lenp2) :: fwrtpr7(pflds)
     619             :     character(len=fieldname_lenp2) :: fwrtpr8(pflds)
     620             :     character(len=fieldname_lenp2) :: fwrtpr9(pflds)
     621             :     character(len=fieldname_lenp2) :: fwrtpr10(pflds)
     622             : 
     623             :     integer                        :: interpolate_nlat(size(interpolate_info))
     624             :     integer                        :: interpolate_nlon(size(interpolate_info))
     625             :     integer                        :: interpolate_gridtype(size(interpolate_info))
     626             :     integer                        :: interpolate_type(size(interpolate_info))
     627             : 
     628             :     ! History namelist items
     629             :     namelist /cam_history_nl/ ndens, nhtfrq, mfilt, inithist, inithist_all,    &
     630             :          avgflag_pertape, empty_htapes, write_nstep0, lcltod_start, lcltod_stop,&
     631             :          fincl1lonlat, fincl2lonlat, fincl3lonlat, fincl4lonlat, fincl5lonlat, &
     632             :          fincl6lonlat, fincl7lonlat, fincl8lonlat, fincl9lonlat,               &
     633             :          fincl10lonlat, collect_column_output, hfilename_spec,                 &
     634             :          fincl1,  fincl2,  fincl3,  fincl4,  fincl5,                           &
     635             :          fincl6,  fincl7,  fincl8,  fincl9,  fincl10,                          &
     636             :          fexcl1,  fexcl2,  fexcl3,  fexcl4,  fexcl5,                           &
     637             :          fexcl6,  fexcl7,  fexcl8,  fexcl9,  fexcl10,                          &
     638             :          fwrtpr1, fwrtpr2, fwrtpr3, fwrtpr4, fwrtpr5,                          &
     639             :          fwrtpr6, fwrtpr7, fwrtpr8, fwrtpr9, fwrtpr10,                         &
     640             :          interpolate_nlat, interpolate_nlon,                                   &
     641             :          interpolate_gridtype, interpolate_type, interpolate_output
     642             : 
     643             :     ! Set namelist defaults (these should match initial values if given)
     644    18451968 :     fincl(:,:)               = ' '
     645    18451968 :     fincllonlat(:,:)         = ' '
     646    18451968 :     fexcl(:,:)               = ' '
     647    18451968 :     fwrtpr(:,:)              = ' '
     648        1536 :     collect_column_output(:) = .false.
     649       19968 :     avgflag_pertape(:)       = ' '
     650       19968 :     ndens                    = 2
     651        1536 :     nhtfrq(1)                = 0
     652       18432 :     nhtfrq(2:)               = -24
     653       19968 :     mfilt                    = 30
     654        1536 :     inithist                 = 'YEARLY'
     655        1536 :     inithist_all             = .false.
     656        1536 :     empty_htapes             = .false.
     657        1536 :     lcltod_start(:)          = 0
     658        1536 :     lcltod_stop(:)           = 0
     659       19968 :     hfilename_spec(:)        = ' '
     660        1536 :     interpolate_nlat(:)      = 0
     661        1536 :     interpolate_nlon(:)      = 0
     662       16896 :     interpolate_gridtype(:)  = 1
     663       16896 :     interpolate_type(:)      = 1
     664        1536 :     interpolate_output(:)    = .false.
     665             : 
     666             :     ! Initialize namelist 'temporary variables'
     667     1537536 :     do f = 1, pflds
     668     1536000 :       fincl1(f)        = ' '
     669     1536000 :       fincl2(f)        = ' '
     670     1536000 :       fincl3(f)        = ' '
     671     1536000 :       fincl4(f)        = ' '
     672     1536000 :       fincl5(f)        = ' '
     673     1536000 :       fincl6(f)        = ' '
     674     1536000 :       fincl7(f)        = ' '
     675     1536000 :       fincl8(f)        = ' '
     676     1536000 :       fincl9(f)        = ' '
     677     1536000 :       fincl10(f)       = ' '
     678     1536000 :       fincl1lonlat(f)  = ' '
     679     1536000 :       fincl2lonlat(f)  = ' '
     680     1536000 :       fincl3lonlat(f)  = ' '
     681     1536000 :       fincl4lonlat(f)  = ' '
     682     1536000 :       fincl5lonlat(f)  = ' '
     683     1536000 :       fincl6lonlat(f)  = ' '
     684     1536000 :       fincl7lonlat(f)  = ' '
     685     1536000 :       fincl8lonlat(f)  = ' '
     686     1536000 :       fincl9lonlat(f)  = ' '
     687     1536000 :       fincl10lonlat(f) = ' '
     688     1536000 :       fexcl1(f)        = ' '
     689     1536000 :       fexcl2(f)        = ' '
     690     1536000 :       fexcl3(f)        = ' '
     691     1536000 :       fexcl4(f)        = ' '
     692     1536000 :       fexcl5(f)        = ' '
     693     1536000 :       fexcl6(f)        = ' '
     694     1536000 :       fexcl7(f)        = ' '
     695     1536000 :       fexcl8(f)        = ' '
     696     1536000 :       fexcl9(f)        = ' '
     697     1536000 :       fexcl10(f)       = ' '
     698     1536000 :       fwrtpr1(f)       = ' '
     699     1536000 :       fwrtpr2(f)       = ' '
     700     1536000 :       fwrtpr3(f)       = ' '
     701     1536000 :       fwrtpr4(f)       = ' '
     702     1536000 :       fwrtpr5(f)       = ' '
     703     1536000 :       fwrtpr6(f)       = ' '
     704     1536000 :       fwrtpr7(f)       = ' '
     705     1536000 :       fwrtpr8(f)       = ' '
     706     1536000 :       fwrtpr9(f)       = ' '
     707     1537536 :       fwrtpr10(f)      = ' '
     708             :     end do
     709             : 
     710             :     if (trim(history_namelist) /= 'cam_history_nl') then
     711             :       call endrun('HISTORY_READNL: CAM history namelist mismatch')
     712             :     end if
     713        1536 :     if (masterproc) then
     714           2 :       write(iulog, *) 'Read in ',history_namelist,' namelist from: ',trim(nlfile)
     715           2 :       unitn = getunit()
     716           2 :       open(unitn, file=trim(nlfile), status='old')
     717           2 :       call find_group_name(unitn, history_namelist, status=ierr)
     718           2 :       if (ierr == 0) then
     719           0 :         read(unitn, cam_history_nl, iostat=ierr)
     720           0 :         if (ierr /= 0) then
     721           0 :           call endrun('history_readnl: ERROR reading namelist, '//trim(history_namelist))
     722             :         end if
     723             :       end if
     724           2 :       close(unitn)
     725           2 :       call freeunit(unitn)
     726             : 
     727        2002 :       do f = 1, pflds
     728        2000 :         fincl(f, 1) = fincl1(f)
     729        2000 :         fincl(f, 2) = fincl2(f)
     730        2000 :         fincl(f, 3) = fincl3(f)
     731        2000 :         fincl(f, 4) = fincl4(f)
     732        2000 :         fincl(f, 5) = fincl5(f)
     733        2000 :         fincl(f, 6) = fincl6(f)
     734        2000 :         fincl(f, 7) = fincl7(f)
     735        2000 :         fincl(f, 8) = fincl8(f)
     736        2000 :         fincl(f, 9) = fincl9(f)
     737        2000 :         fincl(f,10) = fincl10(f)
     738             : 
     739        2000 :         fincllonlat(f, 1) = fincl1lonlat(f)
     740        2000 :         fincllonlat(f, 2) = fincl2lonlat(f)
     741        2000 :         fincllonlat(f, 3) = fincl3lonlat(f)
     742        2000 :         fincllonlat(f, 4) = fincl4lonlat(f)
     743        2000 :         fincllonlat(f, 5) = fincl5lonlat(f)
     744        2000 :         fincllonlat(f, 6) = fincl6lonlat(f)
     745        2000 :         fincllonlat(f, 7) = fincl7lonlat(f)
     746        2000 :         fincllonlat(f, 8) = fincl8lonlat(f)
     747        2000 :         fincllonlat(f, 9) = fincl9lonlat(f)
     748        2000 :         fincllonlat(f,10) = fincl10lonlat(f)
     749             : 
     750        2000 :         fexcl(f, 1) = fexcl1(f)
     751        2000 :         fexcl(f, 2) = fexcl2(f)
     752        2000 :         fexcl(f, 3) = fexcl3(f)
     753        2000 :         fexcl(f, 4) = fexcl4(f)
     754        2000 :         fexcl(f, 5) = fexcl5(f)
     755        2000 :         fexcl(f, 6) = fexcl6(f)
     756        2000 :         fexcl(f, 7) = fexcl7(f)
     757        2000 :         fexcl(f, 8) = fexcl8(f)
     758        2000 :         fexcl(f, 9) = fexcl9(f)
     759        2000 :         fexcl(f,10) = fexcl10(f)
     760             : 
     761        2000 :         fwrtpr(f, 1) = fwrtpr1(f)
     762        2000 :         fwrtpr(f, 2) = fwrtpr2(f)
     763        2000 :         fwrtpr(f, 3) = fwrtpr3(f)
     764        2000 :         fwrtpr(f, 4) = fwrtpr4(f)
     765        2000 :         fwrtpr(f, 5) = fwrtpr5(f)
     766        2000 :         fwrtpr(f, 6) = fwrtpr6(f)
     767        2000 :         fwrtpr(f, 7) = fwrtpr7(f)
     768        2000 :         fwrtpr(f, 8) = fwrtpr8(f)
     769        2000 :         fwrtpr(f, 9) = fwrtpr9(f)
     770        2002 :         fwrtpr(f,10) = fwrtpr10(f)
     771             :       end do
     772             : 
     773             :       !
     774             :       ! If generate an initial conditions history file as an auxillary tape:
     775             :       !
     776           2 :       ctemp = shr_string_toUpper(inithist)
     777           2 :       inithist = trim(ctemp)
     778             :       if ( (inithist /= '6-HOURLY') .and. (inithist /= 'DAILY')  .and.        &
     779             :            (inithist /= 'MONTHLY')  .and. (inithist /= 'YEARLY') .and.        &
     780           2 :            (inithist /= 'CAMIOP')   .and. (inithist /= 'ENDOFRUN')) then
     781           0 :         inithist = 'NONE'
     782             :       end if
     783             :       !
     784             :       ! History file write times
     785             :       ! Convert write freq. of hist files from hours to timesteps if necessary.
     786             :       !
     787           2 :       dtime = get_step_size()
     788          26 :       do t = 1, ptapes
     789          26 :         if (nhtfrq(t) < 0) then
     790          22 :           nhtfrq(t) = nint((-nhtfrq(t) * 3600._r8) / dtime)
     791             :         end if
     792             :       end do
     793             :       ! If nhtfrq == 1, then the output is instantaneous.  Enforce this by setting
     794             :       ! the per-file averaging flag.
     795          26 :       do t = 1, ptapes
     796          26 :         if (nhtfrq(t) == 1) then
     797           0 :           avgflag_pertape(t) = 'I'
     798             :         end if
     799             :       end do
     800             :       !
     801             :       ! Initialize the filename specifier if not already set
     802             :       ! This is the format for the history filenames:
     803             :       ! %c= caseid, %t=tape no., %y=year, %m=month, %d=day, %s=second, %%=%
     804             :       ! See the filenames module for more information
     805             :       !
     806          26 :       do t = 1, ptapes
     807          24 :         if ( len_trim(hfilename_spec(t)) == 0 )then
     808          24 :           if ( nhtfrq(t) == 0 )then
     809             :             ! Monthly files
     810           2 :             hfilename_spec(t) = '%c.cam' // trim(inst_suffix) // '.h%t%f.%y-%m.nc'
     811             :           else
     812          22 :             hfilename_spec(t) = '%c.cam' // trim(inst_suffix) // '.h%t%f.%y-%m-%d-%s.nc'
     813             :           end if
     814             :         else
     815             :            ! Append file type - instantaneous or accumulated - to filename
     816             :            ! specifier provided (in front of the .nc extension).
     817           0 :            filename_len = len_trim(hfilename_spec(t))
     818           0 :            hfilename_spec(t) = hfilename_spec(t)(:filename_len-3)  // '%f.nc'
     819             :         end if
     820             :         !
     821             :         ! Only one time sample allowed per monthly average file
     822             :         !
     823          26 :         if (nhtfrq(t) == 0) then
     824           2 :           mfilt(t) = 1
     825             :         end if
     826             :       end do
     827             :     end if ! masterproc
     828             : 
     829             :     ! log output
     830        1536 :     if (masterproc) then
     831             : 
     832           2 :       if (write_nstep0) then
     833           0 :         write(iulog,*)'nstep==0 time sample will be written to all files except monthly average.'
     834             :       end if
     835             : 
     836             :       ! Print per-tape averaging flags
     837          26 :       do t = 1, ptapes
     838          24 :         if (avgflag_pertape(t) /= ' ') then
     839           0 :           write(iulog,*)'Unless overridden by namelist input on a per-field basis (FINCL),'
     840           0 :           write(iulog,*)'All fields on history file ',t,' will have averaging flag ',avgflag_pertape(t)
     841             :         end if
     842             :         ! Enforce no interpolation for satellite files
     843          24 :         if (is_satfile(t) .and. interpolate_output(t)) then
     844           0 :           write(iulog, *) 'WARNING: Interpolated output not supported for a satellite history file, ignored'
     845           0 :           interpolate_output(t) = .false.
     846             :         end if
     847             :         ! Enforce no interpolation for IC files
     848          26 :         if (is_initfile(t) .and. interpolate_output(t)) then
     849           0 :           write(iulog, *) 'WARNING: Interpolated output not supported for an initial data (IC) history file, ignored'
     850           0 :           interpolate_output(t) = .false.
     851             :         end if
     852             :       end do
     853             :     end if
     854             : 
     855             :     ! Write out inithist info
     856        1536 :     if (masterproc) then
     857           2 :       if (inithist == '6-HOURLY' ) then
     858           0 :         write(iulog,*)'Initial conditions history files will be written 6-hourly.'
     859           2 :       else if (inithist == 'DAILY' ) then
     860           0 :         write(iulog,*)'Initial conditions history files will be written daily.'
     861           2 :       else if (inithist == 'MONTHLY' ) then
     862           0 :         write(iulog,*)'Initial conditions history files will be written monthly.'
     863           2 :       else if (inithist == 'YEARLY' ) then
     864           2 :         write(iulog,*)'Initial conditions history files will be written yearly.'
     865           0 :       else if (inithist == 'CAMIOP' ) then
     866           0 :         write(iulog,*)'Initial conditions history files will be written for IOP.'
     867           0 :       else if (inithist == 'ENDOFRUN' ) then
     868           0 :         write(iulog,*)'Initial conditions history files will be written at end of run.'
     869             :       else
     870           0 :         write(iulog,*)'Initial conditions history files will not be created'
     871             :       end if
     872             :     end if
     873             : 
     874             :     ! Print out column-output information
     875       19968 :     do t = 1, size(fincllonlat, 2)
     876    18451968 :       if (ANY(len_trim(fincllonlat(:,t)) > 0)) then
     877           0 :         if (collect_column_output(t)) then
     878           0 :           write(iulog, '(a,i2,a)') 'History file, ',t,', has patch output, columns will be collected into ncol dimension'
     879             :         else
     880           0 :           write(iulog, '(a,i2,a)') 'History file, ',t,', has patch output, patches will be written to individual variables'
     881             :         end if
     882             :       end if
     883             :     end do
     884             : 
     885             :     ! Broadcast namelist variables
     886        1536 :     call mpi_bcast(ndens, ptapes, mpi_integer, masterprocid, mpicom, ierr)
     887        1536 :     call mpi_bcast(nhtfrq, ptapes, mpi_integer, masterprocid, mpicom, ierr)
     888        1536 :     call mpi_bcast(mfilt, ptapes, mpi_integer, masterprocid, mpicom, ierr)
     889        1536 :     call mpi_bcast(inithist,len(inithist), mpi_character, masterprocid, mpicom, ierr)
     890        1536 :     call mpi_bcast(inithist_all,1, mpi_logical, masterprocid, mpicom, ierr)
     891        1536 :     call mpi_bcast(lcltod_start, ptapes, mpi_integer, masterprocid, mpicom, ierr)
     892        1536 :     call mpi_bcast(lcltod_stop,  ptapes, mpi_integer, masterprocid, mpicom, ierr)
     893        1536 :     call mpi_bcast(collect_column_output, ptapes, mpi_logical, masterprocid, mpicom, ierr)
     894        1536 :     call mpi_bcast(empty_htapes,1, mpi_logical, masterprocid, mpicom, ierr)
     895        1536 :     call mpi_bcast(write_nstep0,1, mpi_logical, masterprocid, mpicom, ierr)
     896        1536 :     call mpi_bcast(avgflag_pertape, ptapes, mpi_character, masterprocid, mpicom, ierr)
     897        1536 :     call mpi_bcast(hfilename_spec, len(hfilename_spec(1))*ptapes, mpi_character, masterprocid, mpicom, ierr)
     898        1536 :     call mpi_bcast(fincl, len(fincl (1,1))*pflds*ptapes, mpi_character, masterprocid, mpicom, ierr)
     899        1536 :     call mpi_bcast(fexcl, len(fexcl (1,1))*pflds*ptapes, mpi_character, masterprocid, mpicom, ierr)
     900             : 
     901        1536 :     call mpi_bcast(fincllonlat, len(fincllonlat (1,1))*pflds*ptapes, mpi_character, masterprocid, mpicom, ierr)
     902             : 
     903        1536 :     call mpi_bcast(fwrtpr, len(fwrtpr(1,1))*pflds*ptapes, mpi_character, masterprocid, mpicom, ierr)
     904        1536 :     t = size(interpolate_nlat, 1)
     905        1536 :     call mpi_bcast(interpolate_nlat, t, mpi_integer, masterprocid, mpicom, ierr)
     906        1536 :     call mpi_bcast(interpolate_nlon, t, mpi_integer, masterprocid, mpicom, ierr)
     907        1536 :     call mpi_bcast(interpolate_gridtype, t, mpi_integer, masterprocid, mpicom, ierr)
     908        1536 :     call mpi_bcast(interpolate_type, t, mpi_integer, masterprocid, mpicom, ierr)
     909        1536 :     call mpi_bcast(interpolate_output, ptapes, mpi_logical, masterprocid, mpicom, ierr)
     910             : 
     911             :     ! Setup the interpolate_info structures
     912       16896 :     do t = 1, size(interpolate_info)
     913       15360 :       interpolate_info(t)%interp_type = interpolate_type(t)
     914       15360 :       interpolate_info(t)%interp_gridtype = interpolate_gridtype(t)
     915       15360 :       interpolate_info(t)%interp_nlat = interpolate_nlat(t)
     916       16896 :       interpolate_info(t)%interp_nlon = interpolate_nlon(t)
     917             :     end do
     918             : 
     919             :     ! separate namelist reader for the satellite history file
     920        1536 :     call sat_hist_readnl(nlfile, hfilename_spec, mfilt, fincl, nhtfrq, avgflag_pertape)
     921             : 
     922        1536 :   end subroutine history_readnl
     923             : 
     924             : !==================================================================================================
     925             : 
     926     5068032 :   subroutine set_field_dimensions(field)
     927        1536 :     use cam_history_support, only: hist_coord_size
     928             :     use cam_grid_support,    only: cam_grid_get_array_bounds, cam_grid_is_block_indexed
     929             :     ! Dummy arguments
     930             :     type(field_info), intent(inout) :: field
     931             : 
     932             :     ! Local variables
     933             :     integer                         :: i
     934             :     integer                         :: msize
     935             :     integer                         :: dimbounds(2,2)
     936             : 
     937     5068032 :     call cam_grid_get_array_bounds(field%decomp_type, dimbounds)
     938     5068032 :     field%begdim1  = dimbounds(1,1)
     939     5068032 :     field%enddim1  = dimbounds(1,2)
     940     5068032 :     field%begdim2  = 1
     941     5068032 :     if (associated(field%mdims)) then
     942     4741632 :       if (size(field%mdims) > 0) then
     943     2833920 :         field%enddim2  = 1
     944     5667840 :         do i = 1, size(field%mdims)
     945     2833920 :           msize = hist_coord_size(field%mdims(i))
     946     2833920 :           if (msize <= 0) then
     947           0 :             call endrun('set_field_dimensions: mdim size must be > 0')
     948             :           end if
     949     5667840 :           field%enddim2 = field%enddim2 * msize
     950             :         end do
     951             :       else
     952     1907712 :         if (field%numlev < 1) then
     953           0 :           if (masterproc) then
     954           0 :             write(iulog, *) 'SET_FIELD_DIMENSIONS WARNING: illegal numlev for ', trim(field%name)
     955             :           end if
     956           0 :           field%numlev = 1
     957             :         end if
     958     1907712 :         field%enddim2 = field%numlev
     959             :       end if
     960             :     else
     961      326400 :       if (field%numlev < 1) then
     962           0 :         if (masterproc) then
     963           0 :           write(iulog, *) 'SET_FIELD_DIMENSIONS WARNING: illegal numlev for ', trim(field%name)
     964             :         end if
     965           0 :         field%numlev = 1
     966             :       end if
     967      326400 :       field%enddim2 = field%numlev
     968             :     end if
     969     5068032 :     field%begdim3  = dimbounds(2,1)
     970     5068032 :     field%enddim3  = dimbounds(2,2)
     971     5068032 :     field%colperchunk = cam_grid_is_block_indexed(field%decomp_type)
     972             : 
     973     5068032 :   end subroutine set_field_dimensions
     974             : 
     975        1536 :   subroutine setup_interpolation_and_define_vector_complements()
     976     5068032 :     use interp_mod, only: setup_history_interpolation
     977             : 
     978             :     ! Local variables
     979             :     integer :: hf, fld, ffld
     980             :     logical :: interp_ok
     981             :     character(len=max_fieldname_len) :: mname
     982             :     character(len=max_fieldname_len) :: zname
     983             :     character(len=*), parameter      :: subname='setup_interpolation_and_define_vector_complements'
     984             : 
     985             :     ! Do not interpolate IC history and sat hist files
     986       19968 :     if (any(interpolate_output)) then
     987             :       call setup_history_interpolation(interp_ok, ptapes-2,                   &
     988           0 :            interpolate_output, interpolate_info)
     989           0 :       do hf = 1, ptapes - 2
     990           0 :         if((.not. is_satfile(hf)) .and. (.not. is_initfile(hf))) then
     991           0 :           do fld = 1, nflds(hf)
     992           0 :             if (field_part_of_vector(trim(tape(hf)%hlist(fld)%field%name),      &
     993           0 :                  mname, zname)) then
     994           0 :               if (len_trim(mname) > 0) then
     995             :                 ! This field is a zonal part of a set, find the meridional partner
     996           0 :                 do ffld = 1, nflds(hf)
     997           0 :                   if (trim(mname) == trim(tape(hf)%hlist(ffld)%field%name)) then
     998           0 :                     tape(hf)%hlist(fld)%field%meridional_complement = ffld
     999           0 :                     tape(hf)%hlist(ffld)%field%zonal_complement     = fld
    1000           0 :                     exit
    1001             :                   end if
    1002           0 :                   if (ffld == nflds(hf)) then
    1003           0 :                     call endrun(trim(subname)//': No meridional match for '//trim(tape(hf)%hlist(fld)%field%name))
    1004             :                   end if
    1005             :                 end do
    1006           0 :               else if (len_trim(zname) > 0) then
    1007             :                 ! This field is a meridional part of a set, find the zonal partner
    1008           0 :                 do ffld = 1, nflds(hf)
    1009           0 :                   if (trim(zname) == trim(tape(hf)%hlist(ffld)%field%name)) then
    1010           0 :                     tape(hf)%hlist(fld)%field%zonal_complement       = ffld
    1011           0 :                     tape(hf)%hlist(ffld)%field%meridional_complement = fld
    1012           0 :                     exit
    1013             :                   end if
    1014           0 :                   if (ffld == nflds(hf)) then
    1015           0 :                     call endrun(trim(subname)//': No zonal match for '//trim(tape(hf)%hlist(fld)%field%name))
    1016             :                   end if
    1017             :                 end do
    1018             :               else
    1019           0 :                 call endrun(trim(subname)//': INTERNAL ERROR, bad vector field')
    1020             :               end if
    1021             :             end if
    1022             :           end do
    1023             :         end if
    1024             :       end do
    1025             :     end if
    1026        1536 :   end subroutine setup_interpolation_and_define_vector_complements
    1027             : 
    1028        9216 :   subroutine define_composed_field_ids(t)
    1029             : 
    1030             :     ! Dummy arguments
    1031             :     integer, intent(in)               :: t     ! Current tape
    1032             : 
    1033             :     ! Local variables
    1034             :     integer :: fld, ffld
    1035             :     character(len=max_fieldname_len) :: field1
    1036             :     character(len=max_fieldname_len) :: field2
    1037             :     character(len=*), parameter      :: subname='define_composed_field_ids'
    1038             :     logical                          :: is_composed
    1039             : 
    1040      312576 :     do fld = 1, nflds(t)
    1041      303360 :        call composed_field_info(tape(t)%hlist(fld)%field%name,is_composed,fname1=field1,fname2=field2)
    1042      312576 :        if (is_composed) then
    1043           0 :           if (len_trim(field1) > 0 .and. len_trim(field2) > 0) then
    1044             :              ! set field1/field2 names for htape from the masterfield list
    1045           0 :              tape(t)%hlist(fld)%op_field1=trim(field1)
    1046           0 :              tape(t)%hlist(fld)%op_field2=trim(field2)
    1047             :              ! find ids for field1/2
    1048           0 :              do ffld = 1, nflds(t)
    1049           0 :                 if (trim(field1) == trim(tape(t)%hlist(ffld)%field%name)) then
    1050           0 :                    tape(t)%hlist(fld)%field%op_field1_id = ffld
    1051             :                 end if
    1052           0 :                 if (trim(field2) == trim(tape(t)%hlist(ffld)%field%name)) then
    1053           0 :                    tape(t)%hlist(fld)%field%op_field2_id = ffld
    1054             :                 end if
    1055             :              end do
    1056           0 :              if (tape(t)%hlist(fld)%field%op_field1_id == -1) then
    1057           0 :                 call endrun(trim(subname)//': No op_field1 match for '//trim(tape(t)%hlist(fld)%field%name))
    1058             :              end if
    1059           0 :              if (tape(t)%hlist(fld)%field%op_field2_id == -1) then
    1060           0 :                 call endrun(trim(subname)//': No op_field2 match for '//trim(tape(t)%hlist(fld)%field%name))
    1061             :              end if
    1062             :           else
    1063           0 :              call endrun(trim(subname)//': Component fields not found for composed field')
    1064             :           end if
    1065             :        end if
    1066             :     end do
    1067        1536 :   end subroutine define_composed_field_ids
    1068             : 
    1069        1536 :   subroutine restart_vars_setnames()
    1070             : 
    1071             :     ! Local variable
    1072             :     integer :: rvindex
    1073             : 
    1074        1536 :     rvindex = 1
    1075        1536 :     restartvars(rvindex)%name = 'rgnht'
    1076        1536 :     restartvars(rvindex)%type = pio_int
    1077        1536 :     restartvars(rvindex)%ndims = 1
    1078        1536 :     restartvars(rvindex)%dims(1) = ptapes_dim_ind
    1079             : 
    1080        1536 :     rvindex = rvindex + 1
    1081        1536 :     restartvars(rvindex)%name = 'nhtfrq'
    1082        1536 :     restartvars(rvindex)%type = pio_int
    1083        1536 :     restartvars(rvindex)%ndims = 1
    1084        1536 :     restartvars(rvindex)%dims(1) = ptapes_dim_ind
    1085             : 
    1086        1536 :     rvindex = rvindex + 1
    1087        1536 :     restartvars(rvindex)%name = 'nflds'
    1088        1536 :     restartvars(rvindex)%type = pio_int
    1089        1536 :     restartvars(rvindex)%ndims = 1
    1090        1536 :     restartvars(rvindex)%dims(1) = ptapes_dim_ind
    1091             : 
    1092        1536 :     rvindex = rvindex + 1
    1093        1536 :     restartvars(rvindex)%name = 'nfils'
    1094        1536 :     restartvars(rvindex)%type = pio_int
    1095        1536 :     restartvars(rvindex)%ndims = 1
    1096        1536 :     restartvars(rvindex)%dims(1) = ptapes_dim_ind
    1097             : 
    1098        1536 :     rvindex = rvindex + 1
    1099        1536 :     restartvars(rvindex)%name = 'mfilt'
    1100        1536 :     restartvars(rvindex)%type = pio_int
    1101        1536 :     restartvars(rvindex)%ndims = 1
    1102        1536 :     restartvars(rvindex)%dims(1) = ptapes_dim_ind
    1103             : 
    1104        1536 :     rvindex = rvindex + 1
    1105        1536 :     restartvars(rvindex)%name = 'nfpath'
    1106        1536 :     restartvars(rvindex)%type = pio_char
    1107        1536 :     restartvars(rvindex)%ndims = 2
    1108        1536 :     restartvars(rvindex)%dims(1) = max_string_len_dim_ind
    1109        1536 :     restartvars(rvindex)%dims(2) = ptapes_dim_ind
    1110             : 
    1111        1536 :     rvindex = rvindex + 1
    1112        1536 :     restartvars(rvindex)%name = 'cpath'
    1113        1536 :     restartvars(rvindex)%type = pio_char
    1114        1536 :     restartvars(rvindex)%ndims = 3
    1115        1536 :     restartvars(rvindex)%dims(1) = max_string_len_dim_ind
    1116        1536 :     restartvars(rvindex)%dims(2) = ptapes_dim_ind
    1117        1536 :     restartvars(rvindex)%dims(3) = max_num_split_files
    1118             : 
    1119        1536 :     rvindex = rvindex + 1
    1120        1536 :     restartvars(rvindex)%name = 'nhfil'
    1121        1536 :     restartvars(rvindex)%type = pio_char
    1122        1536 :     restartvars(rvindex)%ndims = 3
    1123        1536 :     restartvars(rvindex)%dims(1) = max_string_len_dim_ind
    1124        1536 :     restartvars(rvindex)%dims(2) = ptapes_dim_ind
    1125        1536 :     restartvars(rvindex)%dims(3) = max_num_split_files
    1126             : 
    1127        1536 :     rvindex = rvindex + 1
    1128        1536 :     restartvars(rvindex)%name = 'ndens'
    1129        1536 :     restartvars(rvindex)%type = pio_int
    1130        1536 :     restartvars(rvindex)%ndims = 1
    1131        1536 :     restartvars(rvindex)%dims(1) = ptapes_dim_ind
    1132             : 
    1133        1536 :     rvindex = rvindex + 1
    1134        1536 :     restartvars(rvindex)%name = 'fincllonlat'
    1135        1536 :     restartvars(rvindex)%type = pio_char
    1136        1536 :     restartvars(rvindex)%ndims = 3
    1137        1536 :     restartvars(rvindex)%dims(1) = max_chars_dim_ind
    1138        1536 :     restartvars(rvindex)%dims(2) = pflds_dim_ind
    1139        1536 :     restartvars(rvindex)%dims(3) = ptapes_dim_ind
    1140             : 
    1141        1536 :     rvindex = rvindex + 1
    1142        1536 :     restartvars(rvindex)%name = 'ncprec'
    1143        1536 :     restartvars(rvindex)%type = pio_int
    1144        1536 :     restartvars(rvindex)%ndims = 1
    1145        1536 :     restartvars(rvindex)%dims(1) = ptapes_dim_ind
    1146             : 
    1147        1536 :     rvindex = rvindex + 1
    1148        1536 :     restartvars(rvindex)%name = 'beg_time'
    1149        1536 :     restartvars(rvindex)%type = pio_double
    1150        1536 :     restartvars(rvindex)%ndims = 1
    1151        1536 :     restartvars(rvindex)%dims(1) = ptapes_dim_ind
    1152             : 
    1153        1536 :     rvindex = rvindex + 1
    1154        1536 :     restartvars(rvindex)%name = 'fincl'
    1155        1536 :     restartvars(rvindex)%type = pio_char
    1156        1536 :     restartvars(rvindex)%ndims = 3
    1157        1536 :     restartvars(rvindex)%dims(1) = fieldname_lenp2_dim_ind
    1158        1536 :     restartvars(rvindex)%dims(2) = pflds_dim_ind
    1159        1536 :     restartvars(rvindex)%dims(3) = ptapes_dim_ind
    1160             : 
    1161        1536 :     rvindex = rvindex + 1
    1162        1536 :     restartvars(rvindex)%name = 'fexcl'
    1163        1536 :     restartvars(rvindex)%type = pio_char
    1164        1536 :     restartvars(rvindex)%ndims = 3
    1165        1536 :     restartvars(rvindex)%dims(1) = fieldname_lenp2_dim_ind
    1166        1536 :     restartvars(rvindex)%dims(2) = pflds_dim_ind
    1167        1536 :     restartvars(rvindex)%dims(3) = ptapes_dim_ind
    1168             : 
    1169        1536 :     rvindex = rvindex + 1
    1170        1536 :     restartvars(rvindex)%name = 'field_name'
    1171        1536 :     restartvars(rvindex)%type = pio_char
    1172        1536 :     restartvars(rvindex)%ndims = 3
    1173        1536 :     restartvars(rvindex)%dims(1) = max_fieldname_len_dim_ind
    1174        1536 :     restartvars(rvindex)%dims(2) = maxnflds_dim_ind
    1175        1536 :     restartvars(rvindex)%dims(3) = ptapes_dim_ind
    1176             : 
    1177        1536 :     rvindex = rvindex + 1
    1178        1536 :     restartvars(rvindex)%name = 'decomp_type'
    1179        1536 :     restartvars(rvindex)%type = pio_int
    1180        1536 :     restartvars(rvindex)%ndims = 2
    1181        1536 :     restartvars(rvindex)%dims(1) = maxnflds_dim_ind
    1182        1536 :     restartvars(rvindex)%dims(2) = ptapes_dim_ind
    1183        1536 :     restartvars(rvindex)%fillset = .true.
    1184        1536 :     restartvars(rvindex)%ifill = 0
    1185             : 
    1186        1536 :     rvindex = rvindex + 1
    1187        1536 :     restartvars(rvindex)%name = 'numlev'
    1188        1536 :     restartvars(rvindex)%type = pio_int
    1189        1536 :     restartvars(rvindex)%ndims = 2
    1190        1536 :     restartvars(rvindex)%dims(1) = maxnflds_dim_ind
    1191        1536 :     restartvars(rvindex)%dims(2) = ptapes_dim_ind
    1192        1536 :     restartvars(rvindex)%fillset = .true.
    1193        1536 :     restartvars(rvindex)%ifill = 0
    1194             : 
    1195        1536 :     rvindex = rvindex + 1
    1196        1536 :     restartvars(rvindex)%name = 'hrestpath'
    1197        1536 :     restartvars(rvindex)%type = pio_char
    1198        1536 :     restartvars(rvindex)%ndims = 2
    1199        1536 :     restartvars(rvindex)%dims(1) = max_string_len_dim_ind
    1200        1536 :     restartvars(rvindex)%dims(2) = ptapes_dim_ind
    1201             : 
    1202        1536 :     rvindex = rvindex + 1
    1203        1536 :     restartvars(rvindex)%name = 'hwrt_prec'
    1204        1536 :     restartvars(rvindex)%type = pio_int
    1205        1536 :     restartvars(rvindex)%ndims = 2
    1206        1536 :     restartvars(rvindex)%dims(1) = maxnflds_dim_ind
    1207        1536 :     restartvars(rvindex)%dims(2) = ptapes_dim_ind
    1208        1536 :     restartvars(rvindex)%fillset = .true.
    1209        1536 :     restartvars(rvindex)%ifill = 0
    1210             : 
    1211        1536 :     rvindex = rvindex + 1
    1212        1536 :     restartvars(rvindex)%name = 'beg_nstep'
    1213        1536 :     restartvars(rvindex)%type = pio_int
    1214        1536 :     restartvars(rvindex)%ndims = 2
    1215        1536 :     restartvars(rvindex)%dims(1) = maxnflds_dim_ind
    1216        1536 :     restartvars(rvindex)%dims(2) = ptapes_dim_ind
    1217        1536 :     restartvars(rvindex)%fillset = .true.
    1218        1536 :     restartvars(rvindex)%ifill = 0
    1219             : 
    1220        1536 :     rvindex = rvindex + 1
    1221        1536 :     restartvars(rvindex)%name = 'hbuf_integral'
    1222        1536 :     restartvars(rvindex)%type = pio_double
    1223        1536 :     restartvars(rvindex)%ndims = 2
    1224        1536 :     restartvars(rvindex)%dims(1) = maxnflds_dim_ind
    1225        1536 :     restartvars(rvindex)%dims(2) = ptapes_dim_ind
    1226        1536 :     restartvars(rvindex)%fillset = .true.
    1227        1536 :     restartvars(rvindex)%ifill = 0
    1228             : 
    1229             : 
    1230        1536 :     rvindex = rvindex + 1
    1231        1536 :     restartvars(rvindex)%name = 'avgflag'
    1232        1536 :     restartvars(rvindex)%type = pio_char
    1233        1536 :     restartvars(rvindex)%ndims = 2
    1234        1536 :     restartvars(rvindex)%dims(1) = maxnflds_dim_ind
    1235        1536 :     restartvars(rvindex)%dims(2) = ptapes_dim_ind
    1236             : 
    1237        1536 :     rvindex = rvindex + 1
    1238        1536 :     restartvars(rvindex)%name = 'sampling_seq'
    1239        1536 :     restartvars(rvindex)%type = pio_char
    1240        1536 :     restartvars(rvindex)%ndims = 3
    1241        1536 :     restartvars(rvindex)%dims(1) = max_chars_dim_ind
    1242        1536 :     restartvars(rvindex)%dims(2) = maxnflds_dim_ind
    1243        1536 :     restartvars(rvindex)%dims(3) = ptapes_dim_ind
    1244             : 
    1245        1536 :     rvindex = rvindex + 1
    1246        1536 :     restartvars(rvindex)%name = 'cell_methods'
    1247        1536 :     restartvars(rvindex)%type = pio_char
    1248        1536 :     restartvars(rvindex)%ndims = 3
    1249        1536 :     restartvars(rvindex)%dims(1) = max_chars_dim_ind
    1250        1536 :     restartvars(rvindex)%dims(2) = maxnflds_dim_ind
    1251        1536 :     restartvars(rvindex)%dims(3) = ptapes_dim_ind
    1252             : 
    1253        1536 :     rvindex = rvindex + 1
    1254        1536 :     restartvars(rvindex)%name = 'long_name'
    1255        1536 :     restartvars(rvindex)%type = pio_char
    1256        1536 :     restartvars(rvindex)%ndims = 3
    1257        1536 :     restartvars(rvindex)%dims(1) = max_chars_dim_ind
    1258        1536 :     restartvars(rvindex)%dims(2) = maxnflds_dim_ind
    1259        1536 :     restartvars(rvindex)%dims(3) = ptapes_dim_ind
    1260             : 
    1261        1536 :     rvindex = rvindex + 1
    1262        1536 :     restartvars(rvindex)%name = 'units'
    1263        1536 :     restartvars(rvindex)%type = pio_char
    1264        1536 :     restartvars(rvindex)%ndims = 3
    1265        1536 :     restartvars(rvindex)%dims(1) = max_chars_dim_ind
    1266        1536 :     restartvars(rvindex)%dims(2) = maxnflds_dim_ind
    1267        1536 :     restartvars(rvindex)%dims(3) = ptapes_dim_ind
    1268             : 
    1269        1536 :     rvindex = rvindex + 1
    1270        1536 :     restartvars(rvindex)%name = 'xyfill'
    1271        1536 :     restartvars(rvindex)%type = pio_int
    1272        1536 :     restartvars(rvindex)%ndims = 2
    1273        1536 :     restartvars(rvindex)%dims(1) = maxnflds_dim_ind
    1274        1536 :     restartvars(rvindex)%dims(2) = ptapes_dim_ind
    1275             : 
    1276        1536 :     rvindex = rvindex + 1
    1277        1536 :     restartvars(rvindex)%name = 'lcltod_start'
    1278        1536 :     restartvars(rvindex)%type = pio_int
    1279        1536 :     restartvars(rvindex)%ndims = 1
    1280        1536 :     restartvars(rvindex)%dims(1) = ptapes_dim_ind
    1281             : 
    1282        1536 :     rvindex = rvindex + 1
    1283        1536 :     restartvars(rvindex)%name = 'lcltod_stop'
    1284        1536 :     restartvars(rvindex)%type = pio_int
    1285        1536 :     restartvars(rvindex)%ndims = 1
    1286        1536 :     restartvars(rvindex)%dims(1) = ptapes_dim_ind
    1287             : 
    1288        1536 :     rvindex = rvindex + 1
    1289        1536 :     restartvars(rvindex)%name = 'fillvalue'
    1290        1536 :     restartvars(rvindex)%type = pio_double
    1291        1536 :     restartvars(rvindex)%ndims = 2
    1292        1536 :     restartvars(rvindex)%dims(1) = maxnflds_dim_ind
    1293        1536 :     restartvars(rvindex)%dims(2) = ptapes_dim_ind
    1294        1536 :     restartvars(rvindex)%fillset = .true.
    1295        1536 :     restartvars(rvindex)%dfill = 0.0_r8
    1296             : 
    1297             : 
    1298        1536 :     rvindex = rvindex + 1
    1299        1536 :     restartvars(rvindex)%name = 'mdims'
    1300        1536 :     restartvars(rvindex)%type = pio_int
    1301        1536 :     restartvars(rvindex)%ndims = 3
    1302        1536 :     restartvars(rvindex)%dims(1) = maxvarmdims_dim_ind
    1303        1536 :     restartvars(rvindex)%dims(2) = maxnflds_dim_ind
    1304        1536 :     restartvars(rvindex)%dims(3) = ptapes_dim_ind
    1305        1536 :     restartvars(rvindex)%fillset = .true.
    1306        1536 :     restartvars(rvindex)%ifill = 0
    1307             : 
    1308        1536 :     rvindex = rvindex + 1
    1309        1536 :     restartvars(rvindex)%name = 'mdimnames'
    1310        1536 :     restartvars(rvindex)%type = pio_char
    1311        1536 :     restartvars(rvindex)%ndims = 2
    1312        1536 :     restartvars(rvindex)%dims(1) = max_hcoordname_len_dim_ind
    1313        1536 :     restartvars(rvindex)%dims(2) = registeredmdims_dim_ind
    1314             : 
    1315        1536 :     rvindex = rvindex + 1
    1316        1536 :     restartvars(rvindex)%name = 'is_subcol'
    1317        1536 :     restartvars(rvindex)%type = pio_int
    1318        1536 :     restartvars(rvindex)%ndims = 2
    1319        1536 :     restartvars(rvindex)%dims(1) = maxnflds_dim_ind
    1320        1536 :     restartvars(rvindex)%dims(2) = ptapes_dim_ind
    1321             : 
    1322        1536 :     rvindex = rvindex + 1
    1323        1536 :     restartvars(rvindex)%name = 'interpolate_output'
    1324        1536 :     restartvars(rvindex)%type = pio_int
    1325        1536 :     restartvars(rvindex)%ndims = 1
    1326        1536 :     restartvars(rvindex)%dims(1) = ptapes_dim_ind
    1327             : 
    1328        1536 :     rvindex = rvindex + 1
    1329        1536 :     restartvars(rvindex)%name = 'interpolate_type'
    1330        1536 :     restartvars(rvindex)%type = pio_int
    1331        1536 :     restartvars(rvindex)%ndims = 1
    1332        1536 :     restartvars(rvindex)%dims(1) = ptapes_dim_ind
    1333             : 
    1334        1536 :     rvindex = rvindex + 1
    1335        1536 :     restartvars(rvindex)%name = 'interpolate_gridtype'
    1336        1536 :     restartvars(rvindex)%type = pio_int
    1337        1536 :     restartvars(rvindex)%ndims = 1
    1338        1536 :     restartvars(rvindex)%dims(1) = ptapes_dim_ind
    1339             : 
    1340        1536 :     rvindex = rvindex + 1
    1341        1536 :     restartvars(rvindex)%name = 'interpolate_nlat'
    1342        1536 :     restartvars(rvindex)%type = pio_int
    1343        1536 :     restartvars(rvindex)%ndims = 1
    1344        1536 :     restartvars(rvindex)%dims(1) = ptapes_dim_ind
    1345             : 
    1346        1536 :     rvindex = rvindex + 1
    1347        1536 :     restartvars(rvindex)%name = 'interpolate_nlon'
    1348        1536 :     restartvars(rvindex)%type = pio_int
    1349        1536 :     restartvars(rvindex)%ndims = 1
    1350        1536 :     restartvars(rvindex)%dims(1) = ptapes_dim_ind
    1351             : 
    1352        1536 :     rvindex = rvindex + 1
    1353        1536 :     restartvars(rvindex)%name = 'meridional_complement'
    1354        1536 :     restartvars(rvindex)%type = pio_int
    1355        1536 :     restartvars(rvindex)%ndims = 2
    1356        1536 :     restartvars(rvindex)%dims(1) = maxnflds_dim_ind
    1357        1536 :     restartvars(rvindex)%dims(2) = ptapes_dim_ind
    1358        1536 :     restartvars(rvindex)%fillset = .true.
    1359        1536 :     restartvars(rvindex)%ifill = 0
    1360             : 
    1361        1536 :     rvindex = rvindex + 1
    1362        1536 :     restartvars(rvindex)%name = 'zonal_complement'
    1363        1536 :     restartvars(rvindex)%type = pio_int
    1364        1536 :     restartvars(rvindex)%ndims = 2
    1365        1536 :     restartvars(rvindex)%dims(1) = maxnflds_dim_ind
    1366        1536 :     restartvars(rvindex)%dims(2) = ptapes_dim_ind
    1367        1536 :     restartvars(rvindex)%fillset = .true.
    1368        1536 :     restartvars(rvindex)%ifill = 0
    1369             : 
    1370        1536 :     rvindex = rvindex + 1
    1371        1536 :     restartvars(rvindex)%name = 'field_op'
    1372        1536 :     restartvars(rvindex)%type = pio_char
    1373        1536 :     restartvars(rvindex)%ndims = 3
    1374        1536 :     restartvars(rvindex)%dims(1) = max_chars_dim_ind
    1375        1536 :     restartvars(rvindex)%dims(2) = maxnflds_dim_ind
    1376        1536 :     restartvars(rvindex)%dims(3) = ptapes_dim_ind
    1377             : 
    1378        1536 :     rvindex = rvindex + 1
    1379        1536 :     restartvars(rvindex)%name = 'op_field1_id'
    1380        1536 :     restartvars(rvindex)%type = pio_int
    1381        1536 :     restartvars(rvindex)%ndims = 2
    1382        1536 :     restartvars(rvindex)%dims(1) = maxnflds_dim_ind
    1383        1536 :     restartvars(rvindex)%dims(2) = ptapes_dim_ind
    1384        1536 :     restartvars(rvindex)%fillset = .true.
    1385        1536 :     restartvars(rvindex)%ifill = 0
    1386             : 
    1387        1536 :     rvindex = rvindex + 1
    1388        1536 :     restartvars(rvindex)%name = 'op_field2_id'
    1389        1536 :     restartvars(rvindex)%type = pio_int
    1390        1536 :     restartvars(rvindex)%ndims = 2
    1391        1536 :     restartvars(rvindex)%dims(1) = maxnflds_dim_ind
    1392        1536 :     restartvars(rvindex)%dims(2) = ptapes_dim_ind
    1393        1536 :     restartvars(rvindex)%fillset = .true.
    1394        1536 :     restartvars(rvindex)%ifill = 0
    1395             : 
    1396        1536 :     rvindex = rvindex + 1
    1397        1536 :     restartvars(rvindex)%name = 'op_field1'
    1398        1536 :     restartvars(rvindex)%type = pio_char
    1399        1536 :     restartvars(rvindex)%ndims = 3
    1400        1536 :     restartvars(rvindex)%dims(1) = max_fieldname_len_dim_ind
    1401        1536 :     restartvars(rvindex)%dims(2) = maxnflds_dim_ind
    1402        1536 :     restartvars(rvindex)%dims(3) = ptapes_dim_ind
    1403             : 
    1404        1536 :     rvindex = rvindex + 1
    1405        1536 :     restartvars(rvindex)%name = 'op_field2'
    1406        1536 :     restartvars(rvindex)%type = pio_char
    1407        1536 :     restartvars(rvindex)%ndims = 3
    1408        1536 :     restartvars(rvindex)%dims(1) = max_fieldname_len_dim_ind
    1409        1536 :     restartvars(rvindex)%dims(2) = maxnflds_dim_ind
    1410        1536 :     restartvars(rvindex)%dims(3) = ptapes_dim_ind
    1411             : 
    1412        1536 :   end subroutine restart_vars_setnames
    1413             : 
    1414        1536 :   subroutine restart_dims_setnames()
    1415             :     use cam_grid_support,    only: max_hcoordname_len
    1416             :     use cam_history_support, only: registeredmdims
    1417             : 
    1418        1536 :     restartdims(ptapes_dim_ind)%name = 'ptapes'
    1419        1536 :     restartdims(ptapes_dim_ind)%len  = ptapes
    1420             : 
    1421        1536 :     restartdims(max_string_len_dim_ind)%name = 'max_string_len'
    1422        1536 :     restartdims(max_string_len_dim_ind)%len  = max_string_len
    1423             : 
    1424        1536 :     restartdims(fieldname_lenp2_dim_ind)%name = 'fieldname_lenp2'
    1425        1536 :     restartdims(fieldname_lenp2_dim_ind)%len  = fieldname_lenp2
    1426             : 
    1427        1536 :     restartdims(pflds_dim_ind)%name = 'pflds'
    1428        1536 :     restartdims(pflds_dim_ind)%len  = pflds
    1429             : 
    1430        1536 :     restartdims(max_chars_dim_ind)%name = 'max_chars'
    1431        1536 :     restartdims(max_chars_dim_ind)%len  = max_chars
    1432             : 
    1433        1536 :     restartdims(max_fieldname_len_dim_ind)%name = 'max_fieldname_len'
    1434        1536 :     restartdims(max_fieldname_len_dim_ind)%len  = max_fieldname_len
    1435             : 
    1436        1536 :     restartdims(maxnflds_dim_ind)%name = 'maxnflds'
    1437       19968 :     restartdims(maxnflds_dim_ind)%len  = maxval(nflds)
    1438             : 
    1439        1536 :     restartdims(maxvarmdims_dim_ind)%name = 'maxvarmdims'
    1440        1536 :     restartdims(maxvarmdims_dim_ind)%len  = maxvarmdims
    1441             : 
    1442        1536 :     restartdims(registeredmdims_dim_ind)%name = 'registeredmdims'
    1443        1536 :     restartdims(registeredmdims_dim_ind)%len  = registeredmdims
    1444             : 
    1445        1536 :     restartdims(max_hcoordname_len_dim_ind)%name = 'max_hcoordname_len'
    1446        1536 :     restartdims(max_hcoordname_len_dim_ind)%len  = max_hcoordname_len
    1447             : 
    1448        1536 :     restartdims(max_num_split_files)%name = 'max_num_split_files'
    1449        1536 :     restartdims(max_num_split_files)%len = maxsplitfiles
    1450             : 
    1451        1536 :   end subroutine restart_dims_setnames
    1452             : 
    1453             : 
    1454        1536 :   subroutine init_restart_history (File)
    1455        1536 :     use cam_pio_utils,  only: cam_pio_def_dim
    1456             :     use cam_pio_utils,  only: cam_pio_handle_error
    1457             : 
    1458             :     !---------------------------------------------------------------------------
    1459             :     !
    1460             :     ! Arguments
    1461             :     !
    1462             :     type(file_desc_t), intent(inout) :: File                 ! Pio file Handle
    1463             :     !
    1464             :     ! Local
    1465             :     !
    1466             :     integer :: dimids(4), ndims
    1467             :     integer :: ierr, i, k
    1468             : 
    1469             :     ! Don't need to write restart data if we have written the file this step
    1470       19968 :     where (hstwr(:))
    1471             :       rgnht(:) = .false.
    1472             :     elsewhere
    1473             :       rgnht(:) = .true.
    1474             :     end where
    1475             : 
    1476       19968 :     if(maxval(nflds)>0) then
    1477        1536 :       call restart_vars_setnames()
    1478        1536 :       call restart_dims_setnames()
    1479             : 
    1480       18432 :       do i=1,restartdimcnt
    1481             :         ! it's possible that one or more of these have been defined elsewhere
    1482       16896 :         call cam_pio_def_dim(File, restartdims(i)%name, restartdims(i)%len,   &
    1483       35328 :              restartdims(i)%dimid, existOK=.true.)
    1484             :       end do
    1485             : 
    1486       70656 :       do i = 1, restartvarcnt
    1487       69120 :         ndims = restartvars(i)%ndims
    1488      205824 :         do k = 1 ,ndims
    1489      205824 :           dimids(k) = restartdims(restartvars(i)%dims(k))%dimid
    1490             :         end do
    1491       69120 :         allocate(restartvars(i)%vdesc)
    1492       69120 :         ierr = pio_def_var(File, restartvars(i)%name, restartvars(i)%type, dimids(1:ndims), restartvars(i)%vdesc)
    1493       69120 :         call cam_pio_handle_error(ierr, 'INIT_RESTART_HISTORY: Error defining '//trim(restartvars(i)%name))
    1494       70656 :         if(restartvars(i)%fillset) then
    1495       16896 :            if(restartvars(i)%type == PIO_INT) then
    1496             :               ierr = pio_put_att(File, restartvars(i)%vdesc, "_FillValue",    &
    1497       13824 :                    restartvars(i)%ifill)
    1498        3072 :            else if(restartvars(i)%type == PIO_REAL) then
    1499             :               ierr = pio_put_att(File, restartvars(i)%vdesc, "_FillValue",    &
    1500           0 :                    restartvars(i)%rfill)
    1501        3072 :            else if(restartvars(i)%type == PIO_DOUBLE) then
    1502             :               ierr = pio_put_att(File, restartvars(i)%vdesc, "_FillValue",    &
    1503        3072 :                    restartvars(i)%dfill)
    1504             :            end if
    1505       16896 :            call cam_pio_handle_error(ierr, 'INIT_RESTART_HISTORY: Error setting fill'//trim(restartvars(i)%name))
    1506             :         end if
    1507             :       end do
    1508             :     end if
    1509        1536 :   end subroutine init_restart_history
    1510             : 
    1511       69120 :   function restartvar_getdesc(name) result(vdesc)
    1512             :     character(len=*), intent(in) :: name
    1513             :     type(var_desc_t), pointer :: vdesc
    1514             :     character(len=max_chars) :: errmsg
    1515             :     integer :: i
    1516             : 
    1517       69120 :     nullify(vdesc)
    1518     1589760 :     do i=1,restartvarcnt
    1519     1589760 :       if(name .eq. restartvars(i)%name) then
    1520       69120 :         vdesc=>restartvars(i)%vdesc
    1521       69120 :         exit
    1522             :       end if
    1523             :     end do
    1524       69120 :     if(.not.associated(vdesc)) then
    1525           0 :       errmsg = 'Could not find restart variable '//name
    1526           0 :       call endrun(errmsg)
    1527             :     end if
    1528        1536 :   end function restartvar_getdesc
    1529             : 
    1530             : 
    1531             :   !#######################################################################
    1532             : 
    1533        1536 :   subroutine write_restart_history ( File, &
    1534             :        yr_spec, mon_spec, day_spec, sec_spec )
    1535             :     use cam_history_support, only: hist_coord_name, registeredmdims
    1536             : 
    1537             :     implicit none
    1538             :     !--------------------------------------------------------------------------------------------------
    1539             :     !
    1540             :     ! Arguments
    1541             :     !
    1542             :     type(file_desc_t), intent(inout) :: file         ! PIO restart file pointer
    1543             :     integer, intent(in), optional :: yr_spec         ! Simulation year
    1544             :     integer, intent(in), optional :: mon_spec        ! Simulation month
    1545             :     integer, intent(in), optional :: day_spec        ! Simulation day
    1546             :     integer, intent(in), optional :: sec_spec        ! Seconds into current simulation day
    1547             :     !
    1548             :     ! Local workspace
    1549             :     !
    1550             :     integer :: ierr, t, fld
    1551             :     integer :: rgnht_int(ptapes), start(2), startc(3)
    1552             :     type(var_desc_t), pointer :: vdesc
    1553             : 
    1554             :     ! PIO variable descriptors
    1555             :     type(var_desc_t), pointer ::  field_name_desc   ! Restart field names
    1556             :     type(var_desc_t), pointer ::  decomp_type_desc
    1557             :     type(var_desc_t), pointer ::  numlev_desc
    1558             :     type(var_desc_t), pointer ::  avgflag_desc
    1559             :     type(var_desc_t), pointer ::  sseq_desc
    1560             :     type(var_desc_t), pointer ::  cm_desc
    1561             :     type(var_desc_t), pointer ::  longname_desc
    1562             :     type(var_desc_t), pointer ::  units_desc
    1563             :     type(var_desc_t), pointer ::  hwrt_prec_desc
    1564             :     type(var_desc_t), pointer ::  hbuf_integral_desc
    1565             :     type(var_desc_t), pointer ::  beg_nstep_desc
    1566             :     type(var_desc_t), pointer ::  xyfill_desc
    1567             :     type(var_desc_t), pointer ::  mdims_desc        ! mdim name indices
    1568             :     type(var_desc_t), pointer ::  mdimname_desc     ! mdim names
    1569             :     type(var_desc_t), pointer ::  issubcol_desc
    1570             :     type(var_desc_t), pointer ::  fillval_desc
    1571             :     type(var_desc_t), pointer ::  interpolate_output_desc
    1572             :     type(var_desc_t), pointer ::  interpolate_type_desc
    1573             :     type(var_desc_t), pointer ::  interpolate_gridtype_desc
    1574             :     type(var_desc_t), pointer ::  interpolate_nlat_desc
    1575             :     type(var_desc_t), pointer ::  interpolate_nlon_desc
    1576             :     type(var_desc_t), pointer ::  meridional_complement_desc
    1577             :     type(var_desc_t), pointer ::  zonal_complement_desc
    1578             :     type(var_desc_t), pointer ::  field_op_desc
    1579             :     type(var_desc_t), pointer ::  op_field1_id_desc
    1580             :     type(var_desc_t), pointer ::  op_field2_id_desc
    1581             :     type(var_desc_t), pointer ::  op_field1_desc
    1582             :     type(var_desc_t), pointer ::  op_field2_desc
    1583             : 
    1584        1536 :     integer, allocatable      ::  allmdims(:,:,:)
    1585        1536 :     integer, allocatable      ::  xyfill(:,:)
    1586        1536 :     integer, allocatable      ::  is_subcol(:,:)
    1587        1536 :     integer, allocatable      ::  interp_output(:)
    1588             : 
    1589             :     integer                   ::  maxnflds
    1590             :     real(r8)                  ::  integral  ! hbuf area weighted integral
    1591             : 
    1592       19968 :     maxnflds = maxval(nflds)
    1593        4608 :     allocate(xyfill(maxnflds, ptapes))
    1594     6471168 :     xyfill = 0
    1595        3072 :     allocate(is_subcol(maxnflds, ptapes))
    1596     6471168 :     is_subcol = 0
    1597        1536 :     allocate(interp_output(ptapes))
    1598       19968 :     interp_output = 0
    1599             : 
    1600             :     !
    1601             :     !-----------------------------------------------------------------------
    1602             :     ! Write the history restart data if necessary
    1603             :     !-----------------------------------------------------------------------
    1604             : 
    1605        1536 :     rgnht_int(:) = 0
    1606             : 
    1607       23040 :     if(.not.allocated(restarthistory_tape)) allocate(restarthistory_tape(ptapes))
    1608             : 
    1609       19968 :     do t=1,ptapes
    1610             :       ! No need to write history IC restart because it is always instantaneous
    1611       18432 :       if (is_initfile(file_index=t)) rgnht(t) = .false.
    1612             :       ! No need to write restart data for empty files
    1613       18432 :       if (nflds(t) == 0) rgnht(t) = .false.
    1614       19968 :       if(rgnht(t)) then
    1615        1536 :         rgnht_int(t) = 1
    1616        1536 :         restarthistory_tape(t)%hlist => history_tape(t)%hlist
    1617             : 
    1618        1536 :         if(associated(history_tape(t)%grid_ids)) then
    1619        1536 :           restarthistory_tape(t)%grid_ids => history_tape(t)%grid_ids
    1620             :         end if
    1621        1536 :         if(associated(history_tape(t)%patches)) then
    1622           0 :           restarthistory_tape(t)%patches => history_tape(t)%patches
    1623             :         end if
    1624             :       end if
    1625             :     end do
    1626             : 
    1627       19968 :     if(maxval(nflds)<=0) return
    1628             : 
    1629        1536 :     call wshist(rgnht)
    1630             : 
    1631        1536 :     vdesc => restartvar_getdesc('fincl')
    1632        1536 :     ierr= pio_put_var(File, vdesc, fincl(:,1:ptapes))
    1633             : 
    1634        1536 :     vdesc => restartvar_getdesc('fincllonlat')
    1635        1536 :     ierr= pio_put_var(File, vdesc, fincllonlat(:,1:ptapes))
    1636             : 
    1637        1536 :     vdesc => restartvar_getdesc('fexcl')
    1638        1536 :     ierr= pio_put_var(File, vdesc, fexcl(:,1:ptapes))
    1639             : 
    1640        1536 :     vdesc => restartvar_getdesc('rgnht')
    1641        1536 :     ierr= pio_put_var(File, vdesc, rgnht_int(1:ptapes))
    1642             : 
    1643        1536 :     vdesc => restartvar_getdesc('nhtfrq')
    1644        1536 :     ierr= pio_put_var(File, vdesc, nhtfrq(1:ptapes))
    1645             : 
    1646        1536 :     vdesc => restartvar_getdesc('nflds')
    1647        1536 :     ierr= pio_put_var(File, vdesc, nflds(1:ptapes))
    1648             : 
    1649        1536 :     vdesc => restartvar_getdesc('nfils')
    1650        1536 :     ierr= pio_put_var(File, vdesc, nfils(1:ptapes))
    1651             : 
    1652        1536 :     vdesc => restartvar_getdesc('mfilt')
    1653        1536 :     ierr= pio_put_var(File, vdesc, mfilt(1:ptapes))
    1654             : 
    1655        1536 :     vdesc => restartvar_getdesc('nfpath')
    1656        1536 :     ierr= pio_put_var(File, vdesc, nfpath(1:ptapes))
    1657             : 
    1658        1536 :     vdesc => restartvar_getdesc('cpath')
    1659        1536 :     ierr= pio_put_var(File, vdesc, cpath(1:ptapes,:))
    1660             : 
    1661        1536 :     vdesc => restartvar_getdesc('nhfil')
    1662        1536 :     ierr= pio_put_var(File, vdesc, nhfil(1:ptapes,:))
    1663             : 
    1664        1536 :     vdesc => restartvar_getdesc('ndens')
    1665        1536 :     ierr= pio_put_var(File, vdesc, ndens(1:ptapes))
    1666        1536 :     vdesc => restartvar_getdesc('ncprec')
    1667        1536 :     ierr= pio_put_var(File, vdesc, ncprec(1:ptapes))
    1668        1536 :     vdesc => restartvar_getdesc('beg_time')
    1669        1536 :     ierr= pio_put_var(File, vdesc, beg_time(1:ptapes))
    1670             : 
    1671        1536 :     vdesc => restartvar_getdesc('hrestpath')
    1672        1536 :     ierr = pio_put_var(File, vdesc, hrestpath(1:ptapes))
    1673             : 
    1674        1536 :     vdesc => restartvar_getdesc('lcltod_start')
    1675        1536 :     ierr = pio_put_var(File, vdesc, lcltod_start(1:ptapes))
    1676             : 
    1677        1536 :     vdesc => restartvar_getdesc('lcltod_stop')
    1678        1536 :     ierr = pio_put_var(File, vdesc, lcltod_stop(1:ptapes))
    1679             : 
    1680        1536 :     field_name_desc => restartvar_getdesc('field_name')
    1681        1536 :     decomp_type_desc => restartvar_getdesc('decomp_type')
    1682        1536 :     numlev_desc => restartvar_getdesc('numlev')
    1683        1536 :     hwrt_prec_desc => restartvar_getdesc('hwrt_prec')
    1684        1536 :     hbuf_integral_desc => restartvar_getdesc('hbuf_integral')
    1685        1536 :     beg_nstep_desc => restartvar_getdesc('beg_nstep')
    1686             : 
    1687        1536 :     sseq_desc => restartvar_getdesc('sampling_seq')
    1688        1536 :     cm_desc => restartvar_getdesc('cell_methods')
    1689        1536 :     longname_desc => restartvar_getdesc('long_name')
    1690        1536 :     units_desc => restartvar_getdesc('units')
    1691        1536 :     avgflag_desc => restartvar_getdesc('avgflag')
    1692        1536 :     xyfill_desc => restartvar_getdesc('xyfill')
    1693        1536 :     issubcol_desc => restartvar_getdesc('is_subcol')
    1694             : 
    1695        1536 :     interpolate_output_desc => restartvar_getdesc('interpolate_output')
    1696        1536 :     interpolate_type_desc => restartvar_getdesc('interpolate_type')
    1697        1536 :     interpolate_gridtype_desc => restartvar_getdesc('interpolate_gridtype')
    1698        1536 :     interpolate_nlat_desc => restartvar_getdesc('interpolate_nlat')
    1699        1536 :     interpolate_nlon_desc => restartvar_getdesc('interpolate_nlon')
    1700             : 
    1701        1536 :     meridional_complement_desc => restartvar_getdesc('meridional_complement')
    1702        1536 :     zonal_complement_desc => restartvar_getdesc('zonal_complement')
    1703             : 
    1704        1536 :     field_op_desc => restartvar_getdesc('field_op')
    1705        1536 :     op_field1_id_desc => restartvar_getdesc('op_field1_id')
    1706        1536 :     op_field2_id_desc => restartvar_getdesc('op_field2_id')
    1707        1536 :     op_field1_desc => restartvar_getdesc('op_field1')
    1708        1536 :     op_field2_desc => restartvar_getdesc('op_field2')
    1709             : 
    1710        1536 :     mdims_desc => restartvar_getdesc('mdims')
    1711        1536 :     mdimname_desc => restartvar_getdesc('mdimnames')
    1712        1536 :     fillval_desc => restartvar_getdesc('fillvalue')
    1713             : 
    1714        1536 :     tape=>history_tape
    1715             : 
    1716             :     ! allmdims specifies the mdim indices for each field
    1717       26112 :     allocate(allmdims(maxvarmdims,maxval(nflds),ptapes))
    1718    12922368 :     allmdims=-1
    1719             : 
    1720        1536 :     startc(1)=1
    1721       19968 :     do t = 1,ptapes
    1722       18432 :       start(2)=t
    1723       18432 :       startc(3)=t
    1724      625152 :       do fld=1,nflds(t)
    1725      606720 :         start(1)=fld
    1726      606720 :         startc(2)=fld
    1727      606720 :         ierr = pio_put_var(File, field_name_desc,startc,tape(t)%hlist(fld)%field%name)
    1728      606720 :         ierr = pio_put_var(File, decomp_type_desc,start,tape(t)%hlist(fld)%field%decomp_type)
    1729      606720 :         ierr = pio_put_var(File, numlev_desc,start,tape(t)%hlist(fld)%field%numlev)
    1730             : 
    1731      606720 :         ierr = pio_put_var(File, hwrt_prec_desc,start,tape(t)%hlist(fld)%hwrt_prec)
    1732      606720 :         call tape(t)%hlist(fld)%get_global(integral)
    1733      606720 :         ierr = pio_put_var(File, hbuf_integral_desc,start,integral)
    1734      606720 :         ierr = pio_put_var(File, beg_nstep_desc,start,tape(t)%hlist(fld)%beg_nstep)
    1735      606720 :         ierr = pio_put_var(File, sseq_desc,startc,tape(t)%hlist(fld)%field%sampling_seq)
    1736      606720 :         ierr = pio_put_var(File, cm_desc,startc,tape(t)%hlist(fld)%field%cell_methods)
    1737      606720 :         ierr = pio_put_var(File, longname_desc,startc,tape(t)%hlist(fld)%field%long_name)
    1738      606720 :         ierr = pio_put_var(File, units_desc,startc,tape(t)%hlist(fld)%field%units)
    1739      606720 :         ierr = pio_put_var(File, avgflag_desc,start, tape(t)%hlist(fld)%avgflag)
    1740             : 
    1741      606720 :         ierr = pio_put_var(File, fillval_desc,start, tape(t)%hlist(fld)%field%fillvalue)
    1742      606720 :         ierr = pio_put_var(File, meridional_complement_desc,start, tape(t)%hlist(fld)%field%meridional_complement)
    1743      606720 :         ierr = pio_put_var(File, zonal_complement_desc,start, tape(t)%hlist(fld)%field%zonal_complement)
    1744      606720 :         ierr = pio_put_var(File, field_op_desc,startc, tape(t)%hlist(fld)%field%field_op)
    1745      606720 :         ierr = pio_put_var(File, op_field1_id_desc,start, tape(t)%hlist(fld)%field%op_field1_id)
    1746      606720 :         ierr = pio_put_var(File, op_field2_id_desc,start, tape(t)%hlist(fld)%field%op_field2_id)
    1747      606720 :         ierr = pio_put_var(File, op_field1_desc,startc, tape(t)%hlist(fld)%op_field1)
    1748      606720 :         ierr = pio_put_var(File, op_field2_desc,startc, tape(t)%hlist(fld)%op_field2)
    1749      606720 :         if(associated(tape(t)%hlist(fld)%field%mdims)) then
    1750      722688 :           allmdims(1:size(tape(t)%hlist(fld)%field%mdims),fld,t) = tape(t)%hlist(fld)%field%mdims
    1751             :         else
    1752             :         end if
    1753      606720 :         if(tape(t)%hlist(fld)%field%flag_xyfill) then
    1754        7680 :            xyfill(fld,t) = 1
    1755             :         end if
    1756      625152 :         if(tape(t)%hlist(fld)%field%is_subcol) then
    1757           0 :            is_subcol(fld,t) = 1
    1758             :         end if
    1759             :       end do
    1760       19968 :       if (interpolate_output(t)) then
    1761           0 :         interp_output(t) = 1
    1762             :       end if
    1763             :     end do
    1764        1536 :     ierr = pio_put_var(File, xyfill_desc, xyfill)
    1765        1536 :     ierr = pio_put_var(File, mdims_desc, allmdims)
    1766        1536 :     ierr = pio_put_var(File, issubcol_desc, is_subcol)
    1767             :     !! Interpolated output variables
    1768        1536 :     ierr = pio_put_var(File, interpolate_output_desc, interp_output)
    1769       19968 :     interp_output = 1
    1770       16896 :     do t = 1, size(interpolate_info)
    1771       16896 :       interp_output(t) = interpolate_info(t)%interp_type
    1772             :     end do
    1773        1536 :     ierr = pio_put_var(File, interpolate_type_desc, interp_output)
    1774       19968 :     interp_output = 1
    1775       16896 :     do t = 1, size(interpolate_info)
    1776       16896 :       interp_output(t) = interpolate_info(t)%interp_gridtype
    1777             :     end do
    1778        1536 :     ierr = pio_put_var(File, interpolate_gridtype_desc, interp_output)
    1779       19968 :     interp_output = 0
    1780       16896 :     do t = 1, size(interpolate_info)
    1781       16896 :       interp_output(t) = interpolate_info(t)%interp_nlat
    1782             :     end do
    1783        1536 :     ierr = pio_put_var(File, interpolate_nlat_desc, interp_output)
    1784       19968 :     interp_output = 0
    1785       16896 :     do t = 1, size(interpolate_info)
    1786       16896 :       interp_output(t) = interpolate_info(t)%interp_nlon
    1787             :     end do
    1788        1536 :     ierr = pio_put_var(File, interpolate_nlon_desc, interp_output)
    1789             :     ! Registered history coordinates
    1790        1536 :     start(1) = 1
    1791       12288 :     do fld = 1, registeredmdims
    1792       10752 :       start(2) = fld
    1793       12288 :       ierr = pio_put_var(File, mdimname_desc, start, hist_coord_name(fld))
    1794             :     end do
    1795             : 
    1796        1536 :     deallocate(xyfill, allmdims, is_subcol, interp_output, restarthistory_tape)
    1797             : 
    1798        1536 :   end subroutine write_restart_history
    1799             : 
    1800             : 
    1801             :   !#######################################################################
    1802             : 
    1803         768 :   subroutine read_restart_history (File)
    1804        1536 :     use pio,                 only: pio_inq_dimid
    1805             :     use pio,                 only: pio_inq_varid, pio_inq_dimname
    1806             :     use cam_pio_utils,       only: cam_pio_openfile, cam_pio_closefile
    1807             :     use cam_pio_utils,       only: cam_pio_var_info
    1808             :     use ioFileMod,           only: getfil
    1809             :     use sat_hist,            only: sat_hist_define, sat_hist_init
    1810             :     use cam_grid_support,    only: cam_grid_read_dist_array, cam_grid_num_grids
    1811             :     use cam_history_support, only: get_hist_coord_index, add_hist_coord, dim_index_2d
    1812             :     use constituents,        only: cnst_get_ind, cnst_get_type_byind
    1813             :     use cam_grid_support,    only: cam_grid_get_areawt
    1814             : 
    1815             :     use shr_sys_mod,         only: shr_sys_getenv
    1816             :     use spmd_utils,          only: mpicom, mpi_character, masterprocid
    1817             :     use time_manager,        only: get_nstep
    1818             :     !
    1819             :     !-----------------------------------------------------------------------
    1820             :     !
    1821             :     ! Arguments
    1822             :     !
    1823             :     type(file_desc_t), intent(inout) :: File            ! unit number
    1824             :     !
    1825             :     ! Local workspace
    1826             :     !
    1827             :     integer t, f, fld, ffld          ! tape, file, field indices
    1828             :     integer begdim2                  ! on-node vert start index
    1829             :     integer enddim2                  ! on-node vert end index
    1830             :     integer begdim1                  ! on-node dim1 start index
    1831             :     integer enddim1                  ! on-node dim1 end index
    1832             :     integer begdim3                  ! on-node chunk or lat start index
    1833             :     integer enddim3                  ! on-node chunk or lat end index
    1834             : 
    1835             : 
    1836             :     integer rgnht_int(ptapes)
    1837             :     integer :: ierr
    1838             : 
    1839             :     character(len=max_string_len)  :: locfn       ! Local filename
    1840         768 :     character(len=max_fieldname_len), allocatable :: tmpname(:,:)
    1841         768 :     character(len=max_fieldname_len), allocatable :: tmpf1name(:,:)
    1842         768 :     character(len=max_fieldname_len), allocatable :: tmpf2name(:,:)
    1843         768 :     integer, allocatable :: decomp(:,:), tmpnumlev(:,:)
    1844         768 :     integer, pointer :: nacs(:,:)    ! outfld accumulation counter
    1845             :     integer          :: beg_nstep  ! start timestep of this slice for nstep accumulation counter
    1846             :     character(len=max_fieldname_len) :: fname_tmp ! local copy of field name
    1847             :     character(len=max_fieldname_len) :: dname_tmp ! local copy of dim name
    1848             : 
    1849             :     integer :: i, ptapes_dimid
    1850             : 
    1851             :     type(var_desc_t)                 :: vdesc
    1852             :     type(var_desc_t)                 :: longname_desc
    1853             :     type(var_desc_t)                 :: units_desc
    1854             :     type(var_desc_t)                 :: avgflag_desc
    1855             :     type(var_desc_t)                 :: sseq_desc
    1856             :     type(var_desc_t)                 :: cm_desc
    1857             :     type(var_desc_t)                 :: fillval_desc
    1858             :     type(var_desc_t)                 :: meridional_complement_desc
    1859             :     type(var_desc_t)                 :: zonal_complement_desc
    1860             :     type(var_desc_t)                 :: field_op_desc
    1861             :     type(var_desc_t)                 :: op_field1_id_desc
    1862             :     type(var_desc_t)                 :: op_field2_id_desc
    1863             :     type(var_desc_t)                 :: op_field1_desc
    1864             :     type(var_desc_t)                 :: op_field2_desc
    1865             :     type(dim_index_2d)               :: dimind    ! 2-D dimension index
    1866         768 :     integer,            allocatable  :: tmpprec(:,:)
    1867         768 :     real(r8),           allocatable  :: tmpintegral(:,:)
    1868         768 :     integer,            allocatable  :: tmpbeg_nstep(:,:)
    1869         768 :     integer,            allocatable  :: xyfill(:,:)
    1870         768 :     integer,            allocatable  :: allmdims(:,:,:)
    1871         768 :     integer,            allocatable  :: is_subcol(:,:)
    1872         768 :     integer,            allocatable  :: interp_output(:)
    1873             :     integer                          :: nacsdimcnt, nacsval
    1874             :     integer                          :: maxnflds, dimid
    1875             : 
    1876             :     ! List of active grids (first dim) for each tape (second dim)
    1877             :     ! An active grid is one for which there is a least one field being output
    1878             :     !    on that grid.
    1879         768 :     integer, allocatable        :: gridsontape(:,:)
    1880             : 
    1881         768 :     character(len=16),  allocatable  :: mdimnames(:) ! Names of all hist coords (inc. vertical)
    1882             :     integer                          :: ndims, dimids(8)
    1883             :     integer                          :: tmpdims(8), dimcnt
    1884             :     integer                          :: dimlens(7)
    1885             :     integer                          :: mtapes, mdimcnt
    1886             :     integer                          :: fdims(3)         ! Field dims
    1887             :     integer                          :: nfdims           ! 2 or 3 (for 2D,3D)
    1888             :     integer                          :: fdecomp          ! Grid ID for field
    1889             :     integer                          :: idx
    1890             :     character(len=3)                 :: mixing_ratio
    1891             :     integer                          :: c,ib,ie,jb,je,k,cnt,wtidx(1)
    1892         768 :     real(r8), pointer                :: areawt(:)  ! pointer to areawt values for attribute
    1893             : 
    1894             :     !
    1895             :     ! Get users logname and machine hostname
    1896             :     !
    1897         770 :     if ( masterproc )then
    1898           1 :       logname = ' '
    1899           1 :       call shr_sys_getenv ('LOGNAME',logname,ierr)
    1900           1 :       host = ' '
    1901           1 :       call shr_sys_getenv ('HOST',host,ierr)
    1902             :     end if
    1903             :     ! PIO requires netcdf attributes have consistant values on all tasks
    1904         768 :     call mpi_bcast(logname, len(logname), mpi_character, masterprocid, mpicom, ierr)
    1905         768 :     call mpi_bcast(host,    len(host),    mpi_character, masterprocid, mpicom, ierr)
    1906             : 
    1907         768 :     call pio_seterrorhandling(File, PIO_BCAST_ERROR)
    1908             : 
    1909         768 :     ierr = pio_inq_dimid(File, 'ptapes', ptapes_dimid)
    1910         768 :     if(ierr/= PIO_NOERR) then
    1911           0 :       if(masterproc) write(iulog,*) 'Not reading history info from restart file', ierr
    1912           0 :       return   ! no history info in restart file
    1913             :     end if
    1914         768 :     call pio_seterrorhandling(File, PIO_INTERNAL_ERROR)
    1915             : 
    1916         768 :     ierr = pio_inq_dimlen(File, ptapes_dimid, mtapes)
    1917             : 
    1918         768 :     ierr = pio_inq_dimid(File, 'maxnflds', dimid)
    1919         768 :     ierr = pio_inq_dimlen(File, dimid, maxnflds)
    1920             : 
    1921         768 :     ierr = pio_inq_dimid(File, 'maxvarmdims', dimid)
    1922         768 :     ierr = pio_inq_dimlen(File, dimid, maxvarmdims)
    1923             : 
    1924         768 :     ierr = pio_inq_varid(File, 'rgnht', vdesc)
    1925         768 :     ierr = pio_get_var(File, vdesc, rgnht_int(1:mtapes))
    1926             : 
    1927         768 :     ierr = pio_inq_varid(File, 'nhtfrq', vdesc)
    1928         768 :     ierr = pio_get_var(File, vdesc, nhtfrq(1:mtapes))
    1929             : 
    1930         768 :     ierr = pio_inq_varid(File, 'nflds', vdesc)
    1931         768 :     ierr = pio_get_var(File, vdesc, nflds(1:mtapes))
    1932         768 :     ierr = pio_inq_varid(File, 'nfils', vdesc)
    1933         768 :     ierr = pio_get_var(File, vdesc, nfils(1:mtapes))
    1934         768 :     ierr = pio_inq_varid(File, 'mfilt', vdesc)
    1935         768 :     ierr = pio_get_var(File, vdesc, mfilt(1:mtapes))
    1936             : 
    1937         768 :     ierr = pio_inq_varid(File, 'nfpath', vdesc)
    1938         768 :     ierr = pio_get_var(File, vdesc, nfpath(1:mtapes))
    1939         768 :     ierr = pio_inq_varid(File, 'cpath', vdesc)
    1940         768 :     ierr = pio_get_var(File, vdesc, cpath(1:mtapes,:))
    1941         768 :     ierr = pio_inq_varid(File, 'nhfil', vdesc)
    1942         768 :     ierr = pio_get_var(File, vdesc, nhfil(1:mtapes,:))
    1943         768 :     ierr = pio_inq_varid(File, 'hrestpath', vdesc)
    1944         768 :     ierr = pio_get_var(File, vdesc, hrestpath(1:mtapes))
    1945             : 
    1946             : 
    1947         768 :     ierr = pio_inq_varid(File, 'ndens', vdesc)
    1948         768 :     ierr = pio_get_var(File, vdesc, ndens(1:mtapes))
    1949         768 :     ierr = pio_inq_varid(File, 'ncprec', vdesc)
    1950         768 :     ierr = pio_get_var(File, vdesc, ncprec(1:mtapes))
    1951         768 :     ierr = pio_inq_varid(File, 'beg_time', vdesc)
    1952         768 :     ierr = pio_get_var(File, vdesc, beg_time(1:mtapes))
    1953             : 
    1954             : 
    1955         768 :     ierr = pio_inq_varid(File, 'fincl', vdesc)
    1956         768 :     ierr = pio_get_var(File, vdesc, fincl(:,1:mtapes))
    1957             : 
    1958         768 :     ierr = pio_inq_varid(File, 'fincllonlat', vdesc)
    1959         768 :     ierr = pio_get_var(File, vdesc, fincllonlat(:,1:mtapes))
    1960             : 
    1961         768 :     ierr = pio_inq_varid(File, 'fexcl', vdesc)
    1962         768 :     ierr = pio_get_var(File, vdesc, fexcl(:,1:mtapes))
    1963             : 
    1964         768 :     ierr = pio_inq_varid(File, 'lcltod_start', vdesc)
    1965         768 :     ierr = pio_get_var(File, vdesc, lcltod_start(1:mtapes))
    1966             : 
    1967         768 :     ierr = pio_inq_varid(File, 'lcltod_stop', vdesc)
    1968         768 :     ierr = pio_get_var(File, vdesc, lcltod_stop(1:mtapes))
    1969             : 
    1970        6912 :     allocate(tmpname(maxnflds, mtapes), decomp(maxnflds, mtapes), tmpnumlev(maxnflds,mtapes))
    1971         768 :     ierr = pio_inq_varid(File, 'field_name', vdesc)
    1972         768 :     ierr = pio_get_var(File, vdesc, tmpname)
    1973         768 :     ierr = pio_inq_varid(File, 'decomp_type', vdesc)
    1974         768 :     ierr = pio_get_var(File, vdesc, decomp)
    1975         768 :     ierr = pio_inq_varid(File, 'numlev', vdesc)
    1976         768 :     ierr = pio_get_var(File, vdesc, tmpnumlev)
    1977             : 
    1978         768 :     ierr = pio_inq_varid(File, 'hbuf_integral',vdesc)
    1979        3072 :     allocate(tmpintegral(maxnflds,mtapes))
    1980         768 :     ierr = pio_get_var(File, vdesc, tmpintegral(:,:))
    1981             : 
    1982             : 
    1983         768 :     ierr = pio_inq_varid(File, 'hwrt_prec',vdesc)
    1984        3072 :     allocate(tmpprec(maxnflds,mtapes))
    1985         768 :     ierr = pio_get_var(File, vdesc, tmpprec(:,:))
    1986             : 
    1987         768 :     ierr = pio_inq_varid(File, 'beg_nstep',vdesc)
    1988        3072 :     allocate(tmpbeg_nstep(maxnflds,mtapes))
    1989         768 :     ierr = pio_get_var(File, vdesc, tmpbeg_nstep(:,:))
    1990             : 
    1991         768 :     ierr = pio_inq_varid(File, 'xyfill', vdesc)
    1992        3072 :     allocate(xyfill(maxnflds,mtapes))
    1993         768 :     ierr = pio_get_var(File, vdesc, xyfill)
    1994             : 
    1995         768 :     ierr = pio_inq_varid(File, 'is_subcol', vdesc)
    1996        3072 :     allocate(is_subcol(maxnflds,mtapes))
    1997         768 :     ierr = pio_get_var(File, vdesc, is_subcol)
    1998             : 
    1999             :     !! interpolated output
    2000         768 :     ierr = pio_inq_varid(File, 'interpolate_output', vdesc)
    2001        2304 :     allocate(interp_output(mtapes))
    2002         768 :     ierr = pio_get_var(File, vdesc, interp_output)
    2003        9984 :     interpolate_output(1:mtapes) = interp_output(1:mtapes) > 0
    2004         768 :     if (ptapes > mtapes) then
    2005           0 :       interpolate_output(mtapes+1:ptapes) = .false.
    2006             :     end if
    2007         768 :     ierr = pio_inq_varid(File, 'interpolate_type', vdesc)
    2008         768 :     ierr = pio_get_var(File, vdesc, interp_output)
    2009        9984 :     do t = 1, mtapes
    2010        9984 :       if (interpolate_output(t)) then
    2011           0 :         interpolate_info(t)%interp_type = interp_output(t)
    2012             :       end if
    2013             :     end do
    2014         768 :     ierr = pio_inq_varid(File, 'interpolate_gridtype', vdesc)
    2015         768 :     ierr = pio_get_var(File, vdesc, interp_output)
    2016        9984 :     do t = 1, mtapes
    2017        9984 :       if (interpolate_output(t)) then
    2018           0 :         interpolate_info(t)%interp_gridtype = interp_output(t)
    2019             :       end if
    2020             :     end do
    2021         768 :     ierr = pio_inq_varid(File, 'interpolate_nlat', vdesc)
    2022         768 :     ierr = pio_get_var(File, vdesc, interp_output)
    2023        9984 :     do t = 1, mtapes
    2024        9984 :       if (interpolate_output(t)) then
    2025           0 :         interpolate_info(t)%interp_nlat = interp_output(t)
    2026             :       end if
    2027             :     end do
    2028         768 :     ierr = pio_inq_varid(File, 'interpolate_nlon', vdesc)
    2029         768 :     ierr = pio_get_var(File, vdesc, interp_output)
    2030        9984 :     do t = 1, mtapes
    2031        9984 :       if (interpolate_output(t)) then
    2032           0 :         interpolate_info(t)%interp_nlon = interp_output(t)
    2033             :       end if
    2034             :     end do
    2035             : 
    2036             :     !! mdim indices
    2037        3840 :     allocate(allmdims(maxvarmdims,maxnflds,mtapes))
    2038         768 :     ierr = pio_inq_varid(File, 'mdims', vdesc)
    2039         768 :     ierr = pio_get_var(File, vdesc, allmdims)
    2040             : 
    2041             :     !! mdim names
    2042             :     ! Read the hist coord names to make sure they are all registered
    2043         768 :     ierr = pio_inq_varid(File, 'mdimnames', vdesc)
    2044         768 :     call cam_pio_var_info(File, vdesc, ndims, dimids, dimlens)
    2045         768 :     mdimcnt = dimlens(2)
    2046        2304 :     allocate(mdimnames(mdimcnt))
    2047         768 :     ierr = pio_get_var(File, vdesc, mdimnames)
    2048        6144 :     do f = 1, mdimcnt
    2049             :       ! Check to see if the mdim is registered
    2050        6144 :       if (get_hist_coord_index(trim(mdimnames(f))) <= 0) then
    2051             :         ! We need to register this mdim (hist_coord)
    2052           0 :         call add_hist_coord(trim(mdimnames(f)))
    2053             :       end if
    2054             :     end do
    2055             : 
    2056        4608 :     allocate(tmpf1name(maxnflds, mtapes), tmpf2name(maxnflds, mtapes))
    2057         768 :     ierr = pio_inq_varid(File, 'op_field1', vdesc)
    2058         768 :     ierr = pio_get_var(File, vdesc, tmpf1name)
    2059         768 :     ierr = pio_inq_varid(File, 'op_field2', vdesc)
    2060         768 :     ierr = pio_get_var(File, vdesc, tmpf2name)
    2061             : 
    2062             : 
    2063         768 :     ierr = pio_inq_varid(File, 'avgflag', avgflag_desc)
    2064             : 
    2065         768 :     ierr = pio_inq_varid(File, 'long_name', longname_desc)
    2066         768 :     ierr = pio_inq_varid(File, 'units', units_desc)
    2067         768 :     ierr = pio_inq_varid(File, 'sampling_seq', sseq_desc)
    2068         768 :     ierr = pio_inq_varid(File, 'cell_methods', cm_desc)
    2069             : 
    2070         768 :     ierr = pio_inq_varid(File, 'fillvalue', fillval_desc)
    2071         768 :     ierr = pio_inq_varid(File, 'meridional_complement', meridional_complement_desc)
    2072         768 :     ierr = pio_inq_varid(File, 'zonal_complement', zonal_complement_desc)
    2073         768 :     ierr = pio_inq_varid(File, 'field_op', field_op_desc)
    2074         768 :     ierr = pio_inq_varid(File, 'op_field1_id', op_field1_id_desc)
    2075         768 :     ierr = pio_inq_varid(File, 'op_field2_id', op_field2_id_desc)
    2076             : 
    2077         768 :     rgnht(:)=.false.
    2078             : 
    2079       13056 :     allocate(history_tape(mtapes))
    2080             : 
    2081         768 :     tape => history_tape
    2082             : 
    2083        9984 :     do t=1,mtapes
    2084             : 
    2085        9216 :       if(rgnht_int(t)==1) rgnht(t)=.true.
    2086             : 
    2087             : 
    2088             :       call strip_null(nfpath(t))
    2089        9216 :       call strip_null(cpath(t,1))
    2090        9216 :       call strip_null(cpath(t,2))
    2091        9216 :       call strip_null(hrestpath(t))
    2092      323328 :       allocate(tape(t)%hlist(nflds(t)))
    2093             : 
    2094      350208 :       do fld=1,nflds(t)
    2095      303360 :         if (associated(tape(t)%hlist(fld)%field%mdims)) then
    2096           0 :           deallocate(tape(t)%hlist(fld)%field%mdims)
    2097             :         end if
    2098      303360 :         nullify(tape(t)%hlist(fld)%field%mdims)
    2099      910080 :         ierr = pio_get_var(File,fillval_desc, (/fld,t/), tape(t)%hlist(fld)%field%fillvalue)
    2100      910080 :         ierr = pio_get_var(File,meridional_complement_desc, (/fld,t/), tape(t)%hlist(fld)%field%meridional_complement)
    2101      910080 :         ierr = pio_get_var(File,zonal_complement_desc, (/fld,t/), tape(t)%hlist(fld)%field%zonal_complement)
    2102      303360 :         tape(t)%hlist(fld)%field%field_op(1:field_op_len) = ' '
    2103     1213440 :         ierr = pio_get_var(File,field_op_desc, (/1,fld,t/), tape(t)%hlist(fld)%field%field_op)
    2104      303360 :         call strip_null(tape(t)%hlist(fld)%field%field_op)
    2105      910080 :         ierr = pio_get_var(File,op_field1_id_desc, (/fld,t/), tape(t)%hlist(fld)%field%op_field1_id)
    2106      910080 :         ierr = pio_get_var(File,op_field2_id_desc, (/fld,t/), tape(t)%hlist(fld)%field%op_field2_id)
    2107      910080 :         ierr = pio_get_var(File,avgflag_desc, (/fld,t/), tape(t)%hlist(fld)%avgflag)
    2108     1213440 :         ierr = pio_get_var(File,longname_desc, (/1,fld,t/), tape(t)%hlist(fld)%field%long_name)
    2109     1213440 :         ierr = pio_get_var(File,units_desc, (/1,fld,t/), tape(t)%hlist(fld)%field%units)
    2110      303360 :         tape(t)%hlist(fld)%field%sampling_seq(1:max_chars) = ' '
    2111     1213440 :         ierr = pio_get_var(File,sseq_desc, (/1,fld,t/), tape(t)%hlist(fld)%field%sampling_seq)
    2112      303360 :         call strip_null(tape(t)%hlist(fld)%field%sampling_seq)
    2113      303360 :         tape(t)%hlist(fld)%field%cell_methods(1:max_chars) = ' '
    2114     1213440 :         ierr = pio_get_var(File,cm_desc, (/1,fld,t/), tape(t)%hlist(fld)%field%cell_methods)
    2115      303360 :         call strip_null(tape(t)%hlist(fld)%field%cell_methods)
    2116      303360 :         if(xyfill(fld,t) ==1) then
    2117        3840 :           tape(t)%hlist(fld)%field%flag_xyfill=.true.
    2118             :         else
    2119      299520 :           tape(t)%hlist(fld)%field%flag_xyfill=.false.
    2120             :         end if
    2121      303360 :         if(is_subcol(fld,t) ==1) then
    2122           0 :            tape(t)%hlist(fld)%field%is_subcol=.true.
    2123             :         else
    2124      303360 :            tape(t)%hlist(fld)%field%is_subcol=.false.
    2125             :         end if
    2126      303360 :         call strip_null(tmpname(fld,t))
    2127      303360 :         call strip_null(tmpf1name(fld,t))
    2128      303360 :         call strip_null(tmpf2name(fld,t))
    2129      303360 :         tape(t)%hlist(fld)%field%name = tmpname(fld,t)
    2130      303360 :         tape(t)%hlist(fld)%op_field1 = tmpf1name(fld,t)
    2131      303360 :         tape(t)%hlist(fld)%op_field2 = tmpf2name(fld,t)
    2132      303360 :         tape(t)%hlist(fld)%field%decomp_type = decomp(fld,t)
    2133      303360 :         tape(t)%hlist(fld)%field%numlev = tmpnumlev(fld,t)
    2134      303360 :         tape(t)%hlist(fld)%hwrt_prec = tmpprec(fld,t)
    2135      303360 :         tape(t)%hlist(fld)%beg_nstep = tmpbeg_nstep(fld,t)
    2136      303360 :         call tape(t)%hlist(fld)%put_global(tmpintegral(fld,t))
    2137             :         ! If the field is an advected constituent set the mixing_ratio attribute
    2138      303360 :         fname_tmp = strip_suffix(tape(t)%hlist(fld)%field%name)
    2139      303360 :         call cnst_get_ind(fname_tmp, idx, abort=.false.)
    2140      303360 :         mixing_ratio = ''
    2141      303360 :         if (idx > 0) then
    2142       62976 :            mixing_ratio = cnst_get_type_byind(idx)
    2143             :         end if
    2144      303360 :         tape(t)%hlist(fld)%field%mixing_ratio = mixing_ratio
    2145             : 
    2146      606720 :         mdimcnt = count(allmdims(:,fld,t) > 0)
    2147     2132736 :         if(mdimcnt > 0) then
    2148      419328 :           allocate(tape(t)%hlist(fld)%field%mdims(mdimcnt))
    2149      279552 :           do i = 1, mdimcnt
    2150      279552 :             tape(t)%hlist(fld)%field%mdims(i) = get_hist_coord_index(mdimnames(allmdims(i,fld,t)))
    2151             :           end do
    2152             :         end if
    2153             :       end do
    2154             :     end do
    2155         768 :     deallocate(tmpname, tmpnumlev, tmpprec, tmpbeg_nstep, decomp, xyfill, is_subcol, tmpintegral)
    2156         768 :     deallocate(mdimnames)
    2157         768 :     deallocate(tmpf1name,tmpf2name)
    2158             : 
    2159        6912 :     allocate(grid_wts(cam_grid_num_grids() + 1))
    2160         768 :     allgrids_wt => grid_wts
    2161             : 
    2162        3072 :     allocate(gridsontape(cam_grid_num_grids() + 1, ptapes))
    2163       65280 :     gridsontape = -1
    2164        9984 :     do t = 1, ptapes
    2165      313344 :       do fld = 1, nflds(t)
    2166      303360 :         if (tape(t)%hlist(fld)%avgflag .ne. 'I') then
    2167      268032 :            hfile_accum(t) = .true.
    2168             :         end if
    2169      303360 :         call set_field_dimensions(tape(t)%hlist(fld)%field)
    2170             : 
    2171      303360 :         begdim1 = tape(t)%hlist(fld)%field%begdim1
    2172      303360 :         enddim1 = tape(t)%hlist(fld)%field%enddim1
    2173      303360 :         begdim2 = tape(t)%hlist(fld)%field%begdim2
    2174      303360 :         enddim2 = tape(t)%hlist(fld)%field%enddim2
    2175      303360 :         begdim3 = tape(t)%hlist(fld)%field%begdim3
    2176      303360 :         enddim3 = tape(t)%hlist(fld)%field%enddim3
    2177             : 
    2178     1516800 :         allocate(tape(t)%hlist(fld)%hbuf(begdim1:enddim1,begdim2:enddim2,begdim3:enddim3))
    2179      303360 :         if (tape(t)%hlist(fld)%avgflag .eq. 'S') then ! allocate the variance buffer for standard dev
    2180           0 :            allocate(tape(t)%hlist(fld)%sbuf(begdim1:enddim1,begdim2:enddim2,begdim3:enddim3))
    2181             :         endif
    2182             : 
    2183      303360 :         if (associated(tape(t)%hlist(fld)%varid)) then
    2184           0 :           deallocate(tape(t)%hlist(fld)%varid)
    2185             :         end if
    2186      303360 :         nullify(tape(t)%hlist(fld)%varid)
    2187      303360 :         if (associated(tape(t)%hlist(fld)%nacs)) then
    2188           0 :           deallocate(tape(t)%hlist(fld)%nacs)
    2189             :         end if
    2190      303360 :         nullify(tape(t)%hlist(fld)%nacs)
    2191      303360 :         if(tape(t)%hlist(fld)%field%flag_xyfill .or. (avgflag_pertape(t)=='L')) then
    2192       15360 :           allocate (tape(t)%hlist(fld)%nacs(begdim1:enddim1,begdim3:enddim3))
    2193             :         else
    2194      898560 :           allocate(tape(t)%hlist(fld)%nacs(1,begdim3:enddim3))
    2195             :         end if
    2196             :         ! initialize all buffers to zero - this will be overwritten later by the
    2197             :         ! data in the history restart file if it exists.
    2198      303360 :         call h_zero(fld,t)
    2199             : 
    2200             :         ! Make sure this field's decomp is listed on the tape
    2201      303360 :         fdecomp = tape(t)%hlist(fld)%field%decomp_type
    2202      303360 :         do ffld = 1, size(gridsontape, 1)
    2203      303360 :           if (fdecomp == gridsontape(ffld, t)) then
    2204             :             exit
    2205        1536 :           else if (gridsontape(ffld, t) < 0) then
    2206        1536 :             gridsontape(ffld, t) = fdecomp
    2207        1536 :             exit
    2208             :           end if
    2209             :         end do
    2210             :         !
    2211             :         !rebuild area wt array and set field wbuf pointer
    2212             :         !
    2213      615936 :         if (tape(t)%hlist(fld)%avgflag .eq. 'N') then ! set up area weight buffer
    2214           0 :            nullify(tape(t)%hlist(fld)%wbuf)
    2215             : 
    2216           0 :            if (any(allgrids_wt(:)%decomp_type == tape(t)%hlist(fld)%field%decomp_type)) then
    2217           0 :               wtidx=MAXLOC(allgrids_wt(:)%decomp_type, MASK = allgrids_wt(:)%decomp_type .EQ. fdecomp)
    2218           0 :               tape(t)%hlist(fld)%wbuf => allgrids_wt(wtidx(1))%wbuf
    2219             :            else
    2220             :               ! area weights not found for this grid, then create them
    2221             :               ! first check for an available spot in the array
    2222           0 :               if (any(allgrids_wt(:)%decomp_type == -1)) then
    2223           0 :                  wtidx=MINLOC(allgrids_wt(:)%decomp_type)
    2224             :               else
    2225           0 :                  call endrun('cam_history.F90:read_restart_history: Error initializing allgrids_wt with area weights')
    2226             :               end if
    2227           0 :               allgrids_wt(wtidx)%decomp_type=fdecomp
    2228           0 :               areawt => cam_grid_get_areawt(fdecomp)
    2229           0 :               allocate(allgrids_wt(wtidx(1))%wbuf(begdim1:enddim1,begdim3:enddim3))
    2230           0 :               cnt=0
    2231           0 :               do c=begdim3,enddim3
    2232           0 :                  dimind = tape(t)%hlist(fld)%field%get_dims(c)
    2233           0 :                  ib=dimind%beg1
    2234           0 :                  ie=dimind%end1
    2235           0 :                  do i=ib,ie
    2236           0 :                     cnt=cnt+1
    2237           0 :                     allgrids_wt(wtidx(1))%wbuf(i,c)=areawt(cnt)
    2238             :                  end do
    2239             :               end do
    2240           0 :               tape(t)%hlist(fld)%wbuf => allgrids_wt(wtidx(1))%wbuf
    2241             :            endif
    2242             :         endif
    2243             :       end do
    2244             :     end do
    2245             :     !
    2246             :     !-----------------------------------------------------------------------
    2247             :     ! Read history restart files
    2248             :     !-----------------------------------------------------------------------
    2249             :     !
    2250             :     ! Loop over the total number of history files declared and
    2251             :     ! read the pathname for any history restart files
    2252             :     ! that are present (if any). Test to see if the run is a restart run
    2253             :     ! AND if any history buffer regen files exist (rgnht=.T.). Note, rgnht
    2254             :     ! is preset to false, reset to true in routine WSDS if hbuf restart files
    2255             :     ! are written and saved in the master restart file. Each history buffer
    2256             :     ! restart file is then obtained.
    2257             :     ! Note: some f90 compilers (e.g. SGI) complain about I/O of
    2258             :     ! derived types which have pointer components, so explicitly read each one.
    2259             :     !
    2260        9984 :     do t=1,mtapes
    2261        9216 :       if (rgnht(t)) then
    2262             :         !
    2263             :         ! Open history restart file
    2264             :         !
    2265             :         call getfil (hrestpath(t), locfn)
    2266         768 :         call cam_pio_openfile(tape(t)%Files(restart_file_index), locfn, 0)
    2267             :         !
    2268             :         ! Read history restart file
    2269             :         !
    2270      269568 :         do fld = 1, nflds(t)
    2271             : 
    2272      268800 :           fname_tmp = strip_suffix(tape(t)%hlist(fld)%field%name)
    2273      268800 :           if(masterproc) write(iulog, *) 'Reading history variable ',fname_tmp
    2274      268800 :           ierr = pio_inq_varid(tape(t)%Files(restart_file_index), fname_tmp, vdesc)
    2275      268800 :           call cam_pio_var_info(tape(t)%Files(restart_file_index), vdesc, ndims, dimids, dimlens)
    2276             : 
    2277      268800 :           if(.not. associated(tape(t)%hlist(fld)%field%mdims)) then
    2278      162816 :             dimcnt = 0
    2279      325632 :             do i=1,ndims
    2280      162816 :               ierr = pio_inq_dimname(tape(t)%Files(restart_file_index), dimids(i), dname_tmp)
    2281      162816 :               dimid = get_hist_coord_index(dname_tmp)
    2282      325632 :               if(dimid >= 1) then
    2283           0 :                 dimcnt = dimcnt + 1
    2284           0 :                 tmpdims(dimcnt) = dimid
    2285             :               ! No else, just looking for mdims (grid dims won't be hist coords)
    2286             :               end if
    2287             :             end do
    2288      162816 :             if(dimcnt > 0) then
    2289           0 :               allocate(tape(t)%hlist(fld)%field%mdims(dimcnt))
    2290           0 :               tape(t)%hlist(fld)%field%mdims(:) = tmpdims(1:dimcnt)
    2291           0 :               if(dimcnt > maxvarmdims) maxvarmdims=dimcnt
    2292             :             end if
    2293             :           end if
    2294      268800 :           call set_field_dimensions(tape(t)%hlist(fld)%field)
    2295      268800 :           begdim1    =  tape(t)%hlist(fld)%field%begdim1
    2296      268800 :           enddim1    =  tape(t)%hlist(fld)%field%enddim1
    2297      268800 :           fdims(1)   =  enddim1 - begdim1 + 1
    2298      268800 :           begdim2    =  tape(t)%hlist(fld)%field%begdim2
    2299      268800 :           enddim2    =  tape(t)%hlist(fld)%field%enddim2
    2300      268800 :           fdims(2)   =  enddim2 - begdim2 + 1
    2301      268800 :           begdim3    =  tape(t)%hlist(fld)%field%begdim3
    2302      268800 :           enddim3    =  tape(t)%hlist(fld)%field%enddim3
    2303      268800 :           fdims(3)   =  enddim3 - begdim3 + 1
    2304      268800 :           if (fdims(2) > 1) then
    2305             :             nfdims = 3
    2306             :           else
    2307      162816 :             nfdims = 2
    2308      162816 :             fdims(2) = fdims(3)
    2309             :           end if
    2310      268800 :           fdecomp = tape(t)%hlist(fld)%field%decomp_type
    2311      268800 :           if (nfdims > 2) then
    2312             :             call cam_grid_read_dist_array(tape(t)%Files(restart_file_index), fdecomp,              &
    2313      105984 :                  fdims(1:nfdims), dimlens(1:ndims), tape(t)%hlist(fld)%hbuf, vdesc)
    2314             :           else
    2315             :             call cam_grid_read_dist_array(tape(t)%Files(restart_file_index), fdecomp,              &
    2316      162816 :                  fdims(1:nfdims), dimlens(1:ndims), tape(t)%hlist(fld)%hbuf(:,1,:), vdesc)
    2317             :           end if
    2318             : 
    2319      268800 :           if ( associated(tape(t)%hlist(fld)%sbuf) ) then
    2320             :              ! read in variance for standard deviation
    2321           0 :              ierr = pio_inq_varid(tape(t)%Files(restart_file_index), trim(fname_tmp)//'_var', vdesc)
    2322           0 :              if (nfdims > 2) then
    2323           0 :                 call cam_grid_read_dist_array(tape(t)%Files(restart_file_index), fdecomp,              &
    2324           0 :                      fdims(1:nfdims), dimlens(1:ndims), tape(t)%hlist(fld)%sbuf, vdesc)
    2325             :              else
    2326           0 :                 call cam_grid_read_dist_array(tape(t)%Files(restart_file_index), fdecomp,              &
    2327           0 :                      fdims(1:nfdims), dimlens(1:ndims), tape(t)%hlist(fld)%sbuf(:,1,:), vdesc)
    2328             :              end if
    2329             :           endif
    2330             : 
    2331      268800 :           ierr = pio_inq_varid(tape(t)%Files(restart_file_index), trim(fname_tmp)//'_nacs', vdesc)
    2332      268800 :           call cam_pio_var_info(tape(t)%Files(restart_file_index), vdesc, nacsdimcnt, dimids, dimlens)
    2333             : 
    2334      268800 :           if(nacsdimcnt > 0) then
    2335        3840 :             if (nfdims > 2) then
    2336             :               ! nacs only has 2 dims (no levels)
    2337           0 :               fdims(2) = fdims(3)
    2338             :             end if
    2339       15360 :             allocate(tape(t)%hlist(fld)%nacs(begdim1:enddim1,begdim3:enddim3))
    2340        3840 :             nacs       => tape(t)%hlist(fld)%nacs(:,:)
    2341             :             call cam_grid_read_dist_array(tape(t)%Files(restart_file_index), fdecomp, fdims(1:2),  &
    2342        3840 :                  dimlens(1:nacsdimcnt), nacs, vdesc)
    2343             :           else
    2344      794880 :             allocate(tape(t)%hlist(fld)%nacs(1,begdim3:enddim3))
    2345      264960 :             ierr = pio_get_var(tape(t)%Files(restart_file_index), vdesc, nacsval)
    2346     1333080 :             tape(t)%hlist(fld)%nacs(1,:)= nacsval
    2347             :           end if
    2348             : 
    2349      268800 :           ierr = pio_inq_varid(tape(t)%Files(restart_file_index), trim(fname_tmp)//'_nacs', vdesc)
    2350      538368 :           call cam_pio_var_info(tape(t)%Files(restart_file_index), vdesc, nacsdimcnt, dimids, dimlens)
    2351             : 
    2352             :         end do
    2353             :         !
    2354             :         ! Done reading this history restart file
    2355             :         !
    2356         768 :         call cam_pio_closefile(tape(t)%Files(restart_file_index))
    2357             : 
    2358             :       end if  ! rgnht(t)
    2359             : 
    2360             :       ! (re)create the master list of grid IDs
    2361        9216 :       ffld = 0
    2362       64512 :       do fld = 1, size(gridsontape, 1)
    2363       64512 :         if (gridsontape(fld, t) > 0) then
    2364        1536 :           ffld = ffld + 1
    2365             :         end if
    2366             :       end do
    2367       19968 :       allocate(tape(t)%grid_ids(ffld))
    2368        9216 :       ffld = 1
    2369       64512 :       do fld = 1, size(gridsontape, 1)
    2370       64512 :         if (gridsontape(fld, t) > 0) then
    2371        1536 :           tape(t)%grid_ids(ffld) = gridsontape(fld, t)
    2372        1536 :           ffld = ffld + 1
    2373             :         end if
    2374             :       end do
    2375        9984 :       call patch_init(t)
    2376             :     end do     ! end of do mtapes loop
    2377             : 
    2378             :     !
    2379             :     ! If the history files are partially complete (contain less than
    2380             :     ! mfilt(t) time samples, then get the files and open them.)
    2381             :     !
    2382             :     ! NOTE:  No need to perform this operation for IC history files or empty files
    2383             :     !
    2384        9984 :     do t=1,mtapes
    2385        9984 :       if (is_initfile(file_index=t)) then
    2386             :         ! Initialize filename specifier for IC file
    2387         768 :         hfilename_spec(t) = '%c.cam' // trim(inst_suffix) // '.i.%y-%m-%d-%s.nc'
    2388         768 :         nfils(t) = 0
    2389        8448 :       else if (nflds(t) == 0) then
    2390        7680 :         nfils(t) = 0
    2391             :       else
    2392         768 :         if (nfils(t) > 0) then
    2393             :            ! Always create the instantaneous file
    2394             :            call getfil (cpath(t,instantaneous_file_index), locfn)
    2395           0 :            call cam_pio_openfile(tape(t)%Files(instantaneous_file_index), locfn, PIO_WRITE)
    2396           0 :            if (hfile_accum(t)) then
    2397             :               ! Conditionally create the accumulated file
    2398           0 :               call getfil (cpath(t,accumulated_file_index), locfn)
    2399           0 :               call cam_pio_openfile(tape(t)%Files(accumulated_file_index), locfn, PIO_WRITE)
    2400             :            end if
    2401           0 :           call h_inquire (t)
    2402           0 :           if(is_satfile(t)) then
    2403             :             !  Initialize the sat following history subsystem
    2404           0 :             call sat_hist_init()
    2405           0 :             call sat_hist_define(tape(t)%Files(sat_file_index))
    2406             :           end if
    2407             :         end if
    2408             :         !
    2409             :         ! If the history file is full, close the current unit
    2410             :         !
    2411         768 :         if (nfils(t) >= mfilt(t)) then
    2412           0 :           if (masterproc) then
    2413           0 :             do f = 1, maxsplitfiles
    2414           0 :                if (pio_file_is_open(tape(t)%Files(f))) then
    2415           0 :                   write(iulog,*)'READ_RESTART_HISTORY: nf_close(',t,')=',nhfil(t,f), mfilt(t)
    2416             :                end if
    2417             :             end do
    2418             :           end if
    2419           0 :           do fld=1,nflds(t)
    2420           0 :             deallocate(tape(t)%hlist(fld)%varid)
    2421           0 :             nullify(tape(t)%hlist(fld)%varid)
    2422             :           end do
    2423           0 :           do f = 1, maxsplitfiles
    2424           0 :              if (pio_file_is_open(tape(t)%Files(f))) then
    2425           0 :                 call cam_pio_closefile(tape(t)%Files(f))
    2426             :              end if
    2427             :           end do
    2428           0 :           nfils(t) = 0
    2429             :         end if
    2430             :       end if
    2431             :     end do
    2432             : 
    2433             :     ! Setup vector pairs for unstructured grid interpolation
    2434         768 :     call setup_interpolation_and_define_vector_complements()
    2435             : 
    2436         768 :     if(mtapes/=ptapes .and. masterproc) then
    2437           0 :       write(iulog,*) ' WARNING: Restart file ptapes setting ',mtapes,' not equal to model setting ',ptapes
    2438             :     end if
    2439             : 
    2440             :     return
    2441        1536 :   end subroutine read_restart_history
    2442             : 
    2443             :   !#######################################################################
    2444             : 
    2445           0 :   character(len=max_string_len) function get_hfilepath( tape, accumulated_flag )
    2446             :     !
    2447             :     !-----------------------------------------------------------------------
    2448             :     !
    2449             :     ! Purpose: Return full filepath of history file for given tape number
    2450             :     ! This allows public read access to the filenames without making
    2451             :     ! the filenames public data.
    2452             :     !
    2453             :     !-----------------------------------------------------------------------
    2454             :     !
    2455             :     integer, intent(in) :: tape  ! Tape number
    2456             :     logical, intent(in) :: accumulated_flag ! True if calling routine wants the accumulated
    2457             :                                             ! file path, False for instantaneous
    2458             : 
    2459           0 :     if (accumulated_flag) then
    2460           0 :        get_hfilepath = cpath( tape, accumulated_file_index )
    2461             :     else
    2462           0 :        get_hfilepath = cpath( tape, instantaneous_file_index )
    2463             :     end if
    2464         768 :   end function get_hfilepath
    2465             : 
    2466             :   !#######################################################################
    2467             : 
    2468           0 :   character(len=max_string_len) function get_hist_restart_filepath( tape )
    2469             :     !
    2470             :     !-----------------------------------------------------------------------
    2471             :     !
    2472             :     ! Purpose: Return full filepath of restart file for given tape number
    2473             :     ! This allows public read access to the filenames without making
    2474             :     ! the filenames public data.
    2475             :     !
    2476             :     !-----------------------------------------------------------------------
    2477             :     !
    2478             :     integer, intent(in) :: tape  ! Tape number
    2479             : 
    2480           0 :     get_hist_restart_filepath = hrestpath( tape )
    2481           0 :   end function get_hist_restart_filepath
    2482             : 
    2483             :   !#######################################################################
    2484             : 
    2485           0 :   integer function get_ptapes( )
    2486             :     !
    2487             :     !-----------------------------------------------------------------------
    2488             :     !
    2489             :     ! Purpose: Return the number of tapes being used.
    2490             :     ! This allows public read access to the number of tapes without making
    2491             :     ! ptapes public data.
    2492             :     !
    2493             :     !-----------------------------------------------------------------------
    2494             :     !
    2495           0 :     get_ptapes = ptapes
    2496           0 :   end function get_ptapes
    2497             : 
    2498             :   !#######################################################################
    2499             : 
    2500  9239170560 :   recursive function get_entry_by_name(listentry, name) result(entry)
    2501             :     type(master_entry),  pointer :: listentry
    2502             :     character(len=*), intent(in) :: name ! variable name
    2503             :     type(master_entry), pointer :: entry
    2504             : 
    2505  9239170560 :     if(associated(listentry)) then
    2506  9234674688 :       if(listentry%field%name .eq. name) then
    2507             :         entry => listentry
    2508             :       else
    2509  9233028864 :         entry=>get_entry_by_name(listentry%next_entry, name)
    2510             :       end if
    2511             :     else
    2512             :       nullify(entry)
    2513             :     end if
    2514  9239170560 :   end function get_entry_by_name
    2515             : 
    2516             :   !#######################################################################
    2517             : 
    2518    54557184 :   subroutine AvgflagToString(avgflag, time_op)
    2519             :     ! Dummy arguments
    2520             :     character(len=1),           intent(in)  :: avgflag ! averaging flag
    2521             :     character(len=max_chars),   intent(out) :: time_op ! time op (e.g. max)
    2522             : 
    2523             :     ! Local variable
    2524             :     character(len=*), parameter             :: subname = 'AvgflagToString'
    2525             : 
    2526    45414912 :     select case (avgflag)
    2527             :     case ('A')
    2528    45414912 :       time_op(:) = 'mean'
    2529             :     case ('B')
    2530           0 :       time_op(:) = 'mean00z'
    2531             :     case ('N')
    2532           0 :       time_op(:) = 'mean_over_nsteps'
    2533             :     case ('I')
    2534     9010176 :       time_op(:) = 'point'
    2535             :     case ('X')
    2536       93696 :       time_op(:) = 'maximum'
    2537             :     case ('M')
    2538       38400 :       time_op(:) = 'minimum'
    2539             :     case('L')
    2540           0 :       time_op(:) = LT_DESC
    2541             :     case ('S')
    2542           0 :       time_op(:) = 'standard_deviation'
    2543             :     case default
    2544    54557184 :       call endrun(subname//': unknown avgflag = '//avgflag)
    2545             :     end select
    2546    54557184 :   end subroutine AvgflagToString
    2547             : 
    2548             :   !#######################################################################
    2549             : 
    2550         768 :   subroutine fldlst ()
    2551             : 
    2552             :     use cam_grid_support, only: cam_grid_num_grids
    2553             :     use spmd_utils,       only: mpicom
    2554             :     use dycore,           only: dycore_is
    2555             : 
    2556             :     !-----------------------------------------------------------------------
    2557             :     !
    2558             :     ! Purpose: Define the contents of each history file based on namelist input for initial or branch
    2559             :     ! run, and restart data if a restart run.
    2560             :     !
    2561             :     ! Method: Use arrays fincl and fexcl to modify default history tape contents.
    2562             :     !         Then sort the result alphanumerically for later use by OUTFLD to
    2563             :     !         allow an n log n search time.
    2564             :     !
    2565             :     !---------------------------Local variables-----------------------------
    2566             :     !
    2567             :     integer t, fld                 ! tape, field indices
    2568             :     integer ffld                   ! index into include, exclude and fprec list
    2569             :     integer :: i
    2570             :     character(len=fieldname_len) :: name ! field name portion of fincl (i.e. no avgflag separator)
    2571             :     character(len=max_fieldname_len) :: mastername ! name from masterlist field
    2572             :     character(len=max_chars) :: errormsg ! error output field
    2573             :     character(len=1) :: avgflag    ! averaging flag
    2574             :     character(len=1) :: prec_wrt   ! history buffer write precision flag
    2575             : 
    2576             :     type (hentry) :: tmp           ! temporary used for swapping
    2577             : 
    2578             :     type(master_entry), pointer :: listentry
    2579             :     logical                     :: fieldontape      ! .true. iff field on tape
    2580             :     integer                     :: errors_found
    2581             : 
    2582             :     ! List of active grids (first dim) for each tape (second dim)
    2583             :     ! An active grid is one for which there is a least one field being output
    2584             :     !    on that grid.
    2585         768 :     integer, allocatable        :: gridsontape(:,:)
    2586             : 
    2587             :     integer :: n_vec_comp, add_fincl_idx
    2588             :     integer, parameter :: nvecmax = 50 ! max number of vector components in a fincl list
    2589             :     character(len=2) :: avg_suffix
    2590             :     character(len=max_fieldname_len) :: vec_comp_names(nvecmax)
    2591             :     character(len=1)                 :: vec_comp_avgflag(nvecmax)
    2592             :     !--------------------------------------------------------------------------
    2593             : 
    2594             :     ! First ensure contents of fincl, fexcl, and fwrtpr are all valid names
    2595             :     !
    2596         768 :     errors_found = 0
    2597        9984 :     do t=1,ptapes
    2598             : 
    2599        9216 :       fld = 1
    2600        9216 :       n_vec_comp       = 0
    2601      470016 :       vec_comp_names   = ' '
    2602      470016 :       vec_comp_avgflag = ' '
    2603        9216 :       do while (fld < pflds .and. fincl(fld,t) /= ' ')
    2604           0 :         name = getname (fincl(fld,t))
    2605             : 
    2606           0 :         mastername=''
    2607           0 :         listentry => get_entry_by_name(masterlinkedlist, name)
    2608           0 :         if (associated(listentry)) mastername = listentry%field%name
    2609           0 :         if (name /= mastername) then
    2610           0 :           write(errormsg,'(3a,2(i0,a))')'FLDLST: ', trim(name), ' in fincl(', fld,', ',t, ') not found'
    2611           0 :           if (masterproc) then
    2612           0 :              write(iulog,*) trim(errormsg)
    2613           0 :              call shr_sys_flush(iulog)
    2614             :           end if
    2615           0 :           errors_found = errors_found + 1
    2616             :         else
    2617           0 :            if (len_trim(mastername)>0 .and. interpolate_output(t)) then
    2618           0 :               if (n_vec_comp >= nvecmax) call endrun('FLDLST: need to increase nvecmax')
    2619             :               ! If this is a vector component then save the name of the complement
    2620           0 :               avgflag = getflag(fincl(fld,t))
    2621           0 :               if (len_trim(listentry%meridional_field) > 0) then
    2622           0 :                  n_vec_comp = n_vec_comp + 1
    2623           0 :                  vec_comp_names(n_vec_comp) = listentry%meridional_field
    2624           0 :                  vec_comp_avgflag(n_vec_comp) = avgflag
    2625           0 :               else if (len_trim(listentry%zonal_field) > 0) then
    2626           0 :                  n_vec_comp = n_vec_comp + 1
    2627           0 :                  vec_comp_names(n_vec_comp) = listentry%zonal_field
    2628           0 :                  vec_comp_avgflag(n_vec_comp) = avgflag
    2629             :               end if
    2630             :            end if
    2631             :         end if
    2632           0 :         fld = fld + 1
    2633             :       end do
    2634             : 
    2635             :       ! Interpolation of vector components requires that both be present.  If the fincl
    2636             :       ! specifier contains any vector components, then the complement was saved in the
    2637             :       ! array vec_comp_names.  Next insure (for interpolated output only) that all complements
    2638             :       ! are also present in the fincl array.
    2639             : 
    2640             :       ! The first empty slot in the current fincl array is index fld from loop above.
    2641        9216 :       add_fincl_idx = fld
    2642        9216 :       if (fld > 1 .and. interpolate_output(t)) then
    2643           0 :          do i = 1, n_vec_comp
    2644           0 :             call list_index(fincl(:,t), vec_comp_names(i), ffld)
    2645           0 :             if (ffld == 0) then
    2646             : 
    2647             :                ! Add vector component to fincl.  Don't need to check whether its in the master
    2648             :                ! list since this was done at the time of registering the vector components.
    2649           0 :                avg_suffix = '  '
    2650           0 :                if (len_trim(vec_comp_avgflag(i)) > 0) avg_suffix = ':' // vec_comp_avgflag(i)
    2651           0 :                fincl(add_fincl_idx,t) = trim(vec_comp_names(i)) // avg_suffix
    2652           0 :                add_fincl_idx = add_fincl_idx + 1
    2653             : 
    2654           0 :                write(errormsg,'(3a,1(i0,a))')'FLDLST: ', trim(vec_comp_names(i)), &
    2655           0 :                   ' added to fincl', t, '.  Both vector components are required for interpolated output.'
    2656           0 :                if (masterproc) then
    2657           0 :                   write(iulog,*) trim(errormsg)
    2658           0 :                   call shr_sys_flush(iulog)
    2659             :                end if
    2660             :             end if
    2661             :          end do
    2662             :       end if
    2663             : 
    2664        9216 :       fld = 1
    2665        9216 :       do while (fld < pflds .and. fexcl(fld,t) /= ' ')
    2666           0 :         mastername=''
    2667           0 :         listentry => get_entry_by_name(masterlinkedlist, fexcl(fld,t))
    2668           0 :         if(associated(listentry)) mastername = listentry%field%name
    2669             : 
    2670           0 :         if (fexcl(fld,t) /= mastername) then
    2671           0 :           write(errormsg,'(3a,2(i0,a))')'FLDLST: ', trim(fexcl(fld,t)), ' in fexcl(', fld,', ',t, ') not found'
    2672           0 :           if (masterproc) then
    2673           0 :              write(iulog,*) trim(errormsg)
    2674           0 :              call shr_sys_flush(iulog)
    2675             :           end if
    2676           0 :           errors_found = errors_found + 1
    2677             :         end if
    2678           0 :         fld = fld + 1
    2679             :       end do
    2680             : 
    2681        9216 :       fld = 1
    2682        9984 :       do while (fld < pflds .and. fwrtpr(fld,t) /= ' ')
    2683           0 :         name = getname (fwrtpr(fld,t))
    2684           0 :         mastername=''
    2685           0 :         listentry => get_entry_by_name(masterlinkedlist, name)
    2686           0 :         if(associated(listentry)) mastername = listentry%field%name
    2687           0 :         if (name /= mastername) then
    2688           0 :           write(errormsg,'(3a,i0,a)')'FLDLST: ', trim(name), ' in fwrtpr(', fld, ') not found'
    2689           0 :           if (masterproc) then
    2690           0 :              write(iulog,*) trim(errormsg)
    2691           0 :              call shr_sys_flush(iulog)
    2692             :           end if
    2693           0 :           errors_found = errors_found + 1
    2694             :         end if
    2695           0 :         do ffld=1,fld-1                 ! If duplicate entry is found, stop
    2696           0 :           if (trim(name) == trim(getname(fwrtpr(ffld,t)))) then
    2697           0 :             write(errormsg,'(3a)')'FLDLST: Duplicate field ', trim(name), ' in fwrtpr'
    2698           0 :             if (masterproc) then
    2699           0 :                write(iulog,*) trim(errormsg)
    2700           0 :                call shr_sys_flush(iulog)
    2701             :             end if
    2702           0 :             errors_found = errors_found + 1
    2703             :           end if
    2704             :         end do
    2705           0 :         fld = fld + 1
    2706             :       end do
    2707             :     end do
    2708             : 
    2709         768 :     if (errors_found > 0) then
    2710             :        ! Give masterproc a chance to write all the log messages
    2711           0 :        call mpi_barrier(mpicom, t)
    2712           0 :        write(errormsg, '(a,i0,a)') 'FLDLST: ',errors_found,' errors found, see log'
    2713           0 :        call endrun(trim(errormsg))
    2714             :     end if
    2715             : 
    2716         768 :     nflds(:) = 0
    2717             :     ! IC history file is to be created, set properties
    2718         768 :     if(is_initfile()) then
    2719         768 :       hfilename_spec(ptapes) = '%c.cam' // trim(inst_suffix) // '.i.%y-%m-%d-%s.nc'
    2720             : 
    2721         768 :       ncprec(ptapes) = pio_double
    2722         768 :       ndens (ptapes) = 1
    2723         768 :       mfilt (ptapes) = 1
    2724             :     end if
    2725             : 
    2726             : 
    2727        6144 :     allocate(grid_wts(cam_grid_num_grids() + 1))
    2728         768 :     allgrids_wt => grid_wts
    2729             : 
    2730        3072 :     allocate(gridsontape(cam_grid_num_grids() + 1, ptapes))
    2731       56064 :     gridsontape = -1
    2732        9984 :     do t=1,ptapes
    2733             :       !
    2734             :       ! Add the field to the tape if specified via namelist (FINCL[1-ptapes]), or if
    2735             :       ! it is on by default and was not excluded via namelist (FEXCL[1-ptapes]).
    2736             :       ! Also set history buffer accumulation and output precision values according
    2737             :       ! to the values specified via namelist (FWRTPR[1-ptapes])
    2738             :       ! or, if not on the list, to the default values given by ndens(t).
    2739             :       !
    2740        9216 :       listentry => masterlinkedlist
    2741    26985216 :       do while(associated(listentry))
    2742    26975232 :         mastername = listentry%field%name
    2743    26975232 :         call list_index (fincl(1,t), mastername, ffld)
    2744             : 
    2745    26975232 :         fieldontape = .false.
    2746    26975232 :         if (ffld > 0) then
    2747             :           fieldontape = .true.
    2748    26975232 :         else if ((.not. empty_htapes) .or. (is_initfile(file_index=t))) then
    2749    26975232 :           call list_index (fexcl(1,t), mastername, ffld)
    2750    26975232 :           if (ffld == 0 .and. listentry%actflag(t)) then
    2751             :             fieldontape = .true.
    2752             :           end if
    2753             :         end if
    2754             :         if (fieldontape) then
    2755             :           ! The field is active so increment the number fo fields and add
    2756             :           ! its decomp type to the list of decomp types on this tape
    2757      303360 :           nflds(t) = nflds(t) + 1
    2758      303360 :           do ffld = 1, size(gridsontape, 1)
    2759      303360 :             if (listentry%field%decomp_type == gridsontape(ffld, t)) then
    2760             :               exit
    2761        1536 :             else if (gridsontape(ffld, t) < 0) then
    2762        1536 :               gridsontape(ffld, t) = listentry%field%decomp_type
    2763        1536 :               exit
    2764             :             end if
    2765             :           end do
    2766             :         end if
    2767    26975232 :         listentry=>listentry%next_entry
    2768             :       end do
    2769             :     end do
    2770             :     !
    2771             :     ! Determine total number of active history tapes
    2772             :     !
    2773         768 :     if (masterproc) then
    2774          13 :       do t=1,ptapes
    2775          13 :         if (nflds(t)  ==  0) then
    2776          10 :           write(iulog,*)'FLDLST: Tape ',t,' is empty'
    2777             :         end if
    2778             :       end do
    2779             :     endif
    2780       11520 :     allocate(history_tape(ptapes))
    2781         768 :     tape=>history_tape
    2782             : 
    2783             : 
    2784        9984 :     do t=1,ptapes
    2785        9216 :       nullify(tape(t)%hlist)
    2786             :       ! Now we have a field count and can allocate
    2787        9216 :       if(nflds(t) > 0) then
    2788             :         ! Allocate the correct number of hentry slots
    2789      307968 :         allocate(tape(t)%hlist(nflds(t)))
    2790             :         ! Count up the number of grids output on this tape
    2791        1536 :         ffld = 0
    2792        9216 :         do fld = 1, size(gridsontape, 1)
    2793        9216 :           if (gridsontape(fld, t) > 0) then
    2794        1536 :             ffld = ffld + 1
    2795             :           end if
    2796             :         end do
    2797        4608 :         allocate(tape(t)%grid_ids(ffld))
    2798        1536 :         ffld = 1
    2799        9216 :         do fld = 1, size(gridsontape, 1)
    2800        9216 :           if (gridsontape(fld, t) > 0) then
    2801        1536 :             tape(t)%grid_ids(ffld) = gridsontape(fld, t)
    2802        1536 :             ffld = ffld + 1
    2803             :           end if
    2804             :         end do
    2805             :       end if
    2806      312576 :       do ffld=1,nflds(t)
    2807      303360 :         nullify(tape(t)%hlist(ffld)%hbuf)
    2808      303360 :         nullify(tape(t)%hlist(ffld)%sbuf)
    2809      303360 :         nullify(tape(t)%hlist(ffld)%wbuf)
    2810      303360 :         nullify(tape(t)%hlist(ffld)%nacs)
    2811      312576 :         nullify(tape(t)%hlist(ffld)%varid)
    2812             :       end do
    2813             : 
    2814             : 
    2815        9216 :       nflds(t) = 0 ! recount to support array based method
    2816        9216 :       listentry => masterlinkedlist
    2817    26984448 :       do while(associated(listentry))
    2818    26975232 :         mastername = listentry%field%name
    2819             : 
    2820    26975232 :         call list_index (fwrtpr(1,t), mastername, ffld)
    2821    26975232 :         if (ffld > 0) then
    2822           0 :           prec_wrt = getflag(fwrtpr(ffld,t))
    2823             :         else
    2824    26975232 :           prec_wrt = ' '
    2825             :         end if
    2826             : 
    2827    26975232 :         call list_index (fincl(1,t), mastername, ffld)
    2828             : 
    2829    26975232 :         if (ffld > 0) then
    2830           0 :           avgflag = getflag (fincl(ffld,t))
    2831           0 :           call inifld (t, listentry, avgflag,  prec_wrt)
    2832    26975232 :         else if ((.not. empty_htapes) .or. (is_initfile(file_index=t))) then
    2833    26975232 :           call list_index (fexcl(1,t), mastername, ffld)
    2834    26975232 :           if (ffld == 0 .and. listentry%actflag(t)) then
    2835      303360 :             call inifld (t, listentry, ' ', prec_wrt)
    2836             :           else
    2837    26671872 :             listentry%actflag(t) = .false.
    2838             :           end if
    2839             :         else
    2840           0 :           listentry%actflag(t) = .false.
    2841             :         end if
    2842    26975232 :         listentry=>listentry%next_entry
    2843             : 
    2844             :       end do
    2845             :       !
    2846             :       ! If column output is specified make sure there are some fields defined
    2847             :       ! for that tape
    2848             :       !
    2849        9216 :       if (nflds(t) .eq. 0 .and. fincllonlat(1,t) .ne. ' ') then
    2850           0 :         write(errormsg,'(a,i2,a)') 'FLDLST: Column output is specified for tape ',t,' but no fields defined for that tape.'
    2851           0 :         call endrun(errormsg)
    2852             :       else
    2853        9216 :         call patch_init(t)
    2854             :       end if
    2855             :       !
    2856             :       ! Specification of tape contents now complete.  Sort each list of active
    2857             :       ! entries for efficiency in OUTFLD.  Simple bubble sort.
    2858             :       !
    2859             : !!XXgoldyXX: v In the future, we will sort according to decomp to speed I/O
    2860      311040 :       do fld=nflds(t)-1,1,-1
    2861    47967744 :         do ffld=1,fld
    2862             : 
    2863    47967744 :           if (tape(t)%hlist(ffld)%field%numlev > tape(t)%hlist(ffld+1)%field%numlev) then
    2864     6508032 :             tmp = tape(t)%hlist(ffld)
    2865     6508032 :             tape(t)%hlist(ffld  ) = tape(t)%hlist(ffld+1)
    2866     6508032 :             tape(t)%hlist(ffld+1) = tmp
    2867             :           end if
    2868             : 
    2869             :         end do
    2870             : 
    2871    47976960 :         do ffld=1,fld
    2872             : 
    2873    47665920 :            if ((tape(t)%hlist(ffld)%field%numlev == tape(t)%hlist(ffld+1)%field%numlev) .and. &
    2874      301824 :                 (tape(t)%hlist(ffld)%field%name > tape(t)%hlist(ffld+1)%field%name)) then
    2875             : 
    2876    11354112 :             tmp = tape(t)%hlist(ffld)
    2877    11354112 :             tape(t)%hlist(ffld  ) = tape(t)%hlist(ffld+1)
    2878    11354112 :             tape(t)%hlist(ffld+1) = tmp
    2879             : 
    2880    36311808 :           else if (tape(t)%hlist(ffld)%field%name == tape(t)%hlist(ffld+1)%field%name) then
    2881             : 
    2882           0 :             write(errormsg,'(2a,2(a,i3))') 'FLDLST: Duplicate field: ', &
    2883           0 :                  trim(tape(t)%hlist(ffld)%field%name),', tape = ', t, ', ffld = ', ffld
    2884           0 :             call endrun(errormsg)
    2885             : 
    2886             :           end if
    2887             : 
    2888             :         end do
    2889             :       end do
    2890             : 
    2891             :       !  Initialize the field names/ids for each composed field on tapes
    2892        9984 :       call define_composed_field_ids(t)
    2893             : 
    2894             :     end do    ! do t=1,ptapes
    2895         768 :     deallocate(gridsontape)
    2896             : 
    2897         768 :     call print_active_fldlst()
    2898             : 
    2899             :     !
    2900             :     ! Packing density, ndens: With netcdf, only 1 (nf_double) and 2 (pio_real)
    2901             :     ! are allowed
    2902             :     !
    2903        9984 :     do t=1,ptapes
    2904        9984 :       if (ndens(t) == 1) then
    2905         768 :         ncprec(t) = pio_double
    2906        8448 :       else if (ndens(t) == 2) then
    2907        8448 :         ncprec(t) = pio_real
    2908             :       else
    2909           0 :         call endrun ('FLDLST: ndens must be 1 or 2')
    2910             :       end if
    2911             : 
    2912             :     end do
    2913             :     !
    2914             :     !  Now that masterlinkedlist is defined, construct primary and secondary hashing
    2915             :     !  tables.
    2916             :     !
    2917         768 :     call bld_outfld_hash_tbls()
    2918         768 :     call bld_htapefld_indices()
    2919             : 
    2920         768 :     return
    2921        1536 :   end subroutine fldlst
    2922             : 
    2923             : !#########################################################################################
    2924             : 
    2925        1536 : subroutine print_active_fldlst()
    2926             : 
    2927             :    integer :: fld, ffld, i, t
    2928             :    integer :: num_patches
    2929             : 
    2930             :    character(len=6) :: prec_str
    2931             :    character(len=max_chars) :: fldname, fname_tmp
    2932             : 
    2933             :    type(active_entry), pointer :: hfile(:) => null()  ! history files
    2934             : 
    2935        1536 :    if (masterproc) then
    2936             : 
    2937           2 :       hfile=>history_tape
    2938             : 
    2939          26 :       do t=1,ptapes
    2940             : 
    2941          24 :          if (nflds(t) > 0) then
    2942           4 :             write(iulog,*) ' '
    2943           4 :             write(iulog,*)'FLDLST: History stream ', t, ' contains ', nflds(t), ' fields'
    2944             : 
    2945           4 :             if (is_initfile(file_index=t)) then
    2946           2 :                write(iulog,*) ' Write frequency:                 ',inithist,' (INITIAL CONDITIONS)'
    2947             :             else
    2948           2 :                if (nhtfrq(t) == 0) then
    2949           2 :                   write(iulog,*) ' Write frequency:                  MONTHLY'
    2950             :                else
    2951           0 :                   write(iulog,*) ' Write frequency:                 ',nhtfrq(t)
    2952             :                end if
    2953             :             end if
    2954             : 
    2955           4 :             write(iulog,*) ' Filename specifier:              ', trim(hfilename_spec(t))
    2956             : 
    2957           4 :             prec_str = 'double'
    2958           4 :             if (ndens(t) == 2) prec_str = 'single'
    2959           4 :             write(iulog,*) ' Output precision:                ', prec_str
    2960           4 :             write(iulog,*) ' Number of time samples per file: ', mfilt(t)
    2961             : 
    2962             :             ! grid info
    2963           4 :             if (associated(hfile(t)%patches)) then
    2964           0 :                write(iulog,*) ' Fields are represented on columns (FIELD_LON_LAT)'
    2965           4 :             else if (associated(hfile(t)%grid_ids)) then
    2966           4 :                write(iulog,*) ' Fields are represented on global grids:'
    2967           8 :                do i = 1, size(hfile(t)%grid_ids)
    2968           8 :                   write(iulog,*) ' ', hfile(t)%grid_ids(i)
    2969             :                end do
    2970             :             else
    2971           0 :                call endrun('print_active_fldlst: error in active_entry object')
    2972             :             end if
    2973             : 
    2974           4 :             write(iulog,*)' Included fields are:'
    2975             : 
    2976             :          end if
    2977             : 
    2978         816 :          do fld = 1, nflds(t)
    2979         814 :             if (associated(hfile(t)%patches)) then
    2980           0 :                num_patches = size(hfile(t)%patches)
    2981           0 :                fldname = strip_suffix(hfile(t)%hlist(fld)%field%name)
    2982           0 :                do i = 1, num_patches
    2983           0 :                   ffld = (fld-1)*num_patches + i
    2984           0 :                   fname_tmp = trim(fldname)
    2985           0 :                   call hfile(t)%patches(i)%field_name(fname_tmp)
    2986           0 :                   write(iulog,9000) ffld, fname_tmp, hfile(t)%hlist(fld)%field%units, &
    2987           0 :                      hfile(t)%hlist(fld)%field%numlev, hfile(t)%hlist(fld)%avgflag,   &
    2988           0 :                      trim(hfile(t)%hlist(fld)%field%long_name)
    2989             :                end do
    2990             :             else
    2991         790 :                fldname = hfile(t)%hlist(fld)%field%name
    2992         790 :                write(iulog,9000) fld, fldname, hfile(t)%hlist(fld)%field%units,  &
    2993         790 :                   hfile(t)%hlist(fld)%field%numlev, hfile(t)%hlist(fld)%avgflag, &
    2994        1580 :                   trim(hfile(t)%hlist(fld)%field%long_name)
    2995             :             end if
    2996             : 
    2997             :          end do
    2998             : 
    2999             :       end do
    3000             : 
    3001             :    end if
    3002             : 
    3003             : 9000 format(i5, 1x, a32, 1x, a16, 1x, i4, 1x, a1, 2x, 256a)
    3004             : 
    3005         768 : end subroutine print_active_fldlst
    3006             : 
    3007             : !#########################################################################################
    3008             : 
    3009      303360 :   subroutine inifld (t, listentry, avgflag, prec_wrt)
    3010             :     use cam_grid_support, only: cam_grid_is_zonal
    3011             :     !
    3012             :     !-----------------------------------------------------------------------
    3013             :     !
    3014             :     ! Purpose: Add a field to the active list for a history tape
    3015             :     !
    3016             :     ! Method: Copy the data from the master field list to the active list for the tape
    3017             :     !         Also: define mapping arrays from (col,chunk) -> (lon,lat)
    3018             :     !
    3019             :     ! Author: CCM Core Group
    3020             :     !
    3021             :     !-----------------------------------------------------------------------
    3022             : 
    3023             : 
    3024             :     !
    3025             :     ! Arguments
    3026             :     !
    3027             :     integer, intent(in)          :: t         ! history tape index
    3028             : 
    3029             :     type(master_entry), pointer  :: listentry
    3030             : 
    3031             :     character(len=1), intent(in) :: avgflag   ! averaging flag
    3032             :     character(len=1), intent(in) :: prec_wrt  ! history output precision flag
    3033             :     !
    3034             :     ! Local workspace
    3035             :     !
    3036             :     integer :: n                  ! field index on defined tape
    3037             : 
    3038             : 
    3039             :     !
    3040             :     ! Ensure that it is not to late to add a field to the history tape
    3041             :     !
    3042      303360 :     if (htapes_defined) then
    3043           0 :       call endrun ('INIFLD: Attempt to add field '//listentry%field%name//' after history files set')
    3044             :     end if
    3045             : 
    3046      303360 :     nflds(t) = nflds(t) + 1
    3047      303360 :     n = nflds(t)
    3048             :     !
    3049             :     ! Copy field info.
    3050             :     !
    3051      303360 :     if(n > size(tape(t)%hlist)) then
    3052           0 :       write(iulog,*) 'tape field miscount error ', n, size(tape(t)%hlist)
    3053           0 :       call endrun()
    3054             :     end if
    3055             : 
    3056      303360 :     tape(t)%hlist(n)%field = listentry%field
    3057             : 
    3058             :     select case (prec_wrt)
    3059             :     case (' ')
    3060      303360 :       if (ndens(t) == 1) then
    3061       34560 :         tape(t)%hlist(n)%hwrt_prec = 8
    3062             :       else
    3063      268800 :         tape(t)%hlist(n)%hwrt_prec = 4
    3064             :       end if
    3065             :     case ('4')
    3066           0 :       tape(t)%hlist(n)%hwrt_prec = 4
    3067           0 :       if (masterproc) then
    3068           0 :         write(iulog,*) 'INIFLD: Output data type for ', tape(t)%hlist(n)%field%name, &
    3069           0 :              ' is real*4'
    3070             :       end if
    3071             :     case ('8')
    3072           0 :       tape(t)%hlist(n)%hwrt_prec = 8
    3073           0 :       if (masterproc) then
    3074           0 :         write(iulog,*) 'INIFLD: Output data type for ', tape(t)%hlist(n)%field%name, &
    3075           0 :              ' is real*8'
    3076             :       end if
    3077             :     case default
    3078      303360 :       call endrun ('INIFLD: unknown prec_wrt='//prec_wrt)
    3079             :     end select
    3080             :     !
    3081             :     ! Override the default averaging (masterlist) averaging flag if non-blank
    3082             :     !
    3083      303360 :     if (avgflag == ' ') then
    3084      303360 :       tape(t)%hlist(n)%avgflag = listentry%avgflag(t)
    3085      303360 :       tape(t)%hlist(n)%time_op = listentry%time_op(t)
    3086             :     else
    3087           0 :       tape(t)%hlist(n)%avgflag = avgflag
    3088           0 :       call AvgflagToString(avgflag, tape(t)%hlist(n)%time_op)
    3089             :     end if
    3090             : 
    3091             :     ! Some things can't be done with zonal fields
    3092      303360 :     if (cam_grid_is_zonal(listentry%field%decomp_type)) then
    3093           0 :       if (tape(t)%hlist(n)%avgflag == 'L') then
    3094           0 :         call endrun("Cannot perform local time processing on zonal data ("//trim(listentry%field%name)//")")
    3095           0 :       else if (is_satfile(t)) then
    3096           0 :         call endrun("Zonal data not valid for satellite history ("//trim(listentry%field%name)//")")
    3097             :       end if
    3098             :     end if
    3099             : 
    3100             : #ifdef HDEBUG
    3101             :     if (masterproc) then
    3102             :       write(iulog,'(a,i0,3a,i0,a,i2)')'HDEBUG: ',__LINE__,' field ',          &
    3103             :            trim(tape(t)%hlist(n)%field%name), ' added as field number ', n,   &
    3104             :            ' on tape ', t
    3105             :       write(iulog,'(2a)')'  units     = ',trim(tape(t)%hlist(n)%field%units)
    3106             :       write(iulog,'(a,i0)')'  numlev    = ',tape(t)%hlist(n)%field%numlev
    3107             :       write(iulog,'(2a)')'  avgflag   = ',tape(t)%hlist(n)%avgflag
    3108             :       write(iulog,'(3a)')'  time_op   = "',trim(tape(t)%hlist(n)%time_op),'"'
    3109             :       write(iulog,'(a,i0)')'  hwrt_prec = ',tape(t)%hlist(n)%hwrt_prec
    3110             :     end if
    3111             : #endif
    3112             : 
    3113      303360 :     return
    3114      303360 :   end subroutine inifld
    3115             : 
    3116             : 
    3117       18432 :   subroutine patch_init(t)
    3118      303360 :     use cam_history_support, only: history_patch_t
    3119             :     use cam_grid_support,    only: cam_grid_compute_patch
    3120             : 
    3121             :     ! Dummy arguments
    3122             :     integer, intent(in)               :: t     ! Current tape
    3123             : 
    3124             :     ! Local variables
    3125             :     integer                           :: ff    ! Loop over fincllonlat entries
    3126             :     integer                           :: i     ! General loop index
    3127             :     integer                           :: npatches
    3128             :     type(history_patch_t), pointer    :: patchptr
    3129             : 
    3130             :     character(len=max_chars)          :: errormsg
    3131             :     character(len=max_chars)          :: lonlatname(pflds)
    3132             :     real(r8)                          :: beglon, beglat, endlon, endlat
    3133             : 
    3134             :     !
    3135             :     ! Setup column information if this field will be written as group
    3136             :     ! First verify the column information in the namelist
    3137             :     ! Duplicates are an error, but we can just ignore them
    3138             :     !
    3139             : 
    3140             :     ! I know, this shouldn't happen . . . yet: (better safe than sorry)
    3141       18432 :     if (associated(tape(t)%patches)) then
    3142           0 :       do i = 1, size(tape(t)%patches)
    3143           0 :         call tape(t)%patches(i)%deallocate()
    3144             :       end do
    3145           0 :       deallocate(tape(t)%patches)
    3146           0 :       nullify(tape(t)%patches)
    3147             :     end if
    3148             : 
    3149             :     ! First, count the number of patches and check for duplicates
    3150             :     ff = 1  ! Index of fincllonlat entry
    3151             :     npatches = 0   ! Number of unique patches in namelist entry
    3152       18432 :     do while (len_trim(fincllonlat(ff, t)) > 0)
    3153           0 :       npatches = npatches + 1
    3154           0 :       lonlatname(npatches) = trim(fincllonlat(ff, t))
    3155             :       ! Check for duplicates
    3156           0 :       do i = 1, npatches - 1
    3157           0 :         if (trim(lonlatname(i)) == trim(lonlatname(npatches))) then
    3158           0 :           write(errormsg, '(a,i0,3a)') 'Duplicate fincl', t, 'lonlat entry.', &
    3159           0 :                'Duplicate entry is ', trim(lonlatname(i))
    3160           0 :           write(iulog, *) 'patch_init: WARNING: '//errormsg
    3161             :           ! Remove the new entry
    3162           0 :           lonlatname(npatches) = ''
    3163           0 :           npatches = npatches - 1
    3164           0 :           exit
    3165             :         end if
    3166             :       end do
    3167           0 :       ff = ff + 1
    3168             :     end do
    3169             : 
    3170             :     ! Now we know how many patches, allocate space
    3171       18432 :     if (npatches > 0) then
    3172           0 :       if (collect_column_output(t)) then
    3173           0 :         allocate(tape(t)%patches(1))
    3174             :       else
    3175           0 :         allocate(tape(t)%patches(npatches))
    3176             :       end if
    3177             : 
    3178             :       ! For each lat/lon specification, parse and create a patch for each grid
    3179           0 :       do ff = 1, npatches
    3180           0 :         if (collect_column_output(t)) then
    3181             :           ! For colleccted column output, we only have one patch
    3182           0 :           patchptr => tape(t)%patches(1)
    3183             :         else
    3184           0 :           patchptr => tape(t)%patches(ff)
    3185           0 :           patchptr%namelist_entry = trim(lonlatname(ff))
    3186             :         end if
    3187             :         ! We need to set up one patch per (active) grid
    3188           0 :         patchptr%collected_output = collect_column_output(t)
    3189           0 :         call parseLonLat(lonlatname(ff),                                      &
    3190             :              beglon, endlon, patchptr%lon_axis_name,                          &
    3191           0 :              beglat, endlat, patchptr%lat_axis_name)
    3192           0 :         if (associated(patchptr%patches)) then
    3193             :           ! One last sanity check
    3194           0 :           if (.not. collect_column_output(t)) then
    3195           0 :             write(errormsg, '(a,i0,2a)') 'Attempt to overwrite fincl', t,     &
    3196           0 :                  'lonlat entry, ', trim(patchptr%namelist_entry)
    3197           0 :             call endrun('patch_init: '//errormsg)
    3198             :           end if
    3199             :         else
    3200           0 :           allocate(patchptr%patches(size(tape(t)%grid_ids)))
    3201             :         end if
    3202           0 :         do i = 1, size(tape(t)%grid_ids)
    3203           0 :           call cam_grid_compute_patch(tape(t)%grid_ids(i), patchptr%patches(i),&
    3204           0 :                beglon, endlon, beglat, endlat, collect_column_output(t))
    3205             :         end do
    3206           0 :         nullify(patchptr)
    3207             :       end do
    3208             :     end if
    3209             :     ! We are done processing this tape's fincl#lonlat entries. Now,
    3210             :     ! compact each patch so that the output variables have no holes
    3211             :     ! We wait until now for when collect_column_output(t) is .true. since
    3212             :     !    all the fincl#lonlat entries are concatenated
    3213       18432 :     if (associated(tape(t)%patches)) then
    3214           0 :       do ff = 1, size(tape(t)%patches)
    3215           0 :         call tape(t)%patches(ff)%compact()
    3216             :       end do
    3217             :     end if
    3218             : 
    3219       18432 :   end subroutine patch_init
    3220             : 
    3221             :   !#######################################################################
    3222             : 
    3223     1857024 :   subroutine strip_null(str)
    3224             :     character(len=*), intent(inout) :: str
    3225             :     integer :: i
    3226   340935168 :     do i=1,len(str)
    3227   340935168 :       if(ichar(str(i:i))==0) str(i:i)=' '
    3228             :     end do
    3229       18432 :   end subroutine strip_null
    3230             : 
    3231     6143232 :   character(len=max_fieldname_len) function strip_suffix (name)
    3232             :     !
    3233             :     !----------------------------------------------------------
    3234             :     !
    3235             :     ! Purpose:  Strip "&IC" suffix from fieldnames if it exists
    3236             :     !
    3237             :     !----------------------------------------------------------
    3238             :     !
    3239             :     ! Arguments
    3240             :     !
    3241             :     character(len=*), intent(in) :: name
    3242             :     !
    3243             :     ! Local workspace
    3244             :     !
    3245             :     integer :: n
    3246             :     !
    3247             :     !-----------------------------------------------------------------------
    3248             :     !
    3249     6143232 :     strip_suffix = ' '
    3250             : 
    3251    51789312 :     do n = 1,fieldname_len
    3252    51789312 :       strip_suffix(n:n) = name(n:n)
    3253    51789312 :       if(name(n+1:n+1         ) == ' '                       ) return
    3254    45768192 :       if(name(n+1:n+fieldname_suffix_len) == fieldname_suffix) return
    3255             :     end do
    3256             : 
    3257           0 :     strip_suffix(fieldname_len+1:max_fieldname_len) = name(fieldname_len+1:max_fieldname_len)
    3258             : 
    3259           0 :     return
    3260             : 
    3261             :   end function strip_suffix
    3262             : 
    3263             :   !#######################################################################
    3264             : 
    3265   134876160 :   character(len=fieldname_len) function getname (inname)
    3266             :     !
    3267             :     !-----------------------------------------------------------------------
    3268             :     !
    3269             :     ! Purpose: retrieve name portion of inname
    3270             :     !
    3271             :     ! Method:  If an averaging flag separater character is present (":") in inname,
    3272             :     !          lop it off
    3273             :     !
    3274             :     !-------------------------------------------------------------------------------
    3275             :     !
    3276             :     ! Arguments
    3277             :     !
    3278             :     character(len=*), intent(in) :: inname
    3279             :     !
    3280             :     ! Local workspace
    3281             :     !
    3282             :     integer :: length
    3283             :     integer :: i
    3284             : 
    3285   134876160 :     length = len (inname)
    3286             : 
    3287   134876160 :     if (length < fieldname_len .or. length > fieldname_lenp2) then
    3288           0 :       write(iulog,*) 'GETNAME: bad length=',length
    3289           0 :       call endrun
    3290             :     end if
    3291             : 
    3292   134876160 :     getname = ' '
    3293  4450913280 :     do i=1,fieldname_len
    3294  4316037120 :       if (inname(i:i) == ':') exit
    3295  4450913280 :       getname(i:i) = inname(i:i)
    3296             :     end do
    3297             : 
    3298   134876160 :     return
    3299             :   end function getname
    3300             : 
    3301             :   !#######################################################################
    3302             : 
    3303             :   ! parseRangeString: Parse either a coordinate descriptor (e.g., 10S) or a
    3304             :   !                   coordinate range (e.g., 10e:20e)
    3305             :   !                   chars represents the allowed coordinate character.
    3306             :   !                   NB: Does not validate numerical values (e.g., lat <= 90)
    3307           0 :   subroutine parseRangeString(rangestr, chars, begval, begchar, begname, endval, endchar, endname)
    3308             : 
    3309             :     ! Dummy arguments
    3310             :     character(len=*),       intent(in)    :: rangestr
    3311             :     character(len=*),       intent(in)    :: chars
    3312             :     real(r8),               intent(out)   :: begval
    3313             :     character,              intent(out)   :: begchar
    3314             :     character(len=*),       intent(out)   :: begname
    3315             :     real(r8),               intent(out)   :: endval
    3316             :     character,              intent(out)   :: endchar
    3317             :     character(len=*),       intent(out)   :: endname
    3318             : 
    3319             :     ! Local variables
    3320             :     character(len=128)                    :: errormsg
    3321             :     integer                               :: colonpos
    3322             :     integer                               :: beglen, endlen
    3323             : 
    3324             :     ! First, see if we have a position or a range
    3325           0 :     colonpos = scan(rangestr, ':')
    3326           0 :     if (colonpos == 0) then
    3327           0 :       begname = trim(rangestr)
    3328           0 :       beglen = len_trim(begname)
    3329           0 :       endname = trim(begname)
    3330             :     else
    3331           0 :       beglen = colonpos - 1
    3332           0 :       begname = rangestr(1:beglen)
    3333           0 :       endname = trim(rangestr(colonpos+1:))
    3334           0 :       endlen = len_trim(endname)
    3335             :     end if
    3336             :     ! begname should be a number (integer or real) followed by a character
    3337           0 :     if (verify(begname, '0123456789.') /= beglen) then
    3338           0 :       write(errormsg, *) 'Coordinate range must begin with number, ', begname
    3339           0 :       call endrun('parseRangeString: '//errormsg)
    3340             :     end if
    3341           0 :     if (verify(begname(beglen:beglen), chars) /= 0) then
    3342           0 :       write(errormsg, *) 'Coordinate range must end with character in the ',  &
    3343           0 :            'set [', trim(chars), '] ', begname
    3344           0 :       call endrun('parseRangeString: '//errormsg)
    3345             :     end if
    3346             :     ! begname parses so collect the values
    3347           0 :     read(begname(1:beglen-1), *) begval
    3348           0 :     begchar = begname(beglen:beglen)
    3349           0 :     if (colonpos /= 0) then
    3350             :       ! endname should be a number (integer or real) followed by a character
    3351           0 :       if (verify(endname, '0123456789.') /= endlen) then
    3352           0 :         write(errormsg, *) 'Coordinate range must begin with number, ', endname
    3353           0 :         call endrun('parseRangeString: '//errormsg)
    3354             :       end if
    3355           0 :       if (verify(endname(endlen:endlen), chars) /= 0) then
    3356           0 :         write(errormsg, *) 'Coordinate range must end with character in the ',&
    3357           0 :              'set [', trim(chars), '] ', endname
    3358           0 :         call endrun('parseRangeString: '//errormsg)
    3359             :       end if
    3360             :       ! endname parses so collect the values
    3361           0 :       read(endname(1:endlen-1), *) endval
    3362           0 :       endchar = endname(endlen:endlen)
    3363             :     else
    3364           0 :       endval = begval
    3365           0 :       endchar = begchar
    3366             :     end if
    3367             : 
    3368           0 :   end subroutine parseRangeString
    3369             : 
    3370             :   ! parseLonLat: Parse a lon_lat description allowed by the fincllonlat(n)
    3371             :   !              namelist entries. Returns the starting and ending values of
    3372             :   !              the point or range specified.
    3373             :   !              NB: Does not validate the range against any particular grid
    3374           0 :   subroutine parseLonLat(lonlatname, beglon, endlon, lonname, beglat, endlat, latname)
    3375             : 
    3376             :     ! Dummy arguments
    3377             :     character(len=*),       intent(in)    :: lonlatname
    3378             :     real(r8),               intent(out)   :: beglon
    3379             :     real(r8),               intent(out)   :: endlon
    3380             :     character(len=*),       intent(out)   :: lonname
    3381             :     real(r8),               intent(out)   :: beglat
    3382             :     real(r8),               intent(out)   :: endlat
    3383             :     character(len=*),       intent(out)   :: latname
    3384             : 
    3385             :     ! Local variables
    3386             :     character(len=128)                    :: errormsg
    3387             :     character(len=MAX_CHARS)              :: lonstr, latstr
    3388             :     character(len=MAX_CHARS)              :: begname, endname
    3389             :     character                             :: begchar, endchar
    3390             :     integer                               :: underpos
    3391             : 
    3392             :     !
    3393             :     ! make sure _ separator is present
    3394             :     !
    3395           0 :     underpos = scan(lonlatname, '_')
    3396           0 :     if (underpos == 0) then
    3397           0 :       write(errormsg,*) 'Improperly formatted fincllonlat string. ',          &
    3398           0 :            'Missing underscore character (xxxE_yyyS) ', lonlatname
    3399           0 :       call endrun('parseLonLat: '//errormsg)
    3400             :     end if
    3401             : 
    3402             :     ! Break out the longitude and latitude sections
    3403           0 :     lonstr = lonlatname(:underpos-1)
    3404           0 :     latstr = trim(lonlatname(underpos+1:))
    3405             : 
    3406             :     ! Parse the longitude section
    3407           0 :     call parseRangeString(lonstr, 'eEwW', beglon, begchar, begname, endlon, endchar, endname)
    3408             :     ! Convert longitude to degrees East
    3409           0 :     if ((begchar == 'w') .or. (begchar == 'W')) then
    3410           0 :       if (beglon > 0.0_r8) then
    3411           0 :         beglon = 360._r8 - beglon
    3412             :       end if
    3413             :     end if
    3414           0 :     if ((beglon < 0._r8) .or. (beglon > 360._r8)) then
    3415           0 :       write(errormsg, *) 'Longitude specification out of range, ', trim(begname)
    3416           0 :       call endrun('parseLonLat: '//errormsg)
    3417             :     end if
    3418           0 :     if ((endchar == 'w') .or. (endchar == 'W')) then
    3419           0 :       if (endlon > 0.0_r8) then
    3420           0 :         endlon = 360._r8 - endlon
    3421             :       end if
    3422             :     end if
    3423           0 :     if ((endlon < 0._r8) .or. (endlon > 360._r8)) then
    3424           0 :       write(errormsg, *) 'Longitude specification out of range, ', trim(endname)
    3425           0 :       call endrun('parseLonLat: '//errormsg)
    3426             :     end if
    3427           0 :     if (beglon == endlon) then
    3428           0 :       lonname = trim(begname)
    3429             :     else
    3430           0 :       lonname = trim(begname)//'_to_'//trim(endname)
    3431             :     end if
    3432             : 
    3433             :     ! Parse the latitude section
    3434           0 :     call parseRangeString(latstr, 'nNsS', beglat, begchar, begname, endlat, endchar, endname)
    3435             :     ! Convert longitude to degrees East
    3436           0 :     if ((begchar == 's') .or. (begchar == 'S')) then
    3437           0 :       beglat = (-1._r8) * beglat
    3438             :     end if
    3439           0 :     if ((beglat < -90._r8) .or. (beglat > 90._r8)) then
    3440           0 :       write(errormsg, *) 'Latitude specification out of range, ', trim(begname)
    3441           0 :       call endrun('parseLonLat: '//errormsg)
    3442             :     end if
    3443           0 :     if ((endchar == 's') .or. (endchar == 'S')) then
    3444           0 :       endlat = (-1._r8) * endlat
    3445             :     end if
    3446           0 :     if ((endlat < -90._r8) .or. (endlat > 90._r8)) then
    3447           0 :       write(errormsg, *) 'Latitude specification out of range, ', trim(endname)
    3448           0 :       call endrun('parseLonLat: '//errormsg)
    3449             :     end if
    3450           0 :     if (beglat == endlat) then
    3451           0 :       latname = trim(begname)
    3452             :     else
    3453           0 :       latname = trim(begname)//'_to_'//trim(endname)
    3454             :     end if
    3455             : 
    3456           0 :   end subroutine parseLonLat
    3457             : 
    3458             : 
    3459             :   !#######################################################################
    3460             : 
    3461           0 :   character(len=1) function getflag (inname)
    3462             :     !
    3463             :     !-----------------------------------------------------------------------
    3464             :     !
    3465             :     ! Purpose: retrieve flag portion of inname
    3466             :     !
    3467             :     ! Method:  If an averaging flag separater character is present (":") in inname,
    3468             :     !          return the character after it as the flag
    3469             :     !
    3470             :     !-------------------------------------------------------------------------------
    3471             :     !
    3472             :     ! Arguments
    3473             :     !
    3474             :     character(len=*), intent(in) :: inname   ! character string
    3475             :     !
    3476             :     ! Local workspace
    3477             :     !
    3478             :     integer :: length         ! length of inname
    3479             :     integer :: i              ! loop index
    3480             : 
    3481           0 :     length = len (inname)
    3482             : 
    3483           0 :     if (length /= fieldname_lenp2) then
    3484           0 :       write(iulog,*) 'GETFLAG: bad length=',length
    3485           0 :       call endrun
    3486             :     end if
    3487             : 
    3488           0 :     getflag = ' '
    3489           0 :     do i=1,fieldname_lenp2-1
    3490           0 :       if (inname(i:i) == ':') then
    3491           0 :         getflag = inname(i+1:i+1)
    3492           0 :         exit
    3493             :       end if
    3494             :     end do
    3495             : 
    3496           0 :     return
    3497             :   end function getflag
    3498             : 
    3499             :   !#######################################################################
    3500             : 
    3501   134876160 :   subroutine list_index (list, name, index)
    3502             :     !
    3503             :     ! Input arguments
    3504             :     !
    3505             :     character(len=*), intent(in) :: list(pflds) ! input list of names, possibly ":" delimited
    3506             :     character(len=max_fieldname_len), intent(in) :: name ! name to be searched for
    3507             :     !
    3508             :     ! Output arguments
    3509             :     !
    3510             :     integer, intent(out) :: index               ! index of "name" in "list"
    3511             :     !
    3512             :     ! Local workspace
    3513             :     !
    3514             :     character(len=fieldname_len) :: listname    ! input name with ":" stripped off.
    3515             :     integer f                       ! field index
    3516             : 
    3517   134876160 :     index = 0
    3518   134876160 :     do f=1,pflds
    3519             :       !
    3520             :       ! Only list items
    3521             :       !
    3522   134876160 :       listname = getname (list(f))
    3523   134876160 :       if (listname == ' ') exit
    3524   134876160 :       if (listname == name) then
    3525           0 :         index = f
    3526           0 :         exit
    3527             :       end if
    3528             :     end do
    3529             : 
    3530   134876160 :     return
    3531             :   end subroutine list_index
    3532             : 
    3533             :   !#######################################################################
    3534             : 
    3535   385547616 :   recursive subroutine outfld (fname, field, idim, c, avg_subcol_field)
    3536             :     use cam_history_buffers, only: hbuf_accum_inst, hbuf_accum_add, hbuf_accum_variance,  &
    3537             :          hbuf_accum_add00z, hbuf_accum_max, hbuf_accum_min,          &
    3538             :          hbuf_accum_addlcltime
    3539             :     use cam_history_support, only: dim_index_2d
    3540             :     use subcol_pack_mod,     only: subcol_unpack
    3541             :     use cam_grid_support,    only: cam_grid_id
    3542             : 
    3543             :     interface
    3544             :       subroutine subcol_field_avg_handler(idim, field_in, c, field_out)
    3545             :         use shr_kind_mod, only: r8 => shr_kind_r8
    3546             :         integer,  intent(in)  :: idim
    3547             :         real(r8), intent(in)  :: field_in(idim, *)
    3548             :         integer,  intent(in)  :: c
    3549             :         real(r8), intent(out) :: field_out(:,:)
    3550             :       end subroutine subcol_field_avg_handler
    3551             :     end interface
    3552             : 
    3553             :     !
    3554             :     !-----------------------------------------------------------------------
    3555             :     !
    3556             :     ! Purpose: Accumulate (or take min, max, etc. as appropriate) input field
    3557             :     !          into its history buffer for appropriate tapes
    3558             :     !
    3559             :     ! Method: Check 'masterlist' whether the requested field 'fname' is active
    3560             :     !         on one or more history tapes, and if so do the accumulation.
    3561             :     !         If not found, return silently.
    3562             :     !         subcol_field_avg_handler:
    3563             :     !            An interface into subcol_field_avg without creating a dependency as
    3564             :     !            this would cause a dependency loop. See subcol.F90
    3565             :     ! Note: We cannot know a priori if field is a grid average field or a subcolumn
    3566             :     !       field because many fields passed to outfld are defined on ncol rather
    3567             :     !       than pcols or psetcols. Therefore, we use the avg_subcol_field input
    3568             :     !       to determine whether to average the field input before accumulation.
    3569             :     !       NB: If output is on a subcolumn grid (requested in addfle), it is
    3570             :     !           an error to use avg_subcol_field. A subcolumn field is assumed and
    3571             :     !           subcol_unpack is called before accumulation.
    3572             :     !
    3573             :     ! Author: CCM Core Group
    3574             :     !
    3575             :     !-----------------------------------------------------------------------
    3576             :     !
    3577             :     ! Arguments
    3578             :     !
    3579             :     character(len=*), intent(in) :: fname ! Field name--should be 8 chars long
    3580             : 
    3581             :     ! For structured grids, idim is the local longitude dimension.
    3582             :     ! For unstructured grids, idim is the local column dimension
    3583             :     ! For phys_decomp, it should be pcols or pcols*psubcols
    3584             :     integer, intent(in)           :: idim
    3585             :     real(r8), intent(in)          :: field(idim,*) ! Array containing field values
    3586             :     integer, intent(in)           :: c             ! chunk (physics) or latitude (dynamics) index
    3587             :     logical, optional, intent(in) :: avg_subcol_field
    3588             :     !
    3589             :     ! Local variables
    3590             :     !
    3591             :     integer               :: t, fld        ! tape, field indices
    3592             : 
    3593             :     character*1           :: avgflag       ! averaging flag
    3594             : 
    3595   192773808 :     type (active_entry), pointer :: otape(:) ! Local history_tape pointer
    3596   192773808 :     real(r8),pointer      :: hbuf(:,:)     ! history buffer
    3597   192773808 :     real(r8),pointer      :: wbuf(:)       ! area weights for field
    3598   192773808 :     real(r8),pointer      :: sbuf(:,:)     ! variance buffer
    3599   192773808 :     integer, pointer      :: nacs(:)       ! accumulation counter
    3600             :     integer               :: begdim2, enddim2, endi
    3601             :     integer               :: phys_decomp
    3602             :     type (dim_index_2d)   :: dimind        ! 2-D dimension index
    3603             :     logical               :: flag_xyfill   ! non-applicable xy points flagged with fillvalue
    3604             :     real(r8)              :: fillvalue
    3605   192773808 :     real(r8), allocatable :: afield(:,:)   ! Averaged field values
    3606   192773808 :     real(r8), allocatable :: ufield(:,:,:) ! Unpacked field values
    3607             :     integer               :: ff            ! masterlist index pointer
    3608             :     integer               :: i, j
    3609             :     logical               :: found
    3610             :     logical               :: avg_subcols   ! average subcols before accum
    3611             :     !-----------------------------------------------------------------------
    3612             : 
    3613   192773808 :     call get_field_properties(fname, found, tape_out=otape, ff_out=ff)
    3614   192773808 :     phys_decomp = cam_grid_id('physgrid')
    3615             : 
    3616             :     ! If this field is not active, return now
    3617   192773808 :     if (.not. found) then
    3618             :       return
    3619             :     end if
    3620             : 
    3621             :     !
    3622             :     ! Note, the field may be on any or all of the history files (primary
    3623             :     ! and auxiliary).
    3624             :     !
    3625             :     !      write(iulog,*)'fname_loc=',fname_loc
    3626   343154448 :     do t = 1, ptapes
    3627   316757952 :       if ( .not. masterlist(ff)%thisentry%actflag(t)) cycle
    3628    26396496 :       fld = masterlist(ff)%thisentry%htapeindx(t)
    3629             :       !
    3630             :       ! Update history buffer
    3631             :       !
    3632    26396496 :       flag_xyfill = otape(t)%hlist(fld)%field%flag_xyfill
    3633    26396496 :       fillvalue = otape(t)%hlist(fld)%field%fillvalue
    3634    26396496 :       avgflag = otape(t)%hlist(fld)%avgflag
    3635    26396496 :       nacs   => otape(t)%hlist(fld)%nacs(:,c)
    3636    26396496 :       hbuf => otape(t)%hlist(fld)%hbuf(:,:,c)
    3637    26396496 :       if (associated(tape(t)%hlist(fld)%wbuf)) then
    3638           0 :          wbuf => otape(t)%hlist(fld)%wbuf(:,c)
    3639             :       endif
    3640    26396496 :       if (associated(tape(t)%hlist(fld)%sbuf)) then
    3641           0 :          sbuf => otape(t)%hlist(fld)%sbuf(:,:,c)
    3642             :       endif
    3643    26396496 :       dimind = otape(t)%hlist(fld)%field%get_dims(c)
    3644             : 
    3645             :       ! See notes above about validity of avg_subcol_field
    3646    26396496 :       if (otape(t)%hlist(fld)%field%is_subcol) then
    3647           0 :         if (present(avg_subcol_field)) then
    3648           0 :           call endrun('OUTFLD: Cannot average '//trim(fname)//', subcolumn output was requested in addfld')
    3649             :         end if
    3650             :         avg_subcols = .false.
    3651    26396496 :       else if (otape(t)%hlist(fld)%field%decomp_type == phys_decomp) then
    3652    26396496 :         if (present(avg_subcol_field)) then
    3653     1235304 :           avg_subcols = avg_subcol_field
    3654             :         else
    3655             :           avg_subcols = .false.
    3656             :         end if
    3657             :       else ! Any dynamics decomposition
    3658           0 :         if (present(avg_subcol_field)) then
    3659           0 :           call endrun('OUTFLD: avg_subcol_field only valid for physgrid')
    3660             :         else
    3661             :           avg_subcols = .false.
    3662             :         end if
    3663             :       end if
    3664             : 
    3665    26396496 :       begdim2 = otape(t)%hlist(fld)%field%begdim2
    3666    26396496 :       enddim2 = otape(t)%hlist(fld)%field%enddim2
    3667    52792992 :       if (avg_subcols) then
    3668           0 :         allocate(afield(pcols, begdim2:enddim2))
    3669           0 :         call subcol_field_avg_handler(idim, field, c, afield)
    3670             :         ! Hack! Avoid duplicating select statement below
    3671           0 :         call outfld(fname, afield, pcols, c)
    3672           0 :         deallocate(afield)
    3673    26396496 :       else if (otape(t)%hlist(fld)%field%is_subcol) then
    3674             :         ! We have to assume that using mdimnames (e.g., psubcols) is
    3675             :         ! incompatible with the begdimx, enddimx usage (checked in addfld)
    3676             :         ! Since psubcols is included in levels, take that out
    3677           0 :         endi = (enddim2 - begdim2 + 1) / psubcols
    3678           0 :         allocate(ufield(pcols, psubcols, endi))
    3679           0 :         allocate(afield(pcols*psubcols, endi))
    3680           0 :         do j = 1, endi
    3681           0 :           do i = 1, idim
    3682           0 :             afield(i, j) = field(i, j)
    3683             :           end do
    3684             :         end do
    3685             :         ! Initialize unused aray locations.
    3686           0 :         if (idim < pcols*psubcols) then
    3687           0 :           if (flag_xyfill) then
    3688           0 :             afield(idim+1:pcols*psubcols, :) = fillvalue
    3689             :           else
    3690           0 :             afield(idim+1:pcols*psubcols, :) = 0.0_r8
    3691             :           end if
    3692             :         end if
    3693           0 :         if (flag_xyfill) then
    3694           0 :           call subcol_unpack(c, afield, ufield, fillvalue)
    3695             :         else
    3696           0 :           call subcol_unpack(c, afield, ufield)
    3697             :         end if
    3698           0 :         deallocate(afield)
    3699           0 :         select case (avgflag)
    3700             : 
    3701             :         case ('I') ! Instantaneous
    3702             :           call hbuf_accum_inst(hbuf, ufield, nacs, dimind, pcols,        &
    3703           0 :                flag_xyfill, fillvalue)
    3704             : 
    3705             :         case ('A') ! Time average
    3706             :           call hbuf_accum_add(hbuf, ufield, nacs, dimind, pcols,         &
    3707           0 :                flag_xyfill, fillvalue)
    3708             : 
    3709             :         case ('B') ! Time average only 00z values
    3710             :           call hbuf_accum_add00z(hbuf, ufield, nacs, dimind, pcols,      &
    3711           0 :                flag_xyfill, fillvalue)
    3712             : 
    3713             :         case ('N') ! Time average over nsteps
    3714             :           call hbuf_accum_add(hbuf, ufield, nacs, dimind, pcols,      &
    3715           0 :                flag_xyfill, fillvalue)
    3716             : 
    3717             :         case ('X') ! Maximum over time
    3718             :           call hbuf_accum_max (hbuf, ufield, nacs, dimind, pcols,        &
    3719           0 :                flag_xyfill, fillvalue)
    3720             : 
    3721             :         case ('M') ! Minimum over time
    3722             :           call hbuf_accum_min(hbuf, ufield, nacs, dimind, pcols,         &
    3723           0 :                flag_xyfill, fillvalue)
    3724             : 
    3725             :         case ('L')
    3726             :           call hbuf_accum_addlcltime(hbuf, ufield, nacs, dimind, pcols,  &
    3727             :                flag_xyfill, fillvalue, c,                                &
    3728           0 :                otape(t)%hlist(fld)%field%decomp_type,                      &
    3729           0 :                lcltod_start(t), lcltod_stop(t))
    3730             : 
    3731             :         case ('S') ! Standard deviation
    3732             :           call hbuf_accum_variance(hbuf, sbuf, ufield, nacs, dimind, pcols,&
    3733           0 :                flag_xyfill, fillvalue)
    3734             : 
    3735             :         case default
    3736           0 :           call endrun ('OUTFLD: invalid avgflag='//avgflag)
    3737             : 
    3738             :         end select
    3739           0 :         deallocate(ufield)
    3740             :       else
    3741       58824 :         select case (avgflag)
    3742             : 
    3743             :         case ('I') ! Instantaneous
    3744             :           call hbuf_accum_inst(hbuf, field, nacs, dimind, idim,          &
    3745       58824 :                flag_xyfill, fillvalue)
    3746             : 
    3747             :         case ('A') ! Time average
    3748             :           call hbuf_accum_add(hbuf, field, nacs, dimind, idim,           &
    3749    26220024 :                flag_xyfill, fillvalue)
    3750             : 
    3751             :         case ('B') ! Time average only 00z values
    3752             :           call hbuf_accum_add00z(hbuf, field, nacs, dimind, idim,        &
    3753           0 :                flag_xyfill, fillvalue)
    3754             : 
    3755             :         case ('N') ! Time average over nsteps
    3756             :           call hbuf_accum_add (hbuf, field, nacs, dimind, idim,        &
    3757           0 :                flag_xyfill, fillvalue)
    3758             : 
    3759             :         case ('X') ! Maximum over time
    3760             :           call hbuf_accum_max (hbuf, field, nacs, dimind, idim,          &
    3761       58824 :                flag_xyfill, fillvalue)
    3762             : 
    3763             :         case ('M') ! Minimum over time
    3764             :           call hbuf_accum_min(hbuf, field, nacs, dimind, idim,           &
    3765       58824 :                flag_xyfill, fillvalue)
    3766             : 
    3767             :         case ('L')
    3768             :           call hbuf_accum_addlcltime(hbuf, field, nacs, dimind, idim,    &
    3769             :                flag_xyfill, fillvalue, c,                                &
    3770             :                otape(t)%hlist(fld)%field%decomp_type,                      &
    3771           0 :                lcltod_start(t), lcltod_stop(t))
    3772             : 
    3773             :         case ('S') ! Standard deviation
    3774             :           call hbuf_accum_variance(hbuf, sbuf, field, nacs, dimind, idim,&
    3775           0 :                flag_xyfill, fillvalue)
    3776             : 
    3777             :         case default
    3778   316757952 :           call endrun ('OUTFLD: invalid avgflag='//avgflag)
    3779             : 
    3780             :         end select
    3781             :       end if
    3782             : 
    3783             :     end do
    3784             : 
    3785             :     return
    3786   385547616 :   end subroutine outfld
    3787             : 
    3788             :   !#######################################################################
    3789             : 
    3790           0 :   subroutine get_field_properties(fname, found, tape_out, ff_out, no_tape_check_in, f_out)
    3791             : 
    3792             :     implicit none
    3793             :     !
    3794             :     !-----------------------------------------------------------------------
    3795             :     !
    3796             :     ! Purpose: If fname is active, lookup and return field information
    3797             :     !
    3798             :     ! Method: Check 'masterlist' whether the requested field 'fname' is active
    3799             :     !         on one or more history tapes, and if so, return the requested
    3800             :     !         field information
    3801             :     !
    3802             :     ! Author: goldy
    3803             :     !
    3804             :     !-----------------------------------------------------------------------
    3805             :     !
    3806             :     ! Arguments
    3807             :     !
    3808             :     character(len=*),   intent(in)  :: fname ! Field name--should be 8 chars long
    3809             :     logical,            intent(out) :: found ! Set to true if fname is active
    3810             :     type(active_entry), pointer, optional :: tape_out(:)
    3811             :     integer,            intent(out), optional :: ff_out
    3812             :     logical,            intent(in), optional  :: no_tape_check_in
    3813             :     integer,            intent(out), optional :: f_out(:)
    3814             : 
    3815             :     !
    3816             :     ! Local variables
    3817             :     !
    3818             :     character*(max_fieldname_len) :: fname_loc  ! max-char equivalent of fname
    3819             :     integer :: t, ff          ! tape, masterindex indices
    3820             :     logical :: no_tape_check
    3821             :      !-----------------------------------------------------------------------
    3822             : 
    3823             :     ! Need to re-cast the field name so that the hashing works #hackalert
    3824   192773808 :     fname_loc = fname
    3825   192773808 :     ff = get_masterlist_indx(fname_loc)
    3826             : 
    3827             :     ! Set the no_tape_check to false, unless is passed in
    3828   192773808 :     if (present(no_tape_check_in)) then
    3829           0 :        no_tape_check = no_tape_check_in
    3830             :     else
    3831             :        no_tape_check = .false.
    3832             :     end if
    3833             : 
    3834             :     ! Set found to .false. so we can return early if fname is not active
    3835   192773808 :     found = .false.
    3836   192773808 :     if (present(tape_out)) then
    3837   192773808 :       nullify(tape_out)
    3838             :     end if
    3839   192773808 :     if (present(ff_out)) then
    3840   192773808 :       ff_out = -1
    3841             :     end if
    3842   192773808 :     if (present(f_out)) then
    3843           0 :       f_out = -1
    3844             :     end if
    3845             : 
    3846             :     !
    3847             :     !  If ( ff < 0 ), the field is not defined on the masterlist. This check
    3848             :     !  is necessary because of coding errors calling outfld without first defining
    3849             :     !  the field on masterlist.
    3850             :     !
    3851   192773808 :     if ( ff < 0 ) then
    3852   166377312 :       return
    3853             :     end if
    3854             :     !
    3855             :     !  Next, check to see whether this field is active on one or more history
    3856             :     !  tapes.
    3857             :     !
    3858   192773808 :     if (no_tape_check) then
    3859           0 :       if (present(ff_out)) ff_out   =  ff  ! Set the output index and return without checking tapes
    3860           0 :       return
    3861   192773808 :     else if ( .not. masterlist(ff)%thisentry%act_sometape )  then
    3862             :       return
    3863             :     end if
    3864             :     !
    3865             :     ! Note, the field may be on any or all of the history files (primary
    3866             :     ! and auxiliary).
    3867             :     !
    3868             : 
    3869    26396496 :     do t=1, ptapes
    3870    52792992 :       if (masterlist(ff)%thisentry%actflag(t)) then
    3871    26396496 :         found    =  .true.
    3872    26396496 :         if (present(tape_out)) then
    3873    26396496 :           tape_out => history_tape
    3874             :         end if
    3875    26396496 :         if (present(ff_out)) then
    3876    26396496 :           ff_out   =  ff
    3877             :         end if
    3878    26396496 :         if (present(f_out)) then
    3879           0 :            f_out(t) = masterlist(ff)%thisentry%htapeindx(t)
    3880             :         else
    3881             :            ! only need to loop through all ptapes if f_out present
    3882             :            exit
    3883             :         end if
    3884             :       end if
    3885             :     end do
    3886             : 
    3887   385547616 :   end subroutine get_field_properties
    3888             : 
    3889             :   !#######################################################################
    3890             : 
    3891    54765078 :   logical function is_initfile (file_index)
    3892             :     !
    3893             :     !------------------------------------------------------------------------
    3894             :     !
    3895             :     ! Purpose: to determine:
    3896             :     !
    3897             :     !   a) if an IC file is active in this model run at all
    3898             :     !       OR,
    3899             :     !   b) if it is active, is the current file index referencing the IC file
    3900             :     !      (IC file is always at ptapes)
    3901             :     !
    3902             :     !------------------------------------------------------------------------
    3903             :     !
    3904             :     ! Arguments
    3905             :     !
    3906             :     integer, intent(in), optional :: file_index ! index of file in question
    3907             : 
    3908    54765078 :     is_initfile = .false.
    3909             : 
    3910    54765078 :     if (present(file_index)) then
    3911    54652446 :       if (inithist /= 'NONE' .and. file_index == ptapes) is_initfile = .true.
    3912             :     else
    3913      112632 :       if (inithist /= 'NONE'                           ) is_initfile = .true.
    3914             :     end if
    3915             : 
    3916             :     return
    3917             : 
    3918             :   end function is_initfile
    3919             : 
    3920             :   !#######################################################################
    3921             : 
    3922             :   integer function strcmpf (name1, name2)
    3923             :     !
    3924             :     !-----------------------------------------------------------------------
    3925             :     !
    3926             :     ! Purpose: Return the lexical difference between two strings
    3927             :     !
    3928             :     ! Method: Use ichar() intrinsic as we loop through the names
    3929             :     !
    3930             :     !-----------------------------------------------------------------------
    3931             :     !
    3932             :     ! Arguments
    3933             :     !
    3934             :     character(len=max_fieldname_len), intent(in) :: name1, name2 ! strings to compare
    3935             :     integer n                                     ! loop index
    3936             : 
    3937             :     do n=1,max_fieldname_len
    3938             :       strcmpf = ichar(name1(n:n)) - ichar(name2(n:n))
    3939             :       if (strcmpf /= 0) exit
    3940             :     end do
    3941             : 
    3942             :     return
    3943             :   end function strcmpf
    3944             : 
    3945             :   !#######################################################################
    3946             : 
    3947           0 :   subroutine h_inquire (t)
    3948             :     use pio,           only: pio_inq_varid, pio_inq_attlen
    3949             :     use cam_pio_utils, only: cam_pio_handle_error
    3950             :    !
    3951             :     !-----------------------------------------------------------------------
    3952             :     !
    3953             :     ! Purpose: Ensure that the proper variables are on a history file
    3954             :     !
    3955             :     ! Method: Issue the appropriate netcdf wrapper calls
    3956             :     !
    3957             :     !-----------------------------------------------------------------------
    3958             :     !
    3959             :     ! Arguments
    3960             :     !
    3961             :     integer, intent(in) :: t   ! tape index
    3962             :     !
    3963             :     ! Local workspace
    3964             :     !
    3965             :     integer                  :: f, fld        ! file, field index
    3966             :     integer                  :: ierr
    3967             :     integer                  :: i
    3968             :     integer                  :: num_patches
    3969             :     integer(pio_offset_kind) :: mdimsize
    3970             :     character(len=max_chars) :: fldname, fname_tmp, basename
    3971             : 
    3972             :     !
    3973             :     !
    3974             :     ! Dimension id's
    3975             :     !
    3976           0 :     tape => history_tape
    3977             : 
    3978             :     !
    3979             :     ! Create variables for model timing and header information
    3980             :     !
    3981           0 :     do f = 1, maxsplitfiles
    3982           0 :        if (.not. pio_file_is_open(tape(t)%Files(f))) then
    3983             :           cycle
    3984             :        end if
    3985           0 :        if(.not. is_satfile(t)) then
    3986           0 :          if (f == instantaneous_file_index) then
    3987           0 :             ierr=pio_inq_varid (tape(t)%Files(f),'ndcur   ',    tape(t)%ndcurid)
    3988           0 :             ierr=pio_inq_varid (tape(t)%Files(f),'nscur   ',    tape(t)%nscurid)
    3989           0 :             ierr=pio_inq_varid (tape(t)%Files(f),'nsteph  ',    tape(t)%nstephid)
    3990             :          end if
    3991           0 :          ierr=pio_inq_varid (tape(t)%Files(f),'time_bounds',   tape(t)%tbndid)
    3992           0 :          ierr=pio_inq_varid (tape(t)%Files(f),'date_written',  tape(t)%date_writtenid)
    3993           0 :          ierr=pio_inq_varid (tape(t)%Files(f),'time_written',  tape(t)%time_writtenid)
    3994             : #if ( defined BFB_CAM_SCAM_IOP )
    3995             :          ierr=pio_inq_varid (tape(t)%Files(f),'tsec    ',tape(t)%tsecid)
    3996             :          ierr=pio_inq_varid (tape(t)%Files(f),'bdate   ',tape(t)%bdateid)
    3997             : #endif
    3998           0 :          if (.not. is_initfile(file_index=t) .and. f == instantaneous_file_index) then
    3999             :            ! Don't write the GHG/Solar forcing data to the IC file.  It is never
    4000             :            ! read from that file so it's confusing to have it there.
    4001             :            ! Only write the GHG/Solar forcing data to the instantaneous file
    4002           0 :            ierr=pio_inq_varid (tape(t)%Files(f),'co2vmr  ',    tape(t)%co2vmrid)
    4003           0 :            ierr=pio_inq_varid (tape(t)%Files(f),'ch4vmr  ',    tape(t)%ch4vmrid)
    4004           0 :            ierr=pio_inq_varid (tape(t)%Files(f),'n2ovmr  ',    tape(t)%n2ovmrid)
    4005           0 :            ierr=pio_inq_varid (tape(t)%Files(f),'f11vmr  ',    tape(t)%f11vmrid)
    4006           0 :            ierr=pio_inq_varid (tape(t)%Files(f),'f12vmr  ',    tape(t)%f12vmrid)
    4007           0 :            ierr=pio_inq_varid (tape(t)%Files(f),'sol_tsi ',    tape(t)%sol_tsiid)
    4008           0 :            if (solar_parms_on) then
    4009           0 :              ierr=pio_inq_varid (tape(t)%Files(f),'f107    ',    tape(t)%f107id)
    4010           0 :              ierr=pio_inq_varid (tape(t)%Files(f),'f107a   ',    tape(t)%f107aid)
    4011           0 :              ierr=pio_inq_varid (tape(t)%Files(f),'f107p   ',    tape(t)%f107pid)
    4012           0 :              ierr=pio_inq_varid (tape(t)%Files(f),'kp      ',    tape(t)%kpid)
    4013           0 :              ierr=pio_inq_varid (tape(t)%Files(f),'ap      ',    tape(t)%apid)
    4014             :            endif
    4015           0 :            if (solar_wind_on) then
    4016           0 :              ierr=pio_inq_varid (tape(t)%Files(f),'byimf', tape(t)%byimfid)
    4017           0 :              ierr=pio_inq_varid (tape(t)%Files(f),'bzimf', tape(t)%bzimfid)
    4018           0 :              ierr=pio_inq_varid (tape(t)%Files(f),'swvel', tape(t)%swvelid)
    4019           0 :              ierr=pio_inq_varid (tape(t)%Files(f),'swden', tape(t)%swdenid)
    4020             :            endif
    4021           0 :            if (epot_active) then
    4022           0 :              ierr=pio_inq_varid (tape(t)%Files(f),'colat_crit1', tape(t)%colat_crit1_id)
    4023           0 :              ierr=pio_inq_varid (tape(t)%Files(f),'colat_crit2', tape(t)%colat_crit2_id)
    4024             :            endif
    4025             :          end if
    4026             :        end if
    4027           0 :        ierr=pio_inq_varid (tape(t)%Files(f),'date    ',    tape(t)%dateid)
    4028           0 :        ierr=pio_inq_varid (tape(t)%Files(f),'datesec ',    tape(t)%datesecid)
    4029           0 :        ierr=pio_inq_varid (tape(t)%Files(f),'time    ',    tape(t)%timeid)
    4030             : 
    4031             :        !
    4032             :        ! Obtain variable name from ID which was read from restart file
    4033             :        !
    4034           0 :        do fld=1,nflds(t)
    4035           0 :          if (f == accumulated_file_index) then
    4036             :             ! this is the accumulated file - skip instantaneous fields
    4037           0 :             if (tape(t)%hlist(fld)%avgflag == 'I') then
    4038             :                cycle
    4039             :             end if
    4040             :          else
    4041             :             ! this is the instantaneous file - skip accumulated fields
    4042           0 :             if (tape(t)%hlist(fld)%avgflag /= 'I') then
    4043             :                cycle
    4044             :             end if
    4045             :          end if
    4046             : 
    4047           0 :          if(.not. associated(tape(t)%hlist(fld)%varid)) then
    4048           0 :            if (associated(tape(t)%patches)) then
    4049           0 :              allocate(tape(t)%hlist(fld)%varid(size(tape(t)%patches)))
    4050             :            else
    4051           0 :              allocate(tape(t)%hlist(fld)%varid(1))
    4052             :            end if
    4053             :          end if
    4054             :          !
    4055             :          ! If this field will be put out as columns then get column names for field
    4056             :          !
    4057           0 :          if (associated(tape(t)%patches)) then
    4058           0 :            num_patches = size(tape(t)%patches)
    4059           0 :            fldname = strip_suffix(tape(t)%hlist(fld)%field%name)
    4060           0 :            do i = 1, num_patches
    4061           0 :              fname_tmp = trim(fldname)
    4062           0 :              call tape(t)%patches(i)%field_name(fname_tmp)
    4063           0 :              ierr = pio_inq_varid(tape(t)%Files(f), trim(fname_tmp), tape(t)%hlist(fld)%varid(i))
    4064           0 :              call cam_pio_handle_error(ierr, 'H_INQUIRE: Error getting ID for '//trim(fname_tmp))
    4065           0 :              ierr = pio_get_att(tape(t)%Files(f), tape(t)%hlist(fld)%varid(i), 'basename', basename)
    4066           0 :              call cam_pio_handle_error(ierr, 'H_INQUIRE: Error getting basename for '//trim(fname_tmp))
    4067           0 :              if (trim(fldname) /= trim(basename)) then
    4068           0 :                call endrun('H_INQUIRE: basename ('//trim(basename)//') does not match fldname ('//trim(fldname)//')')
    4069             :              end if
    4070             :            end do
    4071             :          else
    4072           0 :            fldname = tape(t)%hlist(fld)%field%name
    4073           0 :            ierr = pio_inq_varid(tape(t)%Files(f), trim(fldname), tape(t)%hlist(fld)%varid(1))
    4074           0 :            call cam_pio_handle_error(ierr, 'H_INQUIRE: Error getting ID for '//trim(fldname))
    4075             :          end if
    4076           0 :          if(tape(t)%hlist(fld)%field%numlev>1) then
    4077           0 :            ierr = pio_inq_attlen(tape(t)%Files(f),tape(t)%hlist(fld)%varid(1),'mdims', mdimsize)
    4078           0 :            if(.not. associated(tape(t)%hlist(fld)%field%mdims)) then
    4079           0 :              allocate(tape(t)%hlist(fld)%field%mdims(mdimsize))
    4080             :            end if
    4081           0 :            ierr=pio_get_att(tape(t)%Files(f),tape(t)%hlist(fld)%varid(1),'mdims', &
    4082           0 :                 tape(t)%hlist(fld)%field%mdims(1:mdimsize))
    4083           0 :            if(mdimsize > int(maxvarmdims, kind=pio_offset_kind)) then
    4084           0 :               maxvarmdims = int(mdimsize)
    4085             :            end if
    4086             :          end if
    4087             : 
    4088             :        end do
    4089             :     end do
    4090           0 :     if(masterproc) then
    4091           0 :       write(iulog,*)'H_INQUIRE: Successfully opened netcdf file '
    4092             :     end if
    4093             : 
    4094           0 :     return
    4095           0 :   end subroutine h_inquire
    4096             : 
    4097             :   !#######################################################################
    4098             : 
    4099      609792 :   subroutine add_default (name, tindex, flag)
    4100             :     !
    4101             :     !-----------------------------------------------------------------------
    4102             :     !
    4103             :     ! Purpose: Add a field to the default "on" list for a given history file
    4104             :     !
    4105             :     ! Method:
    4106             :     !
    4107             :     !-----------------------------------------------------------------------
    4108             :     !
    4109             :     ! Arguments
    4110             :     !
    4111             :     character(len=*), intent(in) :: name  ! field name
    4112             :     character(len=1), intent(in) :: flag  ! averaging flag
    4113             : 
    4114             :     integer, intent(in) :: tindex         ! history tape index
    4115             :     !
    4116             :     ! Local workspace
    4117             :     !
    4118             :     integer :: t            ! file index
    4119             :     type(master_entry), pointer :: listentry
    4120             : 
    4121      609792 :     if (htapes_defined) then
    4122           0 :       call endrun ('ADD_DEFAULT: Attempt to add hist default '//trim(name)//' after history files set')
    4123             :     end if
    4124             :     !
    4125             :     ! Check validity of input arguments
    4126             :     !
    4127      609792 :     if (tindex > ptapes) then
    4128           0 :       write(iulog,*)'ADD_DEFAULT: tape index=', tindex, ' is too big'
    4129           0 :       call endrun
    4130             :     end if
    4131             : 
    4132             :     ! Add to IC file if tindex = 0, reset to ptapes
    4133      609792 :     if (tindex == 0) then
    4134       69120 :       t = ptapes
    4135       69120 :       if ( .not. is_initfile(file_index=t) ) return
    4136             :     else
    4137      540672 :       t = tindex
    4138             :     end if
    4139             : 
    4140      609792 :     if (verify(flag, HIST_AVG_FLAGS) /= 0) then
    4141           0 :       call endrun ('ADD_DEFAULT: unknown averaging flag='//flag)
    4142             :     end if
    4143             :     !
    4144             :     ! Look through master list for input field name.  When found, set active
    4145             :     ! flag for that tape to true.  Also set averaging flag if told to use other
    4146             :     ! than default.
    4147             :     !
    4148      609792 :     listentry => get_entry_by_name(masterlinkedlist, trim(name))
    4149      609792 :     if(.not.associated(listentry)) then
    4150           0 :       call endrun ('ADD_DEFAULT: field = "'//trim(name)//'" not found')
    4151             :     end if
    4152      609792 :     listentry%actflag(t) = .true.
    4153      609792 :     if (flag /= ' ') then
    4154       69120 :       listentry%avgflag(t) = flag
    4155             :       call AvgflagToString(flag, listentry%time_op(t))
    4156             :     end if
    4157             : 
    4158             :     return
    4159           0 :   end subroutine add_default
    4160             : 
    4161             :   !#######################################################################
    4162             : 
    4163           0 :   subroutine h_override (t)
    4164             :     !
    4165             :     !-----------------------------------------------------------------------
    4166             :     !
    4167             :     ! Purpose: Override default history tape contents for a specific tape
    4168             :     !
    4169             :     ! Method: Copy the flag into the master field list
    4170             :     !
    4171             :     !-----------------------------------------------------------------------
    4172             :     !
    4173             :     ! Arguments
    4174             :     !
    4175             :     integer, intent(in) :: t         ! history tape index
    4176             :     !
    4177             :     ! Local workspace
    4178             :     !
    4179             :     character(len=1) :: avgflg       ! lcl equiv of avgflag_pertape(t) (to address xlf90 compiler bug)
    4180             : 
    4181             :     type(master_entry), pointer :: listentry
    4182             : 
    4183           0 :     avgflg = avgflag_pertape(t)
    4184             : 
    4185           0 :     listentry=>masterlinkedlist
    4186           0 :     do while(associated(listentry))
    4187             :        ! Budgets require flag to be N, dont override
    4188           0 :        if (listentry%avgflag(t) /= 'N' ) then
    4189             :           call AvgflagToString(avgflg, listentry%time_op(t))
    4190           0 :           listentry%avgflag(t) = avgflag_pertape(t)
    4191             :        end if
    4192           0 :        listentry=>listentry%next_entry
    4193             :     end do
    4194             : 
    4195           0 :   end subroutine h_override
    4196             : 
    4197             :   !#######################################################################
    4198             : 
    4199        1536 :   subroutine h_define (t, restart)
    4200             :     !
    4201             :     !-----------------------------------------------------------------------
    4202             :     !
    4203             :     ! Purpose: Define contents of history file t
    4204             :     !
    4205             :     ! Method: Issue the required netcdf wrapper calls to define the history file contents
    4206             :     !
    4207             :     !-----------------------------------------------------------------------
    4208             :     use phys_control,    only: phys_getopts
    4209             :     use cam_grid_support, only: cam_grid_header_info_t
    4210             :     use cam_grid_support, only: cam_grid_write_attr, cam_grid_write_var
    4211             :     use time_manager,     only: get_step_size, get_ref_date, timemgr_get_calendar_cf
    4212             :     use cam_abortutils,   only: endrun
    4213             :     use cam_pio_utils,    only: vdesc_ptr, cam_pio_handle_error, cam_pio_def_dim
    4214             :     use cam_pio_utils,    only: cam_pio_createfile, cam_pio_def_var
    4215             :     use sat_hist,         only: sat_hist_define
    4216             : 
    4217             :     !-----------------------------------------------------------------------
    4218             : 
    4219             :     !
    4220             :     ! Input arguments
    4221             :     !
    4222             :     integer, intent(in) :: t   ! tape index
    4223             :     logical, intent(in) :: restart
    4224             :     !
    4225             :     ! Local workspace
    4226             :     !
    4227             :     integer :: i, j, f         ! longitude, latitude, file indices
    4228             :     integer :: grd             ! indices for looping through grids
    4229             :     integer :: fld             ! field index
    4230             :     integer :: ncreal          ! real data type for output
    4231             :     integer :: dtime           ! timestep size
    4232             :     integer :: sec_nhtfrq      ! nhtfrq converted to seconds
    4233             :     integer :: ndbase = 0      ! days component of base time
    4234             :     integer :: nsbase = 0      ! seconds component of base time
    4235             :     integer :: nbdate          ! base date in yyyymmdd format
    4236             :     integer :: nbsec           ! time of day component of base date [seconds]
    4237             :     integer :: yr, mon, day    ! year, month, day components of a date
    4238             : 
    4239             :     character(len=max_chars) :: str       ! character temporary
    4240             :     character(len=max_chars) :: fname_tmp ! local copy of field name
    4241             :     character(len=max_chars) :: calendar  ! Calendar type
    4242             :     character(len=max_chars) :: cell_methods ! For cell_methods attribute
    4243             :     character(len=16)        :: time_per_freq
    4244             :     character(len=128)       :: errormsg
    4245             : 
    4246             :     integer :: ret                        ! function return value
    4247             : 
    4248             :     !
    4249             :     ! netcdf dimensions
    4250             :     !
    4251             :     integer :: chardim            ! character dimension id
    4252             :     integer :: dimenchar(2)       ! character dimension ids
    4253             :     integer :: nacsdims(2)        ! dimension ids for nacs (used in restart file)
    4254             :     integer :: bnddim             ! bounds dimension id
    4255             :     integer :: timdim             ! unlimited dimension id
    4256             : 
    4257             :     integer :: dimindex(8)        ! dimension ids for variable declaration
    4258             :     integer :: dimids_tmp(8)      ! dimension ids for variable declaration
    4259             : 
    4260             :     !
    4261             :     ! netcdf variables
    4262             :     !
    4263             :     ! A structure to hold the horizontal dimension and coordinate info
    4264        1536 :     type(cam_grid_header_info_t), allocatable :: header_info(:)
    4265             :     ! For satellite files and column output
    4266        1536 :     type(vdesc_ptr), allocatable :: latvar(:)    ! latitude variable ids
    4267        1536 :     type(vdesc_ptr), allocatable :: lonvar(:)    ! longitude variable ids
    4268             : 
    4269             :     type(var_desc_t), pointer        :: varid => NULL() ! temporary variable descriptor
    4270             :     integer                          :: num_hdims, fdims
    4271             :     integer                          :: num_patches ! How many entries for a field on this tape?
    4272             :     integer,          pointer        :: mdims(:) => NULL()
    4273             :     integer                          :: mdimsize
    4274             :     integer                          :: ierr
    4275        1536 :     integer,          allocatable    :: mdimids(:)
    4276             :     integer                          :: amode
    4277             :     logical                          :: interpolate
    4278             :     logical                          :: patch_output
    4279             :     integer                          :: cam_snapshot_before_num
    4280             :     integer                          :: cam_snapshot_after_num
    4281             :     character(len=32)                :: cam_take_snapshot_before
    4282             :     character(len=32)                :: cam_take_snapshot_after
    4283             : 
    4284             : 
    4285             :     call phys_getopts(cam_take_snapshot_before_out= cam_take_snapshot_before, &
    4286             :                       cam_take_snapshot_after_out = cam_take_snapshot_after,  &
    4287             :                       cam_snapshot_before_num_out = cam_snapshot_before_num,  &
    4288        1536 :                       cam_snapshot_after_num_out  = cam_snapshot_after_num)
    4289             : 
    4290        1536 :     if(restart) then
    4291        1536 :       tape => restarthistory_tape
    4292        1536 :       if(masterproc) write(iulog,*)'Opening netcdf history restart file ', trim(hrestpath(t))
    4293             :     else
    4294           0 :       tape => history_tape
    4295           0 :       if(masterproc) then
    4296           0 :          if (hfile_accum(t)) then
    4297             :             ! We have an accumulated file in addition to the instantaneous
    4298           0 :             write(iulog,*)'Opening netcdf history files ', trim(nhfil(t,accumulated_file_index)), &
    4299           0 :                   '  ', trim(nhfil(t,instantaneous_file_index))
    4300             :          else
    4301             :             ! We just have the instantaneous file
    4302           0 :             write(iulog,*)'Opening instantaneous netcdf history file ', trim(nhfil(t,instantaneous_file_index))
    4303             :          end if
    4304             :       end if
    4305             :     end if
    4306             : 
    4307        1536 :     amode = PIO_CLOBBER
    4308             : 
    4309        1536 :     if(restart) then
    4310        1536 :       call cam_pio_createfile (tape(t)%Files(restart_file_index), hrestpath(t), amode)
    4311           0 :     else if (is_initfile(file_index=t) .or. is_satfile(t)) then
    4312           0 :       call cam_pio_createfile (tape(t)%Files(sat_file_index), nhfil(t,sat_file_index), amode)
    4313             :     else
    4314             :       ! figure out how many history files to generate for this tape
    4315             :       ! Always create the instantaneous file
    4316           0 :       call cam_pio_createfile (tape(t)%Files(instantaneous_file_index), nhfil(t,instantaneous_file_index), amode)
    4317           0 :       if (hfile_accum(t)) then
    4318             :          ! Conditionally create the accumulated file
    4319           0 :          call cam_pio_createfile (tape(t)%Files(accumulated_file_index), nhfil(t,accumulated_file_index), amode)
    4320             :       end if
    4321             :     end if
    4322        1536 :     if(is_satfile(t)) then
    4323           0 :       interpolate = .false. ! !!XXgoldyXX: Do we ever want to support this?
    4324           0 :       patch_output = .false.
    4325           0 :       call cam_pio_def_dim(tape(t)%Files(sat_file_index), 'ncol', pio_unlimited, timdim)
    4326           0 :       call cam_pio_def_dim(tape(t)%Files(sat_file_index), 'nbnd', 2, bnddim)
    4327             : 
    4328           0 :       allocate(latvar(1), lonvar(1))
    4329           0 :       allocate(latvar(1)%vd, lonvar(1)%vd)
    4330           0 :       call cam_pio_def_var(tape(t)%Files(sat_file_index), 'lat', pio_double, (/timdim/),       &
    4331           0 :            latvar(1)%vd)
    4332           0 :       ierr=pio_put_att (tape(t)%Files(sat_file_index), latvar(1)%vd, 'long_name', 'latitude')
    4333           0 :       ierr=pio_put_att (tape(t)%Files(sat_file_index), latvar(1)%vd, 'units', 'degrees_north')
    4334             : 
    4335           0 :       call cam_pio_def_var(tape(t)%Files(sat_file_index), 'lon', pio_double, (/timdim/),       &
    4336           0 :            lonvar(1)%vd)
    4337           0 :       ierr=pio_put_att (tape(t)%Files(sat_file_index), lonvar(1)%vd,'long_name','longitude')
    4338           0 :       ierr=pio_put_att (tape(t)%Files(sat_file_index), lonvar(1)%vd,'units','degrees_east')
    4339             :     else
    4340             :       !
    4341             :       ! Setup netcdf file - create the dimensions of lat,lon,time,level
    4342             :       !
    4343             :       ! interpolate is only supported for unstructured dycores
    4344        1536 :       interpolate = (interpolate_output(t) .and. (.not. restart))
    4345        1536 :       patch_output = (associated(tape(t)%patches) .and. (.not. restart))
    4346             : 
    4347             :       ! First define the horizontal grid dims
    4348             :       ! Interpolation is special in that we ignore the native grids
    4349        1536 :       if(interpolate) then
    4350           0 :         allocate(header_info(1))
    4351           0 :         do f = 1, maxsplitfiles
    4352           0 :            if (pio_file_is_open(tape(t)%Files(f))) then
    4353           0 :               call cam_grid_write_attr(tape(t)%Files(f), interpolate_info(t)%grid_id, header_info(1), file_index=f)
    4354             :            end if
    4355             :         end do
    4356        1536 :       else if (patch_output) then
    4357             :         ! We are doing patch (column) output
    4358             :         if (allocated(header_info)) then
    4359             :           ! We shouldn't have any header_info yet
    4360             :           call endrun('H_DEFINE: header_info should not be allocated for patch output')
    4361             :         end if
    4362           0 :         do i = 1, size(tape(t)%patches)
    4363           0 :           do f = 1, maxsplitfiles
    4364           0 :              if (pio_file_is_open(tape(t)%Files(f))) then
    4365           0 :                 call tape(t)%patches(i)%write_attrs(tape(t)%Files(f))
    4366             :              end if
    4367             :           end do
    4368             :         end do
    4369             :       else
    4370        6144 :         allocate(header_info(size(tape(t)%grid_ids)))
    4371        3072 :         do i = 1, size(tape(t)%grid_ids)
    4372        6144 :           do f = 1, maxsplitfiles
    4373        4608 :              if (pio_file_is_open(tape(t)%Files(f))) then
    4374        1536 :                 call cam_grid_write_attr(tape(t)%Files(f), tape(t)%grid_ids(i), header_info(i), file_index=f)
    4375             :              end if
    4376             :           end do
    4377             :         end do
    4378             :       end if   ! interpolate
    4379             :       ! Define the unlimited time dim
    4380        4608 :       do f = 1, maxsplitfiles
    4381        4608 :          if (pio_file_is_open(tape(t)%Files(f))) then
    4382        1536 :             call cam_pio_def_dim(tape(t)%Files(f), 'time', pio_unlimited, timdim)
    4383        1536 :             call cam_pio_def_dim(tape(t)%Files(f), 'nbnd', 2, bnddim, existOK=.true.)
    4384        1536 :             call cam_pio_def_dim(tape(t)%Files(f), 'chars', 8, chardim)
    4385             :          end if
    4386             :       end do
    4387             :     end if   ! is satfile
    4388             : 
    4389        1536 :     call get_ref_date(yr, mon, day, nbsec)
    4390        1536 :     nbdate = yr*10000 + mon*100 + day
    4391        1536 :     calendar = timemgr_get_calendar_cf()
    4392             :     ! Determine what time period frequency is being output for each file
    4393             :     ! Note that nhtfrq is now in timesteps
    4394        1536 :     sec_nhtfrq = nhtfrq(t)
    4395             :     ! If nhtfrq is in hours, convert to seconds
    4396        1536 :     if (nhtfrq(t) < 0) then
    4397           0 :       sec_nhtfrq = abs(nhtfrq(t))*3600
    4398             :     end if
    4399        1536 :     dtime = get_step_size()
    4400        1536 :     if (sec_nhtfrq == 0) then                                !month
    4401        1536 :       time_per_freq = 'month_1'
    4402           0 :     else if (mod(sec_nhtfrq*dtime,86400) == 0) then          ! day
    4403           0 :       write(time_per_freq,999) 'day_',sec_nhtfrq*dtime/86400
    4404           0 :     else if (mod(sec_nhtfrq*dtime,3600) == 0) then           ! hour
    4405           0 :       write(time_per_freq,999) 'hour_',(sec_nhtfrq*dtime)/3600
    4406           0 :     else if (mod(sec_nhtfrq*dtime,60) == 0) then             ! minute
    4407           0 :       write(time_per_freq,999) 'minute_',(sec_nhtfrq*dtime)/60
    4408             :     else                                                     ! second
    4409           0 :       write(time_per_freq,999) 'second_',sec_nhtfrq*dtime
    4410             :     end if
    4411             : 999 format(a,i0)
    4412        4608 :     do f = 1, maxsplitfiles
    4413        3072 :        if (.not. pio_file_is_open(tape(t)%Files(f))) then
    4414             :           cycle
    4415             :        end if
    4416             :        ! Store snapshot location
    4417        1536 :        if (t == cam_snapshot_before_num) then
    4418           0 :           ierr=pio_put_att(tape(t)%Files(f), PIO_GLOBAL, 'cam_snapshot_before',      &
    4419           0 :                trim(cam_take_snapshot_before))
    4420             :        end if
    4421        1536 :        if (t == cam_snapshot_after_num) then
    4422           0 :           ierr=pio_put_att(tape(t)%Files(f), PIO_GLOBAL, 'cam_snapshot_after',       &
    4423           0 :                trim(cam_take_snapshot_after))
    4424             :        end if
    4425             : 
    4426             :        ! Populate the history coordinate (well, mdims anyway) attributes
    4427             :        ! This routine also allocates the mdimids array
    4428        1536 :        call write_hist_coord_attrs(tape(t)%Files(f), bnddim, mdimids, restart)
    4429             : 
    4430        3072 :        ierr=pio_def_var (tape(t)%Files(f),'time',pio_double,(/timdim/),tape(t)%timeid)
    4431             : 
    4432        1536 :        ierr=pio_put_att (tape(t)%Files(f), tape(t)%timeid, 'long_name', 'time')
    4433        1536 :        str = 'days since ' // date2yyyymmdd(nbdate) // ' ' // sec2hms(nbsec)
    4434        1536 :        ierr=pio_put_att (tape(t)%Files(f), tape(t)%timeid, 'units', trim(str))
    4435             : 
    4436        1536 :        ierr=pio_put_att (tape(t)%Files(f), tape(t)%timeid, 'calendar', trim(calendar))
    4437             : 
    4438        3072 :        ierr=pio_def_var (tape(t)%Files(f),'date    ',pio_int,(/timdim/),tape(t)%dateid)
    4439        1536 :        str = 'current date (YYYYMMDD)'
    4440        1536 :        ierr=pio_put_att (tape(t)%Files(f), tape(t)%dateid, 'long_name', trim(str))
    4441             : 
    4442        3072 :        ierr=pio_def_var (tape(t)%Files(f),'datesec ',pio_int,(/timdim/), tape(t)%datesecid)
    4443        1536 :        str = 'current seconds of current date'
    4444        1536 :        ierr=pio_put_att (tape(t)%Files(f), tape(t)%datesecid, 'long_name', trim(str))
    4445             : 
    4446             :        !
    4447             :        ! Character header information
    4448             :        !
    4449        1536 :        str = 'CF-1.0'
    4450        1536 :        ierr=pio_put_att (tape(t)%Files(f), PIO_GLOBAL, 'Conventions', trim(str))
    4451        1536 :        ierr=pio_put_att (tape(t)%Files(f), PIO_GLOBAL, 'source', 'CAM')
    4452             : #if ( defined BFB_CAM_SCAM_IOP )
    4453             :        ierr=pio_put_att (tape(t)%Files(f), PIO_GLOBAL, 'CAM_GENERATED_FORCING','create SCAM IOP dataset')
    4454             : #endif
    4455        1536 :        ierr=pio_put_att (tape(t)%Files(f), PIO_GLOBAL, 'case',caseid)
    4456        1536 :        ierr=pio_put_att (tape(t)%Files(f), PIO_GLOBAL, 'logname',logname)
    4457        1536 :        ierr=pio_put_att (tape(t)%Files(f), PIO_GLOBAL, 'host', host)
    4458             : 
    4459        1536 :        ierr=pio_put_att (tape(t)%Files(f), PIO_GLOBAL, 'initial_file', ncdata)
    4460        1536 :        ierr=pio_put_att (tape(t)%Files(f), PIO_GLOBAL, 'topography_file', bnd_topo)
    4461        1536 :        if (len_trim(model_doi_url) > 0) then
    4462        1536 :           ierr=pio_put_att (tape(t)%Files(f), PIO_GLOBAL, 'model_doi_url', model_doi_url)
    4463             :        end if
    4464             : 
    4465        1536 :        ierr=pio_put_att (tape(t)%Files(f), PIO_GLOBAL, 'time_period_freq', trim(time_per_freq))
    4466             : 
    4467        1536 :        if(.not. is_satfile(t)) then
    4468             : 
    4469        1536 :          ierr=pio_put_att (tape(t)%Files(f), tape(t)%timeid, 'bounds', 'time_bounds')
    4470             : 
    4471        4608 :          ierr=pio_def_var (tape(t)%Files(f),'time_bounds',pio_double,(/bnddim,timdim/),tape(t)%tbndid)
    4472        1536 :          ierr=pio_put_att (tape(t)%Files(f), tape(t)%tbndid, 'long_name', 'time interval endpoints')
    4473        1536 :          str = 'days since ' // date2yyyymmdd(nbdate) // ' ' // sec2hms(nbsec)
    4474        1536 :          ierr=pio_put_att (tape(t)%Files(f), tape(t)%tbndid, 'units', trim(str))
    4475        1536 :          ierr=pio_put_att (tape(t)%Files(f), tape(t)%tbndid, 'calendar', trim(calendar))
    4476             :          !
    4477             :          ! Character
    4478             :          !
    4479        1536 :          dimenchar(1) = chardim
    4480        1536 :          dimenchar(2) = timdim
    4481        1536 :          ierr=pio_def_var (tape(t)%Files(f),'date_written',PIO_CHAR,dimenchar, tape(t)%date_writtenid)
    4482        1536 :          ierr=pio_def_var (tape(t)%Files(f),'time_written',PIO_CHAR,dimenchar, tape(t)%time_writtenid)
    4483             :          !
    4484             :          ! Integer Header
    4485             :          !
    4486             : 
    4487        1536 :          ierr=pio_def_var (tape(t)%Files(f),'ndbase',PIO_INT,tape(t)%ndbaseid)
    4488        1536 :          str = 'base day'
    4489        1536 :          ierr=pio_put_att (tape(t)%Files(f), tape(t)%ndbaseid, 'long_name', trim(str))
    4490             : 
    4491        1536 :          ierr=pio_def_var (tape(t)%Files(f),'nsbase',PIO_INT,tape(t)%nsbaseid)
    4492        1536 :          str = 'seconds of base day'
    4493        1536 :          ierr=pio_put_att (tape(t)%Files(f), tape(t)%nsbaseid, 'long_name', trim(str))
    4494             : 
    4495        1536 :          ierr=pio_def_var (tape(t)%Files(f),'nbdate',PIO_INT,tape(t)%nbdateid)
    4496        1536 :          str = 'base date (YYYYMMDD)'
    4497        1536 :          ierr=pio_put_att (tape(t)%Files(f), tape(t)%nbdateid, 'long_name', trim(str))
    4498             : 
    4499             : #if ( defined BFB_CAM_SCAM_IOP )
    4500             :          ierr=pio_def_var (tape(t)%Files(f),'bdate',PIO_INT,tape(t)%bdateid)
    4501             :          str = 'base date (YYYYMMDD)'
    4502             :          ierr=pio_put_att (tape(t)%Files(f), tape(t)%bdateid, 'long_name', trim(str))
    4503             : #endif
    4504        1536 :          ierr=pio_def_var (tape(t)%Files(f),'nbsec',PIO_INT,tape(t)%nbsecid)
    4505        1536 :          str = 'seconds of base date'
    4506        1536 :          ierr=pio_put_att (tape(t)%Files(f), tape(t)%nbsecid, 'long_name', trim(str))
    4507             : 
    4508        1536 :          ierr=pio_def_var (tape(t)%Files(f),'mdt',PIO_INT,tape(t)%mdtid)
    4509        1536 :          ierr=pio_put_att (tape(t)%Files(f), tape(t)%mdtid, 'long_name', 'timestep')
    4510        1536 :          ierr=pio_put_att (tape(t)%Files(f), tape(t)%mdtid, 'units', 's')
    4511             : 
    4512             :          !
    4513             :          ! Create variables for model timing and header information
    4514             :          !
    4515        1536 :          if (f == instantaneous_file_index) then
    4516        3072 :             ierr=pio_def_var (tape(t)%Files(f),'ndcur   ',pio_int,(/timdim/),tape(t)%ndcurid)
    4517        1536 :             str = 'current day (from base day)'
    4518        1536 :             ierr=pio_put_att (tape(t)%Files(f), tape(t)%ndcurid, 'long_name', trim(str))
    4519        3072 :             ierr=pio_def_var (tape(t)%Files(f),'nscur   ',pio_int,(/timdim/),tape(t)%nscurid)
    4520        1536 :             str = 'current seconds of current day'
    4521        1536 :             ierr=pio_put_att (tape(t)%Files(f), tape(t)%nscurid, 'long_name', trim(str))
    4522             :          end if
    4523             : 
    4524             : 
    4525        1536 :          if (.not. is_initfile(file_index=t) .and. f == instantaneous_file_index) then
    4526             :            ! Don't write the GHG/Solar forcing data to the IC file.
    4527             :            ! Only write the GHG/Solar forcing data to the instantaneous file
    4528        3072 :            ierr=pio_def_var (tape(t)%Files(f),'co2vmr  ',pio_double,(/timdim/),tape(t)%co2vmrid)
    4529        1536 :            str = 'co2 volume mixing ratio'
    4530        1536 :            ierr=pio_put_att (tape(t)%Files(f), tape(t)%co2vmrid, 'long_name', trim(str))
    4531             : 
    4532        3072 :            ierr=pio_def_var (tape(t)%Files(f),'ch4vmr  ',pio_double,(/timdim/),tape(t)%ch4vmrid)
    4533        1536 :            str = 'ch4 volume mixing ratio'
    4534        1536 :            ierr=pio_put_att (tape(t)%Files(f), tape(t)%ch4vmrid, 'long_name', trim(str))
    4535             : 
    4536        3072 :            ierr=pio_def_var (tape(t)%Files(f),'n2ovmr  ',pio_double,(/timdim/),tape(t)%n2ovmrid)
    4537        1536 :            str = 'n2o volume mixing ratio'
    4538        1536 :            ierr=pio_put_att (tape(t)%Files(f), tape(t)%n2ovmrid, 'long_name', trim(str))
    4539             : 
    4540        3072 :            ierr=pio_def_var (tape(t)%Files(f),'f11vmr  ',pio_double,(/timdim/),tape(t)%f11vmrid)
    4541        1536 :            str = 'f11 volume mixing ratio'
    4542        1536 :            ierr=pio_put_att (tape(t)%Files(f), tape(t)%f11vmrid, 'long_name', trim(str))
    4543             : 
    4544        3072 :            ierr=pio_def_var (tape(t)%Files(f),'f12vmr  ',pio_double,(/timdim/),tape(t)%f12vmrid)
    4545        1536 :            str = 'f12 volume mixing ratio'
    4546        1536 :            ierr=pio_put_att (tape(t)%Files(f), tape(t)%f12vmrid, 'long_name', trim(str))
    4547             : 
    4548        3072 :            ierr=pio_def_var (tape(t)%Files(f),'sol_tsi ',pio_double,(/timdim/),tape(t)%sol_tsiid)
    4549        1536 :            str = 'total solar irradiance'
    4550        1536 :            ierr=pio_put_att (tape(t)%Files(f), tape(t)%sol_tsiid, 'long_name', trim(str))
    4551        1536 :            str = 'W/m2'
    4552        1536 :            ierr=pio_put_att (tape(t)%Files(f), tape(t)%sol_tsiid, 'units', trim(str))
    4553             : 
    4554        1536 :            if (solar_parms_on) then
    4555             :              ! solar / geomagnetic activity indices...
    4556           0 :              ierr=pio_def_var (tape(t)%Files(f),'f107',pio_double,(/timdim/),tape(t)%f107id)
    4557           0 :              str = '10.7 cm solar radio flux (F10.7)'
    4558           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%f107id, 'long_name', trim(str))
    4559           0 :              str = '10^-22 W m^-2 Hz^-1'
    4560           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%f107id, 'units', trim(str))
    4561             : 
    4562           0 :              ierr=pio_def_var (tape(t)%Files(f),'f107a',pio_double,(/timdim/),tape(t)%f107aid)
    4563           0 :              str = '81-day centered mean of 10.7 cm solar radio flux (F10.7)'
    4564           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%f107aid, 'long_name', trim(str))
    4565             : 
    4566           0 :              ierr=pio_def_var (tape(t)%Files(f),'f107p',pio_double,(/timdim/),tape(t)%f107pid)
    4567           0 :              str = 'Pervious day 10.7 cm solar radio flux (F10.7)'
    4568           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%f107pid, 'long_name', trim(str))
    4569             : 
    4570           0 :              ierr=pio_def_var (tape(t)%Files(f),'kp',pio_double,(/timdim/),tape(t)%kpid)
    4571           0 :              str = 'Daily planetary K geomagnetic index'
    4572           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%kpid, 'long_name', trim(str))
    4573             : 
    4574           0 :              ierr=pio_def_var (tape(t)%Files(f),'ap',pio_double,(/timdim/),tape(t)%apid)
    4575           0 :              str = 'Daily planetary A geomagnetic index'
    4576           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%apid, 'long_name', trim(str))
    4577             :            endif
    4578        1536 :            if (solar_wind_on) then
    4579             : 
    4580           0 :              ierr=pio_def_var (tape(t)%Files(f),'byimf',pio_double,(/timdim/),tape(t)%byimfid)
    4581           0 :              str = 'Y component of the interplanetary magnetic field'
    4582           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%byimfid, 'long_name', trim(str))
    4583           0 :              str = 'nT'
    4584           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%byimfid, 'units', trim(str))
    4585             : 
    4586           0 :              ierr=pio_def_var (tape(t)%Files(f),'bzimf',pio_double,(/timdim/),tape(t)%bzimfid)
    4587           0 :              str = 'Z component of the interplanetary magnetic field'
    4588           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%bzimfid, 'long_name', trim(str))
    4589           0 :              str = 'nT'
    4590           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%bzimfid, 'units', trim(str))
    4591             : 
    4592           0 :              ierr=pio_def_var (tape(t)%Files(f),'swvel',pio_double,(/timdim/),tape(t)%swvelid)
    4593           0 :              str = 'Solar wind speed'
    4594           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%swvelid, 'long_name', trim(str))
    4595           0 :              str = 'km/sec'
    4596           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%swvelid, 'units', trim(str))
    4597             : 
    4598           0 :              ierr=pio_def_var (tape(t)%Files(f),'swden',pio_double,(/timdim/),tape(t)%swdenid)
    4599           0 :              str = 'Solar wind ion number density'
    4600           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%swdenid, 'long_name', trim(str))
    4601           0 :              str = 'cm-3'
    4602           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%swdenid, 'units', trim(str))
    4603             : 
    4604             :            endif
    4605        1536 :            if (epot_active) then
    4606           0 :              ierr=pio_def_var (tape(t)%Files(f),'colat_crit1',pio_double,(/timdim/),tape(t)%colat_crit1_id)
    4607           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%colat_crit1_id, 'long_name', &
    4608           0 :                               'First co-latitude of electro-potential critical angle')
    4609           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%colat_crit1_id, 'units', 'degrees')
    4610             : 
    4611           0 :              ierr=pio_def_var (tape(t)%Files(f),'colat_crit2',pio_double,(/timdim/),tape(t)%colat_crit2_id)
    4612           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%colat_crit2_id, 'long_name',&
    4613           0 :                               'Second co-latitude of electro-potential critical angle')
    4614           0 :              ierr=pio_put_att (tape(t)%Files(f), tape(t)%colat_crit2_id, 'units', 'degrees')
    4615             :            endif
    4616             :          end if
    4617             : 
    4618        1536 :          if (f == instantaneous_file_index) then
    4619             : #if ( defined BFB_CAM_SCAM_IOP )
    4620             :             ierr=pio_def_var (tape(t)%Files(f),'tsec ',pio_int,(/timdim/), tape(t)%tsecid)
    4621             :             str = 'current seconds of current date needed for scam'
    4622             :             ierr=pio_put_att (tape(t)%Files(f), tape(t)%tsecid, 'long_name', trim(str))
    4623             : #endif
    4624        3072 :             ierr=pio_def_var (tape(t)%Files(f),'nsteph  ',pio_int,(/timdim/),tape(t)%nstephid)
    4625        1536 :             str = 'current timestep'
    4626        1536 :             ierr=pio_put_att (tape(t)%Files(f), tape(t)%nstephid, 'long_name', trim(str))
    4627             :          end if
    4628             :        end if ! .not. is_satfile
    4629             : 
    4630             :        !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    4631             :        !
    4632             :        ! Create variables and attributes for field list
    4633             :        !
    4634             :        !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    4635             : 
    4636      539136 :        do fld = 1, nflds(t)
    4637      537600 :          if (.not. is_satfile(t) .and. .not. restart .and. .not. is_initfile(t)) then
    4638           0 :             if (f == accumulated_file_index) then
    4639             :                ! this is the accumulated file of a potentially split history tape - skip instantaneous fields
    4640           0 :                if (tape(t)%hlist(fld)%avgflag == 'I') then
    4641             :                   cycle
    4642             :                end if
    4643             :             else
    4644             :                ! this is the instantaneous file of a potentially split history tape - skip accumulated fields
    4645           0 :                if (tape(t)%hlist(fld)%avgflag /= 'I') then
    4646             :                   cycle
    4647             :                end if
    4648             :             end if
    4649             :          end if
    4650             :          !! Collect some field properties
    4651      537600 :          call AvgflagToString(tape(t)%hlist(fld)%avgflag, tape(t)%hlist(fld)%time_op)
    4652      537600 :          if ((tape(t)%hlist(fld)%hwrt_prec == 8) .or. restart) then
    4653      537600 :            ncreal = pio_double
    4654             :          else
    4655           0 :            ncreal = pio_real
    4656             :          end if
    4657             : 
    4658      537600 :          if(associated(tape(t)%hlist(fld)%field%mdims)) then
    4659      374784 :            mdims => tape(t)%hlist(fld)%field%mdims
    4660      374784 :            mdimsize = size(mdims)
    4661      162816 :          else if(tape(t)%hlist(fld)%field%numlev > 1) then
    4662           0 :            call endrun('mdims not defined for variable '//trim(tape(t)%hlist(fld)%field%name))
    4663             :          else
    4664             :            mdimsize=0
    4665             :          end if
    4666             : 
    4667             :          ! num_patches will loop through the number of patches (or just one
    4668             :          !             for the whole grid) for this field for this tape
    4669      537600 :          if (patch_output) then
    4670           0 :            num_patches = size(tape(t)%patches)
    4671             :          else
    4672             :            num_patches = 1
    4673             :          end if
    4674      537600 :          if(.not.associated(tape(t)%hlist(fld)%varid)) then
    4675     1612800 :            allocate(tape(t)%hlist(fld)%varid(num_patches))
    4676             :          end if
    4677      537600 :          fname_tmp = strip_suffix(tape(t)%hlist(fld)%field%name)
    4678             : 
    4679      537600 :          if(is_satfile(t)) then
    4680           0 :            num_hdims=0
    4681           0 :            nfils(t)=1
    4682           0 :            call sat_hist_define(tape(t)%Files(f))
    4683      537600 :          else if (interpolate) then
    4684             :            ! Interpolate can't use normal grid code since we are forcing fields
    4685             :            ! to use interpolate decomp
    4686           0 :            if (.not. allocated(header_info)) then
    4687             :              ! Safety check
    4688           0 :              call endrun('h_define: header_info not allocated')
    4689             :            end if
    4690           0 :            num_hdims = 2
    4691           0 :            do i = 1, num_hdims
    4692           0 :              dimindex(i) = header_info(1)%get_hdimid(i)
    4693           0 :              nacsdims(i) = header_info(1)%get_hdimid(i)
    4694             :            end do
    4695      537600 :          else if (patch_output) then
    4696             :            ! All patches for this variable should be on the same grid
    4697           0 :            num_hdims = tape(t)%patches(1)%num_hdims(tape(t)%hlist(fld)%field%decomp_type)
    4698             :          else
    4699             :            ! Normal grid output
    4700             :            ! Find appropriate grid in header_info
    4701      537600 :            if (.not. allocated(header_info)) then
    4702             :              ! Safety check
    4703           0 :              call endrun('h_define: header_info not allocated')
    4704             :            end if
    4705      537600 :            grd = -1
    4706      537600 :            do i = 1, size(header_info)
    4707      537600 :              if (header_info(i)%get_gridid() == tape(t)%hlist(fld)%field%decomp_type) then
    4708      537600 :                grd = i
    4709      537600 :                exit
    4710             :              end if
    4711             :            end do
    4712      537600 :            if (grd < 0) then
    4713           0 :              write(errormsg, '(a,i0,2a)') 'grid, ',tape(t)%hlist(fld)%field%decomp_type,', not found for ',trim(fname_tmp)
    4714           0 :              call endrun('H_DEFINE: '//errormsg)
    4715             :            end if
    4716      537600 :            num_hdims = header_info(grd)%num_hdims()
    4717     1075200 :            do i = 1, num_hdims
    4718      537600 :              dimindex(i) = header_info(grd)%get_hdimid(i)
    4719     1075200 :              nacsdims(i) = header_info(grd)%get_hdimid(i)
    4720             :            end do
    4721             :          end if     ! is_satfile
    4722             : 
    4723             :          !
    4724             :          !  Create variables and atributes for fields written out as columns
    4725             :          !
    4726             : 
    4727     1614336 :          do i = 1, num_patches
    4728      537600 :            fname_tmp = strip_suffix(tape(t)%hlist(fld)%field%name)
    4729      537600 :            varid => tape(t)%hlist(fld)%varid(i)
    4730      537600 :            dimids_tmp = dimindex
    4731             :            ! Figure the dimension ID array for this field
    4732             :            ! We have defined the horizontal grid dimensions in dimindex
    4733      537600 :            fdims = num_hdims
    4734      749568 :            do j = 1, mdimsize
    4735      211968 :              fdims = fdims + 1
    4736      749568 :              dimids_tmp(fdims) = mdimids(mdims(j))
    4737             :            end do
    4738      537600 :            if(.not. restart) then
    4739             :              ! Only add time dimension if this is not a restart history tape
    4740           0 :              fdims = fdims + 1
    4741           0 :              dimids_tmp(fdims) = timdim
    4742             :            end if
    4743      537600 :            if (patch_output) then
    4744             :              ! For patch output, we need new dimension IDs and a different name
    4745           0 :              call tape(t)%patches(i)%get_var_data(fname_tmp,                     &
    4746           0 :                   dimids_tmp(1:fdims), tape(t)%hlist(fld)%field%decomp_type)
    4747             :            end if
    4748             :            ! Define the variable
    4749      537600 :            call cam_pio_def_var(tape(t)%Files(f), trim(fname_tmp), ncreal,           &
    4750     1075200 :                 dimids_tmp(1:fdims), varid)
    4751      537600 :            if (mdimsize > 0) then
    4752      211968 :              ierr = pio_put_att(tape(t)%Files(f), varid, 'mdims', mdims(1:mdimsize))
    4753      211968 :              call cam_pio_handle_error(ierr, 'h_define: cannot define mdims for '//trim(fname_tmp))
    4754             :            end if
    4755      537600 :            str = tape(t)%hlist(fld)%field%sampling_seq
    4756      537600 :            if (len_trim(str) > 0) then
    4757       35328 :              ierr = pio_put_att(tape(t)%Files(f), varid, 'Sampling_Sequence', trim(str))
    4758       35328 :              call cam_pio_handle_error(ierr, 'h_define: cannot define Sampling_Sequence for '//trim(fname_tmp))
    4759             :            end if
    4760             : 
    4761      537600 :            if (tape(t)%hlist(fld)%field%flag_xyfill) then
    4762             :              ! Add both _FillValue and missing_value to cover expectations
    4763             :              !     of various applications.
    4764             :              ! The attribute type must match the data type.
    4765        7680 :              if ((tape(t)%hlist(fld)%hwrt_prec == 8) .or. restart) then
    4766        7680 :                ierr = pio_put_att(tape(t)%Files(f), varid, '_FillValue',             &
    4767       15360 :                     tape(t)%hlist(fld)%field%fillvalue)
    4768             :                call cam_pio_handle_error(ierr,                                   &
    4769        7680 :                     'h_define: cannot define _FillValue for '//trim(fname_tmp))
    4770        7680 :                ierr = pio_put_att(tape(t)%Files(f), varid, 'missing_value',          &
    4771       15360 :                     tape(t)%hlist(fld)%field%fillvalue)
    4772             :                call cam_pio_handle_error(ierr,                                   &
    4773        7680 :                     'h_define: cannot define missing_value for '//trim(fname_tmp))
    4774             :              else
    4775           0 :                ierr = pio_put_att(tape(t)%Files(f), varid, '_FillValue',             &
    4776           0 :                     REAL(tape(t)%hlist(fld)%field%fillvalue,r4))
    4777             :                call cam_pio_handle_error(ierr,                                   &
    4778           0 :                     'h_define: cannot define _FillValue for '//trim(fname_tmp))
    4779           0 :                ierr = pio_put_att(tape(t)%Files(f), varid, 'missing_value',          &
    4780           0 :                     REAL(tape(t)%hlist(fld)%field%fillvalue,r4))
    4781             :                call cam_pio_handle_error(ierr,                                   &
    4782           0 :                     'h_define: cannot define missing_value for '//trim(fname_tmp))
    4783             :              end if
    4784             :            end if
    4785             : 
    4786      537600 :            str = tape(t)%hlist(fld)%field%units
    4787      537600 :            if (len_trim(str) > 0) then
    4788      531456 :              ierr=pio_put_att (tape(t)%Files(f), varid, 'units', trim(str))
    4789             :              call cam_pio_handle_error(ierr,                                     &
    4790      531456 :                   'h_define: cannot define units for '//trim(fname_tmp))
    4791             :            end if
    4792             : 
    4793      537600 :            str = tape(t)%hlist(fld)%field%mixing_ratio
    4794      537600 :            if (len_trim(str) > 0) then
    4795       62976 :              ierr=pio_put_att (tape(t)%Files(f), varid, 'mixing_ratio', trim(str))
    4796             :              call cam_pio_handle_error(ierr,                                     &
    4797       62976 :                   'h_define: cannot define mixing_ratio for '//trim(fname_tmp))
    4798             :            end if
    4799             : 
    4800      537600 :            str = tape(t)%hlist(fld)%field%long_name
    4801      537600 :            ierr=pio_put_att (tape(t)%Files(f), varid, 'long_name', trim(str))
    4802             :            call cam_pio_handle_error(ierr,                                       &
    4803      537600 :                 'h_define: cannot define long_name for '//trim(fname_tmp))
    4804             : 
    4805             :            ! Assign field attributes defining valid levels and averaging info
    4806             : 
    4807      537600 :            cell_methods = ''
    4808      537600 :            if (len_trim(tape(t)%hlist(fld)%field%cell_methods) > 0) then
    4809           0 :              if (len_trim(cell_methods) > 0) then
    4810           0 :                cell_methods = trim(cell_methods)//' '//trim(tape(t)%hlist(fld)%field%cell_methods)
    4811             :              else
    4812           0 :                cell_methods = trim(cell_methods)//trim(tape(t)%hlist(fld)%field%cell_methods)
    4813             :              end if
    4814             :            end if
    4815             :            ! Time cell methods is after field method because time averaging is
    4816             :            ! applied later (just before output) than field method which is applied
    4817             :            ! before outfld call.
    4818      537600 :            str = tape(t)%hlist(fld)%time_op
    4819      537600 :            if (tape(t)%hlist(fld)%avgflag == 'I') then
    4820        1536 :               str = 'point'
    4821             :            else
    4822      536064 :               str = tape(t)%hlist(fld)%time_op
    4823             :            end if
    4824      537600 :            cell_methods = adjustl(trim(cell_methods)//' '//'time: '//str)
    4825      537600 :            if (len_trim(cell_methods) > 0) then
    4826      537600 :              ierr = pio_put_att(tape(t)%Files(f), varid, 'cell_methods', trim(cell_methods))
    4827             :              call cam_pio_handle_error(ierr,                                     &
    4828      537600 :                   'h_define: cannot define cell_methods for '//trim(fname_tmp))
    4829             :            end if
    4830      537600 :            if (patch_output) then
    4831           0 :              ierr = pio_put_att(tape(t)%Files(f), varid, 'basename',                 &
    4832           0 :                   tape(t)%hlist(fld)%field%name)
    4833             :              call cam_pio_handle_error(ierr,                                     &
    4834           0 :                   'h_define: cannot define basename for '//trim(fname_tmp))
    4835             :            end if
    4836             : 
    4837     1075200 :            if (restart) then
    4838             :              ! For restart history files, we need to save accumulation counts
    4839      537600 :              fname_tmp = trim(fname_tmp)//'_nacs'
    4840      537600 :              if (.not. associated(tape(t)%hlist(fld)%nacs_varid)) then
    4841      537600 :                allocate(tape(t)%hlist(fld)%nacs_varid)
    4842             :              end if
    4843      537600 :              if (size(tape(t)%hlist(fld)%nacs, 1) > 1) then
    4844        7680 :                call cam_pio_def_var(tape(t)%Files(f), trim(fname_tmp), pio_int,      &
    4845       15360 :                     nacsdims(1:num_hdims), tape(t)%hlist(fld)%nacs_varid)
    4846             :              else
    4847             :                ! Save just one value representing all chunks
    4848      529920 :                call cam_pio_def_var(tape(t)%Files(f), trim(fname_tmp), pio_int,      &
    4849     1059840 :                     tape(t)%hlist(fld)%nacs_varid)
    4850             :              end if
    4851             :              ! for standard deviation
    4852      537600 :              if (associated(tape(t)%hlist(fld)%sbuf)) then
    4853           0 :                 fname_tmp = strip_suffix(tape(t)%hlist(fld)%field%name)
    4854           0 :                 fname_tmp = trim(fname_tmp)//'_var'
    4855           0 :                 if ( .not.associated(tape(t)%hlist(fld)%sbuf_varid)) then
    4856           0 :                    allocate(tape(t)%hlist(fld)%sbuf_varid)
    4857             :                 endif
    4858           0 :                 call cam_pio_def_var(tape(t)%Files(f), trim(fname_tmp), pio_double,      &
    4859           0 :                      dimids_tmp(1:fdims), tape(t)%hlist(fld)%sbuf_varid)
    4860             :              endif
    4861             :            end if
    4862             :          end do ! Loop over output patches
    4863             :        end do   ! Loop over fields
    4864             :        !
    4865        1536 :        deallocate(mdimids)
    4866        1536 :        ret = pio_enddef(tape(t)%Files(f))
    4867        1536 :        if (ret /= PIO_NOERR) then
    4868           0 :           call endrun('H_DEFINE: ERROR exiting define mode in PIO')
    4869             :        end if
    4870             : 
    4871        4608 :        if(masterproc) then
    4872           2 :          write(iulog,*)'H_DEFINE: Successfully opened netcdf file '
    4873             :        endif
    4874             :     end do ! Loop over files
    4875             :     !
    4876             :     ! Write time-invariant portion of history header
    4877             :     !
    4878        1536 :     if(.not. is_satfile(t)) then
    4879        1536 :       if(interpolate) then
    4880           0 :         do f = 1, maxsplitfiles
    4881           0 :            if (pio_file_is_open(tape(t)%Files(f))) then
    4882           0 :               call cam_grid_write_var(tape(t)%Files(f), interpolate_info(t)%grid_id, file_index=f)
    4883             :            end if
    4884             :         end do
    4885        1536 :       else if((.not. patch_output) .or. restart) then
    4886        3072 :         do i = 1, size(tape(t)%grid_ids)
    4887        6144 :           do f = 1, maxsplitfiles
    4888        4608 :              if (pio_file_is_open(tape(t)%Files(f))) then
    4889        1536 :                 call cam_grid_write_var(tape(t)%Files(f), tape(t)%grid_ids(i), file_index=f)
    4890             :              end if
    4891             :           end do
    4892             :         end do
    4893             :       else
    4894             :         ! Patch output
    4895           0 :         do i = 1, size(tape(t)%patches)
    4896           0 :           do f = 1, maxsplitfiles
    4897           0 :              if (pio_file_is_open(tape(t)%Files(f))) then
    4898           0 :                 call tape(t)%patches(i)%write_vals(tape(t)%Files(f))
    4899             :              end if
    4900             :           end do
    4901             :         end do
    4902             :       end if ! interpolate
    4903        1536 :       if (allocated(lonvar)) then
    4904           0 :         deallocate(lonvar)
    4905             :       end if
    4906        1536 :       if (allocated(latvar)) then
    4907           0 :         deallocate(latvar)
    4908             :       end if
    4909             : 
    4910        1536 :       dtime = get_step_size()
    4911        4608 :       do f = 1, maxsplitfiles
    4912        3072 :          if (.not. pio_file_is_open(tape(t)%Files(f))) then
    4913             :             cycle
    4914             :          end if
    4915        3072 :          ierr = pio_put_var(tape(t)%Files(f), tape(t)%mdtid, (/dtime/))
    4916        1536 :          call cam_pio_handle_error(ierr, 'h_define: cannot put mdt')
    4917             :          !
    4918             :          ! Model date info
    4919             :          !
    4920        3072 :          ierr = pio_put_var(tape(t)%Files(f), tape(t)%ndbaseid, (/ndbase/))
    4921        1536 :          call cam_pio_handle_error(ierr, 'h_define: cannot put ndbase')
    4922        3072 :          ierr = pio_put_var(tape(t)%Files(f), tape(t)%nsbaseid, (/nsbase/))
    4923        1536 :          call cam_pio_handle_error(ierr, 'h_define: cannot put nsbase')
    4924             : 
    4925        3072 :          ierr = pio_put_var(tape(t)%Files(f), tape(t)%nbdateid, (/nbdate/))
    4926        1536 :          call cam_pio_handle_error(ierr, 'h_define: cannot put nbdate')
    4927             : #if ( defined BFB_CAM_SCAM_IOP )
    4928             :          ierr = pio_put_var(tape(t)%Files(f), tape(t)%bdateid, (/nbdate/))
    4929             :          call cam_pio_handle_error(ierr, 'h_define: cannot put bdate')
    4930             : #endif
    4931        3072 :          ierr = pio_put_var(tape(t)%Files(f), tape(t)%nbsecid, (/nbsec/))
    4932        4608 :          call cam_pio_handle_error(ierr, 'h_define: cannot put nbsec')
    4933             :          !
    4934             :          ! Reduced grid info
    4935             :          !
    4936             :       end do
    4937             :     end if ! .not. is_satfile
    4938             : 
    4939        1536 :     if (allocated(header_info)) then
    4940        3072 :       do i = 1, size(header_info)
    4941        3072 :         call header_info(i)%deallocate()
    4942             :       end do
    4943        3072 :       deallocate(header_info)
    4944             :     end if
    4945             : 
    4946             :     ! Write the mdim variable data
    4947        4608 :     do f = 1, maxsplitfiles
    4948        4608 :        if (pio_file_is_open(tape(t)%Files(f))) then
    4949        1536 :           call write_hist_coord_vars(tape(t)%Files(f), restart)
    4950             :        end if
    4951             :     end do
    4952             : 
    4953        1536 :   end subroutine h_define
    4954             : 
    4955             :   !#######################################################################
    4956             : 
    4957           0 :   subroutine h_normalize (fld, t)
    4958             : 
    4959        1536 :     use cam_history_support, only: dim_index_2d
    4960             :     use time_manager, only: get_nstep
    4961             : 
    4962             :     !
    4963             :     !-----------------------------------------------------------------------
    4964             :     !
    4965             :     ! Purpose: Normalize fields on a history file by the number of accumulations
    4966             :     !
    4967             :     ! Method: Loop over fields on the tape.  Need averaging flag and number of
    4968             :     !         accumulations to perform normalization.
    4969             :     !
    4970             :     !-----------------------------------------------------------------------
    4971             :     !
    4972             :     ! Input arguments
    4973             :     !
    4974             :     integer, intent(in) :: fld     ! field index
    4975             :     integer, intent(in) :: t       ! tape index
    4976             :     !
    4977             :     ! Local workspace
    4978             :     !
    4979             :     type (dim_index_2d) :: dimind  ! 2-D dimension index
    4980             :     integer     :: c               ! chunk (or lat) index
    4981             :     integer     :: ib, ie    ! beginning and ending indices of first dimension
    4982             :     integer     :: jb, je    ! beginning and ending indices of second dimension
    4983             :     integer     :: begdim3, enddim3 ! Chunk or block bounds
    4984             :     integer     :: k         ! level
    4985             :     integer     :: i, ii
    4986             :     integer     :: currstep, nsteps
    4987             :     real(r8) :: variance, tmpfill
    4988             : 
    4989             :     logical     :: flag_xyfill ! non-applicable xy points flagged with fillvalue
    4990             :     character*1 :: avgflag     ! averaging flag
    4991             :     character(len=max_chars) :: errmsg
    4992             :     character(len=*), parameter      :: sub='H_NORMALIZE:'
    4993             : 
    4994           0 :     call t_startf ('h_normalize')
    4995             : 
    4996           0 :     call tape(t)%hlist(fld)%field%get_bounds(3, begdim3, enddim3)
    4997             : 
    4998             :     !
    4999             :     ! normalize by number of accumulations for averaged case
    5000             :     !
    5001           0 :     flag_xyfill = tape(t)%hlist(fld)%field%flag_xyfill
    5002           0 :     avgflag = tape(t)%hlist(fld)%avgflag
    5003             : 
    5004           0 :     do c = begdim3, enddim3
    5005           0 :       dimind = tape(t)%hlist(fld)%field%get_dims(c)
    5006             : 
    5007           0 :       ib = dimind%beg1
    5008           0 :       ie = dimind%end1
    5009           0 :       jb = dimind%beg2
    5010           0 :       je = dimind%end2
    5011             : 
    5012           0 :       if (flag_xyfill) then
    5013           0 :         do k = jb, je
    5014           0 :           where (tape(t)%hlist(fld)%nacs(ib:ie, c) == 0)
    5015           0 :             tape(t)%hlist(fld)%hbuf(ib:ie,k,c) = tape(t)%hlist(fld)%field%fillvalue
    5016             :           endwhere
    5017             :         end do
    5018             :       end if
    5019             : 
    5020           0 :       if (avgflag == 'A' .or. avgflag == 'B' .or. avgflag == 'L') then
    5021           0 :         if (size(tape(t)%hlist(fld)%nacs, 1) > 1) then
    5022           0 :           do k = jb, je
    5023           0 :             where (tape(t)%hlist(fld)%nacs(ib:ie,c) /= 0)
    5024             :               tape(t)%hlist(fld)%hbuf(ib:ie,k,c) = &
    5025           0 :                    tape(t)%hlist(fld)%hbuf(ib:ie,k,c) &
    5026           0 :                    / tape(t)%hlist(fld)%nacs(ib:ie,c)
    5027             :             endwhere
    5028             :           end do
    5029           0 :         else if(tape(t)%hlist(fld)%nacs(1,c) > 0) then
    5030           0 :           do k=jb,je
    5031             :             tape(t)%hlist(fld)%hbuf(ib:ie,k,c) = &
    5032           0 :                  tape(t)%hlist(fld)%hbuf(ib:ie,k,c) &
    5033           0 :                  / tape(t)%hlist(fld)%nacs(1,c)
    5034             :           end do
    5035             :         end if
    5036             :       end if
    5037           0 :       currstep=get_nstep()
    5038           0 :       if (avgflag == 'N' .and. currstep >  0) then
    5039           0 :          if( currstep > tape(t)%hlist(fld)%beg_nstep) then
    5040           0 :             nsteps=currstep-tape(t)%hlist(fld)%beg_nstep
    5041           0 :             do k=jb,je
    5042             :                tape(t)%hlist(fld)%hbuf(ib:ie,k,c) = &
    5043           0 :                     tape(t)%hlist(fld)%hbuf(ib:ie,k,c) &
    5044           0 :                     / nsteps
    5045             :             end do
    5046             :          else
    5047           0 :             write(errmsg,*) sub,'FATAL: bad nstep normalization, currstep, beg_nstep=',currstep,',',tape(t)%hlist(fld)%beg_nstep
    5048           0 :             call endrun(trim(errmsg))
    5049             :          end if
    5050             :       end if
    5051           0 :       if (avgflag == 'S') then
    5052             :          ! standard deviation ...
    5053             :          ! from http://www.johndcook.com/blog/standard_deviation/
    5054           0 :          tmpfill = merge(tape(t)%hlist(fld)%field%fillvalue,0._r8,flag_xyfill)
    5055           0 :          do k=jb,je
    5056           0 :             do i = ib,ie
    5057           0 :                ii = merge(i,1,flag_xyfill)
    5058           0 :                if (tape(t)%hlist(fld)%nacs(ii,c) > 1) then
    5059           0 :                   variance = tape(t)%hlist(fld)%sbuf(i,k,c)/(tape(t)%hlist(fld)%nacs(ii,c)-1)
    5060           0 :                   tape(t)%hlist(fld)%hbuf(i,k,c) = sqrt(variance)
    5061             :                else
    5062           0 :                   tape(t)%hlist(fld)%hbuf(i,k,c) = tmpfill
    5063             :                endif
    5064             :             end do
    5065             :          end do
    5066             :       endif
    5067             :     end do
    5068             : 
    5069           0 :     call t_stopf ('h_normalize')
    5070             : 
    5071           0 :     return
    5072           0 :   end subroutine h_normalize
    5073             : 
    5074             :   !#######################################################################
    5075             : 
    5076      303360 :   subroutine h_zero (fld, t)
    5077           0 :     use cam_history_support, only: dim_index_2d
    5078             :     use time_manager, only: get_nstep, is_first_restart_step
    5079             :     !
    5080             :     !-----------------------------------------------------------------------
    5081             :     !
    5082             :     ! Purpose: Zero out accumulation buffers for a tape
    5083             :     !
    5084             :     ! Method: Loop through fields on the tape
    5085             :     !
    5086             :     !-----------------------------------------------------------------------
    5087             :     !
    5088             :     integer, intent(in) :: fld   ! field index
    5089             :     integer, intent(in) :: t     ! tape index
    5090             :     !
    5091             :     ! Local workspace
    5092             :     !
    5093             :     type (dim_index_2d) :: dimind   ! 2-D dimension index
    5094             :     integer :: c                    ! chunk index
    5095             :     integer :: begdim3              ! on-node chunk or lat start index
    5096             :     integer :: enddim3              ! on-node chunk or lat end index
    5097             : 
    5098      303360 :     call t_startf ('h_zero')
    5099             : 
    5100      303360 :     call tape(t)%hlist(fld)%field%get_bounds(3, begdim3, enddim3)
    5101             : 
    5102     1629960 :     do c = begdim3, enddim3
    5103     1326600 :       dimind = tape(t)%hlist(fld)%field%get_dims(c)
    5104  1052213760 :       tape(t)%hlist(fld)%hbuf(dimind%beg1:dimind%end1,dimind%beg2:dimind%end2,c)=0._r8
    5105     1629960 :       if (associated(tape(t)%hlist(fld)%sbuf)) then ! zero out variance buffer for standard deviation
    5106           0 :          tape(t)%hlist(fld)%sbuf(dimind%beg1:dimind%end1,dimind%beg2:dimind%end2,c)=0._r8
    5107             :       end if
    5108             :     end do
    5109     3188760 :     tape(t)%hlist(fld)%nacs(:,:) = 0
    5110             : 
    5111             :     !Don't reset beg_nstep if this is a restart
    5112      303360 :     if (.not. is_first_restart_step()) tape(t)%hlist(fld)%beg_nstep = get_nstep()
    5113             : 
    5114      303360 :     call t_stopf ('h_zero')
    5115             : 
    5116      303360 :     return
    5117      303360 :   end subroutine h_zero
    5118             : 
    5119             :   !#######################################################################
    5120             : 
    5121      537600 :   subroutine h_global (fld, t)
    5122             : 
    5123      303360 :     use cam_history_support, only: dim_index_2d
    5124             :     use shr_reprosum_mod,    only: shr_reprosum_calc
    5125             :     use spmd_utils,          only: mpicom
    5126             :     !
    5127             :     !-----------------------------------------------------------------------
    5128             :     !
    5129             :     ! Purpose: compute globals of field
    5130             :     !
    5131             :     ! Method: Loop through fields on the tape
    5132             :     !
    5133             :     !-----------------------------------------------------------------------
    5134             :     !
    5135             :     integer, intent(in) :: fld   ! field index
    5136             :     integer, intent(in) :: t     ! tape index
    5137             :     !
    5138             :     ! Local workspace
    5139             :     !
    5140             :     type (dim_index_2d)     :: dimind    ! 2-D dimension index
    5141             :     integer                 :: ie        ! dim3 index
    5142             :     integer                 :: count     ! tmp index
    5143             :     integer                 :: i1        ! dim1 index
    5144             :     integer                 :: j1        ! dim2 index
    5145             :     integer                 :: fdims(3)  ! array shape
    5146             :     integer                 :: begdim1,enddim1,begdim2,enddim2,begdim3,enddim3        !
    5147             :     real(r8)                :: globalsum(1) ! globalsum
    5148      537600 :     real(r8), allocatable   :: globalarr(:) ! globalarr values for this pe
    5149             : 
    5150      537600 :     call t_startf ('h_global')
    5151             : 
    5152             :     ! wbuf contains the area weighting for this field decomposition
    5153      537600 :     if (associated(tape(t)%hlist(fld)%wbuf) ) then
    5154             : 
    5155           0 :        begdim1    =  tape(t)%hlist(fld)%field%begdim1
    5156           0 :        enddim1    =  tape(t)%hlist(fld)%field%enddim1
    5157           0 :        fdims(1)   =  enddim1 - begdim1 + 1
    5158           0 :        begdim2    =  tape(t)%hlist(fld)%field%begdim2
    5159           0 :        enddim2    =  tape(t)%hlist(fld)%field%enddim2
    5160           0 :        fdims(2)   =  enddim2 - begdim2 + 1
    5161           0 :        begdim3    =  tape(t)%hlist(fld)%field%begdim3
    5162           0 :        enddim3    =  tape(t)%hlist(fld)%field%enddim3
    5163           0 :        fdims(3)   =  enddim3 - begdim3 + 1
    5164             : 
    5165           0 :        allocate(globalarr(fdims(1)*fdims(2)*fdims(3)))
    5166           0 :        count=0
    5167           0 :        globalarr=0._r8
    5168           0 :        do ie = begdim3, enddim3
    5169           0 :           dimind = tape(t)%hlist(fld)%field%get_dims(ie)
    5170           0 :           do j1 = dimind%beg2, dimind%end2
    5171           0 :              do i1 = dimind%beg1, dimind%end1
    5172           0 :                 count=count+1
    5173           0 :                 globalarr(count)=globalarr(count)+tape(t)%hlist(fld)%hbuf(i1,j1,ie)*tape(t)%hlist(fld)%wbuf(i1,ie)
    5174             :              end do
    5175             :           end do
    5176             :        end do
    5177             :        ! call fixed-point algorithm
    5178           0 :        call shr_reprosum_calc (globalarr, globalsum, count, count, 1, commid=mpicom)
    5179           0 :        if (masterproc) write(iulog,*)'h_global:field:',trim(tape(t)%hlist(fld)%field%name),' global integral=',globalsum(1)
    5180             :        ! store global entry for this history tape entry
    5181           0 :        call tape(t)%hlist(fld)%put_global(globalsum(1))
    5182             :        ! deallocate temp array
    5183           0 :        deallocate(globalarr)
    5184             :     end if
    5185      537600 :     call t_stopf ('h_global')
    5186      537600 :   end subroutine h_global
    5187             : 
    5188           0 :   subroutine h_field_op (fld, t)
    5189      537600 :     use cam_history_support, only: dim_index_2d
    5190             :     !
    5191             :     !-----------------------------------------------------------------------
    5192             :     !
    5193             :     ! Purpose: run field sum or dif opperation on all contructed fields
    5194             :     !
    5195             :     ! Method: Loop through fields on the tape
    5196             :     !
    5197             :     !-----------------------------------------------------------------------
    5198             :     !
    5199             :     integer, intent(in) :: fld      ! field index
    5200             :     integer, intent(in) :: t        ! tape index
    5201             :     !
    5202             :     ! Local workspace
    5203             :     !
    5204             :     type (dim_index_2d) :: dimind   ! 2-D dimension index
    5205             :     integer :: c                    ! chunk index
    5206             :     integer :: fld1,fld2            ! fields to be operated on
    5207             :     integer :: begdim1, begdim2, begdim3              ! on-node chunk or lat start index
    5208             :     integer :: enddim1, enddim2, enddim3              ! on-node chunk or lat end index
    5209             :     character(len=field_op_len) :: optype             ! field operation only sum or diff supported
    5210             : 
    5211           0 :     call t_startf ('h_field_op')
    5212           0 :     fld1 = tape(t)%hlist(fld)%field%op_field1_id
    5213           0 :     fld2 = tape(t)%hlist(fld)%field%op_field2_id
    5214           0 :     optype =  trim(adjustl(tape(t)%hlist(fld)%field%field_op))
    5215             : 
    5216           0 :     begdim3  = tape(t)%hlist(fld)%field%begdim3
    5217           0 :     enddim3  = tape(t)%hlist(fld)%field%enddim3
    5218             : 
    5219           0 :     do c = begdim3, enddim3
    5220           0 :       dimind = tape(t)%hlist(fld)%field%get_dims(c)
    5221           0 :       if (trim(optype) == 'dif') then
    5222           0 :          tape(t)%hlist(fld)%hbuf(dimind%beg1:dimind%end1,dimind%beg2:dimind%end2,c) = &
    5223           0 :          tape(t)%hlist(fld1)%hbuf(dimind%beg1:dimind%end1,dimind%beg2:dimind%end2,c) - &
    5224           0 :          tape(t)%hlist(fld2)%hbuf(dimind%beg1:dimind%end1,dimind%beg2:dimind%end2,c)
    5225           0 :       else if (trim(optype) == 'sum') then
    5226           0 :          tape(t)%hlist(fld)%hbuf(dimind%beg1:dimind%end1,dimind%beg2:dimind%end2,c) = &
    5227           0 :          tape(t)%hlist(fld1)%hbuf(dimind%beg1:dimind%end1,dimind%beg2:dimind%end2,c) + &
    5228           0 :          tape(t)%hlist(fld2)%hbuf(dimind%beg1:dimind%end1,dimind%beg2:dimind%end2,c)
    5229             :       else
    5230           0 :          call endrun('h_field_op: ERROR: composed field operation type unknown:'//trim(optype))
    5231             :       end if
    5232             :     end do
    5233             :     ! Set nsteps for composed fields using value of one of the component fields
    5234           0 :     tape(t)%hlist(fld)%beg_nstep=tape(t)%hlist(fld1)%beg_nstep
    5235           0 :     tape(t)%hlist(fld)%nacs(:,:)=tape(t)%hlist(fld1)%nacs(:,:)
    5236           0 :     call t_stopf ('h_field_op')
    5237           0 :   end subroutine h_field_op
    5238             : 
    5239             :   !#######################################################################
    5240             : 
    5241      537600 :   subroutine dump_field (fld, t, f, restart)
    5242           0 :     use cam_history_support, only: history_patch_t, dim_index_2d, dim_index_3d
    5243             :     use cam_grid_support,    only: cam_grid_write_dist_array, cam_grid_dimensions
    5244             :     use interp_mod,       only : write_interpolated
    5245             : 
    5246             :     ! Dummy arguments
    5247             :     integer,     intent(in)    :: fld              ! Field index
    5248             :     integer,     intent(in)    :: t                ! Tape index
    5249             :     integer,     intent(in)    :: f                ! File index
    5250             :     logical,     intent(in)    :: restart
    5251             :     !
    5252             :     !-----------------------------------------------------------------------
    5253             :     !
    5254             :     ! Purpose: Write a variable to a history tape using PIO
    5255             :     !          For restart tapes, also write the accumulation buffer (nacs)
    5256             :     !
    5257             :     !-----------------------------------------------------------------------
    5258             :     ! Local variables
    5259             :     integer                          :: ierr
    5260             :     type(var_desc_t),      pointer   :: varid      ! PIO ID for var
    5261             :     type(var_desc_t),      pointer   :: compid     ! PIO ID for vector comp.
    5262             :     integer                          :: compind    ! index of vector comp.
    5263             :     integer                          :: fdims(8)   ! Field file dim sizes
    5264             :     integer                          :: frank      ! Field file rank
    5265             :     integer                          :: nacsrank   ! Field file rank for nacs
    5266             :     type(dim_index_2d)               :: dimind2    ! 2-D dimension index
    5267             :     type(dim_index_3d)               :: dimind     ! 3-D dimension index
    5268             :     integer                          :: adims(3)   ! Field array dim sizes
    5269             :     integer                          :: nadims     ! # of used adims
    5270             :     integer                          :: fdecomp
    5271             :     integer                          :: num_patches
    5272             :     integer                          :: mdimsize   ! Total # on-node elements
    5273             :     integer                          :: bdim3, edim3
    5274             :     integer                          :: ncreal     ! Real output kind (double or single)
    5275             :     logical                          :: interpolate
    5276             :     logical                          :: patch_output
    5277             :     type(history_patch_t), pointer   :: patchptr
    5278             :     integer                          :: index
    5279      537600 :     real(r4),            allocatable :: rtemp2(:,:)
    5280      537600 :     real(r4),            allocatable :: rtemp3(:,:,:)
    5281             :     integer                          :: begdim3, enddim3, ind3
    5282             : 
    5283      537600 :     interpolate = (interpolate_output(t) .and. (.not. restart))
    5284      537600 :     patch_output = (associated(tape(t)%patches) .and. (.not. restart))
    5285             : 
    5286             :     !!! Get the field's shape and decomposition
    5287             : 
    5288             :     ! Shape on disk
    5289      537600 :     call tape(t)%hlist(fld)%field%get_shape(fdims, frank)
    5290             : 
    5291             :     ! Shape of array
    5292      537600 :     dimind = tape(t)%hlist(fld)%field%get_dims()
    5293      537600 :     call dimind%dim_sizes(adims)
    5294      537600 :     if (adims(2) <= 1) then
    5295      325632 :       adims(2) = adims(3)
    5296      325632 :       nadims = 2
    5297             :     else
    5298             :       nadims = 3
    5299             :     end if
    5300      537600 :     fdecomp = tape(t)%hlist(fld)%field%decomp_type
    5301             : 
    5302             :     ! num_patches will loop through the number of patches (or just one
    5303             :     !             for the whole grid) for this field for this tape
    5304      537600 :     if (patch_output) then
    5305           0 :       num_patches = size(tape(t)%patches)
    5306             :     else
    5307             :       num_patches = 1
    5308             :     end if
    5309             : 
    5310     1075200 :     do index = 1, num_patches
    5311      537600 :       varid => tape(t)%hlist(fld)%varid(index)
    5312             : 
    5313      537600 :       if (restart) then
    5314      537600 :         call pio_setframe(tape(t)%Files(f), varid, int(-1,kind=PIO_OFFSET_KIND))
    5315             :       else
    5316           0 :         call pio_setframe(tape(t)%Files(f), varid, int(max(1,nfils(t)),kind=PIO_OFFSET_KIND))
    5317             :       end if
    5318     1075200 :       if (patch_output) then
    5319             :         ! We are outputting patches
    5320           0 :         patchptr => tape(t)%patches(index)
    5321           0 :         if (interpolate) then
    5322           0 :           call endrun('dump_field: interpolate incompatible with regional output')
    5323             :         end if
    5324           0 :         call patchptr%write_var(tape(t)%Files(f), fdecomp, adims(1:nadims),       &
    5325           0 :              pio_double, tape(t)%hlist(fld)%hbuf, varid)
    5326             :       else
    5327             :         ! We are doing output via the field's grid
    5328      537600 :         if (interpolate) then
    5329             : 
    5330             :           !Determine what the output field kind should be:
    5331           0 :           if (tape(t)%hlist(fld)%hwrt_prec == 8) then
    5332           0 :             ncreal = pio_double
    5333             :           else
    5334           0 :             ncreal = pio_real
    5335             :           end if
    5336             : 
    5337           0 :           mdimsize = tape(t)%hlist(fld)%field%enddim2 - tape(t)%hlist(fld)%field%begdim2 + 1
    5338           0 :           if (mdimsize == 0) then
    5339           0 :             mdimsize = tape(t)%hlist(fld)%field%numlev
    5340             :           end if
    5341           0 :           if (tape(t)%hlist(fld)%field%meridional_complement > 0) then
    5342           0 :             compind = tape(t)%hlist(fld)%field%meridional_complement
    5343           0 :             compid => tape(t)%hlist(compind)%varid(index)
    5344             :             ! We didn't call set frame on the meridional complement field
    5345           0 :             call pio_setframe(tape(t)%Files(f), compid, int(max(1,nfils(t)),kind=PIO_OFFSET_KIND))
    5346           0 :             call write_interpolated(tape(t)%Files(f), varid, compid,              &
    5347           0 :                  tape(t)%hlist(fld)%hbuf, tape(t)%hlist(compind)%hbuf,          &
    5348           0 :                  mdimsize, ncreal, fdecomp)
    5349           0 :           else if (tape(t)%hlist(fld)%field%zonal_complement <= 0) then
    5350             :             ! Scalar field
    5351           0 :             call write_interpolated(tape(t)%Files(f), varid,                      &
    5352           0 :                  tape(t)%hlist(fld)%hbuf, mdimsize, ncreal, fdecomp)
    5353             :           end if
    5354      537600 :         else if (nadims == 2) then
    5355             :           ! Special case for 2D field (no levels) due to hbuf structure
    5356      325632 :            if ((tape(t)%hlist(fld)%hwrt_prec == 4) .and. (.not. restart)) then
    5357           0 :               call tape(t)%hlist(fld)%field%get_bounds(3, begdim3, enddim3)
    5358           0 :               allocate(rtemp2(dimind%beg1:dimind%end1, begdim3:enddim3))
    5359           0 :               rtemp2 = 0.0_r4
    5360           0 :               do ind3 = begdim3, enddim3
    5361           0 :                  dimind2 = tape(t)%hlist(fld)%field%get_dims(ind3)
    5362           0 :                  rtemp2(dimind2%beg1:dimind2%end1,ind3) = &
    5363           0 :                       tape(t)%hlist(fld)%hbuf(dimind2%beg1:dimind2%end1, 1, ind3)
    5364             :               end do
    5365           0 :               call cam_grid_write_dist_array(tape(t)%Files(f), fdecomp,           &
    5366           0 :                    adims(1:nadims), fdims(1:frank), rtemp2, varid)
    5367           0 :               deallocate(rtemp2)
    5368             :            else
    5369      325632 :               call cam_grid_write_dist_array(tape(t)%Files(f), fdecomp,           &
    5370           0 :                    adims(1:nadims), fdims(1:frank),                           &
    5371      651264 :                    tape(t)%hlist(fld)%hbuf(:,1,:), varid)
    5372             :            end if
    5373             :         else
    5374      211968 :            if ((tape(t)%hlist(fld)%hwrt_prec == 4) .and. (.not. restart)) then
    5375           0 :               call tape(t)%hlist(fld)%field%get_bounds(3, begdim3, enddim3)
    5376           0 :               allocate(rtemp3(dimind%beg1:dimind%end1,                        &
    5377           0 :                    dimind%beg2:dimind%end2, begdim3:enddim3))
    5378           0 :               rtemp3 = 0.0_r4
    5379           0 :               do ind3 = begdim3, enddim3
    5380           0 :                  dimind2 = tape(t)%hlist(fld)%field%get_dims(ind3)
    5381           0 :                  rtemp3(dimind2%beg1:dimind2%end1, dimind2%beg2:dimind2%end2, &
    5382           0 :                       ind3) = tape(t)%hlist(fld)%hbuf(dimind2%beg1:dimind2%end1,&
    5383           0 :                       dimind2%beg2:dimind2%end2, ind3)
    5384             :               end do
    5385           0 :               call cam_grid_write_dist_array(tape(t)%Files(f), fdecomp, adims,    &
    5386           0 :                    fdims(1:frank), rtemp3, varid)
    5387           0 :               deallocate(rtemp3)
    5388             :            else
    5389      211968 :               call cam_grid_write_dist_array(tape(t)%Files(f), fdecomp, adims,    &
    5390           0 :                    fdims(1:frank),                                            &
    5391      423936 :                    tape(t)%hlist(fld)%hbuf, varid)
    5392             :            end if
    5393             :         end if
    5394             :       end if
    5395             :     end do
    5396             :     !! write accumulation counter and variance to hist restart file
    5397      537600 :     if(restart) then
    5398      537600 :        if (associated(tape(t)%hlist(fld)%sbuf) ) then
    5399             :            ! write variance data to restart file for standard deviation calc
    5400           0 :           if (nadims == 2) then
    5401             :            ! Special case for 2D field (no levels) due to sbuf structure
    5402           0 :              call cam_grid_write_dist_array(tape(t)%Files(f), fdecomp,        &
    5403           0 :                   adims(1:nadims), fdims(1:frank),                            &
    5404           0 :                   tape(t)%hlist(fld)%sbuf(:,1,:), tape(t)%hlist(fld)%sbuf_varid)
    5405             :           else
    5406           0 :              call cam_grid_write_dist_array(tape(t)%Files(f), fdecomp, adims, &
    5407           0 :                   fdims(1:frank), tape(t)%hlist(fld)%sbuf,                    &
    5408           0 :                   tape(t)%hlist(fld)%sbuf_varid)
    5409             :           endif
    5410             :        endif
    5411             :      !! NACS
    5412      537600 :        if (size(tape(t)%hlist(fld)%nacs, 1) > 1) then
    5413        7680 :           if (nadims > 2) then
    5414           0 :              adims(2) = adims(3)
    5415           0 :              nadims = 2
    5416             :           end if
    5417        7680 :           call cam_grid_dimensions(fdecomp, fdims(1:2), nacsrank)
    5418        7680 :           call cam_grid_write_dist_array(tape(t)%Files(f), fdecomp, &
    5419           0 :                adims(1:nadims), fdims(1:nacsrank), &
    5420       15360 :                tape(t)%hlist(fld)%nacs, tape(t)%hlist(fld)%nacs_varid)
    5421             :        else
    5422      529920 :           bdim3 = tape(t)%hlist(fld)%field%begdim3
    5423      529920 :           edim3 = tape(t)%hlist(fld)%field%enddim3
    5424      529920 :           ierr = pio_put_var(tape(t)%Files(f), tape(t)%hlist(fld)%nacs_varid,       &
    5425     1059840 :                tape(t)%hlist(fld)%nacs(:, bdim3:edim3))
    5426             :        end if
    5427             :     end if
    5428             : 
    5429      537600 :     return
    5430      537600 :   end subroutine dump_field
    5431             : 
    5432             :   !#######################################################################
    5433             : 
    5434      111864 :   logical function write_inithist ()
    5435             :     !
    5436             :     !-----------------------------------------------------------------------
    5437             :     !
    5438             :     ! Purpose: Set flags that will initiate dump to IC file when OUTFLD and
    5439             :     ! WSHIST are called
    5440             :     !
    5441             :     !-----------------------------------------------------------------------
    5442             :     !
    5443      537600 :     use time_manager, only: get_nstep, get_curr_date, get_step_size, is_last_step
    5444             :     !
    5445             :     ! Local workspace
    5446             :     !
    5447             :     integer :: yr, mon, day      ! year, month, and day components of
    5448             :     ! a date
    5449             :     integer :: nstep             ! current timestep number
    5450             :     integer :: ncsec             ! current time of day [seconds]
    5451             :     integer :: dtime             ! timestep size
    5452             : 
    5453             :     !-----------------------------------------------------------------------
    5454             : 
    5455      111864 :     write_inithist  = .false.
    5456             : 
    5457      111864 :     if(is_initfile()) then
    5458             : 
    5459      111864 :       nstep = get_nstep()
    5460      111864 :       call get_curr_date(yr, mon, day, ncsec)
    5461             : 
    5462      111864 :       if    (inithist == '6-HOURLY') then
    5463           0 :         dtime  = get_step_size()
    5464           0 :         write_inithist = nstep /= 0 .and. mod( nstep, nint((6._r8*3600._r8)/dtime) ) == 0
    5465      111864 :       elseif(inithist == 'DAILY'   ) then
    5466           0 :         write_inithist = nstep /= 0 .and. ncsec == 0
    5467      111864 :       elseif(inithist == 'MONTHLY' ) then
    5468           0 :         write_inithist = nstep /= 0 .and. ncsec == 0 .and. day == 1
    5469      111864 :       elseif(inithist == 'YEARLY'  ) then
    5470      111864 :         write_inithist = nstep /= 0 .and. ncsec == 0 .and. day == 1 .and. mon == 1
    5471           0 :       elseif(inithist == 'CAMIOP'  ) then
    5472           0 :         write_inithist = nstep == 0
    5473           0 :       elseif(inithist == 'ENDOFRUN'  ) then
    5474           0 :         write_inithist = nstep /= 0 .and. is_last_step()
    5475             :       end if
    5476             :     end if
    5477             : 
    5478             :     return
    5479      111864 :   end function write_inithist
    5480             : 
    5481             :   !#######################################################################
    5482             : 
    5483       16128 :   subroutine wshist (rgnht_in)
    5484             :     !
    5485             :     !-----------------------------------------------------------------------
    5486             :     !
    5487             :     ! Purpose: Driver routine to write fields on history tape t
    5488             :     !
    5489             :     !
    5490             :     !-----------------------------------------------------------------------
    5491      111864 :     use time_manager,  only: get_nstep, get_curr_date, get_curr_time, get_step_size
    5492             :     use time_manager,  only: set_date_from_time_float
    5493             :     use chem_surfvals, only: chem_surfvals_get, chem_surfvals_co2_rad
    5494             :     use solar_irrad_data, only: sol_tsi
    5495             :     use sat_hist,      only: sat_hist_write
    5496             :     use interp_mod,    only: set_interp_hfile
    5497             :     use datetime_mod,  only: datetime
    5498             :     use cam_pio_utils, only: cam_pio_closefile
    5499             : 
    5500             :     logical, intent(in), optional :: rgnht_in(ptapes)
    5501             :     !
    5502             :     ! Local workspace
    5503             :     !
    5504             :     character(len=8) :: cdate  ! system date
    5505             :     character(len=8) :: ctime  ! system time
    5506             : 
    5507             :     logical  :: rgnht(ptapes), restart
    5508             :     integer t, f, fld          ! tape, file, field indices
    5509             :     integer start              ! starting index required by nf_put_vara
    5510             :     integer count1             ! count values required by nf_put_vara
    5511             :     integer startc(2)          ! start values required by nf_put_vara (character)
    5512             :     integer countc(2)          ! count values required by nf_put_vara (character)
    5513             : #ifdef HDEBUG
    5514             :     !      integer begdim3
    5515             :     !      integer enddim3
    5516             : #endif
    5517             : 
    5518             :     integer :: yr, mon, day      ! year, month, and day components of a date
    5519             :     integer :: yr_mid, mon_mid, day_mid ! year, month, and day components of midpoint date
    5520             :     integer :: nstep             ! current timestep number
    5521             :     integer :: ncdate(maxsplitfiles) ! current (or midpoint) date in integer format [yyyymmdd]
    5522             :     integer :: ncsec(maxsplitfiles)  ! current (or midpoint) time of day [seconds]
    5523             :     integer :: ndcur             ! day component of current time
    5524             :     integer :: nscur             ! seconds component of current time
    5525             :     real(r8) :: time             ! current (or midpoint) time
    5526             :     real(r8) :: tdata(2)         ! time interval boundaries
    5527             :     character(len=max_string_len) :: fname ! Filename
    5528             :     character(len=max_string_len) :: fname_inst ! Filename for instantaneous tape
    5529             :     character(len=max_string_len) :: fname_acc ! Filename for accumulated tape
    5530             :     logical :: prev              ! Label file with previous date rather than current
    5531             :     logical :: duplicate         ! Flag for duplicate file name
    5532             :     integer :: ierr
    5533             : #if ( defined BFB_CAM_SCAM_IOP )
    5534             :     integer :: tsec             ! day component of current time
    5535             :     integer :: dtime            ! seconds component of current time
    5536             : #endif
    5537       16128 :     if(present(rgnht_in)) then
    5538        1536 :       rgnht=rgnht_in
    5539        1536 :       restart=.true.
    5540        1536 :       tape => restarthistory_tape
    5541             :     else
    5542       14592 :       rgnht=.false.
    5543       14592 :       restart=.false.
    5544       14592 :       tape => history_tape
    5545             :     end if
    5546             : 
    5547       16128 :     nstep = get_nstep()
    5548       16128 :     call get_curr_date(yr, mon, day, ncsec(instantaneous_file_index))
    5549       16128 :     ncdate(instantaneous_file_index) = yr*10000 + mon*100 + day
    5550       16128 :     call get_curr_time(ndcur, nscur)
    5551             :     !
    5552             :     ! Write time-varying portion of history file header
    5553             :     !
    5554      209664 :     do t=1,ptapes
    5555      193536 :       if (nflds(t) == 0 .or. (restart .and.(.not.rgnht(t)))) cycle
    5556             :       !
    5557             :       ! Check if this is the IC file and if it's time to write.
    5558             :       ! Else, use "nhtfrq" to determine if it's time to write
    5559             :       ! the other history files.
    5560             :       !
    5561       30720 :       if((.not. restart) .or. rgnht(t)) then
    5562       30720 :         if( is_initfile(file_index=t) ) then
    5563       14592 :           hstwr(t) =  write_inithist()
    5564       14592 :           prev     = .false.
    5565             :         else
    5566       16128 :           if (nhtfrq(t) == 0) then
    5567       16128 :             hstwr(t) = nstep /= 0 .and. day == 1 .and. ncsec(instantaneous_file_index) == 0
    5568       16128 :             prev     = .true.
    5569             :           else
    5570           0 :             if (nstep == 0) then
    5571           0 :               if (write_nstep0) then
    5572           0 :                 hstwr(t) = .true.
    5573             :               else
    5574             :                 ! zero the buffers if nstep==0 data not written
    5575           0 :                 do f = 1, nflds(t)
    5576           0 :                   call h_zero(f, t)
    5577             :                 end do
    5578             :               end if
    5579             :             else
    5580           0 :               hstwr(t) = mod(nstep,nhtfrq(t)) == 0
    5581             :             endif
    5582           0 :             prev = .false.
    5583             :            end if
    5584             :         end if
    5585             :       end if
    5586             : 
    5587       30720 :       time = ndcur + nscur/86400._r8
    5588       30720 :       if (is_initfile(file_index=t)) then
    5589       43776 :         tdata = time   ! Inithist file is always instantanious data
    5590             :       else
    5591       16128 :         tdata(1) = beg_time(t)
    5592       16128 :         tdata(2) = time
    5593             :       end if
    5594             : 
    5595             :       ! Set midpoint date/datesec for accumulated file
    5596             :       call set_date_from_time_float((tdata(1) + tdata(2)) / 2._r8, &
    5597       30720 :          yr_mid, mon_mid, day_mid, ncsec(accumulated_file_index) )
    5598       30720 :       ncdate(accumulated_file_index) = yr_mid*10000 + mon_mid*100 + day_mid
    5599             : 
    5600       46848 :       if (hstwr(t) .or. (restart .and. rgnht(t))) then
    5601        1536 :         if(masterproc) then
    5602           2 :           if(is_initfile(file_index=t)) then
    5603           0 :             write(iulog,100) yr,mon,day,ncsec(init_file_index)
    5604             : 100         format('WSHIST: writing time sample to Initial Conditions h-file', &
    5605             :                  ' DATE=',i4.4,'/',i2.2,'/',i2.2,' NCSEC=',i6)
    5606           2 :           else if(is_satfile(t)) then
    5607           0 :             write(iulog,150) nfils(t),t,yr,mon,day,ncsec(sat_file_index)
    5608             : 150         format('WSHIST: writing sat columns ',i6,' to h-file ', &
    5609             :                  i1,' DATE=',i4.4,'/',i2.2,'/',i2.2,' NCSEC=',i6)
    5610           2 :           else if(hstwr(t)) then
    5611           0 :             do f = 1, maxsplitfiles
    5612           0 :               if (f == instantaneous_file_index) then
    5613           0 :                 write(iulog,200) nfils(t),'instantaneous',t,yr,mon,day,ncsec(f)
    5614             :               else
    5615           0 :                 write(iulog,200) nfils(t),'accumulated',t,yr_mid,mon_mid,day_mid,ncsec(f)
    5616             :               end if
    5617             : 200           format('WSHIST: writing time sample ',i3,' to ', a, ' h-file ', &
    5618             :                    i1,' DATE=',i4.4,'/',i2.2,'/',i2.2,' NCSEC=',i6)
    5619             :             end do
    5620           2 :           else if(restart .and. rgnht(t)) then
    5621           2 :             write(iulog,300) nfils(t),t,yr,mon,day,ncsec(restart_file_index)
    5622             : 300         format('WSHIST: writing history restart ',i3,' to hr-file ', &
    5623             :                  i1,' DATE=',i4.4,'/',i2.2,'/',i2.2,' NCSEC=',i6)
    5624             :           end if
    5625           2 :           write(iulog,*)
    5626             :         end if
    5627             :         !
    5628             :         ! Starting a new volume => define the metadata
    5629             :         !
    5630        1536 :         fname = ''
    5631        1536 :         fname_acc = ''
    5632        1536 :         fname_inst = ''
    5633        1536 :         if (nfils(t)==0 .or. (restart.and.rgnht(t))) then
    5634        1536 :           if(restart) then
    5635        1536 :             rhfilename_spec = '%c.cam' // trim(inst_suffix) // '.rh%t.%y-%m-%d-%s.nc'
    5636        1536 :             fname = interpret_filename_spec( rhfilename_spec, number=(t-1))
    5637        1536 :             hrestpath(t)=fname
    5638           0 :           else if(is_initfile(file_index=t)) then
    5639           0 :             fname = interpret_filename_spec( hfilename_spec(t) )
    5640             :           else
    5641             :             fname_acc = interpret_filename_spec( hfilename_spec(t), number=(t-1), &
    5642           0 :                  prev=prev, flag_spec='a' )
    5643           0 :             fname_inst = interpret_filename_spec( hfilename_spec(t), number=(t-1), &
    5644           0 :                  prev=prev, flag_spec='i' )
    5645             :           end if
    5646             :           !
    5647             :           ! Check that this new filename isn't the same as a previous or current filename
    5648             :           !
    5649        1536 :           duplicate = .false.
    5650        3072 :           do f = 1, t
    5651        3072 :             if (masterproc)then
    5652           2 :               if (trim(fname) == trim(nhfil(f,1)) .and. trim(fname) /= '') then
    5653           0 :                  write(iulog,*)'WSHIST: New filename same as old file = ', trim(fname)
    5654             :                  duplicate = .true.
    5655           2 :               else if (trim(fname_acc) == trim(nhfil(f,accumulated_file_index)) .and. trim(fname_acc) /= '') then
    5656           0 :                  write(iulog,*)'WSHIST: New accumulated filename same as old file = ', trim(fname_acc)
    5657             :                  duplicate = .true.
    5658           2 :               else if (trim(fname_inst) == trim(nhfil(f,instantaneous_file_index)) .and. trim(fname_inst) /= '') then
    5659           0 :                  write(iulog,*)'WSHIST: New instantaneous filename same as old file = ', trim(fname_inst)
    5660             :                  duplicate = .true.
    5661             :               end if
    5662           2 :               if (duplicate) then
    5663           0 :                  write(iulog,*)'Is there an error in your filename specifiers?'
    5664           0 :                  write(iulog,*)'hfilename_spec(', t, ') = ', trim(hfilename_spec(t))
    5665           0 :                  if ( t /= f )then
    5666           0 :                    write(iulog,*)'hfilename_spec(', f, ') = ', trim(hfilename_spec(f))
    5667             :                  end if
    5668           0 :                  call endrun('WSHIST: ERROR - see atm log file for information')
    5669             :               end if
    5670             :             end if
    5671             :           end do
    5672        1536 :           if(.not. restart) then
    5673           0 :             if (is_initfile(file_index=t)) then
    5674           0 :                nhfil(t,:) = fname
    5675           0 :                if(masterproc) then
    5676           0 :                   write(iulog,*)'WSHIST: initfile nhfil(',t,')=',trim(nhfil(t,init_file_index))
    5677             :                end if
    5678             :             else
    5679           0 :                nhfil(t,accumulated_file_index) = fname_acc
    5680           0 :                nhfil(t,instantaneous_file_index) = fname_inst
    5681           0 :                if(masterproc) then
    5682           0 :                   write(iulog,*)'WSHIST: accumulated nhfil(',t,')=',trim(nhfil(t,accumulated_file_index))
    5683           0 :                   write(iulog,*)'WSHIST: instantaneous nhfil(',t,')=',trim(nhfil(t,instantaneous_file_index))
    5684             :                end if
    5685             :             end if
    5686           0 :             cpath(t,:) = nhfil(t,:)
    5687           0 :             if ( len_trim(nfpath(t)) == 0 ) nfpath(t) = cpath(t, 1)
    5688             :           end if
    5689        1536 :           call h_define (t, restart)
    5690             :         end if
    5691             : 
    5692        1536 :         if(is_satfile(t)) then
    5693           0 :           call sat_hist_write( tape(t), nflds(t), nfils(t))
    5694             :         else
    5695        1536 :           if(restart) then
    5696             :             start=1
    5697             :           else
    5698           0 :             nfils(t) = nfils(t) + 1
    5699             :             start = nfils(t)
    5700             :           end if
    5701        1536 :           count1 = 1
    5702             :           ! Setup interpolation data if history file is interpolated
    5703        1536 :           if (interpolate_output(t) .and. (.not. restart)) then
    5704           0 :             call set_interp_hfile(t, interpolate_info)
    5705             :           end if
    5706        6144 :           ierr = pio_put_var (tape(t)%Files(instantaneous_file_index),tape(t)%ndcurid,(/start/),(/count1/),(/ndcur/))
    5707        6144 :           ierr = pio_put_var (tape(t)%Files(instantaneous_file_index), tape(t)%nscurid,(/start/),(/count1/),(/nscur/))
    5708        4608 :           do f = 1, maxsplitfiles
    5709        4608 :              if (pio_file_is_open(tape(t)%Files(f))) then
    5710        6144 :                 ierr = pio_put_var (tape(t)%Files(f), tape(t)%dateid,(/start/),(/count1/),(/ncdate(f)/))
    5711             :              end if
    5712             :           end do
    5713             : 
    5714        4608 :           do f = 1, maxsplitfiles
    5715        4608 :             if (.not. is_initfile(file_index=t) .and. f == instantaneous_file_index) then
    5716             :               ! Don't write the GHG/Solar forcing data to the IC file.
    5717             :               ! Only write GHG/Solar forcing data to the instantaneous file
    5718        6144 :               ierr=pio_put_var (tape(t)%Files(f), tape(t)%co2vmrid,(/start/), (/count1/),(/chem_surfvals_co2_rad(vmr_in=.true.)/))
    5719        6144 :               ierr=pio_put_var (tape(t)%Files(f), tape(t)%ch4vmrid,(/start/), (/count1/),(/chem_surfvals_get('CH4VMR')/))
    5720        6144 :               ierr=pio_put_var (tape(t)%Files(f), tape(t)%n2ovmrid,(/start/), (/count1/),(/chem_surfvals_get('N2OVMR')/))
    5721        6144 :               ierr=pio_put_var (tape(t)%Files(f), tape(t)%f11vmrid,(/start/), (/count1/),(/chem_surfvals_get('F11VMR')/))
    5722        6144 :               ierr=pio_put_var (tape(t)%Files(f), tape(t)%f12vmrid,(/start/), (/count1/),(/chem_surfvals_get('F12VMR')/))
    5723        6144 :               ierr=pio_put_var (tape(t)%Files(f), tape(t)%sol_tsiid,(/start/), (/count1/),(/sol_tsi/))
    5724             : 
    5725        1536 :               if (solar_parms_on) then
    5726           0 :                 ierr=pio_put_var (tape(t)%Files(f), tape(t)%f107id, (/start/), (/count1/),(/ f107 /) )
    5727           0 :                 ierr=pio_put_var (tape(t)%Files(f), tape(t)%f107aid,(/start/), (/count1/),(/ f107a /) )
    5728           0 :                 ierr=pio_put_var (tape(t)%Files(f), tape(t)%f107pid,(/start/), (/count1/),(/ f107p /) )
    5729           0 :                 ierr=pio_put_var (tape(t)%Files(f), tape(t)%kpid,   (/start/), (/count1/),(/ kp /) )
    5730           0 :                 ierr=pio_put_var (tape(t)%Files(f), tape(t)%apid,   (/start/), (/count1/),(/ ap /) )
    5731             :               endif
    5732        1536 :               if (solar_wind_on) then
    5733           0 :                 ierr=pio_put_var (tape(t)%Files(f), tape(t)%byimfid, (/start/), (/count1/),(/ byimf /) )
    5734           0 :                 ierr=pio_put_var (tape(t)%Files(f), tape(t)%bzimfid, (/start/), (/count1/),(/ bzimf /) )
    5735           0 :                 ierr=pio_put_var (tape(t)%Files(f), tape(t)%swvelid, (/start/), (/count1/),(/ swvel /) )
    5736           0 :                 ierr=pio_put_var (tape(t)%Files(f), tape(t)%swdenid, (/start/), (/count1/),(/ swden /) )
    5737             :               endif
    5738        1536 :               if (epot_active) then
    5739           0 :                 ierr=pio_put_var (tape(t)%Files(f), tape(t)%colat_crit1_id, (/start/), (/count1/),(/ epot_crit_colats(1) /) )
    5740           0 :                 ierr=pio_put_var (tape(t)%Files(f), tape(t)%colat_crit2_id, (/start/), (/count1/),(/ epot_crit_colats(2) /) )
    5741             :               endif
    5742             :             end if
    5743             :           end do
    5744        4608 :           do f = 1, maxsplitfiles
    5745        4608 :              if (pio_file_is_open(tape(t)%Files(f))) then
    5746        6144 :                 ierr = pio_put_var (tape(t)%Files(f),tape(t)%datesecid,(/start/),(/count1/),(/ncsec(f)/))
    5747             :              end if
    5748             :           end do
    5749             : #if ( defined BFB_CAM_SCAM_IOP )
    5750             :           dtime = get_step_size()
    5751             :           tsec=dtime*nstep
    5752             :           do f = 1, maxsplitfiles
    5753             :              if (pio_file_is_open(tape(t)%Files(f))) then
    5754             :                 ierr = pio_put_var (tape(t)%Files(f),tape(t)%tsecid,(/start/),(/count1/),(/tsec/))
    5755             :              end if
    5756             :           end do
    5757             : #endif
    5758        6144 :           ierr = pio_put_var (tape(t)%Files(instantaneous_file_index),tape(t)%nstephid,(/start/),(/count1/),(/nstep/))
    5759        1536 :           startc(1) = 1
    5760        1536 :           startc(2) = start
    5761        1536 :           countc(1) = 2
    5762        1536 :           countc(2) = 1
    5763        4608 :           do f = 1, maxsplitfiles
    5764        3072 :              if (.not. pio_file_is_open(tape(t)%Files(f))) then
    5765             :                 cycle
    5766             :              end if
    5767             :              ! We have two files - one for accumulated and one for instantaneous fields
    5768        1536 :              if (f == accumulated_file_index .and. .not. restart .and. .not. is_initfile(t)) then
    5769             :                 ! accumulated tape - time is midpoint of time_bounds
    5770           0 :                 ierr=pio_put_var (tape(t)%Files(f), tape(t)%timeid, (/start/),(/count1/),(/(tdata(1) + tdata(2)) / 2._r8/))
    5771             :              else
    5772             :                 ! not an accumulated history tape - time is current time
    5773        6144 :                 ierr=pio_put_var (tape(t)%Files(f), tape(t)%timeid, (/start/),(/count1/),(/time/))
    5774             :              end if
    5775        4608 :              ierr=pio_put_var (tape(t)%Files(f), tape(t)%tbndid, startc, countc, tdata)
    5776             :           end do
    5777        1536 :           if(.not.restart) beg_time(t) = time  ! update beginning time of next interval
    5778        1536 :           startc(1) = 1
    5779        1536 :           startc(2) = start
    5780        1536 :           countc(1) = 8
    5781        1536 :           countc(2) = 1
    5782        1536 :           call datetime (cdate, ctime)
    5783        4608 :           do f = 1, maxsplitfiles
    5784        4608 :              if (pio_file_is_open(tape(t)%Files(f))) then
    5785        3072 :                 ierr = pio_put_var (tape(t)%Files(f), tape(t)%date_writtenid, startc, countc, (/cdate/))
    5786        3072 :                 ierr = pio_put_var (tape(t)%Files(f), tape(t)%time_writtenid, startc, countc, (/ctime/))
    5787             :              end if
    5788             :           end do
    5789             : 
    5790        1536 :           if(.not. restart) then
    5791             :              !$OMP PARALLEL DO PRIVATE (FLD)
    5792           0 :              do fld=1,nflds(t)
    5793             :                 ! Normalize all non composed fields, composed fields are calculated next using the normalized components
    5794           0 :                 if (tape(t)%hlist(fld)%avgflag /= 'I'.and..not.tape(t)%hlist(fld)%field%is_composed()) then
    5795           0 :                    call h_normalize (fld, t)
    5796             :                 end if
    5797             :              end do
    5798             :           end if
    5799             : 
    5800        1536 :           if(.not. restart) then
    5801             :              !$OMP PARALLEL DO PRIVATE (FLD)
    5802           0 :              do fld=1,nflds(t)
    5803             :                 ! calculate composed fields from normalized components
    5804           0 :                 if (tape(t)%hlist(fld)%field%is_composed()) then
    5805           0 :                    call h_field_op (fld, t)
    5806             :                 end if
    5807             :              end do
    5808             :           end if
    5809             :           !
    5810             :           ! Write field to history tape.  Note that this is NOT threaded due to netcdf limitations
    5811             :           !
    5812        1536 :           call t_startf ('dump_field')
    5813      539136 :           do fld=1,nflds(t)
    5814     1614336 :             do f = 1, maxsplitfiles
    5815     1075200 :                if (.not. pio_file_is_open(tape(t)%Files(f))) then
    5816             :                   cycle
    5817             :                end if
    5818             :                ! we may have a history split, conditionally skip fields that are for the other file
    5819      537600 :                if ((tape(t)%hlist(fld)%avgflag .eq. 'I') .and. f == accumulated_file_index .and. .not. restart) then
    5820             :                   cycle
    5821      537600 :                else if ((tape(t)%hlist(fld)%avgflag .ne. 'I') .and. f == instantaneous_file_index .and. .not. restart) then
    5822             :                   cycle
    5823             :                end if
    5824     1612800 :                call dump_field(fld, t, f, restart)
    5825             :             end do
    5826             :           end do
    5827        1536 :           call t_stopf ('dump_field')
    5828             :           !
    5829             :           ! Calculate globals
    5830             :           !
    5831      539136 :           do fld=1,nflds(t)
    5832      539136 :              call h_global(fld, t)
    5833             :           end do
    5834             :           !
    5835             :           ! Zero history buffers and accumulators now that the fields have been written.
    5836             :           !
    5837        1536 :           if(restart) then
    5838      539136 :             do fld=1,nflds(t)
    5839      539136 :               if(associated(tape(t)%hlist(fld)%varid)) then
    5840      537600 :                 deallocate(tape(t)%hlist(fld)%varid)
    5841      537600 :                 nullify(tape(t)%hlist(fld)%varid)
    5842             :               end if
    5843             :             end do
    5844        1536 :             call cam_pio_closefile(tape(t)%Files(restart_file_index))
    5845             :           else
    5846             :             !$OMP PARALLEL DO PRIVATE (FLD)
    5847           0 :             do fld=1,nflds(t)
    5848           0 :               call h_zero (fld, t)
    5849             :             end do
    5850             :           end if
    5851             :         end if
    5852             :       end if
    5853             : 
    5854             :     end do
    5855             : 
    5856       16128 :     return
    5857       16128 :   end subroutine wshist
    5858             : 
    5859             :   !#######################################################################
    5860             : 
    5861           0 :   subroutine addfld_1d(fname, vdim_name, avgflag, units, long_name,           &
    5862             :        gridname, flag_xyfill, sampling_seq, standard_name, fill_value,        &
    5863             :        optype, op_f1name, op_f2name)
    5864             : 
    5865             :     !
    5866             :     !-----------------------------------------------------------------------
    5867             :     !
    5868             :     ! Purpose: Add a field to the master field list
    5869             :     !
    5870             :     ! Method: Put input arguments of field name, units, number of levels,
    5871             :     !         averaging flag, and long name into a type entry in the global
    5872             :     !         master field list (masterlist).
    5873             :     !
    5874             :     !-----------------------------------------------------------------------
    5875             : 
    5876             :     !
    5877             :     ! Arguments
    5878             :     !
    5879             :     character(len=*), intent(in)  :: fname      ! field name (max_fieldname_len)
    5880             :     character(len=*), intent(in)  :: vdim_name  ! NetCDF dimension name (or scalar coordinate)
    5881             :     character(len=1), intent(in)  :: avgflag    ! averaging flag
    5882             :     character(len=*), intent(in)  :: units      ! units of fname (max_chars)
    5883             :     character(len=*), intent(in)  :: long_name  ! long name of field (max_chars)
    5884             : 
    5885             :     character(len=*), intent(in), optional :: gridname    ! decomposition type
    5886             :     logical, intent(in), optional :: flag_xyfill ! non-applicable xy points flagged with fillvalue
    5887             :     character(len=*), intent(in), optional :: sampling_seq ! sampling sequence - if not every timestep,
    5888             :     ! how often field is sampled:
    5889             :     ! every other; only during LW/SW radiation calcs, etc.
    5890             :     character(len=*), intent(in), optional :: standard_name  ! CF standard name (max_chars)
    5891             :     real(r8),         intent(in), optional :: fill_value
    5892             :     character(len=*), intent(in), optional :: optype       ! currently 'dif' or 'sum' is supported
    5893             :     character(len=*), intent(in), optional :: op_f1name    ! first field to be operated on
    5894             :     character(len=*), intent(in), optional :: op_f2name    ! second field which is subtracted from or added to first field
    5895             :     !
    5896             :     ! Local workspace
    5897             :     !
    5898     1907712 :     character(len=max_chars), allocatable :: dimnames(:)
    5899             :     integer                               :: index
    5900             : 
    5901     1907712 :     if (trim(vdim_name) == trim(horiz_only)) then
    5902     1907712 :       allocate(dimnames(0))
    5903             :     else
    5904           0 :       index = get_hist_coord_index(trim(vdim_name))
    5905           0 :       if (index < 1) then
    5906           0 :         call endrun('ADDFLD: Invalid coordinate, '//trim(vdim_name))
    5907             :       end if
    5908           0 :       allocate(dimnames(1))
    5909           0 :       dimnames(1) = trim(vdim_name)
    5910             :     end if
    5911             :     call addfld(fname, dimnames, avgflag, units, long_name, gridname,         &
    5912             :          flag_xyfill, sampling_seq, standard_name, fill_value, optype, op_f1name, &
    5913    13271040 :          op_f2name)
    5914             : 
    5915     1923840 :   end subroutine addfld_1d
    5916             : 
    5917     4495872 :   subroutine addfld_nd(fname, dimnames, avgflag, units, long_name,            &
    5918             :        gridname, flag_xyfill, sampling_seq, standard_name, fill_value, optype,    &
    5919             :        op_f1name, op_f2name)
    5920             : 
    5921             :     !
    5922             :     !-----------------------------------------------------------------------
    5923             :     !
    5924             :     ! Purpose: Add a field to the master field list
    5925             :     !
    5926             :     ! Method: Put input arguments of field name, units, number of levels,
    5927             :     !         averaging flag, and long name into a type entry in the global
    5928             :     !         master field list (masterlist).
    5929             :     !
    5930             :     !-----------------------------------------------------------------------
    5931             :     use cam_history_support, only: fillvalue, hist_coord_find_levels
    5932             :     use cam_grid_support,    only: cam_grid_id, cam_grid_is_zonal
    5933             :     use cam_grid_support,    only: cam_grid_get_coord_names
    5934             :     use constituents,        only: cnst_get_ind, cnst_get_type_byind
    5935             : 
    5936             :     !
    5937             :     ! Arguments
    5938             :     !
    5939             :     character(len=*), intent(in)  :: fname      ! field name (max_fieldname_len)
    5940             :     character(len=*), intent(in)  :: dimnames(:) ! NetCDF dimension names (except grid dims)
    5941             :     character(len=1), intent(in)  :: avgflag    ! averaging flag
    5942             :     character(len=*), intent(in)  :: units      ! units of fname (max_chars)
    5943             :     character(len=*), intent(in)  :: long_name  ! long name of field (max_chars)
    5944             : 
    5945             :     character(len=*), intent(in), optional :: gridname    ! decomposition type
    5946             :     logical, intent(in), optional :: flag_xyfill ! non-applicable xy points flagged with fillvalue
    5947             :     character(len=*), intent(in), optional :: sampling_seq ! sampling sequence - if not every timestep,
    5948             :     ! how often field is sampled:
    5949             :     ! every other; only during LW/SW radiation calcs, etc.
    5950             :     character(len=*), intent(in), optional :: standard_name  ! CF standard name (max_chars)
    5951             :     real(r8),         intent(in), optional :: fill_value
    5952             :     character(len=*), intent(in), optional :: optype       ! currently 'dif' or 'sum' supported
    5953             :     character(len=*), intent(in), optional :: op_f1name    ! first field to be operated on
    5954             :     character(len=*), intent(in), optional :: op_f2name    ! second field which is subtracted from or added to first field
    5955             : 
    5956             :     !
    5957             :     ! Local workspace
    5958             :     !
    5959             :     character(len=max_fieldname_len) :: fname_tmp ! local copy of fname
    5960             :     character(len=max_fieldname_len) :: coord_name ! for cell_methods
    5961             :     character(len=128)               :: errormsg
    5962             :     character(len=3)                 :: mixing_ratio
    5963             :     type(master_entry), pointer      :: listentry
    5964             :     type(master_entry), pointer      :: f1listentry,f2listentry
    5965             : 
    5966             :     integer :: dimcnt
    5967             :     integer :: idx
    5968             : 
    5969             :     character(len=*), parameter      :: subname='ADDFLD_ND'
    5970             : 
    5971     4495872 :     if (htapes_defined) then
    5972           0 :       call endrun ('ADDFLD: Attempt to add field '//trim(fname)//' after history files set')
    5973             :     end if
    5974             : 
    5975             :     !
    5976             :     ! Ensure that new field name is not all blanks
    5977             :     !
    5978     4495872 :     if (len_trim(fname)==0) then
    5979           0 :       call endrun('ADDFLD: blank field name not allowed')
    5980             :     end if
    5981             :     !
    5982             :     ! Ensure that new field name is not longer than allowed
    5983             :     ! (strip "&IC" suffix if it exists)
    5984             :     !
    5985     4495872 :     fname_tmp  = fname
    5986     4495872 :     fname_tmp  = strip_suffix(fname_tmp)
    5987             : 
    5988     4495872 :     if (len_trim(fname_tmp) > fieldname_len) then
    5989           0 :       write(iulog,*)'ADDFLD: field name cannot be longer than ',fieldname_len,' characters long'
    5990           0 :       write(iulog,*)'Field name:  ',fname
    5991           0 :       write(errormsg, *) 'Field name, "', trim(fname), '" is too long'
    5992           0 :       call endrun('ADDFLD: '//trim(errormsg))
    5993             :     end if
    5994             :     !
    5995             :     ! Ensure that new field doesn't already exist
    5996             :     !
    5997     4495872 :     listentry => get_entry_by_name(masterlinkedlist, fname)
    5998     4495872 :     if(associated(listentry)) then
    5999           0 :       call endrun ('ADDFLD:  '//fname//' already on list')
    6000             :     end if
    6001             : 
    6002             :     ! If the field is an advected constituent determine whether its concentration
    6003             :     ! is based on dry or wet air.
    6004     4495872 :     call cnst_get_ind(fname_tmp, idx, abort=.false.)
    6005     4495872 :     mixing_ratio = ''
    6006     4495872 :     if (idx > 0) then
    6007      125952 :        mixing_ratio = cnst_get_type_byind(idx)
    6008             :     end if
    6009             : 
    6010             :     ! Add field to Master Field List arrays fieldn and iflds
    6011             :     !
    6012     4495872 :     allocate(listentry)
    6013     4495872 :     listentry%field%name         = fname
    6014     4495872 :     listentry%field%long_name    = long_name
    6015     4495872 :     listentry%field%numlev       = 1        ! Will change if lev or ilev in shape
    6016     4495872 :     listentry%field%units        = units
    6017     4495872 :     listentry%field%mixing_ratio = mixing_ratio
    6018     4495872 :     listentry%field%meridional_complement = -1
    6019     4495872 :     listentry%field%zonal_complement      = -1
    6020     4495872 :     listentry%field%field_op  = ''
    6021     4495872 :     listentry%field%op_field1_id  = -1
    6022     4495872 :     listentry%field%op_field2_id  = -1
    6023     4495872 :     listentry%op_field1  = ''
    6024     4495872 :     listentry%op_field2  = ''
    6025    58446336 :     listentry%htapeindx(:) = -1
    6026     4495872 :     listentry%act_sometape = .false.
    6027    58446336 :     listentry%actflag(:) = .false.
    6028             : 
    6029             :     ! Make sure we have a valid gridname
    6030     4495872 :     if (present(gridname)) then
    6031      317952 :       listentry%field%decomp_type = cam_grid_id(trim(gridname))
    6032             :     else
    6033     4177920 :       listentry%field%decomp_type = cam_grid_id('physgrid')
    6034             :     end if
    6035     4495872 :     if (listentry%field%decomp_type < 0) then
    6036           0 :       write(errormsg, *) 'Invalid grid name, "', trim(gridname), '" for ',    &
    6037           0 :            trim(fname)
    6038           0 :       call endrun('ADDFLD: '//trim(errormsg))
    6039             :     end if
    6040             : 
    6041             :     !
    6042             :     ! Indicate sampling sequence of field (i.e., how often "outfld" is called)
    6043             :     ! If not every timestep (default), then give a descriptor indicating the
    6044             :     ! sampling pattern.  Currently, the only valid value is "rad_lwsw" for sampling
    6045             :     ! during LW/SW radiation timesteps only
    6046             :     !
    6047     4495872 :     if (present(sampling_seq)) then
    6048       92160 :       listentry%field%sampling_seq = sampling_seq
    6049             :     else
    6050     4403712 :       listentry%field%sampling_seq = ' '
    6051             :     end if
    6052             :     ! Indicate if some field pre-processing occurred (e.g., zonal mean)
    6053     4495872 :     if (cam_grid_is_zonal(listentry%field%decomp_type)) then
    6054           0 :       call cam_grid_get_coord_names(listentry%field%decomp_type, coord_name, errormsg)
    6055             :       ! Zonal method currently hardcoded to 'mean'.
    6056           0 :       listentry%field%cell_methods = trim(coord_name)//': mean'
    6057             :     else
    6058     4495872 :       listentry%field%cell_methods = ''
    6059             :     end if
    6060             :     !
    6061             :     ! Whether to apply xy fillvalue: default is false
    6062             :     !
    6063     4495872 :     if (present(flag_xyfill)) then
    6064      155136 :       listentry%field%flag_xyfill = flag_xyfill
    6065             :     else
    6066     4340736 :       listentry%field%flag_xyfill = .false.
    6067             :     end if
    6068             : 
    6069             :     !
    6070             :     !    Allow external packages to have fillvalues different than default
    6071             :     !
    6072             : 
    6073     4495872 :     if(present(fill_value)) then
    6074        1536 :       listentry%field%fillvalue = fill_value
    6075             :     else
    6076     4494336 :       listentry%field%fillvalue = fillvalue
    6077             :     endif
    6078             : 
    6079             :     !
    6080             :     ! Process shape
    6081             :     !
    6082             : 
    6083     4495872 :     if (associated(listentry%field%mdims)) then
    6084           0 :       deallocate(listentry%field%mdims)
    6085             :     end if
    6086     4495872 :     nullify(listentry%field%mdims)
    6087     4495872 :     dimcnt = size(dimnames)
    6088    11579904 :     allocate(listentry%field%mdims(dimcnt))
    6089     4495872 :     call lookup_hist_coord_indices(dimnames, listentry%field%mdims)
    6090     4495872 :     if(dimcnt > maxvarmdims) then
    6091           0 :       maxvarmdims = dimcnt
    6092             :     end if
    6093             :     ! Check for subcols (currently limited to first dimension)
    6094     4495872 :     listentry%field%is_subcol = .false.
    6095     4495872 :     if (size(dimnames) > 0) then
    6096     2588160 :       if (trim(dimnames(1)) == 'psubcols') then
    6097           0 :         if (listentry%field%decomp_type /= cam_grid_id('physgrid')) then
    6098           0 :           write(errormsg, *) "Cannot add ", trim(fname),                      &
    6099           0 :                "Subcolumn history output only allowed on physgrid"
    6100           0 :           call endrun("ADDFLD: "//errormsg)
    6101             :         end if
    6102           0 :         listentry%field%is_subcol = .true.
    6103             :       end if
    6104             :     end if
    6105             :     ! Levels
    6106     4495872 :     listentry%field%numlev = hist_coord_find_levels(dimnames)
    6107     4495872 :     if (listentry%field%numlev <= 0) then
    6108     1907712 :       listentry%field%numlev = 1
    6109             :     end if
    6110             : 
    6111             :     !
    6112             :     ! Dimension history info based on decomposition type (grid)
    6113             :     !
    6114     4495872 :     call set_field_dimensions(listentry%field)
    6115             : 
    6116             :     !
    6117             :     ! These 2 fields are used only in master field list, not runtime field list
    6118             :     !
    6119    58446336 :     listentry%avgflag(:) = avgflag
    6120    58446336 :     listentry%actflag(:) = .false.
    6121             : 
    6122    58446336 :     do dimcnt = 1, ptapes
    6123    58446336 :       call AvgflagToString(avgflag, listentry%time_op(dimcnt))
    6124             :     end do
    6125             : 
    6126     4495872 :     if (present(optype)) then
    6127             :        ! make sure optype is "sum" or "dif"
    6128           0 :        if (.not.(trim(optype) == 'dif' .or. trim(optype) == 'sum')) then
    6129           0 :           write(errormsg, '(2a)')': Fatal : optype must be "sum" or "dif" not ',trim(optype)
    6130           0 :           call endrun (trim(subname)//errormsg)
    6131             :        end if
    6132           0 :        listentry%field%field_op = optype
    6133           0 :        if (present(op_f1name).and.present(op_f2name)) then
    6134             :           ! Look for the field IDs
    6135           0 :           f1listentry => get_entry_by_name(masterlinkedlist, trim(op_f1name))
    6136           0 :           f2listentry => get_entry_by_name(masterlinkedlist, trim(op_f2name))
    6137           0 :           if (associated(f1listentry).and.associated(f2listentry)) then
    6138           0 :              listentry%op_field1=trim(op_f1name)
    6139           0 :              listentry%op_field2=trim(op_f2name)
    6140             :           else
    6141           0 :              write(errormsg, '(5a)') ': Attempt to create a composed field using  (',         &
    6142           0 :                   trim(op_f1name), ', ', trim(op_f2name),         &
    6143           0 :                   ') but both fields have not been added to masterlist via addfld first'
    6144           0 :              call endrun (trim(subname)//errormsg)
    6145             :           end if
    6146             :        else
    6147           0 :           write(errormsg, *) ': Attempt to create a composed field but no component fields have been specified'
    6148           0 :           call endrun (trim(subname)//errormsg)
    6149             :        end if
    6150             : 
    6151             :     else
    6152     4495872 :        if (present(op_f1name)) then
    6153           0 :           write(errormsg, '(3a)') ': creating a composed field using component field 1:',&
    6154           0 :                trim(op_f1name),' but no field operation (optype=sum or dif) has been defined'
    6155           0 :           call endrun (trim(subname)//errormsg)
    6156             :        end if
    6157     4495872 :        if (present(op_f2name)) then
    6158           0 :           write(errormsg, '(3a)') ': creating a composed field using component field 2:',&
    6159           0 :                trim(op_f2name),' but no field operation (optype=sum or dif) has been defined'
    6160           0 :           call endrun (trim(subname)//errormsg)
    6161             :        end if
    6162             :     end if
    6163             : 
    6164             : 
    6165     4495872 :     nullify(listentry%next_entry)
    6166             : 
    6167     4495872 :     call add_entry_to_master(listentry)
    6168     4495872 :     return
    6169     8991744 :   end subroutine addfld_nd
    6170             : 
    6171             :   !#######################################################################
    6172             : 
    6173             :   ! field_part_of_vector: Determine if fname is part of a vector set
    6174             :   !       Optionally fill in the names of the vector set fields
    6175           0 :   logical function field_part_of_vector(fname, meridional_name, zonal_name)
    6176             : 
    6177             :     ! Dummy arguments
    6178             :     character(len=*),           intent(in)  :: fname
    6179             :     character(len=*), optional, intent(out) :: meridional_name
    6180             :     character(len=*), optional, intent(out) :: zonal_name
    6181             : 
    6182             :     ! Local variables
    6183             :     type(master_entry), pointer             :: listentry
    6184             : 
    6185           0 :     listentry => get_entry_by_name(masterlinkedlist, fname)
    6186           0 :     if (associated(listentry)) then
    6187           0 :       if ( (len_trim(listentry%meridional_field) > 0) .or.                     &
    6188             :            (len_trim(listentry%zonal_field) > 0)) then
    6189           0 :         field_part_of_vector = .true.
    6190           0 :         if (present(meridional_name)) then
    6191           0 :           meridional_name = listentry%meridional_field
    6192             :         end if
    6193           0 :         if (present(zonal_name)) then
    6194           0 :           zonal_name = listentry%zonal_field
    6195             :         end if
    6196             :       else
    6197             :         field_part_of_vector = .false.
    6198             :       end if
    6199             :     else
    6200             :       field_part_of_vector = .false.
    6201             :     end if
    6202             :     if (.not. field_part_of_vector) then
    6203           0 :       if (present(meridional_name)) then
    6204           0 :         meridional_name = ''
    6205             :       end if
    6206           0 :       if (present(zonal_name)) then
    6207           0 :         zonal_name = ''
    6208             :       end if
    6209             :     end if
    6210             : 
    6211     4495872 :   end function field_part_of_vector
    6212             : 
    6213             :   !#######################################################################
    6214             :   ! composed field_info: Determine if a field is derived from a mathematical
    6215             :   !       operation using 2 other defined fields.  Optionally,
    6216             :   !       retrieve names of the composing fields
    6217      303360 :   subroutine composed_field_info(fname, is_composed, fname1, fname2)
    6218             : 
    6219             :     ! Dummy arguments
    6220             :     character(len=*),           intent(in)  :: fname
    6221             :     logical,                    intent(out) :: is_composed
    6222             :     character(len=*), optional, intent(out) :: fname1
    6223             :     character(len=*), optional, intent(out) :: fname2
    6224             : 
    6225             :     ! Local variables
    6226             :     type(master_entry), pointer             :: listentry
    6227             :     character(len=128)                      :: errormsg
    6228             :     character(len=*), parameter             :: subname='composed_field_info'
    6229             : 
    6230      606720 :     listentry => get_entry_by_name(masterlinkedlist, fname)
    6231      303360 :     if (associated(listentry)) then
    6232      303360 :       if ( (len_trim(listentry%op_field1) > 0) .or.                     &
    6233             :            (len_trim(listentry%op_field2) > 0)) then
    6234           0 :          is_composed = .true.
    6235             :       else
    6236      303360 :          is_composed = .false.
    6237             :       end if
    6238      303360 :       if (is_composed) then
    6239           0 :          if (present(fname1)) then
    6240           0 :             fname1=trim(listentry%op_field1)
    6241             :          end if
    6242           0 :          if (present(fname2)) then
    6243           0 :             fname2=trim(listentry%op_field2)
    6244             :          end if
    6245             :       else
    6246      303360 :          if (present(fname1)) then
    6247      303360 :             fname1 = ''
    6248             :          end if
    6249      303360 :          if (present(fname2)) then
    6250      303360 :             fname2 = ''
    6251             :          end if
    6252             :       end if
    6253             :    else
    6254           0 :       write(errormsg, '(3a)') ': Field:',trim(fname),' not defined in masterlist'
    6255           0 :       call endrun (trim(subname)//errormsg)
    6256             :    end if
    6257             : 
    6258      303360 :  end subroutine composed_field_info
    6259             : 
    6260             : 
    6261             :   ! register_vector_field: Register a pair of history field names as
    6262             :   !           being a vector complement set.
    6263             :   !           This information is used to set up interpolated history output.
    6264             :   ! NB: register_vector_field must be called after both fields are defined
    6265             :   !     with addfld
    6266       62976 :   subroutine register_vector_field(zonal_field_name, meridional_field_name)
    6267             : 
    6268             :     ! Dummy arguments
    6269             :     character(len=*),             intent(in) :: zonal_field_name
    6270             :     character(len=*),             intent(in) :: meridional_field_name
    6271             : 
    6272             :     ! Local variables
    6273             :     type(master_entry), pointer      :: mlistentry
    6274             :     type(master_entry), pointer      :: zlistentry
    6275             :     character(len=*),   parameter    :: subname = 'REGISTER_VECTOR_FIELD'
    6276             :     character(len=max_chars)         :: errormsg
    6277             : 
    6278       62976 :     if (htapes_defined) then
    6279           0 :       write(errormsg, '(5a)') ': Attempt to register vector field (',         &
    6280           0 :            trim(zonal_field_name), ', ', trim(meridional_field_name),         &
    6281           0 :            ') after history files set'
    6282           0 :       call endrun (trim(subname)//errormsg)
    6283             :     end if
    6284             : 
    6285             :     ! Look for the field IDs
    6286       62976 :     zlistentry => get_entry_by_name(masterlinkedlist, zonal_field_name)
    6287       62976 :     mlistentry => get_entry_by_name(masterlinkedlist, meridional_field_name)
    6288             :     ! Has either of these fields been previously registered?
    6289       62976 :     if (associated(mlistentry)) then
    6290       62976 :       if (len_trim(mlistentry%meridional_field) > 0) then
    6291           0 :         write(errormsg, '(9a)') ': ERROR attempting to register vector ',     &
    6292           0 :              'field (', trim(zonal_field_name), ', ',                         &
    6293           0 :              trim(meridional_field_name), '), ', trim(meridional_field_name), &
    6294           0 :              ' has been registered as part of a vector field with ',          &
    6295           0 :              trim(mlistentry%meridional_field)
    6296           0 :         call endrun (trim(subname)//errormsg)
    6297       62976 :       else if (len_trim(mlistentry%zonal_field) > 0) then
    6298           0 :         write(errormsg, '(9a)') ': ERROR attempting to register vector ',     &
    6299           0 :              'field (', trim(zonal_field_name), ', ',                         &
    6300           0 :              trim(meridional_field_name), '), ', trim(meridional_field_name), &
    6301           0 :              ' has been registered as part of a vector field with ',          &
    6302           0 :              trim(mlistentry%zonal_field)
    6303           0 :         call endrun (trim(subname)//errormsg)
    6304             :       end if
    6305             :     end if
    6306       62976 :     if (associated(zlistentry)) then
    6307       62976 :       if (len_trim(zlistentry%meridional_field) > 0) then
    6308           0 :         write(errormsg, '(9a)') ': ERROR attempting to register vector ',     &
    6309           0 :              'field (', trim(zonal_field_name), ', ',                         &
    6310           0 :              trim(meridional_field_name), '), ', trim(zonal_field_name),      &
    6311           0 :              ' has been registered as part of a vector field with ',          &
    6312           0 :              trim(zlistentry%meridional_field)
    6313           0 :         call endrun (trim(subname)//errormsg)
    6314       62976 :       else if (len_trim(zlistentry%zonal_field) > 0) then
    6315           0 :         write(errormsg, '(9a)') ': ERROR attempting to register vector ',     &
    6316           0 :              'field (', trim(zonal_field_name), ', ',                         &
    6317           0 :              trim(meridional_field_name), '), ', trim(zonal_field_name),      &
    6318           0 :              ' has been registered as part of a vector field with ',          &
    6319           0 :              trim(zlistentry%meridional_field)
    6320           0 :         call endrun (trim(subname)//errormsg)
    6321             :       end if
    6322             :     end if
    6323       62976 :     if(associated(mlistentry) .and. associated(zlistentry)) then
    6324       62976 :       zlistentry%meridional_field = mlistentry%field%name
    6325       62976 :       zlistentry%zonal_field      = ''
    6326       62976 :       mlistentry%meridional_field = ''
    6327       62976 :       mlistentry%zonal_field      = zlistentry%field%name
    6328           0 :     else if (associated(mlistentry)) then
    6329           0 :       write(errormsg, '(7a)') ': ERROR attempting to register vector field (',&
    6330           0 :            trim(zonal_field_name), ', ', trim(meridional_field_name),         &
    6331           0 :            '), ', trim(zonal_field_name), ' is not defined'
    6332           0 :       call endrun (trim(subname)//errormsg)
    6333           0 :     else if (associated(zlistentry)) then
    6334           0 :       write(errormsg, '(7a)') ': ERROR attempting to register vector field (',&
    6335           0 :            trim(zonal_field_name), ', ', trim(meridional_field_name),         &
    6336           0 :            '), ', trim(meridional_field_name), ' is not defined'
    6337           0 :       call endrun (trim(subname)//errormsg)
    6338             :     else
    6339           0 :       write(errormsg, '(5a)') ': ERROR attempting to register vector field (',&
    6340           0 :            trim(zonal_field_name), ', ', trim(meridional_field_name),         &
    6341           0 :            '), neither field is defined'
    6342           0 :       call endrun (trim(subname)//errormsg)
    6343             :     end if
    6344       62976 :   end subroutine register_vector_field
    6345             : 
    6346     4495872 :   subroutine add_entry_to_master( newentry)
    6347             :     type(master_entry), target, intent(in) :: newentry
    6348             :     type(master_entry), pointer :: listentry
    6349             : 
    6350     4495872 :     if(associated(masterlinkedlist)) then
    6351             :       listentry => masterlinkedlist
    6352  6577460736 :       do while(associated(listentry%next_entry))
    6353     4494336 :         listentry=>listentry%next_entry
    6354             :       end do
    6355     4494336 :       listentry%next_entry=>newentry
    6356             :     else
    6357        1536 :       masterlinkedlist=>newentry
    6358             :     end if
    6359             : 
    6360     4495872 :   end subroutine add_entry_to_master
    6361             : 
    6362             :   !#######################################################################
    6363             : 
    6364       14592 :   subroutine wrapup (rstwr, nlend)
    6365             :     !
    6366             :     !-----------------------------------------------------------------------
    6367             :     !
    6368             :     ! Purpose:
    6369             :     ! Close history files.
    6370             :     !
    6371             :     ! Method:
    6372             :     ! This routine will close any full hist. files
    6373             :     ! or any hist. file that has data on it when restart files are being
    6374             :     ! written.
    6375             :     ! If a partially full history file was disposed (for restart
    6376             :     ! purposes), then wrapup will open that unit back up and position
    6377             :     ! it for appending new data.
    6378             :     !
    6379             :     ! Original version: CCM2
    6380             :     !
    6381             :     !-----------------------------------------------------------------------
    6382             :     !
    6383             :     use shr_kind_mod,  only: r8 => shr_kind_r8
    6384             :     use ioFileMod
    6385             :     use time_manager,  only: get_nstep, get_curr_date, get_curr_time
    6386             :     use cam_pio_utils, only: cam_pio_openfile, cam_pio_closefile
    6387             : 
    6388             :     !
    6389             :     ! Input arguments
    6390             :     !
    6391             :     logical, intent(in) :: rstwr   ! true => restart files are written this timestep
    6392             :     logical, intent(in) :: nlend   ! Flag if time to end
    6393             : 
    6394             :     !
    6395             :     ! Local workspace
    6396             :     !
    6397             :     integer  :: nstep            ! current timestep number
    6398             :     integer  :: ncsec            ! time of day relative to current date [secs]
    6399             :     integer  :: ndcur            ! days component of current time
    6400             :     integer  :: nscur            ! seconds component of current time
    6401             :     integer  :: yr, mon, day     ! year, month, day components of a date
    6402             : 
    6403             :     logical  :: lfill   (ptapes) ! Is history file ready to dispose?
    6404             :     logical  :: lhdisp           ! true => history file is disposed
    6405             :     logical  :: lhfill           ! true => history file is full
    6406             : 
    6407             :     integer  :: t                ! History file number
    6408             :     integer  :: f                ! File index
    6409             :     integer  :: fld              ! Field index
    6410             :     real(r8) :: tday             ! Model day number for printout
    6411             :     !-----------------------------------------------------------------------
    6412             : 
    6413       14592 :     tape => history_tape
    6414             : 
    6415       14592 :     nstep = get_nstep()
    6416       14592 :     call get_curr_date(yr, mon, day, ncsec)
    6417       14592 :     call get_curr_time(ndcur, nscur)
    6418             :     !
    6419             :     !-----------------------------------------------------------------------
    6420             :     ! Dispose history files.
    6421             :     !-----------------------------------------------------------------------
    6422             :     !
    6423             :     ! Begin loop over ptapes (the no. of declared history files - primary
    6424             :     ! and auxiliary).  This loop disposes a history file to Mass Store
    6425             :     ! when appropriate.
    6426             :     !
    6427      189696 :     do t=1,ptapes
    6428      175104 :       if (nflds(t) == 0) cycle
    6429       29184 :       lfill(t) = .false.
    6430             :       !
    6431             :       ! Find out if file is full
    6432             :       !
    6433       29184 :       if (hstwr(t) .and. nfils(t) >= mfilt(t)) then
    6434           0 :         lfill(t) = .true.
    6435             :       endif
    6436             :       !
    6437             :       ! Dispose history file if
    6438             :       !    1) file is filled or
    6439             :       !    2) this is the end of run and file has data on it or
    6440             :       !    3) restarts are being put out and history file has data on it
    6441             :       !
    6442       43776 :       if (lfill(t) .or. (nlend .and. nfils(t) >= 1) .or. (rstwr .and. nfils(t) >= 1)) then
    6443             :         !
    6444             :         ! Dispose history file
    6445             :         !
    6446             :         !
    6447             :         ! Is this the 0 timestep data of a monthly run?
    6448             :         ! If so, just close primary unit do not dispose.
    6449             :         !
    6450           0 :         if (masterproc) then
    6451           0 :            do f = 1, maxsplitfiles
    6452           0 :               if (pio_file_is_open(tape(t)%Files(f))) then
    6453           0 :                  write(iulog,*)'WRAPUP: nf_close(',t,')=',trim(nhfil(t,f))
    6454             :               end if
    6455             :            end do
    6456             :         end if
    6457           0 :         if(pio_file_is_open(tape(t)%Files(accumulated_file_index)) .or. &
    6458             :            pio_file_is_open(tape(t)%Files(instantaneous_file_index))) then
    6459           0 :           if (nlend .or. lfill(t)) then
    6460           0 :             do fld=1,nflds(t)
    6461           0 :               if (associated(tape(t)%hlist(fld)%varid)) then
    6462           0 :                 deallocate(tape(t)%hlist(fld)%varid)
    6463           0 :                 nullify(tape(t)%hlist(fld)%varid)
    6464             :               end if
    6465             :             end do
    6466             :           end if
    6467             :         end if
    6468           0 :         do f = 1, maxsplitfiles
    6469           0 :           if (pio_file_is_open(tape(t)%Files(f))) then
    6470           0 :              call cam_pio_closefile(tape(t)%Files(f))
    6471             :           end if
    6472             :         end do
    6473           0 :         if (nhtfrq(t) /= 0 .or. nstep > 0) then
    6474             : 
    6475             :           !
    6476             :           ! Print information concerning model output.
    6477             :           ! Model day number = iteration number of history file data * delta-t / (seconds per day)
    6478             :           !
    6479           0 :           tday = ndcur + nscur/86400._r8
    6480           0 :           if(masterproc) then
    6481           0 :             if (t==1) then
    6482           0 :               write(iulog,*)'   Primary history file'
    6483             :             else
    6484           0 :               write(iulog,*)'   Auxiliary history file number ', t-1
    6485             :             end if
    6486           0 :             write(iulog,9003)nstep,nfils(t),tday
    6487           0 :             write(iulog,9004)
    6488             :           end if
    6489             :           !
    6490             :           ! Auxilary files may have been closed and saved off without being full.
    6491             :           ! We must reopen the files and position them for more data.
    6492             :           ! Must position auxiliary files if not full
    6493             :           !
    6494           0 :           if (.not.nlend .and. .not.lfill(t)) then
    6495             :             ! Always open the instantaneous file
    6496           0 :             call cam_PIO_openfile (tape(t)%Files(instantaneous_file_index), nhfil(t,instantaneous_file_index), PIO_WRITE)
    6497           0 :             if (hfile_accum(t)) then
    6498             :                ! Conditionally open the accumulated file
    6499           0 :                call cam_PIO_openfile (tape(t)%Files(accumulated_file_index), nhfil(t,accumulated_file_index), PIO_WRITE)
    6500             :             end if
    6501           0 :             call h_inquire(t)
    6502             :           end if
    6503             :         endif                 ! if 0 timestep of montly run****
    6504             :       end if                      ! if time dispose history fiels***
    6505             :     end do                         ! do ptapes
    6506             :     !
    6507             :     ! Reset number of files on each history tape
    6508             :     !
    6509      189696 :     do t=1,ptapes
    6510      175104 :       if (nflds(t) == 0) cycle
    6511       29184 :       lhfill = hstwr(t) .and. nfils(t) >= mfilt(t)
    6512             :       lhdisp = lhfill .or. (nlend .and. nfils(t) >= 1) .or. &
    6513       29184 :            (rstwr .and. nfils(t) >= 1)
    6514       43776 :       if (lhfill.and.lhdisp) then
    6515           0 :         nfils(t) = 0
    6516             :       endif
    6517             :     end do
    6518       14592 :     return
    6519             : 9003 format('    Output at NSTEP     = ',i10,/, &
    6520             :          '    Number of time samples on this file = ',i10,/, &
    6521             :          '    Model Day           = ',f10.2)
    6522             : 9004 format('---------------------------------------')
    6523       14592 :   end subroutine wrapup
    6524             : 
    6525             : 
    6526   211000896 :   integer function gen_hash_key(string)
    6527             :     !
    6528             :     !-----------------------------------------------------------------------
    6529             :     !
    6530             :     ! Purpose: Generate a hash key on the interval [0 .. tbl_hash_pri_sz-1]
    6531             :     !          given a character string.
    6532             :     !
    6533             :     ! Algorithm is a variant of perl's internal hashing function.
    6534             :     !
    6535             :     !-----------------------------------------------------------------------
    6536             :     !
    6537             :     implicit none
    6538             :     !
    6539             :     !  Arguments:
    6540             :     !
    6541             :     character(len=*), intent(in) :: string
    6542             :     !
    6543             :     !  Local.
    6544             :     !
    6545             :     integer :: hash
    6546             :     integer :: i
    6547             : 
    6548   211000896 :     hash = gen_hash_key_offset
    6549             : 
    6550   211000896 :     if ( len(string) /= 19 ) then
    6551             :       !
    6552             :       !     Process arbitrary string length.
    6553             :       !
    6554  7596032256 :       do i = 1, len(string)
    6555  7596032256 :         hash = ieor(hash, (ichar(string(i:i)) * tbl_gen_hash_key(iand(i-1,tbl_max_idx))))
    6556             :       end do
    6557             :     else
    6558             :       !
    6559             :       !     Special case string length = 19
    6560             :       !
    6561           0 :       hash = ieor(hash , ichar(string(1:1))   * 61)
    6562           0 :       hash = ieor(hash , ichar(string(2:2))   * 59)
    6563           0 :       hash = ieor(hash , ichar(string(3:3))   * 53)
    6564           0 :       hash = ieor(hash , ichar(string(4:4))   * 47)
    6565           0 :       hash = ieor(hash , ichar(string(5:5))   * 43)
    6566           0 :       hash = ieor(hash , ichar(string(6:6))   * 41)
    6567           0 :       hash = ieor(hash , ichar(string(7:7))   * 37)
    6568           0 :       hash = ieor(hash , ichar(string(8:8))   * 31)
    6569           0 :       hash = ieor(hash , ichar(string(9:9))   * 29)
    6570           0 :       hash = ieor(hash , ichar(string(10:10)) * 23)
    6571           0 :       hash = ieor(hash , ichar(string(11:11)) * 17)
    6572           0 :       hash = ieor(hash , ichar(string(12:12)) * 13)
    6573           0 :       hash = ieor(hash , ichar(string(13:13)) * 11)
    6574           0 :       hash = ieor(hash , ichar(string(14:14)) * 7)
    6575           0 :       hash = ieor(hash , ichar(string(15:15)) * 3)
    6576           0 :       hash = ieor(hash , ichar(string(16:16)) * 1)
    6577           0 :       hash = ieor(hash , ichar(string(17:17)) * 61)
    6578           0 :       hash = ieor(hash , ichar(string(18:18)) * 59)
    6579           0 :       hash = ieor(hash , ichar(string(19:19)) * 53)
    6580             :     end if
    6581             : 
    6582   211000896 :     gen_hash_key = iand(hash, tbl_hash_pri_sz-1)
    6583             : 
    6584             :     return
    6585             : 
    6586       14592 :   end function gen_hash_key
    6587             : 
    6588             :   !#######################################################################
    6589             : 
    6590   202009152 :   integer function get_masterlist_indx(fldname)
    6591             :     !
    6592             :     !-----------------------------------------------------------------------
    6593             :     !
    6594             :     ! Purpose: Return the the index of the field's name on the master file list.
    6595             :     !
    6596             :     !          If the field is not found on the masterlist, return -1.
    6597             :     !
    6598             :     !-----------------------------------------------------------------------
    6599             :     !
    6600             :     !  Arguments:
    6601             :     !
    6602             :     character(len=*), intent(in) :: fldname
    6603             :     !
    6604             :     !  Local.
    6605             :     !
    6606             :     integer :: hash_key
    6607             :     integer :: ff
    6608             :     integer :: ii
    6609             :     integer :: io   ! Index of overflow chain in overflow table
    6610             :     integer :: in   ! Number of entries on overflow chain
    6611             : 
    6612   202009152 :     hash_key = gen_hash_key(fldname)
    6613   202009152 :     ff = tbl_hash_pri(hash_key)
    6614   202009152 :     if ( ff < 0 ) then
    6615    69895176 :       io = abs(ff)
    6616    69895176 :       in = tbl_hash_oflow(io)
    6617   119870688 :       do ii = 1, in
    6618   119870688 :         ff = tbl_hash_oflow(io+ii)
    6619   119870688 :         if ( masterlist(ff)%thisentry%field%name == fldname ) exit
    6620             :       end do
    6621             :     end if
    6622             : 
    6623   202009152 :     if (ff == 0) then
    6624             :       ! fldname generated a hash key that doesn't have an entry in tbl_hash_pri.
    6625             :       ! This means that fldname isn't in the masterlist
    6626           0 :       call endrun ('GET_MASTERLIST_INDX: attemping to output field '//fldname//' not on master list')
    6627             :     end if
    6628             : 
    6629   202009152 :     if (associated(masterlist(ff)%thisentry) .and. masterlist(ff)%thisentry%field%name /= fldname ) then
    6630           0 :       call endrun ('GET_MASTERLIST_INDX: error finding field '//fldname//' on master list')
    6631             :     end if
    6632             : 
    6633   202009152 :     get_masterlist_indx = ff
    6634             :     return
    6635             :   end function get_masterlist_indx
    6636             :   !#######################################################################
    6637             : 
    6638        1536 :   subroutine bld_outfld_hash_tbls()
    6639             :     !
    6640             :     !-----------------------------------------------------------------------
    6641             :     !
    6642             :     ! Purpose: Build primary and overflow hash tables for outfld processing.
    6643             :     !
    6644             :     ! Steps:
    6645             :     !  1) Foreach field on masterlist, find all collisions.
    6646             :     !  2) Given the number of collisions, verify overflow table has sufficient
    6647             :     !     space.
    6648             :     !  3) Build primary and overflow indices.
    6649             :     !
    6650             :     !-----------------------------------------------------------------------
    6651             :     !
    6652             :     !  Local.
    6653             :     !
    6654             :     integer :: ff
    6655             :     integer :: ii
    6656             :     integer :: itemp
    6657             :     integer :: ncollisions
    6658             :     integer :: hash_key
    6659             :     type(master_entry), pointer :: listentry
    6660             :     !
    6661             :     !  1) Find all collisions.
    6662             :     !
    6663        1536 :     tbl_hash_pri = 0
    6664             : 
    6665        1536 :     ff=0
    6666     4500480 :     allocate(masterlist(nfmaster))
    6667        1536 :     listentry=>masterlinkedlist
    6668     4497408 :     do while(associated(listentry))
    6669     4495872 :       ff=ff+1
    6670     4495872 :       masterlist(ff)%thisentry=>listentry
    6671     4495872 :       listentry=>listentry%next_entry
    6672             :     end do
    6673        1536 :     if(ff /= nfmaster) then
    6674           0 :       write(iulog,*) 'nfmaster = ',nfmaster, ' ff=',ff
    6675           0 :       call endrun('mismatch in expected size of nfmaster')
    6676             :     end if
    6677             : 
    6678             : 
    6679     4497408 :     do ff = 1, nfmaster
    6680     4495872 :       hash_key = gen_hash_key(masterlist(ff)%thisentry%field%name)
    6681     4497408 :       tbl_hash_pri(hash_key) = tbl_hash_pri(hash_key) + 1
    6682             :     end do
    6683             : 
    6684             :     !
    6685             :     !  2) Count number of collisions and define start of a individual
    6686             :     !     collision's chain in overflow table. A collision is defined to be any
    6687             :     !     location in tbl_hash_pri that has a value > 1.
    6688             :     !
    6689        1536 :     ncollisions = 0
    6690   100664832 :     do ii = 0, tbl_hash_pri_sz-1
    6691   100664832 :       if ( tbl_hash_pri(ii) > 1 ) then  ! Define start of chain in O.F. table
    6692      695808 :         itemp = tbl_hash_pri(ii)
    6693      695808 :         tbl_hash_pri(ii) = -(ncollisions + 1)
    6694      695808 :         ncollisions = ncollisions + itemp + 1
    6695             :       end if
    6696             :     end do
    6697             : 
    6698        1536 :     if ( ncollisions > tbl_hash_oflow_sz ) then
    6699           0 :       write(iulog,*) 'BLD_OUTFLD_HASH_TBLS: ncollisions > tbl_hash_oflow_sz', &
    6700           0 :            ncollisions, tbl_hash_oflow_sz
    6701           0 :       call endrun()
    6702             :     end if
    6703             : 
    6704             :     !
    6705             :     !  3) Build primary and overflow tables.
    6706             :     !     i - set collisions in tbl_hash_pri to point to their respective
    6707             :     !         chain in the overflow table.
    6708             :     !
    6709        1536 :     tbl_hash_oflow = 0
    6710             : 
    6711     4497408 :     do ff = 1, nfmaster
    6712     4495872 :       hash_key = gen_hash_key(masterlist(ff)%thisentry%field%name)
    6713     4497408 :       if ( tbl_hash_pri(hash_key) < 0 ) then
    6714     1499136 :         ii = abs(tbl_hash_pri(hash_key))
    6715     1499136 :         tbl_hash_oflow(ii) = tbl_hash_oflow(ii) + 1
    6716     1499136 :         tbl_hash_oflow(ii+tbl_hash_oflow(ii)) = ff
    6717             :       else
    6718     2996736 :         tbl_hash_pri(hash_key) = ff
    6719             :       end if
    6720             :     end do
    6721             : 
    6722        1536 :   end subroutine bld_outfld_hash_tbls
    6723             : 
    6724             :   !#######################################################################
    6725             : 
    6726        1536 :   subroutine bld_htapefld_indices
    6727             :     !
    6728             :     !-----------------------------------------------------------------------
    6729             :     !
    6730             :     ! Purpose: Set history tape field indicies in masterlist for each
    6731             :     !          field defined on every tape.
    6732             :     !
    6733             :     ! Note: because of restart processing, the actflag field is cleared and
    6734             :     !       then set only for active output fields on the different history
    6735             :     !       tapes.
    6736             :     !
    6737             :     !-----------------------------------------------------------------------
    6738             :     !
    6739             :     !  Arguments:
    6740             :     !
    6741             : 
    6742             :     !
    6743             :     !  Local.
    6744             :     !
    6745             :     integer :: fld
    6746             :     integer :: t
    6747             : 
    6748             :     !
    6749             :     !  Initialize htapeindx to an invalid value.
    6750             :     !
    6751             :     type(master_entry), pointer :: listentry
    6752             : 
    6753             :     ! reset all the active flags to false
    6754             :     ! this is needed so that restarts work properly -- fvitt
    6755        1536 :     listentry=>masterlinkedlist
    6756     4497408 :     do while(associated(listentry))
    6757    58446336 :       listentry%actflag(:) = .false.
    6758     4495872 :       listentry%act_sometape = .false.
    6759     4495872 :       listentry=>listentry%next_entry
    6760             :     end do
    6761             : 
    6762       19968 :     do t = 1, ptapes
    6763      626688 :       do fld = 1, nflds(t)
    6764      606720 :         listentry => get_entry_by_name(masterlinkedlist, tape(t)%hlist(fld)%field%name)
    6765      606720 :         if(.not.associated(listentry)) then
    6766           0 :           write(iulog,*) 'BLD_HTAPEFLD_INDICES: something wrong, field not found on masterlist'
    6767           0 :           write(iulog,*) 'BLD_HTAPEFLD_INDICES: t, f, ff = ', t, fld
    6768           0 :           write(iulog,*) 'BLD_HTAPEFLD_INDICES: tape%name = ', tape(t)%hlist(fld)%field%name
    6769           0 :           call endrun
    6770             :         end if
    6771      606720 :         listentry%act_sometape = .true.
    6772      606720 :         listentry%actflag(t) = .true.
    6773      625152 :         listentry%htapeindx(t) = fld
    6774             :       end do
    6775             :     end do
    6776             : 
    6777             :     !
    6778             :     ! set flag indicating h-tape contents are now defined (needed by addfld)
    6779             :     !
    6780        1536 :     htapes_defined = .true.
    6781             : 
    6782        1536 :     return
    6783             :   end subroutine bld_htapefld_indices
    6784             : 
    6785             :   !#######################################################################
    6786             : 
    6787     9235344 :   logical function hist_fld_active(fname)
    6788             :     !
    6789             :     !------------------------------------------------------------------------
    6790             :     !
    6791             :     ! Purpose: determine if a field is active on any history file
    6792             :     !
    6793             :     !------------------------------------------------------------------------
    6794             :     !
    6795             :     ! Arguments
    6796             :     !
    6797             :     character(len=*), intent(in) :: fname ! Field name
    6798             :     !
    6799             :     ! Local variables
    6800             :     !
    6801             :     character*(max_fieldname_len) :: fname_loc  ! max-char equivalent of fname
    6802             :     integer :: ff                  ! masterlist index pointer
    6803             :     !-----------------------------------------------------------------------
    6804             : 
    6805     9235344 :     fname_loc = fname
    6806     9235344 :     ff = get_masterlist_indx(fname_loc)
    6807     9235344 :     if ( ff < 0 ) then
    6808             :       hist_fld_active = .false.
    6809             :     else
    6810     9235344 :       hist_fld_active = masterlist(ff)%thisentry%act_sometape
    6811             :     end if
    6812             : 
    6813     9235344 :   end function hist_fld_active
    6814             : 
    6815             :   !#######################################################################
    6816             : 
    6817           0 :   function hist_fld_col_active(fname, lchnk, numcols)
    6818             :     use cam_history_support, only: history_patch_t
    6819             : 
    6820             :     ! Determine whether each column in a field is active on any history file.
    6821             :     ! The purpose of this routine is to provide information which would allow
    6822             :     ! a diagnostic physics parameterization to only be run on a subset of
    6823             :     ! columns in the case when only column or regional output is requested.
    6824             :     !
    6825             :     ! **N.B.** The field is assumed to be using the physics decomposition.
    6826             : 
    6827             :     ! Arguments
    6828             :     character(len=*), intent(in) :: fname   ! Field name
    6829             :     integer,          intent(in) :: lchnk   ! chunk ID
    6830             :     integer,          intent(in) :: numcols ! Size of return array
    6831             : 
    6832             :     ! Return value
    6833             :     logical :: hist_fld_col_active(numcols)
    6834             : 
    6835             :     ! Local variables
    6836             :     integer                         :: ffld        ! masterlist index pointer
    6837             :     integer                         :: i
    6838             :     integer                         :: t           ! history file (tape) index
    6839             :     integer                         :: fld         ! field index
    6840             :     integer                         :: decomp
    6841           0 :     logical                         :: activeloc(numcols)
    6842             :     integer                         :: num_patches
    6843             :     logical                         :: patch_output
    6844             :     logical                         :: found
    6845             :     type(history_patch_t), pointer  :: patchptr
    6846             : 
    6847           0 :     type (active_entry),   pointer  :: tape(:)
    6848             : 
    6849             :     !-----------------------------------------------------------------------
    6850             : 
    6851             :     ! Initialize to false.  Then look to see if and where active.
    6852           0 :     hist_fld_col_active = .false.
    6853             : 
    6854             :     ! Check for name in the master list.
    6855           0 :     call get_field_properties(fname, found, tape_out=tape, ff_out=ffld)
    6856             : 
    6857             :     ! If not in master list then return.
    6858           0 :     if (.not. found) return
    6859             : 
    6860             :     ! If in master list, but not active on any file then return
    6861           0 :     if (.not. masterlist(ffld)%thisentry%act_sometape) return
    6862             : 
    6863             :     ! Loop over history files and check for the field/column in each one
    6864           0 :     do t = 1, ptapes
    6865             : 
    6866             :       ! Is the field active in this file?  If not the cycle to next file.
    6867           0 :       if (.not. masterlist(ffld)%thisentry%actflag(t)) cycle
    6868             : 
    6869           0 :       fld = masterlist(ffld)%thisentry%htapeindx(t)
    6870           0 :       decomp = tape(t)%hlist(fld)%field%decomp_type
    6871           0 :       patch_output = associated(tape(t)%patches)
    6872             : 
    6873             :       ! Check whether this file has patch (column) output.
    6874           0 :       if (patch_output) then
    6875           0 :         num_patches = size(tape(t)%patches)
    6876             : 
    6877           0 :         do i = 1, num_patches
    6878           0 :           patchptr => tape(t)%patches(i)
    6879           0 :           activeloc = .false.
    6880           0 :           call patchptr%active_cols(decomp, lchnk, activeloc)
    6881           0 :           hist_fld_col_active = hist_fld_col_active .or. activeloc
    6882             :         end do
    6883             :       else
    6884             : 
    6885             :         ! No column output has been requested.  In that case the field has
    6886             :         ! global output which implies all columns are active.  No need to
    6887             :         ! check any other history files.
    6888           0 :         hist_fld_col_active = .true.
    6889             :         exit
    6890             : 
    6891             :       end if
    6892             : 
    6893             :     end do ! history files
    6894             : 
    6895           0 :   end function hist_fld_col_active
    6896             : 
    6897           0 :   subroutine cam_history_snapshot_deactivate(name)
    6898             : 
    6899             :   ! This subroutine deactivates (sets actflag to false) for all tapes
    6900             : 
    6901             :   character(len=*), intent(in) :: name
    6902             : 
    6903             :   logical :: found
    6904             :   integer :: ff
    6905             : 
    6906           0 :   call get_field_properties(trim(name), found, ff_out=ff, no_tape_check_in=.true.)
    6907           0 :   masterlist(ff)%thisentry%actflag(:) = .false.
    6908             : 
    6909           0 :   end subroutine cam_history_snapshot_deactivate
    6910             : 
    6911           0 :   subroutine cam_history_snapshot_activate(name, tape)
    6912             : 
    6913             :   ! This subroutine activates (set aftflag to true) for the requested tape number
    6914             : 
    6915             :   character(len=*), intent(in) :: name
    6916             :   integer,          intent(in) :: tape
    6917             : 
    6918             :   logical :: found
    6919             :   integer :: ff
    6920             : 
    6921           0 :   call get_field_properties(trim(name), found, ff_out=ff, no_tape_check_in=.true.)
    6922           0 :   masterlist(ff)%thisentry%actflag(tape) = .true.
    6923             : 
    6924           0 :   end subroutine cam_history_snapshot_activate
    6925             : 
    6926           0 : end module cam_history

Generated by: LCOV version 1.14