!
      subroutine outhist(istep,mins)
!
! Determine if its time to write a history, and if so call
! output_hist and/or output_sech as required. This routine
! is called at every time step. 
!
      use hist_module,only: mtime,iseries,nseries,
     |  isechist,iseries_sech,nseries_sech,nstep_hist,nstep_save,
     |  nstep_sechist,nstep_secsave,istep_sech
      use input_module,only: start,stop,hist,save,secstart,step,
     |  secstop,sechist,secsave
      implicit none
      include "params.h" ! for mxseries, mxseries_sech (can be removed?)
!
! Args:
      integer,intent(in) :: istep,mins
!
! Local (note mins_start,mins_stop, etc must be saved):
      integer :: isecsave,isave
      integer,save :: mins_start,mins_stop,mins_secstart,mins_secstop
      logical :: newseries
!
! External:
      integer,external :: mtime_to_mins,mtime_to_nstep
!
!     write(6,"('Enter outhist: istep=',i5,' mins=',i6,' iseries=',
!    |  i2)") istep,mins,iseries
!
! Beginning of run (istep==0): echo source history to primary 
! history output if this is an initial run (i.e., if source file 
! was provided). Also write initial secondary history if necessary.
!
      if (istep==0) then
        call output_hist(istep,0,.false.)
        if (isechist > 0 .and. all(mtime(:)==secstart(:,1)))
     |    call output_sechist(istep,0,.false.)
        istep_sech = 0
        return
      endif
      istep_sech = istep_sech+1
!
! Increment iseries if this is stop time of current time series:
      if (mins == mtime_to_mins(stop(:,iseries)).and.
     |    iseries < nseries) then
        iseries = iseries+1    ! advance to next time series
        if (iseries > mxseries) write(6,"('>>> WARNING outhist:',
     |    ' iseries=',i3,' mxseries=',i3)") iseries,mxseries
      endif
!
! Define new primary history time series:
      newseries = .false.
      if (mins == mtime_to_mins(start(:,iseries)).or.istep==1) then
        mins_start = mtime_to_mins(start(:,iseries))
        mins_stop  = mtime_to_mins(stop (:,iseries))
        nstep_hist = mtime_to_nstep(hist(:,iseries),step)
        nstep_save = mtime_to_nstep(save(:,iseries),step)
        if (iseries > 1) newseries = .true.
        write(6,"(/,'Begin primary history time series ',i2,':')")
     |    iseries
        write(6,"(
     |    '  START=',i3,',',i2,',',i2,
     |    '  STOP =',i3,',',i2,',',i2,
     |    '  HIST =',i3,',',i2,',',i2,
     |    '  SAVE =',i3,',',i2,',',i2,/)")
     |    start(:,iseries),stop(:,iseries),
     |    hist(:,iseries),save(:,iseries)
      endif
!
! Current time is in a primary history time series:
      if (mins >= mins_start.and.mins <= mins_stop) then
!
! Time to write a primary history:
        if (mod(istep,nstep_hist)==0) then
          isave = 0
          if (mod(istep,nstep_save)==0) isave = 1
          call output_hist(istep,isave,newseries)
        endif
      endif   ! in primary time series
!
! Write secondary history:
      if (isechist > 0) then
!
! Increment iseries_sech if this is stop time of current time series:
        if (mins == mtime_to_mins(secstop(:,iseries_sech)).and.
     |    iseries_sech < nseries_sech) then
          iseries_sech = iseries_sech+1    ! advance to next time series
! put this check in input:
          if (iseries_sech > mxseries_sech) write(6,"('>>> WARNING:',
     |      ' iseries_sech=',i3,' mxseries_sech=',i3)") iseries_sech,
     |      mxseries_sech
        endif
!
! Check for beginning of sechist time series and update:
        newseries = .false.
        if (mins == mtime_to_mins(secstart(:,iseries_sech)).or.
     |     (istep==1.and.all(start(:,1)==secstart(:,1)))) then 
          if (iseries_sech > 1) newseries = .true.
