!
      subroutine outhist(istep,modeltime)
!
! Determine if its time to write a history, and if so call
! output_hist and/or output_sechist to write primary and/or
! secondary histories as required. This routine is called at 
! every time step from advance (or from tstwrhist).
!
      use hist_module,only: iseries,iseries_sech ! read/write
      implicit none
!
! Args:
      integer,intent(in) :: istep,modeltime(4)
!
! Local:
      logical :: time2write,
     |  wrprim,  save_prim,
     |  wrsech,  save_sech
!
! External:
      logical,external :: wrhist
!
! Determine if it is time to write a history:
! (istep and modeltime are input, remaining 6 args are output)
!
      time2write = wrhist(istep,modeltime,
     |  wrprim,save_prim,iseries,
     |  wrsech,save_sech,iseries_sech)
!
! Write primary history:
      if (wrprim) then
!       write(6,"('outhist write primary: istep=',i4,' modeltime=',
!    |    4i3,' save_prim=',l1,' iseries_prim=',i1)") 
!    |    istep,modeltime,save_prim,iseries
        call output_hist(save_prim,iseries)
      endif
!
! Write secondary history:
      if (wrsech) then
!       write(6,"('outhist write secondary: modeltime=',4i3,
!    |    ' save_sech=',l1,' iseries_sech=',i1)") modeltime,
!    |    save_sech,iseries_sech
        call output_sechist(save_sech,iseries_sech)
      endif
      end subroutine outhist
!-----------------------------------------------------------------------
      subroutine output_hist(svfile,iseries)
!
! Write a primary history to current output disk file. If svfile==T, 
! save a link to tempdir, and if dispose==1 also save file to mss. 
!
! The input svfile (from function wrhist) is based on the input history 
!   save interval HIST, i.e., svfile==T if we are at a HIST interval,
!   and the current file should be saved before the current history
!   is written. Wrhist's svfile does *not* consider a full history file. 
!   This routine *does* keep track of the number of histories on a file 
!   (nhist), and will save a file, and open a new one, if the current 
!   file is full (i.e., nhist==mxhist_prim). This is the same for
!   secondary histories.
!
! If a source file was provided by input (nsource==1), then this is an
!   initial run, the source history will be read from the source file,
!   and all output files will be new. If a source file was *not* provided
!   at input, then this is a continuation run, and the source history 
!   (starting model time) is to be found on the 1st output file. If the
!   1st output file is not full, then new histories are appended to it 
!   until it is full before proceeding to the next output file. This is
!   not an issue for secondary histories.
!
      use input_module,only:  ! input_mod.f
     |  output,      ! output file paths provided by input
     |  tempdir,     ! temporary scratch directory for saving
     |  dispose,     ! 0/1 for do/donot save file to ncar mss
     |  mxhist_prim  ! max number of histories on a primary file
      use hist_module,only:   ! hist_mod.f
     |  iprint,      ! print flag (read only)
     |  ioutfile,    ! index to current output file (read/write)
     |  ncid,        ! netcdf file pointer (read/write)
     |  nhist,       ! number of histories on current file (read/write)
     |  modeltime,   ! current model time (read only)
     |  nhist_total, ! total prim histories to be written (read only)
     |  nsource      ! 0/1 number of source files provided (read only)
      use netcdf_module,only: ! nchist_mod.F
     |  nc_open,     ! subroutine to open a netcdf file
     |  nc_define,   ! subroutine to define vars in a new netcdf file
     |  nc_wrhist    ! subroutine to write history to an open netcdf file
      implicit none
!
! Args:
      integer,intent(in) :: iseries  ! index to current time series
      logical,intent(in) :: svfile   ! save current output file if true
!
! Local:
      character(len=80) :: diskfile 
      integer :: iprinthist=0 
      integer,save :: ihist_total=0, iseriesloc=0
      logical :: newseries,fullfile,reopen
!
! Init:
      if (ihist_total==0) ioutfile = 0 ! first history of a run
      newseries = .false.
      if (iseries /= iseriesloc) newseries = .true. ! begin new time series
      fullfile = .false.
      if (nhist == mxhist_prim) fullfile = .true.   ! file is full
      if (ihist_total==0.and.nsource==0) ioutfile = 1
