LCOV - code coverage report
Current view: top level - control - cam_history.F90 (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2060 3086 66.8 %
Date: 2025-01-13 21:54:50 Functions: 45 64 70.3 %

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

Generated by: LCOV version 1.14