!
! Define new secondary history time series:
          mins_secstart = mtime_to_mins(secstart(:,iseries_sech))
          mins_secstop  = mtime_to_mins(secstop(:,iseries_sech))
          nstep_sechist = mtime_to_nstep(sechist(:,iseries_sech),step)
          nstep_secsave = mtime_to_nstep(secsave(:,iseries_sech),step)
          write(6,"(/,'Begin secondary history time series ',i2,':')")
     |      iseries_sech
          write(6,"(
     |      '  SECSTART=',i3,',',i2,',',i2,
     |      '  SECSTOP =',i3,',',i2,',',i2,
     |      '  SECHIST =',i3,',',i2,',',i2,
     |      '  SECSAVE =',i3,',',i2,',',i2,/)")
     |      secstart(:,iseries_sech),secstop(:,iseries_sech),
     |      sechist(:,iseries_sech),secsave(:,iseries_sech)
        endif
!
! Current time is in a secondary time series:
        if (mins >= mins_secstart.and.mins <= mins_secstop) then
          if (mins==mins_secstart) istep_sech = 0
!
! Time to write a secondary history:
          if (mod(istep_sech,nstep_sechist)==0) then
            isecsave = 0
            if (mod(istep_sech,nstep_secsave)==0) isecsave = 1
            call output_sechist(istep,isecsave,newseries)
          endif
        endif   ! in sech time series
      endif     ! isechist==1 (doing secondary histories)
      end subroutine outhist
!-----------------------------------------------------------------------
      subroutine output_hist(istep,isave,newseries)
!
! Write primary history to output disk file. If isave==1, save a
! link to tempdir, and if dispose==1 also save file to mss. 
! Current time step is istep (istep==0 if beginning of run).
!
      use input_module,only: output,tempdir,dispose
      use hist_module,only: 
     |  iprint,nsource,ioutfile,ncid,nhist,mtime,nhist_total,
     |  noutput,nstep
      use netcdf_module,only: nc_open,nc_define,nc_wrhist
      implicit none
      include "params.h" ! for mxhist
!
! Args:
      integer,intent(in) :: 
     |  istep, ! current step this run (0->nstep)
     |  isave  ! save to mss if isave==1
      logical,intent(in) :: newseries ! true if new time series
!
! Local:
      character(len=80) :: diskfile
      integer :: istat,ireopen,iprinthist
      integer,save :: ihist_total
      data ihist_total/0/
!
      diskfile = ' '
      if (iprint > 0) write(6,"(/,72('-'),/,'Primary History Output:',
     |  ' istep=',i6,' isave=',i2)") istep,isave
      if (ihist_total == 0) then
        iprinthist = 1
      else
        iprinthist = iprint
      endif
!
! istep==0 means source history has been read but no steps taken. 
! In this case, and a source file was provided at input (an initial
! run), then open a new output file (the first) and echo the source 
! history that file (i.e., initial runs start with the source history).
! Use start time from input for this history (mtime will == start).
!
! If a source file was NOT provided (beginning a continuation run, 
! istep==0.and.nsource==0), then the source history is NOT written. 
!
! If not beginning of run (istep > 0), then current output file has
! been left open for appending.
! 
! Initial run -- open new output file and copy source history into it:

!     write(6,"('output_hist: istep=',i2,' nsource=',i2,' ncid=',
!    |  i2,' newseries=',l1,' nhist=',i3)") istep,nsource,ncid,
!    |  newseries,nhist
!
      if (istep==0.and.nsource > 0) then
        ioutfile = 1  ! index to output file name array
        call mkdiskflnm(output(ioutfile),diskfile)
        call nc_open(ncid,diskfile,'REPLACE','WRITE')
        nhist = 1     ! one history on current output file
        call define_hist('primary')            ! define history structure
        call nc_define(ncid)  ! define netcdf file
        call nc_wrhist(ncid,iprinthist)
        ihist_total = ihist_total+1
!       write(6,"('Wrote primary   history ',i2,' (',i3,',',i2,',',i2,
!    |    ') to ',a,' (',i3,' of ',i3,')')") nhist,mtime,
!    |    trim(diskfile),ihist_total,nhist_total
        write(6,"('Wrote primary   history ',i3,',',i2,',',i2,
     |    ' to ',a,' (',i3,' of ',i3,')')") mtime,
     |    trim(diskfile),ihist_total,nhist_total
      elseif (istep > 0) then ! at least 1 step has been taken
!
! Its time to write a history (not the source history). An output file 
! should currently be open. If this file can take another history, 
! write to it, otherwise close it, save it if necessary, then open 
! and write to the next new output file. Also, if newseries is true
! open a new file (this insures that delta time between histories
! is consistent per file). The following common vars (hist.h) should 
! already be defined as follows:
! 
!   nhist:    Number of histories on current output file
!   ioutfile: Current output path name is output(ioutfile)
!
        call mkdiskflnm(output(ioutfile),diskfile)