!
!     write(6,"(/,'Enter output_hist: mtime=',3i3,' newseries=',l1,
!    |  ' fullfile=',l1,' svfile=',l1,' nhist=',i2,' ihist_total='i2)")
!    |  modeltime(1:3),newseries,fullfile,svfile,nhist,ihist_total
!     write(6,"('iseries=',i3,' iseriesloc=',i3)") iseries,iseriesloc
!
      diskfile = ' '
      if (iprint > 0) write(6,"(/,72('-'),/,'Primary History Output:',
     |  ' model time (day,hour,min) = ',3i4)") modeltime
      if (ihist_total == 0) then
        iprinthist = 1
      else
        iprinthist = iprint
      endif
!
! File is full, or we are starting a new time series. Save current
!   file (if not first history), then open and define a new file:
!
      if (newseries.or.fullfile) then
!
! Close and save current file:
        if (ihist_total > 0) then ! this is not the first history
          reopen = .false.
          call mkdiskflnm(output(ioutfile),diskfile)
          call savefile(ncid,diskfile,output(ioutfile),tempdir,
     |      dispose,reopen,iprint)
        endif
!
! Open and define a new file:
! If a source file was *not* provided, i.e., this is a continuation 
!  run, then append the history to the first output file (where
!  the source history was read). In this case we open a new file
!  only if the first output file is full.
!
        if (nsource > 0.or.     ! source was provided, i.e., initial run
     |     (nsource==0.and.fullfile)) then ! continuation but full
          ioutfile = ioutfile+1 ! index to file paths
          nhist = 0             ! number of histories on current file
          call mkdiskflnm(output(ioutfile),diskfile)
          call nc_open(ncid,diskfile,'REPLACE','WRITE')
        endif
      endif
!
! Define and write the current history:
      nhist = nhist+1
      call define_hist('primary')      ! define history structure
      if (newseries.or.fullfile) then
        if (nsource > 0.or.(nsource==0.and.fullfile))
     |    call nc_define(ncid)         ! define new netcdf file
      endif
      call nc_wrhist(ncid,iprinthist)  ! write the history
      ihist_total = ihist_total+1
!
! Report to stdout:
      call mkdiskflnm(output(ioutfile),diskfile)
      write(6,"('Wrote primary   history ',i3,',',i2,',',i2,
     |  ' to ',a,' (',i3,' of ',i3,')')") modeltime(1:3),
     |  trim(diskfile),ihist_total,nhist_total
!
! Save existing file if we are at a history save interval within
! the time series (reopen the file for appending unless this was
! the last history of the run):
!
      if (svfile.and..not.newseries.and..not.fullfile) then
        reopen = .true.
        if (ihist_total==nhist_total) reopen = .false.
        call mkdiskflnm(output(ioutfile),diskfile)
        call savefile(ncid,diskfile,output(ioutfile),tempdir,
     |    dispose,reopen,iprint)
      endif
      iseriesloc = iseries
      if (iprint > 0) write(6,"(72('-'),/)")
      end subroutine output_hist
!-----------------------------------------------------------------------
      subroutine output_sechist(svfile,iseries)
!
! Write secondary history to output disk file. If svfile==T, 
! save a link to tempdir, and if dispose==1 also save file to mss. 
! See also comments at top of output_hist above.
!
      use input_module,only: secout,tempdir,dispose,mxhist_sech
      use hist_module,only: iprint,isecout,ncidsech,nsech,modeltime,
     |  nsech_total
      use netcdf_module,only: nc_open,nc_define,nc_wrhist
      implicit none
!
! Args:
      integer,intent(in) :: iseries ! index to current time series
      logical,intent(in) :: svfile  ! if true, on a history save interval
!
! Local:
      character(len=80) :: diskfile 
      integer :: iprinthist=0 
      integer,save :: ihist_total=0, iseriesloc=0
      logical :: newseries,fullfile,reopen
!
! Init:
      if (ihist_total==0) isecout = 0 ! first history of a run
      newseries = .false.
      if (iseries /= iseriesloc) newseries = .true. ! begin new time series
      fullfile = .false.
      if (nsech == mxhist_sech) fullfile = .true.   ! file is full
!
!     write(6,"(/,'Enter output_sechist: mtime=',3i3,' newseries=',l1,
!    |  ' fullfile=',l1,' svfile=',l1,' nsech=',i2,' ihist_total='i2)")
!    |  modeltime(1:3),newseries,fullfile,svfile,nsech,ihist_total
!
      diskfile = ' '
      if (iprint > 0) write(6,"(/,72('-'),/,'Secondary History Output:',
     |  ' model time (day,hour,min) = ',3i4)") modeltime
      if (ihist_total == 0) then
        iprinthist = 1
      else
        iprinthist = iprint
      endif