!
! There is room for another history and we are not starting a
! new time series:
!
        if (nhist < mxhist .and. .not.newseries) then 
          nhist = nhist+1
          call define_hist('primary')
          call nc_wrhist(ncid,iprinthist)
          ihist_total = ihist_total+1
!         write(6,"('Wrote primary   history ',i2,' (',i3,',',i2,',',i2,
!    |      ') to ',a,' (',i3,' of ',i3,')')") nhist,mtime,
!    |      trim(diskfile),ihist_total,nhist_total
          write(6,"('Wrote primary   history ',i3,',',i2,',',i2,
     |      ' to ',a,' (',i3,' of ',i3,')')") mtime,
     |      trim(diskfile),ihist_total,nhist_total
        else
!
! Current file is full or we are starting a new time series, 
! so save current file (even if isave /= 1), and open the next 
! output file:
!
          if (iprint > 0) then
            if (nhist >= mxhist) then
              write(6,"('File ',a,' is full (nhist=',i2,')')")
     |          trim(diskfile),nhist
            elseif (newseries) then
              write(6,"('Starting new primary history time series,',
     |          ' so open a new file.')") 
            endif
          endif
          call savefile(ncid,diskfile,output(ioutfile),tempdir,
     |      dispose,0,iprint)
          ioutfile = ioutfile+1
!
! Make sure there is a next output file, but there should be
! because of check in input.f using nstep and mxhist:
          if (ioutfile > noutput) then
            write(6,"(/'>>> OUTPUT: need another output file.'/)") 
            stop 'output'
          endif
          call mkdiskflnm(output(ioutfile),diskfile)
          call nc_open(ncid,diskfile,'REPLACE','WRITE')
          nhist = 1 ! this is first history on the new file
          call define_hist('primary')
          call nc_define(ncid)
          call nc_wrhist(ncid,iprinthist)
          ihist_total = ihist_total+1
!         write(6,"('Wrote primary   history ',i2,' (',i3,',',i2,',',i2,
!    |      ') to ',a,' (',i3,' of ',i3,')')") nhist,mtime,
!    |      trim(diskfile),ihist_total,nhist_total
          write(6,"('Wrote primary   history ',i3,',',i2,',',i2,
     |      ' to ',a,' (',i3,' of ',i3,')')") mtime,
     |      trim(diskfile),ihist_total,nhist_total
        endif ! file full or not
      endif   ! istep and nsource
!
! Save the file if necessary:
! (if nhist==mxhist, file will be saved next call)
!
      if (istep==nstep.or.(isave > 0.and.nhist /= mxhist)) then
        ireopen = 1
        if (istep==nstep) ireopen = 0
        call savefile(ncid,diskfile,output(ioutfile),tempdir,dispose,
     |    ireopen,iprint)
      endif
      if (iprint > 0) write(6,"(72('-'),/)")
      end subroutine output_hist
!-----------------------------------------------------------------------
      subroutine output_sechist(istep,isave,newseries)
!
! Write secondary history to output disk file. If isave==1, save a
! link to tempdir, and if dispose==1 also save file to mss. 
! Current time step is istep (will be > 0).
!
      use input_module,only: secout,tempdir,dispose
      use hist_module,only: iprint,isecout,ncidsech,nsech,
     |  mtime,nsecout,nsech_total,nstep,nhist
      use netcdf_module,only: nc_open,nc_define,nc_wrhist
      implicit none
      include "params.h" ! mxhist_sech
!
! Args:
      integer,intent(in) :: 
     |  istep, ! current step this run (0->nstep)
     |  isave  ! save to mss if isave==1
      logical,intent(in) :: newseries
!
! Local:
      character(len=80) :: diskfile
      integer :: istat,ireopen,iprinthist
      integer,save :: isech_total
      data isech_total/0/
!
! Externals:
      integer,external :: iunlink
!
      diskfile = ' '
      if (iprint > 0) 
     |  write(6,"(/,72('-'),/,'Secondary History Output: istep=',i6,
     |    ' isave=',i2)") istep,isave
      if (isech_total==0) then
        iprinthist = 1
      else
        iprinthist = iprint
      endif