!
! File is full, or we are starting a new time series. Save current
!   file (if not first history), then open and define a new file:
!
      if (newseries.or.fullfile) then
!
! Close and save current file:
        if (ihist_total > 0) then ! this is not the first history
          reopen = .false.
          call mkdiskflnm(secout(isecout),diskfile)
          call savefile(ncidsech,diskfile,secout(isecout),tempdir,
     |      dispose,reopen,iprint)
        endif
!
! Open and define a new file:
        isecout = isecout+1 ! index to file paths
        nsech = 0           ! number of histories on current file
        call mkdiskflnm(secout(isecout),diskfile)
        call nc_open(ncidsech,diskfile,'REPLACE','WRITE')
      endif
!
! Define and write the current history:
      nsech = nsech+1
      call define_hist('secondary')        ! define history structure
      if (newseries.or.fullfile) then
        call nc_define(ncidsech)           ! define new netcdf file
      endif
      call nc_wrhist(ncidsech,iprinthist)  ! write the history
      ihist_total = ihist_total+1
!
! Report to stdout:
      call mkdiskflnm(secout(isecout),diskfile)
      write(6,"('Wrote secondary history ',i3,',',i2,',',i2,
     |  ' to ',a,' (',i3,' of ',i3,')')") modeltime(1:3),
     |  trim(diskfile),ihist_total,nsech_total
!
! Save existing file if we are at a history save interval within
! the time series (reopen the file for appending unless this was
! the last history of the run):
!
      if (svfile.and..not.newseries.and..not.fullfile) then
        reopen = .true.
        if (ihist_total==nsech_total) reopen = .false.
        call mkdiskflnm(secout(isecout),diskfile)
        call savefile(ncidsech,diskfile,secout(isecout),tempdir,
     |    dispose,reopen,iprint)
      endif
      iseriesloc = iseries
      if (iprint > 0) write(6,"(72('-'),/)")
      end subroutine output_sechist
!-----------------------------------------------------------------------
      subroutine savefile(ncid,diskfile,outpath,tempdir,idispose,
     |  reopen,iprint)
      use netcdf_module,only: nc_open,nc_close,nc_fileinfo
!
! Save file diskfile to tempdir and/or mss.
!
      implicit none
!
! Args:
      integer,intent(in) :: idispose,iprint
      logical,intent(in) :: reopen
      integer,intent(inout) :: ncid
      character(len=*),intent(in) :: diskfile,outpath,tempdir
!
! Local:
      integer :: istat,ier
      character(len=80) :: fileinfo
!
! External:
      integer,external :: ilink,iunlink
!
! Make fileinfo string for mss comment field and add as a
! global file attribute:
!
!     write(6,"('savefile calling nc_fileinfo for diskfile=',a)")
!    |  trim(diskfile)
      call nc_fileinfo(ncid,fileinfo)
!     write(6,"('History file info: ',a)") trim(fileinfo)
!
! Close file:
      call nc_close(ncid)
!
! Dispose to mss only if dispose flag is set, otherwise 
! save link on tempdir.
!     subroutine putms(mspath,dskfile,tmpdir,lnkfile,wrpass,msscomment)
!
      if (idispose==1) then
        call putms(outpath,diskfile,tempdir,' ','NCARTGCM',fileinfo)
        write(6,"('Saved file ',a,' to mss path ',a)")
     |    trim(diskfile),trim(outpath)
      else
!
! Do not link to tempdir if tempdir is also cwd:
        if (trim(tempdir) /= '.') then
          istat = iunlink(trim(tempdir)//'/'//trim(diskfile),iprint)
!
! Let ilink report to stdout regardless of iprint:
          istat = ilink(diskfile,trim(tempdir)//'/'//trim(diskfile),1)
          if (istat /= 0) 
     |      write(6,"('>>> savefile: error ',i3,' from ilink.')") istat
          if (iprint > 0)
     |      write(6,"('(File was NOT disposed to mss)')")
        else
          write(6,"('NOT linking file ',a,' to tempdir ',
     |      'because tempdir==cwd')") trim(diskfile)
        endif
      endif
!
! Reopen file for appending:
      if (reopen) call nc_open(ncid,diskfile,'OLD','APPEND')
      end subroutine savefile
!-----------------------------------------------------------------------
      subroutine define_hist(type)
!
! Define history structure h from commons in hist.h, prior to 
!   writing history file.
! On input, type is either "prim" or "sech" for primary or
!   secondary histories.
!
      use hist_module,only: h,hist_initype,nhist,nsech,modeltime,
     |  isecout,ioutfile,nsource,iseries,iseries_sech
      use input_module,only: output,secout,date,step,power,ctpoten,
     |  byimf,f107,f107a,mag,tide,tide2,colfac,source,hist,sechist
      use init_module,only: rundate,runtime,logname,host,system,p0,
     |  iyear,iday,istep 
      use fields_module,only: nfprog,fprog,fsech,fsechmag
      implicit none
      include "params.h"
!
! Args:
      character(len=*),intent(in) :: type ! primary or secondary
!
! Local:
      integer :: i,ier
!
! External:
      integer,external :: mtime_to_mins,mtime_to_nstep
!
! Init:
      call hist_initype(h,istep)
!
! Define primary or secondary history structure (hist_mod.f):
      select case(type)
        case ('primary')
          h%ihist = nhist
          h%delhmins = mtime_to_mins(hist(:,iseries))
          h%mss_path = output(ioutfile)
          if (nsource > 0) then
            h%mss_source = source
          else
            h%mss_source = output(1)
          endif
          h%nflds = nfprog ! is parameter for now
          if (h%nflds > 0 .and. .not.associated(h%fnames)) then
            allocate(h%fnames(h%nflds),stat=ier)
            if (ier /= 0) then
              write(6,"('>>> define_hist: error allocating h%fnames',
     |          ' for primary history: h%nflds=',i3)") h%nflds
            else
              do i=1,h%nflds
                h%fnames(i) = fprog(i)%name
              enddo
            endif
          endif
          h%nfgeo = h%nflds
          h%nfmag = 0       ! no magnetic fields on primary history
        case ('secondary')
          h%ihist = nsech
          h%delhmins = mtime_to_mins(sechist(:,iseries_sech))
          h%mss_path = secout(isecout)
          h%nfgeo = count(len_trim(fsech%name) > 0)    ! # geographic fields
          h%nfmag = count(len_trim(fsechmag%name) > 0) ! # magnetic fields
          h%nflds = h%nfgeo+h%nfmag
          if (h%nflds > 0 .and. .not.associated(h%fnames)) then
            allocate(h%fnames(h%nflds),stat=ier)
            if (ier /= 0) then
              write(6,"('>>> define_hist: error allocating h%fnames',
     |          ' for secondary history: h%nflds=',i3)") h%nflds
            else
              if (h%nfgeo > 0) then
                do i=1,h%nfgeo
                  h%fnames(i) = fsech(i)%name
                enddo
              endif
              if (h%nfmag > 0) then
                do i=1,h%nfmag
                  h%fnames(h%nfgeo+i) = fsechmag(i)%name
                enddo
              endif
            endif
          endif
        case default
          write(6,"('>>> define_hist: unknown type = ',a)") type
      end select
!
      h%year    = iyear
      h%calday  = iday
      h%rundate = rundate//' '//runtime
      h%logname = logname
      h%host    = host
      h%system  = system
      h%model_name    = tgcm_name
      h%model_version = tgcm_version
      h%type  = type
      h%modeltime = modeltime
      h%time  = mtime_to_mins(modeltime(1:3))
      h%iter  = mtime_to_nstep(modeltime(1:3),step)
      h%ut    = float(modeltime(2))+float(modeltime(3))/60.+
     |          float(modeltime(4))/3600.
      h%mag(:,:)  = mag(:,:)
      h%dtide(:)  = tide2(:)
      h%sdtide(:) = tide(:)
!
! If istep==0, then h%f107, etc were defined from source history,
! otherwise (istep > 0), at least one step has been taken and 
! f107, etc were defined either by user or by getgpi.
!
      if (istep > 0) then
        h%f107d     = f107
        h%f107a     = f107a
        h%hpower    = power
        h%ctpoten   = ctpoten
      endif
      h%byimf     = byimf
      h%colfac    = colfac
      h%p0        = p0 ! init_mod
      h%step      = step
      h%missing_value = spval
      end subroutine define_hist