!
! Open new file if this is first time:
      if (isech_total==0) then
        isecout = 1   ! index to output file name array
        call mkdiskflnm(secout(isecout),diskfile)
        call nc_open(ncidsech,diskfile,'REPLACE','WRITE')
        call define_hist('secondary')
        call nc_define(ncidsech)
        nsech = 0     ! there are no histories on current output file
      else
        call mkdiskflnm(secout(isecout),diskfile)
      endif
!
! Check if there is room for another history on current file,
! and we are not starting a new time series:
      if (nsech < mxhist_sech .and. .not.newseries) then
        nsech = nsech+1
        call define_hist('secondary')
        call nc_wrhist(ncidsech,iprinthist)
        isech_total = isech_total+1
!       write(6,"('Wrote secondary history ',i2,' (',i3,',',i2,
!    |    ',',i2,') to ',a,' (',i3,' of ',i3,')')") nsech,mtime,
!    |    trim(diskfile),isech_total,nsech_total
        write(6,"('Wrote secondary history ',i3,',',i2,
     |    ',',i2,' to ',a,' (',i3,' of ',i3,')')") mtime,
     |    trim(diskfile),isech_total,nsech_total
      else
!
! Current file is full (or we are starting a new time series), so 
! save current file (even if isave /= 1), and open the next output 
! file:
        if (iprint > 0) then
          if (nsech >= mxhist_sech) then
            write(6,"('File ',a,' is full (nhist=',i2,')')")
     |        trim(diskfile),nsech
          elseif (newseries) then
            write(6,"('Starting new secondary history time series,',
     |        ' so open a new file.')") 
          endif
        endif
        call savefile(ncidsech,diskfile,secout(isecout),tempdir,
     |    dispose,0,iprint)
        isecout = isecout+1
!
! Make sure there is a next output file, but there should be
! because of check in input.f using nsech and mxhist_sech:
        if (isecout > nsecout) then
          write(6,"(/'>>> OUTPUT_sechist: need another output file.'/)") 
          stop 'output_sech'
        endif
!
! Open new file and write history:
        call mkdiskflnm(secout(isecout),diskfile)
        call nc_open(ncidsech,diskfile,'REPLACE','WRITE')
        nsech = 1 ! this is first history on the new file
        call define_hist('secondary')
        call nc_define(ncidsech)
        call nc_wrhist(ncidsech,iprinthist)
        isech_total = isech_total+1
!       write(6,"('Wrote secondary history ',i2,' (',i3,',',i2,
!    |    ',',i2,') to ',a,' (',i3,' of ',i3,')')") nsech,mtime,
!    |    trim(diskfile),isech_total,nsech_total
        write(6,"('Wrote secondary history ',i3,',',i2,
     |    ',',i2,' to ',a,' (',i3,' of ',i3,')')") mtime,
     |    trim(diskfile),isech_total,nsech_total
      endif ! file full or not
!
! Save the file if necessary:
      if (isave > 0) then
        ireopen = 1
        if (istep==nstep) ireopen = 0
        call savefile(ncidsech,diskfile,secout(isecout),tempdir,dispose,
     |    ireopen,iprint)
      endif
      if (iprint > 0) write(6,"(72('-'),/)")
      end subroutine output_sechist
!-----------------------------------------------------------------------
      subroutine savefile(ncid,diskfile,outpath,tempdir,idispose,
     |  ireopen,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,ireopen,iprint
      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:
!
      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 (ireopen > 0) 
     |  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,mtime,isecout,
     |  ioutfile,nstep_hist,nstep_sechist,nsource
      use input_module,only: output,secout,date,step,power,ctpoten,
     |  byimf,f107,f107a,mag,tide,tide2,colfac,secflds,source
      use init_module,only: rundate,runtime,logname,host,system,p0,
     |  iyear,iday,istep 
      use fields_module,only: nfprog,fprog,fsech
      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 h structure from hist.h commons:
      select case(type)
        case ('primary')
          h%ihist = nhist
          h%delhmins = nstep_hist*(step/60)
          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
        case ('secondary')
          h%ihist = nsech
          h%delhmins = nstep_sechist*(step/60)
          h%mss_path = secout(isecout)
          h%nflds = count(len_trim(fsech%name) > 0)
          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
              do i=1,h%nflds
                h%fnames(i) = fsech(i)%name
              enddo
            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%mtime = mtime
      h%time  = mtime_to_mins(mtime)
      h%iter  = mtime_to_nstep(mtime,step)
      h%ut    = float(mtime(2))+float(mtime(3))/60.
      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
