#include "rundeck_opts.h"
CAOO   Just to test CVS

      PROGRAM GISS_modelE,226
!@sum  MAIN GISS modelE main time-stepping routine
!@auth Original Development Team
!@ver  1.0 (Based originally on B399)
      USE FILEMANAGER, only : openunit,closeunit
      USE TIMINGS, only : ntimemax,ntimeacc,timing,timestr
      USE PARAM
      USE MODEL_COM
      USE DOMAIN_DECOMP, ONLY : init_app,grid,AM_I_ROOT,pack_data
      USE DOMAIN_DECOMP, ONLY : ESMF_BCAST
      USE DYNAMICS
      USE RAD_COM, only : dimrad_sv
      USE RANDOM
      USE GETTIME_MOD
#if (defined TRACERS_ON) || (defined TRACERS_OCEAN)
      USE TRACER_COM, only: mtrace
#endif
      USE DIAG_COM, only : oa,monacc,koa,acc_period
      USE SOIL_DRV, only: daily_earth, ground_e
      USE SUBDAILY, only : nsubdd,init_subdd,get_subdd,reset_subdd
      USE DIAG_SERIAL, only : print_diags
#ifdef USE_FVCORE
      USE FV_INTERFACE_MOD, only: fv_core
      USE FV_INTERFACE_MOD, only: Initialize
      USE FV_INTERFACE_MOD, only: Run
      USE FV_INTERFACE_MOD, only: Checkpoint
      USE FV_INTERFACE_MOD, only: Finalize
      USE FV_INTERFACE_MOD, only: Compute_Tendencies
      USE FV_INTERFACE_MOD, only: init_app_clock
c$$$      USE MODEL_COM, only: clock
      USE ESMF_MOD, only: ESMF_Clock
      USE ESMF_CUSTOM_MOD, Only: vm => modelE_vm
#endif
      USE ATMDYN, only : DYNAM,CALC_TROP,PGRAD_PBL,SDRAG
     &     ,DISSIP,FILTER,CALC_AMPK, COMPUTE_DYNAM_AIJ_DIAGNOSTICS
     &     ,COMPUTE_WSAVE, getTotalEnergy, addEnergyAsDiffuseHeat
#ifdef TRACERS_ON
     &     ,trdynam
#endif
      USE ATMDYN_QDYNAM, only : QDYNAM
      use soil_drv, only : conserv_wtg, conserv_htg
      IMPLICIT NONE

      INTEGER K,M,MSTART,MNOW,MODD5D,months,ioerr,Ldate,istart
      INTEGER iu_VFLXO,iu_ACC,iu_RSF,iu_ODA
      INTEGER :: mpi_err, MDUM = 0

      REAL*8, DIMENSION(NTIMEMAX) :: PERCENT
      REAL*8 DTIME,TOTALT , oa_glob(im,jm,koa)

      CHARACTER aDATE*14
      CHARACTER*8 :: flg_go='___GO___'      ! green light
      integer :: iflag=1
      external sig_stop_model

C**** Command line options
      LOGICAL :: qcrestart=.false.
      CHARACTER*32 :: ifile
      real :: lat_min=-90.,lat_max=90.,longt_min=0.,longt_max=360.
      integer :: tloopbegin, tloopend
#ifdef USE_FVCORE
      Character(Len=*), Parameter :: fv_config = 'fv_config.rc'
      Type (FV_CORE) :: fv
      Type (ESMF_CLOCK) :: clock
      character(len=28) :: fv_fname, fv_dfname
#endif
      integer :: L
      real*8 :: initialTotalEnergy, finalTotalEnergy
      ! tmp arrays
      real*8 w_ghy_j_2(jm),w_ghy_j_1(jm), w_lake_j_2(jm),w_lake_j_1(jm)
      real*8 h_ghy_j_2(jm),h_ghy_j_1(jm), h_lake_j_2(jm),h_lake_j_1(jm)

      call init_app(grid,im,jm,lm)
      call alloc_drv()
C****
C**** Processing command line options
C****
      call read_options( qcrestart, ifile )
      if ( qcrestart ) then
        call print_restart_info
        call stop_model("Terminated normally: printed restart info",-1)
      endif
C****
C**** INITIALIZATIONS
C****
         CALL TIMER (MNOW,MDUM)

#ifdef USE_FVCORE
      CALL INPUT (istart,ifile,clock)
#else
      CALL INPUT (istart,ifile)
#endif

C**** Set run_status to "run in progress"
      if(istart > 0) call write_run_status("Run in progress...",1)

C****
C**** If run is already done, just produce diagnostic printout
C****
      IF (Itime.GE.ItimeE.and.Kradia.le.0) then ! includes ISTART<1 case
        if (ItimeE.gt.0) then
          months=(Jyear-Jyear0)*JMperY + JMON-JMON0
          call aPERIOD (JMON0,JYEAR0,months,1,0, acc_period,Ldate)
        end if
        call print_diags(0)
        if(istart < 1) then
          call stop_model ('Finished post-processing',-1)
        else
          call stop_model ('The run has already completed',13)
        end if
        ! no output files are affected
      END IF

      IF (AM_I_ROOT()) Then
         open(3,file='flagGoStop',form='FORMATTED',status='REPLACE')
         write (3,'(A8)') flg_go
         close (3)
      END IF
      call sys_signal( 15, sig_stop_model )  ! works only on single CPU
         MSTART=MNOW
         DO M=1,NTIMEACC
           MSTART= MSTART-TIMING(M)
         END DO
C**** INITIALIZE TIME PARAMETERS
      NSTEP=(Itime-ItimeI)*NIdyn
         MODD5K=1000
      CALL DAILY(.false.)                  ! not end_of_day
      CALL daily_RAD(.false.)
      if (istart.le.9) call reset_diag(0)
      if(Kradia==10) call daily_OCEAN(.false.) ! to test OCLIM
      if (Kradia.le.0) then
        CALL daily_EARTH(.false.)          ! not end_of_day
        CALL daily_OCEAN(.false.)          ! not end_of_day
        CALL CALC_AMPK(LS1-1)
#if (defined TRACERS_ON) || (defined TRACERS_OCEAN)
        CALL daily_tracer(0)
#endif
           if (kradia.le.0) CALL CHECKT ('INPUT ')
      end if
      CALL UPDTYPE

C****
C**** Initialize FV dynamical core (ESMF component) if requested
C****
#ifdef USE_FVCORE
      Call Initialize(fv, istart, vm, grid%esmf_grid, clock,fv_config)
#endif

      if (AM_I_ROOT())
     *   WRITE (6,'(A,11X,A4,I5,A5,I3,A4,I3,6X,A,I4,I10)')
     *   '0NASA/GISS Climate Model (re)started',
     *   'Year',JYEAR,aMON,JDATE,', Hr',JHOUR,
     *   'Internal clock: DTsrc-steps since 1/1/',Iyear1,ITIME
         CALL TIMER (MNOW,MELSE)
C****
C**** Open and position output history files if needed
C****
C**** Monthly files
      if (Kradia.ne.0 .and. Kradia<10) then
        write(aDATE(1:7),'(a3,I4.4)') aMON(1:3),Jyear
        if (Kradia.gt.0) aDATE(4:7)='    '
        call openunit(trim('RAD'//aDATE(1:7)),iu_RAD,.true.,.false.)
        if (Kradia.lt.0) call io_POS(iu_RAD,Itime-1,2*dimrad_sv,Nrad)
      end if
C**** Files for an accumulation period (1-12 months)
      write(aDATE(1:7),'(a3,I4.4)') aMON0(1:3),Jyear0
      if (Kvflxo.ne.0) then
        call openunit('VFLXO'//aDATE(1:7),iu_VFLXO,.true.,.false.)
        call io_POS(iu_VFLXO,Itime,2*im*jm*koa,Nday) ! real*8-dim -> 2*
      end if
C**** Initiallise file for sub-daily diagnostics, controlled by
C**** space-separated string segments in SUBDD & SUBDD1 in the rundeck
      call init_subdd(aDATE)
      call sys_flush(6)
C****
C**** MAIN LOOP
C****
      call gettime(tloopbegin)
      DO WHILE (Itime.lt.ItimeE)

c$$$         call test_save(__LINE__, itime)
C**** Every Ndisk Time Steps (DTsrc), starting with the first one,
C**** write restart information alternately onto 2 disk files
      IF (MOD(Itime-ItimeI,Ndisk).eq.0) THEN
         CALL RFINAL (IRAND)
         call set_param( "IRAND", IRAND, 'o' )
         iu_RSF=-1
         IF (AM_I_ROOT())
     *        call openunit(rsf_file_name(KDISK),iu_RSF,.true.,.false.)
         call io_rsf(iu_RSF,Itime,iowrite,ioerr)
         IF (AM_I_ROOT()) call closeunit(iu_RSF)
#ifdef USE_FVCORE
         fv_fname='fv.'   ; write(fv_fname(4:4),'(i1)') kdisk
         fv_dfname='dfv.' ; write(fv_dfname(5:5),'(i1)') kdisk
         call Checkpoint(fv, clock, fv_fname, fv_dfname)
#endif
         if (AM_I_ROOT())
     *        WRITE (6,'(A,I1,45X,A4,I5,A5,I3,A4,I3,A,I8)')
     *     '0Restart file written on fort.',KDISK,'Year',
     *     JYEAR,aMON,JDATE,', Hr',JHOUR,'  Internal clock time:',ITIME
         KDISK=3-KDISK
         CALL TIMER (MNOW,MELSE)
      END IF
C**** THINGS THAT GET DONE AT THE BEGINNING OF EVERY DAY
      IF (MOD(Itime,NDAY).eq.0) THEN
C**** INITIALIZE SOME DIAG. ARRAYS AT THE BEGINNING OF SPECIFIED DAYS
        if (kradia.le.0) call daily_DIAG
C**** THINGS THAT GET DONE AT THE BEGINNING OF EVERY MONTH
        IF ( JDAY.eq.1+JDendOfM(Jmon-1) ) then
          write(aDATE(1:7),'(a3,I4.4)') aMON(1:3),Jyear
          if (Kradia.ne.0 .and. Kradia<10) then
            if (Kradia.gt.0) aDATE(4:7)='    '
            call closeunit( iu_RAD )
            call openunit(trim('RAD'//aDATE(1:7)),iu_RAD,.true.,.false.)
          end if
C**** THINGS THAT GET DONE AT THE BEGINNING OF EVERY ACC.PERIOD
          months=(Jyear-Jyear0)*JMperY + JMON-JMON0
          if ( months.ge.NMONAV ) then
            call reset_DIAG(0)
            if (Kvflxo.ne.0) then
              call closeunit( iu_VFLXO )
              call openunit('VFLXO'//aDATE(1:7),iu_VFLXO,.true.,.false.)
            end if
C**** reset sub-daily diag files
            call reset_subdd(aDATE)
          end if   !  beginning of acc.period
        END IF     !  beginning of month
      END IF       !  beginning of day
C****
C**** INTEGRATE DYNAMIC TERMS (DIAGA AND DIAGB ARE CALLED FROM DYNAM)
C****
      if(Kradia>9) go to 100 ! to test daily/monthly procedures fast
      CALL CHECKT ('DYNAM0')
      if (kradia.le.0) then                   ! full model,kradia le 0
         MODD5D=MOD(Itime-ItimeI,NDA5D)
         IF (MODD5D.EQ.0) IDACC(7)=IDACC(7)+1
         IF (MODD5D.EQ.0) CALL DIAG5A (2,0)
         IF (MODD5D.EQ.0) CALL DIAGCA (1)


      PTOLD = P ! save for clouds
C**** Initialize pressure for mass fluxes used by tracers and Q
      PS (:,:)   = P(:,:)

C**** Initialise total energy (J/m^2)
      initialTotalEnergy = getTotalEnergy()

#ifndef USE_FVCORE
      CALL DYNAM()
#else
      ! Using FV instead
         IF (MOD(Itime-ItimeI,NDAA).eq.0) CALL DIAGA0
      call Run(fv, clock)

      CALL SDRAG (DTsrc)
         if (MOD(Itime-ItimeI,NDAA).eq.0) THEN
           call DIAGA
           call DIAGB
           call EPFLUX (U,V,T,P)
         endif

#endif
C**** This fix adjusts thermal energy to conserve total energy TE=KE+PE
C**** Currently energy is put in uniformly weighted by mass
      finalTotalEnergy = getTotalEnergy()
      call addEnergyAsDiffuseHeat(finalTotalEnergy - initialTotalEnergy)
      call COMPUTE_DYNAM_AIJ_DIAGNOSTICS(PUA, PVA, DT)
      SD_CLOUDS(:,:,:) = CONV(:,:,:)
      call COMPUTE_WSAVE(wsave, sda, T, PK, PEDN, NIdyn)

C**** Scale WM mixing ratios to conserve liquid water
!$OMP  PARALLEL DO PRIVATE (L)
      DO L=1,LS1-1
        WM(:,:,L)=WM(:,:,L)* (PTOLD/P)
      END DO
!$OMP  END PARALLEL DO

      CALL QDYNAM  ! Advection of Q by integrated fluxes
         CALL TIMER (MNOW,MDYN)
#ifdef TRACERS_ON
      CALL TrDYNAM   ! tracer dynamics
         CALL TIMER (MNOW,MTRACE)
#endif
C****
C**** Calculate tropopause level and pressure
C****
      CALL CALC_TROP
C**** calculate some dynamic variables for the PBL
      CALL PGRAD_PBL
C**** calculate zenith angle for current time step
      CALL CALC_ZENITH_ANGLE

         CALL CHECKT ('DYNAM ')
         CALL TIMER (MNOW,MSURF)
         IF (MODD5D.EQ.0) CALL DIAG5A (7,NIdyn)
         IF (MODD5D.EQ.0) CALL DIAGCA (2)
         IF (MOD(Itime,NDAY/2).eq.0) CALL DIAG7A
C****
C**** INTEGRATE SOURCE TERMS
C****
         IDACC(1)=IDACC(1)+1
         MODD5S=MOD(Itime-ItimeI,NDA5S)
         IF (MODD5S.EQ.0) IDACC(8)=IDACC(8)+1
         IF (MODD5S.EQ.0.AND.MODD5D.NE.0) CALL DIAG5A (1,0)
         IF (MODD5S.EQ.0.AND.MODD5D.NE.0) CALL DIAGCA (1)

C**** FIRST CALL MELT_SI SO THAT TOO SMALL ICE FRACTIONS ARE REMOVED
C**** AND ICE FRACTION CAN THEN STAY CONSTANT UNTIL END OF TIMESTEP
      CALL MELT_SI
         CALL UPDTYPE
         CALL TIMER (MNOW,MSURF)
C**** CONDENSATION, SUPER SATURATION AND MOIST CONVECTION
      CALL CONDSE
         CALL CHECKT ('CONDSE')
         CALL TIMER (MNOW,MCNDS)
         IF (MODD5S.EQ.0) CALL DIAG5A (9,NIdyn)
         IF (MODD5S.EQ.0) CALL DIAGCA (3)
      end if                                  ! full model,kradia le 0
C**** RADIATION, SOLAR AND THERMAL
      MODRD=MOD(Itime-ItimeI,NRAD)
      if (kradia.le.0. or. MODRD.eq.0) then
         CALL RADIA
         if (kradia.le.0) CALL CHECKT ('RADIA ')
      end if
         CALL TIMER (MNOW,MRAD)
      if (kradia.le.0) then                    ! full model,kradia le 0
         IF (MODD5S.EQ.0) CALL DIAG5A (11,NIdyn)
C****
C**** SURFACE INTERACTION AND GROUND CALCULATION
C****
C**** NOTE THAT FLUXES ARE APPLIED IN TOP-DOWN ORDER SO THAT THE
C**** FLUXES FROM ONE MODULE CAN BE SUBSEQUENTLY APPLIED TO THAT BELOW
C****
         IF (MODD5S.EQ.0) CALL DIAGCA (4)
C**** APPLY PRECIPITATION TO SEA/LAKE/LAND ICE
      CALL PRECIP_SI
      CALL PRECIP_LI
C**** APPLY PRECIPITATION AND RUNOFF TO LAKES/OCEANS
      CALL PRECIP_LK
      CALL PRECIP_OC
         CALL TIMER (MNOW,MSURF)
         CALL CHECKT ('PRECIP')
#ifdef TRACERS_ON
C**** Calculate non-interactive tracer surface sources and sinks
         call set_tracer_2Dsource
         CALL TIMER (MNOW,MTRACE)
#endif
C**** CALCULATE SURFACE FLUXES AND EARTH
      CALL SURFCE
         CALL CHECKT ('SURFCE')
         CALL TIMER (MNOW,MSURF)
         IF (MODD5S.EQ.0) CALL DIAGCA (5)
C**** CALCULATE ICE DYNAMICS
      CALL DYNSI
C**** CALCULATE BASE ICE-OCEAN/LAKE FLUXES
      CALL UNDERICE
C**** APPLY SURFACE/BASE FLUXES TO SEA/LAKE ICE
      CALL GROUND_SI
C**** APPLY SURFACE FLUXES TO LAND ICE
      CALL GROUND_LI
         CALL CHECKT ('GRNDSI')
C**** APPLY FLUXES TO LAKES AND DETERMINE ICE FORMATION
      CALL GROUND_LK
         CALL CHECKT ('GRNDLK')
         CALL TIMER (MNOW,MSURF)
         IF (MODD5S.EQ.0) CALL DIAGCA (6)
C**** CALCULATE RIVER RUNOFF FROM LAKE MASS
      CALL RIVERF
      CALL GROUND_E    ! diagnostic only - should be merged with EARTH
C**** APPLY FLUXES TO OCEAN, DO OCEAN DYNAMICS AND CALC. ICE FORMATION
      CALL OCEANS
         CALL CHECKT ('OCEANS')
C**** APPLY ICE FORMED IN THE OCEAN/LAKES TO ICE VARIABLES
      CALL FORM_SI
         CALL CHECKT ('FORMSI')
C**** IF ATURB is used in rundeck then this is a dummy call
C**** CALCULATE DRY CONVECTION ABOVE PBL
      CALL ATM_DIFFUS (2,LM-1,dtsrc)
         CALL CHECKT ('DRYCNV')
         CALL TIMER (MNOW,MSURF)
         IF (MODD5S.EQ.0) CALL DIAGCA (9)
C**** ADVECT ICE
      CALL ADVSI
      CALL ADVSI_DIAG ! needed to update qflux model, dummy otherwise
         CALL CHECKT ('ADVSI ')
C**** UPDATE DIAGNOSTIC TYPES
      CALL UPDTYPE
C**** ADD DISSIPATED KE FROM SURFACE CALCULATION BACK AS LOCAL HEAT
      CALL DISSIP
         CALL CHECKT ('DISSIP')
         CALL TIMER (MNOW,MSURF)
         IF (MODD5S.EQ.0) CALL DIAGCA (7)
         IF (MODD5S.EQ.0) CALL DIAG5A (12,NIdyn)

C**** SEA LEVEL PRESSURE FILTER
      IF (MFILTR.GT.0.AND.MOD(Itime-ItimeI,NFILTR).EQ.0) THEN
           IDACC(10)=IDACC(10)+1
           IF (MODD5S.NE.0) CALL DIAG5A (1,0)
           CALL DIAGCA (1)
        CALL FILTER
           CALL CHECKT ('FILTER')
           CALL TIMER (MNOW,MDYN)
           CALL DIAG5A (14,NFILTR*NIdyn)
           CALL DIAGCA (8)
      END IF
#ifdef TRACERS_ON
C**** 3D Tracer sources and sinks
C**** Tracer gravitational settling for aerosols
      CALL TRGRAV
C**** Tracer radioactive decay (and possible source)
      CALL TDECAY
C**** Calculate 3D tracers sources and sinks

      call tracer_3Dsource
C**** Accumulate tracer distribution diagnostics
      CALL TRACEA
         CALL TIMER (MNOW,MTRACE)
         CALL CHECKT ('T3DSRC')
#endif
      end if                                  ! full model,kradia le 0
C****
C**** WRITE SUB-DAILY DIAGNOSTICS EVERY NSUBDD hours
C****
      if (Nsubdd.ne.0) then
        if (mod(Itime+1,Nsubdd).eq.0) call get_subdd
      end if
#ifdef TRACERS_DUST
      call ahourly
#endif
C****
C**** UPDATE Internal MODEL TIME AND CALL DAILY IF REQUIRED
C****
  100 Itime=Itime+1                       ! DTsrc-steps since 1/1/Iyear1
      Jhour=MOD(Itime*24/NDAY,24)         ! Hour (0-23)
      Nstep=Nstep+NIdyn                   ! counts DT(dyn)-steps

      IF (MOD(Itime,NDAY).eq.0) THEN      ! NEW DAY
      if (kradia.gt.0) then               ! radiative forcing run
        CALL DAILY(.false.)
        if(Kradia<10)  CALL daily_RAD(.true.)
        if(Kradia==10) CALL daily_OCEAN(.true.) ! to test OCLIM
        months=(Jyear-Jyear0)*JMperY + JMON-JMON0
      else                                ! full model, kradia le 0
           CALL DIAG5A (1,0)
           CALL DIAGCA (1)
        CALL DAILY(.true.)                 ! end_of_day
        CALL daily_RAD(.true.)
        months=(Jyear-Jyear0)*JMperY + JMON-JMON0
           CALL TIMER (MNOW,MELSE)
cddd           call conserv_wtg(w_ghy_j_1)
cddd           call conserv_LKM(w_lake_j_1)
cddd           call conserv_htg(h_ghy_j_1)
cddd           call conserv_LKE(h_lake_j_1)
        call daily_LAKE
        call daily_EARTH(.true.)           ! end_of_day
cddd           call conserv_wtg(w_ghy_j_2)
cddd           call conserv_LKM(w_lake_j_2)
cddd           call conserv_htg(h_ghy_j_2)
cddd           call conserv_LKE(h_lake_j_2)
cddd           print *,"GHY_LAKE_CONSERV:",
cddd     &          sum( w_ghy_j_1+w_lake_j_1 ),
cddd     &          sum( w_ghy_j_2-w_ghy_j_1+w_lake_j_2-w_lake_j_1 ),
cddd     &          sum( h_ghy_j_1+h_lake_j_1 ),
cddd     &          sum( h_ghy_j_2-h_ghy_j_1+h_lake_j_2-h_lake_j_1 )
cddd            print *,"GHY_LAKE tot hgy, tot lake, d ghy, d lake",
cddd     &          sum( w_ghy_j_1 ), sum( w_lake_j_1 ),
cddd     &          sum( w_ghy_j_2-w_ghy_j_1 ),
cddd     &          sum( w_lake_j_2-w_lake_j_1 )
cddd  !          print *,"GHY_LAKE errors:",
cddd  !   &           w_ghy_j_2-w_ghy_j_1+w_lake_j_2-w_lake_j_1
cddd            print *,"GHY_LAKE_E tot hgy, tot lake, d ghy, d lake",
cddd     &          sum( h_ghy_j_1 ), sum( h_lake_j_1 ),
cddd     &          sum( h_ghy_j_2-h_ghy_j_1 ),
cddd     &          sum( h_lake_j_2-h_lake_j_1 )
cddd            print *,"GHY_LAKE errors:",
cddd     &           h_ghy_j_2-h_ghy_j_1+h_lake_j_2-h_lake_j_1
        call daily_OCEAN(.true.)           ! end_of_day
        call daily_ICE
        call daily_LI
#if (defined TRACERS_ON) || (defined TRACERS_OCEAN)
        call daily_tracer(1)
           CALL TIMER (MNOW,MTRACE)
#endif
           CALL CHECKT ('DAILY ')
           CALL TIMER (MNOW,MSURF)
           CALL DIAG5A (16,NDAY*NIdyn)
           CALL DIAGCA (10)
        call sys_flush(6)
      end if   ! kradia: full model (or rad.forcing run)
      CALL UPDTYPE
      END IF   !  NEW DAY

#ifdef USE_FVCORE
      Call Compute_Tendencies(fv)
#endif

      if (kradia.le.0) then   ! full model
C****
C**** WRITE INFORMATION FOR OHT CALCULATION EVERY 24 HOURS
C****
      IF (Kvflxo.EQ.0.) OA(:,:,4:KOA)=0. ! to prepare for future saves
      IF (Kvflxo.NE.0.) THEN
         IF (MOD(Itime,NDAY).eq.0) THEN
            call pack_data (grid, OA, OA_glob)
            if (am_I_root())
     *         call WRITEI8 (iu_vflxo,Itime,OA_glob,im*jm*koa)
C**** ZERO OUT INTEGRATED QUANTITIES
            OA(:,:,4:KOA)=0.
         ELSEIF (MOD(Itime,NDAY/2).eq.0) THEN
            call vflx_OCEAN
         END IF
         CALL TIMER (MNOW,MELSE)
      END IF

C****
C**** CALL DIAGNOSTIC ROUTINES
C****
      IF (MOD(Itime-ItimeI,NDA4).EQ.0) CALL DIAG4A ! at hr 23 E-history
C**** PRINT CURRENT DIAGNOSTICS (INCLUDING THE INITIAL CONDITIONS)
      IF (NIPRNT.GT.0) THEN
        acc_period='PARTIAL      '
        call print_diags(1)
        NIPRNT=NIPRNT-1
        call set_param( "NIPRNT", NIPRNT, 'o' )
      END IF
      end if   ! full model ; kradia le 0

C**** THINGS TO DO BEFORE ZEROING OUT THE ACCUMULATING ARRAYS
C****    done at the end of (selected) months
      IF (months.ge.NMONAV .and.   ! next 2 conditions are rarely needed
     *    JDAY.eq.1+JDendOfM(JMON-1) .and. MOD(Itime,NDAY).eq.0) THEN

C**** PRINT DIAGNOSTIC TIME AVERAGED QUANTITIES
      call aPERIOD (JMON0,JYEAR0,months,1,0, aDATE(1:12),Ldate)
      acc_period=aDATE(1:12)
      WRITE (aDATE(8:14),'(A3,I4.4)') aMON(1:3),JYEAR
      if (kradia.le.0) call print_diags(0)
C**** SAVE ONE OR BOTH PARTS OF THE FINAL RESTART DATA SET
        IF (KCOPY.GT.0) THEN
C**** KCOPY > 0 : SAVE THE DIAGNOSTIC ACCUM ARRAYS IN SINGLE PRECISION
          monacc = 0
          do k=JMON0,JMON0+NMONAV-1
            m = k
            if(m.gt.12) m = m-12
            monacc(m) = 1
          end do
          If (AM_I_ROOT())
     *       call openunit(aDATE(1:7)//'.acc'//XLABEL(1:LRUNID),iu_ACC,
     *        .true.,.false.)
          call io_rsf (iu_ACC,Itime,iowrite_single,ioerr)
          If (AM_I_ROOT()) call closeunit(iu_ACC)
C**** KCOPY > 1 : ALSO SAVE THE RESTART INFORMATION
          IF (KCOPY.GT.1) THEN
            CALL RFINAL (IRAND)
            call set_param( "IRAND", IRAND, 'o' )
            IF (AM_I_ROOT())
     *          call openunit('1'//aDATE(8:14)//'.rsf'//XLABEL(1:LRUNID)
     *           ,iu_RSF,.true.,.false.)
            call io_rsf(iu_RSF,Itime,iowrite_mon,ioerr)
            IF (AM_I_ROOT()) call closeunit(iu_RSF)
#ifdef USE_FVCORE
            fv_fname  = '1'//aDATE(8:14)//'.fv'//XLABEL(1:LRUNID)
            fv_dfname = '1'//aDATE(8:14)//'.dfv'//XLABEL(1:LRUNID)
            call Checkpoint(fv, clock, fv_fname, fv_dfname)
#endif
          END IF
C**** KCOPY > 2 : ALSO SAVE THE OCEAN DATA TO INITIALIZE DEEP OCEAN RUNS
          IF (KCOPY.GT.2) THEN
            If (AM_I_ROOT())
     *           call openunit(aDATE(1:7)//'.oda'//XLABEL(1:LRUNID)
     *           ,iu_ODA,.true.,.false.)
            call io_oda(iu_ODA,Itime,iowrite,ioerr)
            IF (AM_I_ROOT()) call closeunit(iu_ODA)
          END IF
        END IF

C**** PRINT AND ZERO OUT THE TIMING NUMBERS
        CALL TIMER (MNOW,MDIAG)
        TOTALT=SUM(TIMING(1:NTIMEACC))
        DO M=1,NTIMEACC
          PERCENT(M) = 100d0*TIMING(M)/(TOTALT+.00001)
        END DO
c        TOTALT=(MNOW-MSTART)/(60.*100.) ! wrong when clock rolls over
        TOTALT=TOTALT/(60.*100.)           ! in minutes
        DTIME = NDAY*TOTALT/(Itime-Itime0)        ! minutes/day
        WRITE (6,'(/A,F7.2,A,/(8(A13,F5.1/))//)')
     *   '0TIME',DTIME,'(MINUTES) ',(TIMESTR(M),PERCENT(M),M=1,NTIMEACC)
        TIMING = 0
        MSTART= MNOW
      END IF

C**** CPU TIME FOR CALLING DIAGNOSTICS
      CALL TIMER (MNOW,MDIAG)
C**** TEST FOR TERMINATION OF RUN
ccc
      IF (MOD(Itime,Nssw).eq.0) then
       IF (AM_I_ROOT()) then
        flg_go = '__STOP__'     ! stop if flagGoStop if missing
        iflag=0
        open(3,file='flagGoStop',form='FORMATTED',status='OLD',err=210)
        read (3,'(A8)',end=210) flg_go
        close (3)
 210    continue
        IF (flg_go .eq. '___GO___') iflag=1
        call ESMF_BCAST( grid, iflag)
       else
        call ESMF_BCAST( grid, iflag)
        if (iflag .eq. 1) flg_go = '___GO___'
        if (iflag .eq. 0) flg_go = '__STOP__'
       end if
      endif
      IF (flg_go.ne.'___GO___' .or. stop_on) THEN
C**** Flag to continue run has been turned off
         WRITE (6,'("0Flag to continue run has been turned off.")')
         EXIT
      END IF

c$$$      call test_save(__LINE__, itime-1)
      END DO

      call gettime(tloopend)
      if (AM_I_ROOT())
     *     write(*,*) "Time spent in the main loop in seconds:",
     *     .01*(tloopend-tloopbegin)
C****
C**** END OF MAIN LOOP
C****

C**** ALWAYS PRINT OUT RSF FILE WHEN EXITING
      CALL RFINAL (IRAND)
      call set_param( "IRAND", IRAND, 'o' )
      IF (AM_I_ROOT())
     *     call openunit(rsf_file_name(KDISK),iu_RSF,.true.,.false.)
      call io_rsf(iu_RSF,Itime,iowrite,ioerr)
      IF (AM_I_ROOT()) call closeunit(iu_RSF)
#ifdef USE_FVCORE
         fv_fname='fv.' ; write(fv_fname(4:4),'(i1)') kdisk
         fv_dfname='dfv.' ; write(fv_dfname(5:5),'(i1)') kdisk
         call Finalize(fv, clock, fv_fname, fv_dfname)
#endif
      if (AM_I_ROOT()) then
      WRITE (6,'(A,I1,45X,A4,I5,A5,I3,A4,I3,A,I8)')
     *  '0Restart file written on fort.',KDISK,'Year',JYEAR,
     *     aMON,JDATE,', Hr',JHOUR,'  Internal clock time:',ITIME
      end if

C**** RUN TERMINATED BECAUSE IT REACHED TAUE (OR SS6 WAS TURNED ON)
      IF (AM_I_ROOT())
     *   WRITE (6,'(/////4(1X,33("****")/)//,A,I8
     *             ///4(1X,33("****")/))')
     *  ' PROGRAM TERMINATED NORMALLY - Internal clock time:',ITIME

      IF (Itime.ge.ItimeE) CALL stop_model (
     &     'Terminated normally (reached maximum time)',13)
      CALL stop_model ('Run stopped with sswE',12)  ! voluntary stop

      END



      subroutine sig_stop_model,1
      USE MODEL_COM, only : stop_on
      implicit none
      stop_on = .true.
      end subroutine sig_stop_model



      subroutine init_Model 1,36
!@sum This program reads most of parameters from the database (DB)
!@+   get_param( "A", X ) reads parameter A into variable X
!@+   if "A" is not in the database, it will generate an error
!@+   message and stop
!@+   sync_param( "B", Y ) reads parameter B into variable Y
!@+   if "B" is not in the database, then Y is unchanged and its
!@+   value is saved in the database as "B" (here sync = synchronize)
      USE MODEL_COM, only : JM,LM,NIPRNT,MFILTR,NFILTR,NRAD
     *     ,NDASF,NDA4,NDA5S,NDA5K,NDA5D,NDAA,Kvflxo,kradia
     *     ,NMONAV,Ndisk,Nssw,KCOPY,KOCEAN,NIsurf,iyear1
     $     ,LS1,IRAND,ItimeI,PSTRAT,UOdrag
     $     ,X_SDRAG,C_SDRAG,LSDRAG,P_SDRAG,LPSDRAG,PP_SDRAG,ang_sdrag
     $     ,P_CSDRAG,CSDRAGL,Wc_Jdrag,COUPLED_CHEM,dt
     *     ,DT_XUfilter,DT_XVfilter,DT_YVfilter,DT_YUfilter,QUVfilter
     &     ,do_polefix,pednl00,pmidl00
      USE DOMAIN_DECOMP, only: AM_I_ROOT
      USE PARAM
      implicit none
      INTEGER L,LCSDRAG

C**** Rundeck parameters:
      call sync_param( "NMONAV", NMONAV )
      call sync_param( "NIPRNT", NIPRNT )
      call sync_param( "DT_XVfilter", DT_XVfilter )
      call sync_param( "DT_XUfilter", DT_XUfilter )
      call sync_param( "DT_YVfilter", DT_YVfilter )
      call sync_param( "DT_YUfilter", DT_YUfilter )
      call sync_param( "MFILTR", MFILTR )
      call sync_param( "X_SDRAG", X_SDRAG, 2 )
      call sync_param( "C_SDRAG", C_SDRAG )
      call sync_param( "P_CSDRAG", P_CSDRAG )
      call sync_param( "P_SDRAG", P_SDRAG )
      call sync_param( "PP_SDRAG", PP_SDRAG )
      call sync_param( "ANG_SDRAG", ANG_SDRAG )
      call sync_param( "Wc_Jdrag", Wc_Jdrag )
      call sync_param( "do_polefix", do_polefix )
      call sync_param( "NDASF", NDASF )
      call sync_param( "NDA4", NDA4 ) !!
      call sync_param( "NDA5S", NDA5S ) !!
      call sync_param( "NDA5K", NDA5K ) !!
      call sync_param( "NDA5D", NDA5D ) !!
      call sync_param( "NDAA", NDAA ) !!
      call sync_param( "NFILTR", NFILTR ) !!
      call sync_param( "NRAD", NRAD ) !!
      call sync_param( "Kvflxo", Kvflxo ) !!
      call sync_param( "Ndisk", Ndisk )
      call sync_param( "Nssw", Nssw )
      call sync_param( "KCOPY", KCOPY )
      call sync_param( "KOCEAN", KOCEAN )
      call sync_param( "KRADIA", KRADIA )
      call sync_param( "NIsurf", NIsurf )
      call sync_param( "UOdrag", UOdrag )
      call sync_param( "IRAND", IRAND )
      call sync_param( "COUPLED_CHEM", COUPLED_CHEM )

C**** Non-Rundeck parameters

C**** Calculate levels for application of SDRAG: LSDRAG,LPSDRAG->LM i.e.
C**** all levels above and including P_SDRAG mb (PP_SDRAG near poles)
C**** If P is the edge between 2 levels, take the higher level.
C**** Also find CSDRAGL, the coefficients of C_Sdrag as a function of L

      LSDRAG=LM ; LPSDRAG=LM ; LCSDRAG=LM ; CSDRAGL=C_SDRAG
      DO L=1,LM
        IF (PEDNL00(L+1)-1d-5.lt.P_SDRAG .and.
     *      PEDNL00(L)  +1d-5.gt.P_SDRAG)         LSDRAG=L
        IF (PEDNL00(L+1)-1d-5.lt.PP_SDRAG .and.
     *      PEDNL00(L)  +1d-5.gt.PP_SDRAG)        LPSDRAG=L
        IF (PEDNL00(L+1)-1d-5.lt.P_CSDRAG .and.
     *      PEDNL00(L)  +1d-5.gt.P_CSDRAG)        LCSDRAG=L
      END DO
      DO L=LCSDRAG,LSDRAG-1
         CSDRAGL(L) = C_SDRAG + max( 0.d0 , (X_SDRAG(1)-C_SDRAG) *
     *     LOG(P_CSDRAG/(PMIDL00(L))) / LOG(P_CSDRAG/P_SDRAG) )
      END DO
      if (AM_I_ROOT()) then
         WRITE(6,*) "Levels for  LSDRAG =",LSDRAG ,"->",LM
         WRITE(6,*) "Levels for LPSDRAG =",LPSDRAG,"->",LM," near poles"
         WRITE(6,*) "C_SDRAG coefficients:",CSDRAGL(LS1:LSDRAG-1)
      end if

C**** Determine if FLTRUV is called.
      QUVfilter = .false.
      if (DT_XUfilter>0. .or. DT_XVfilter>0. .or.
     *    DT_YUfilter>0. .or. DT_YVfilter>0.)  QUVfilter = .true.
      if (QUVfilter) then
         if (DT_XUfilter > 0. .and. DT_XUfilter < DT) then
             DT_XUfilter = DT
             WRITE(6,*) "DT_XUfilter too small; reset to :",DT_XUfilter
         end if
         if (DT_XVfilter > 0. .and. DT_XVfilter < DT) then
             DT_XVfilter = DT
             WRITE(6,*) "DT_XVfilter too small; reset to :",DT_XVfilter
         end if
         if (DT_YUfilter > 0. .and. DT_YUfilter < DT) then
             DT_YUfilter = DT
             WRITE(6,*) "DT_YUfilter too small; reset to :",DT_YUfilter
         end if
         if (DT_YVfilter > 0. .and. DT_YVfilter < DT) then
             DT_YVfilter = DT
             WRITE(6,*) "DT_YVfilter too small; reset to :",DT_YVfilter
         end if
      end if
c Warn if polar fixes requested for a model not having a half polar box
c     if(do_polefix.eq.1 .and. jm.ne.46) then
c        do_polefix = 0
c        write(6,*) 'Polar fixes are currently applicable only to'//
c    &           'models having a half polar box; no fixes applied'
c     endif
      RETURN
C****
      end subroutine init_Model

#ifdef USE_FVCORE

      SUBROUTINE INPUT (istart,ifile,clock) 2,187
#else

      SUBROUTINE INPUT (istart,ifile) 2,187
#endif
C****
C**** THIS SUBROUTINE SETS THE PARAMETERS IN THE C ARRAY, READS IN THE
C**** INITIAL CONDITIONS, AND CALCULATES THE DISTANCE PROJECTION ARRAYS
C****
      USE FILEMANAGER, only : openunit,closeunit,nameunit
      USE TIMINGS, only : timing,ntimeacc
      USE PARAM
      USE PARSER
      USE CONSTANT, only : grav,kapa,sday,by3
      USE MODEL_COM, only : im,jm,lm,wm,u,v,t,p,q,fearth0,fland
     *     ,focean,flake0,flice,hlake,zatmo,plbot,sig,dsig,sige,kradia
     *     ,bydsig,xlabel,lrunid,nmonav,qcheck,irand,ptop
     *     ,nisurf,nidyn,nday,dt,dtsrc,kdisk,jmon0,jyear0
     *     ,iyear1,itime,itimei,itimee
     *     ,ls1,psfmpt,pstrat,idacc,jyear,jmon,jday,jdate,jhour
     *     ,aMONTH,jdendofm,jdpery,aMON,aMON0,ioread,irerun
     *     ,ioread_single,irsfic,irsficnt,iowrite_single,ioreadnt
     *     ,irsficno,mdyn,mcnds,mrad,msurf,mdiag,melse,Itime0,Jdate0
     *     ,Jhour0,rsf_file_name,lm_req
     *     ,pl00,aml00,pednl00,pdsigl00,pmidl00,byaml00
      USE SOMTQ_COM, only : tmom,qmom
      USE GEOM, only : geom_b,imaxj
      USE RANDOM
      USE RAD_COM, only : rqt,cloud_rad_forc
      USE DYNAMICS, only : pk,pmid,pedn
      USE CLOUDS_COM, only : ttold,qtold,svlhx,rhsav,cldsav
#if (defined TRACERS_ON) || (defined TRACERS_OCEAN)
      USE TRACER_COM,only: MTRACE,NTM,TRNAME
#ifdef TRACERS_SPECIAL_Shindell
     *     ,mchem
#endif
#endif
#ifdef TRACERS_AMP
      USE AERO_CONFIG
      USE AERO_COAG
      USE AERO_INIT
      USE AERO_SETUP
      USE AERO_SUBS
      USE AERO_NPF
      USE AERO_DIAM
      USE AMP_AEROSOL
#endif
      USE DIAG_COM, only : acc_period,monacc,jreg,titreg,namreg
     &  ,hr_in_day,iwrite,jwrite,itwrite,kdiag,qdiag,qdiag_ratios,oa
      USE PBLCOM
     &     , only : wsavg,tsavg,qsavg,dclev,usavg,vsavg,tauavg,ustar_pbl
     &  ,egcm,w2gcm,tgvavg,qgavg
      USE LAKES_COM, only : flake
      USE GHY_COM, only : fearth
      USE SOIL_DRV, only: init_gh
      USE DOMAIN_DECOMP, only : grid, GET, READT_PARALLEL, AM_I_ROOT
      USE DOMAIN_DECOMP, only : HALO_UPDATE, NORTH, HERE
#ifdef USE_FVCORE
      USE FV_INTERFACE_MOD, only: init_app_clock
      USE CONSTANT, only : hrday
      USE ESMF_MOD, only: ESMF_Clock
#endif
      USE ATMDYN, only : init_ATMDYN,CALC_AMPK
#ifdef USE_ENT
      USE ENT_DRV, only : init_module_ent
#endif

      IMPLICIT NONE
      CHARACTER(*) :: ifile
!@var iu_AIC,iu_TOPO,iu_GIC,iu_REG,iu_RSF unit numbers for input files
      INTEGER iu_AIC,iu_TOPO,iu_GIC,iu_REG,iu_RSF,iu_IFILE
!@var num_acc_files number of acc files for diag postprocessing
      INTEGER I,J,L,K,LID1,LID2,ITYPE,IM1,NOFF,ioerr,num_acc_files
!@nlparam HOURI,DATEI,MONTHI,YEARI        start of model run
!@nlparam TIMEE,HOURE,DATEE,MONTHE,YEARE,IHOURE   end of model run
!@var  IHRI,IHOURE start and end of run in hours (from 1/1/IYEAR1 hr 0)
      INTEGER ::   HOURI=0 , DATEI=1, MONTHI=1, YEARI=-1, IHRI=-1,
     *    TIMEE=-1,HOURE=0 , DATEE=1, MONTHE=1, YEARE=-1, IHOURE=-1,
!@nlparam ISTART  postprocessing(-1)/start(1-8)/restart(>8)  option
!@nlparam IRANDI  random number seed to perturb init.state (if>0)
     *             ISTART, IRANDI=0
      REAL*8 TIJL,CDM,TEMP,X
      INTEGER Itime1,Itime2,ItimeX,IhrX, LMR

!@ egcm_init_max maximum initial vaule of egcm
      real*8, parameter :: egcm_init_max=0.5d0

      LOGICAL :: redoGH = .FALSE.,iniPBL = .FALSE., inilake = .FALSE.,
     &           iniSNOW = .FALSE.  ! true = restart from "no snow" rsf
     &           ,iniOCEAN = .FALSE.
#ifdef USE_ENT
     &     ,iniENT = .FALSE.
#endif
#ifdef USE_FVCORE
      type (ESMF_Clock) :: clock
      integer :: minti,minte
      character(len=1) :: suffix
#endif
      CHARACTER NLREC*80,filenm*100,RLABEL*132
      NAMELIST/INPUTZ/ ISTART,IRANDI
     *     ,IWRITE,JWRITE,ITWRITE,QCHECK,QDIAG,KDIAG,QDIAG_RATIOS
     *     ,IHOURE, TIMEE,HOURE,DATEE,MONTHE,YEARE,IYEAR1
C****    List of parameters that are disregarded at restarts
     *     ,        HOURI,DATEI,MONTHI,YEARI
      integer ISTART_kradia, nl_soil

c**** Extract domain decomposition info
      INTEGER :: J_0, J_1, J_0S, J_1S, J_0H, J_1H
      LOGICAL :: HAVE_SOUTH_POLE, HAVE_NORTH_POLE
CCCC      INTEGER :: stdin ! used to read 'I' file
      CALL GET(grid, J_STRT = J_0, J_STOP = J_1,
     &               J_STRT_SKP = J_0S, J_STOP_SKP  = J_1S,
     &               J_STRT_HALO= J_0H, J_STOP_HALO = J_1H,
     &               HAVE_SOUTH_POLE = HAVE_SOUTH_POLE,
     &               HAVE_NORTH_POLE = HAVE_NORTH_POLE)

C****
C**** Default setting for ISTART : restart from latest save-file (10)
C****
      ISTART=10
      num_acc_files=0
C****
C**** Set dependent vertical resolution variables
C****
      SIGE(:) = (PLbot(:)-PTOP)/PSFMPT
      SIG(:)  = (sige(1:lm)+sige(2:lm+1))*0.5d0
      DSIG(:) =  sige(1:lm)-sige(2:lm+1)
      byDSIG  =  1./DSIG
C**** CALCULATE SPHERICAL GEOMETRY
      CALL GEOM_B
C**** Calculate default vertical arrays (including rad. eq. layers)
      LMR=LM+LM_REQ
      CALL CALC_VERT_AMP(PSFMPT,LMR,PL00,AML00,PDSIGL00,PEDNL00,PMIDL00)
      BYAML00(:)=1./AML00(:)
C****
C**** default settings for prog. variables etc
C****
      TEMP=250.
      TSAVG(:,:)=TEMP
      U(:,:,:)=0.
      V(:,:,:)=0.
      T(:,:,:)=TEMP  ! will be changed to pot.temp later
      Q(:,:,:)=3.D-6
      P(:,:)=PSFMPT
C**** Advection terms for first and second order moments
      TMOM(:,:,:,:)=0.
      QMOM(:,:,:,:)=0.
C**** Auxiliary clouds arrays
      RHSAV (:,:,:)=.85d0
      CLDSAV(:,:,:)=0.
      SVLHX (:,:,:)=0.
      WM    (:,:,:)=0.
C****    Ocean info saved for ocean heat transport calculations
         OA = 0.
C**** All diagn. are enabled unless KDIAG is changed in the rundeck
      KDIAG(1:12)=0
      KDIAG(13)=9
C**** Set global default timing descriptions
C**** Other speciality descriptions can be added/used locally
      NTIMEACC = 0
      CALL SET_TIMER("ATMOS. DYNAM",MDYN)
      CALL SET_TIMER("CONDENSATION",MCNDS)
      CALL SET_TIMER("   RADIATION",MRAD)
      CALL SET_TIMER("     SURFACE",MSURF)
      CALL SET_TIMER(" DIAGNOSTICS",MDIAG)
      CALL SET_TIMER("       OTHER",MELSE)
#if (defined TRACERS_ON) || (defined TRACERS_OCEAN)
      CALL SET_TIMER("     TRACERS",MTRACE)
#endif
#ifdef TRACERS_SPECIAL_Shindell
      CALL SET_TIMER("   CHEMISTRY",MCHEM)
#endif
C****
C**** Set some documentary parameters in the database
C****
      call set_param("IM",IM)
      call set_param("JM",JM)
      call set_param("LM",LM)
      call set_param("LS1",LS1)
      call set_param("PLBOT",Plbot,LM+1)
#if (defined TRACERS_ON) || (defined TRACERS_OCEAN)
      call set_param("NTM",NTM)
      call set_param("TRNAME",TRNAME,ntm)
#endif
C****
C**** Print Header and Label (2 lines) from rundeck
C****
      call openunit(trim(ifile),iu_IFILE,.false.,.true.)
      if (AM_I_ROOT()) WRITE (6,'(A,40X,A/)') '0','GISS CLIMATE MODEL'
      READ(iu_IFILE,'(A80)') XLABEL(1:80),NLREC
      NOFF=0
      IF (XLABEL(73:80).EQ.'        ') NOFF=8   ! for 72-column rundecks
      XLABEL(81-NOFF:132)=NLREC(1:52+NOFF)
      if (AM_I_ROOT()) WRITE (6,'(A,A/)') '0',XLABEL
      RLABEL = XLABEL !@var RLABEL rundeck-label
      IF(AM_I_ROOT()) THEN
C****
C**** Print preprocessing options (if any are defined)
C****
#if (defined TRACERS_ON) || (defined TRACERS_OCEAN)
      write(6,*) 'This program includes tracer code'
#endif
#ifdef TRACERS_WATER
      write(6,*) '...and water tracer code'
#ifndef TRACERS_ON
      call stop_model(
     &' Water tracers need TRACERS_ON as well as TRACERS_WATER',255)
#endif
#endif
#ifdef TRACERS_OCEAN
      write(6,*) '...and ocean tracer code'
#endif
#ifdef TRACERS_SPECIAL_O18
      write(6,*) '...and water isotope code'
#ifndef TRACERS_WATER
      call stop_model('Water isotope tracers need TRACERS_WATER '//
     *'as well as TRACERS_SPECIAL_O18',255)
#endif
#endif
#ifdef TRACERS_SPECIAL_Lerner
      write(6,*) '...and Jean/David tracers and chemistry'
#endif
#ifdef TRACERS_GASEXCH_Natassa
      write(6,*) '          '
      write(6,*) '...and Natassa Romanou air-sea GAS EXCHANGE'
#ifdef TRACERS_GASEXCH_CFC_Natassa
      write(6,*) '****CFC flux across air/sea interface****'
#endif
#ifdef TRACERS_GASEXCH_CO2_Natassa
      write(6,*) '****CO2 flux across air/sea interface****'
#endif
#endif
#ifdef TRACERS_SPECIAL_Shindell
      write(6,*) '...and Drew Shindell tracers and chemistry'
#endif
#ifdef TRACERS_AEROSOLS_Koch
      write(6,*) '...and Dorothy Koch aerosols'
#endif
#ifdef TRACERS_DRYDEP
      write(6,*) '...and tracer dry deposition'
#endif
#ifdef EDGAR_HYDE_SOURCES
      write(6,*) '...and EDGAR HYDE sources instead of GISS'
#endif
#ifdef SHINDELL_STRAT_CHEM
      write(6,*) '...and Drew Shindell stratospheric chemistry'
#endif
#ifdef SHINDELL_STRAT_EXTRA
      write(6,*) '...and Drew Shindell extra strat tracers'
#endif
#ifdef regional_Ox_tracers
      write(6,*) '...and regional Ox tracers'
#endif
#ifdef INTERACTIVE_WETLANDS_CH4
      write(6,*) '...and interactive CH4 wetlands emissions'
#endif
#ifdef NUDGE_ON
      write(6,*) '...and nudging of meteorology'
#endif
      ENDIF ! AM_I_ROOT()
C****
C**** Read parameters from the rundeck to database and namelist
C****
      call parse_params(iu_IFILE)
      READ (iu_IFILE,NML=INPUTZ,ERR=900)
      call closeunit(iu_IFILE)

C**** Get those parameters which are needed in this subroutine
      if(is_set_param("DTsrc"))  call get_param( "DTsrc", DTsrc )
      if(is_set_param("DT"))     call get_param( "DT", DT )
      if(is_set_param("NIsurf")) call get_param( "NIsurf", NIsurf ) !
      if(is_set_param("IRAND"))  call get_param( "IRAND", IRAND )
      if(is_set_param("NMONAV")) call get_param( "NMONAV", NMONAV )
      if(is_set_param("Kradia")) call get_param( "Kradia", Kradia )

C***********************************************************************
C****                                                               ****
C****        Post-process one or more ACC-files : ISTART < 1        ****
C****                                                               ****
C***********************************************************************
      if (istart.le.0) then
        call reset_diag(1)
        monacc = 0
        do
          call nextarg(filenm, 0)
          if ( filenm == "" ) exit ! end of args
          call openunit(filenm,iu_AIC,.true.,.true.)
          call io_rsf(iu_AIC,itime,ioread_single,ioerr)
          call closeunit(iu_AIC)
          num_acc_files = num_acc_files + 1
        end do
        GO TO 500
      end if
      if (istart.ge.9 .or. Kradia.gt.0) go to 400
C***********************************************************************
C****                                                               ****
C****                  INITIAL STARTS - ISTART: 1 to 8              ****
C****                                                               ****
C****   Current settings: 1 - from defaults                         ****
C****                     2 - from observed data                    ****
C****                     3 - so far unused                         ****
C****                     4 - from coupled model M-file - reset ocn ****
C****                     5 - tracer run from M-file w/o tracers    ****
C****                     6 - pred.ocn run from M-file w/o ocn data ****
C****                     7 - from mod. II' M-file - reset snow/ocn ****
C****                     8 - from current model M-file - no resets ****
C****                                                               ****
C***********************************************************************
C**** get unit for atmospheric initial conditions if needed
      IF (ISTART.gt.1) call openunit("AIC",iu_AIC,.true.,.true.)
C****
C**** Set quantities that are derived from the namelist parameters
C****
!@var NDAY=(1 day)/DTsrc : even integer; adjust DTsrc later if necessary
      NDAY = 2*NINT(.5*SDAY/DTsrc)

C**** Get Start Time; at least YearI HAS to be specified in the rundeck
      IF (YearI.lt.0) then
        IF (AM_I_ROOT())
     *   WRITE(6,*) 'Please choose a proper start year yearI, not',yearI
        call stop_model('INPUT: yearI not provided',255)
      END IF
      IF (Iyear1.lt.0) Iyear1 = yearI
      IhrI = HourI +
     +  HR_IN_DAY*(dateI-1 + JDendofM(monthI-1) + JDperY*(yearI-Iyear1))
      ITimeI = IhrI*NDAY/HR_IN_DAY ! internal clock counts DTsrc-steps
      Itime=ItimeI
      IF (IhrI.lt.0) then
        IF (AM_I_ROOT())
     *  WRITE(6,*) 'Improper start time OR Iyear1=',Iyear1,' > yearI;',
     *  ' yearI,monthI,dateI,hourI=',yearI,monthI,dateI,hourI
        call stop_model(
     &       'INPUT: Improper start date or base year Iyear1',255)
      END IF
C**** Check the vertical layering defined in RES_ (is sige(ls1)=0 ?)
      IF (SIGE(LS1).ne.0.) then
        if (AM_I_ROOT())
     *       write(6,*) 'bad vertical layering: ls1,sige(ls1)',
     &       ls1,sige(ls1)
        call stop_model('INPUT: ls1 incorrectly set in RES_',255)
      END IF
C****
C**** Get Ground conditions from a separate file - ISTART=1,2
C****
      IF (ISTART.LE.2) THEN
C**** Set flag to initialise pbl and snow variables
        iniPBL=.TRUE.
        iniSNOW = .TRUE.  ! extract snow data from first soil layer
        iniOCEAN = .TRUE. ! read in ocean ic
#ifdef USE_ENT
        iniENT = .TRUE.
#endif
        if (istart.eq.1) redogh=.true.
C**** Read in ground initial conditions
        call openunit("GIC",iu_GIC,.true.,.true.)
        ioerr=-1
        read(iu_GIC)  ! ignore first line (ocean ic done in init_OCEAN)
        call io_seaice (iu_GIC,ioreadnt,ioerr)
        call io_earth  (iu_GIC,ioreadnt,ioerr)
        call io_soils  (iu_GIC,ioreadnt,ioerr)
        call io_landice(iu_GIC,ioreadnt,ioerr)
        if (ioerr.eq.1) then
          IF (AM_I_ROOT())
     *          WRITE(6,*) "I/O ERROR IN GIC FILE: KUNIT=",iu_GIC
          call stop_model("INPUT: GIC READ IN ERROR",255)
        end if
        call closeunit (iu_GIC)
      END IF
C****
C**** Get primary Atmospheric data from NMC tapes - ISTART=2
C****
      IF (ISTART.EQ.2) THEN
C**** Use title of first record to get the date and make sure  ???
C**** it is consistent with IHRI (at least equal mod 8760)     ???
C****            not yet implemented but could easily be done  ???
        XLABEL(1:80)='Observed atmospheric data from NMC tape'
Csoon   READ (iu_AIC) XLABEL(1:80)
        CALL READT_PARALLEL(grid,iu_AIC,NAMEUNIT(iu_AIC),0,P,1) ! Psurf
        DO J=J_0,J_1
          DO I=1,IM
            P(I,J)=P(I,J)-PTOP                        ! Psurf -> P
          END DO
        END DO
        DO L=1,LM
        CALL READT_PARALLEL(grid,iu_AIC,NAMEUNIT(iu_AIC),0,U(:,:,L),1) ! U
        END DO
        DO L=1,LM
        CALL READT_PARALLEL(grid,iu_AIC,NAMEUNIT(iu_AIC),0,V(:,:,L),1) ! V
        END DO
        DO L=1,LM
        CALL READT_PARALLEL(grid,iu_AIC,NAMEUNIT(iu_AIC),0,T(:,:,L),1) ! Temperature
        END DO
        DO L=1,LM  ! alternatively, only read in L=1,LS1 ; skip rest
        CALL READT_PARALLEL(grid,iu_AIC,NAMEUNIT(iu_AIC),0,Q(:,:,L),1) ! Q
        END DO
        CALL READT_PARALLEL(grid,iu_AIC,NAMEUNIT(iu_AIC),0,TSAVG,1)  ! Tsurf
      END IF
C****
C**** Derive other data from primary data if necessary - ISTART=1,2
C****                                                    currently
      IF (ISTART.LE.2) THEN
         If (HAVE_SOUTH_POLE) THEN
           WSAVG(1:im,1)=SQRT(U(1,2,1)*U(1,2,1)+V(1,2,1)*V(1,2,1))
           USAVG(1:im,1)=U(1,2,1)
           VSAVG(1:im,1)=V(1,2,1)
         End If
         If (HAVE_NORTH_POLE) THEN
           WSAVG(1:im,JM)=SQRT(U(1,JM,1)*U(1,JM,1)+V(1,JM,1)*V(1,JM,1))
           USAVG(1:im,JM)=U(1,JM,1)
           VSAVG(1:im,JM)=V(1,JM,1)
         End If

         CALL HALO_UPDATE(grid, U, FROM=NORTH)
         CALL HALO_UPDATE(grid, V, FROM=NORTH)
        DO J=J_0S,J_1S
        IM1=IM
        DO I=1,IM
          WSAVG(I,J)=.25*SQRT(
     *         (U(IM1,J,1)+U(I,J,1)+U(IM1,J+1,1)+U(I,J+1,1))**2
     *         +(V(IM1,J,1)+V(I,J,1)+V(IM1,J+1,1)+V(I,J+1,1))**2)
          USAVG(I,J)=.25*(U(IM1,J,1)+U(I,J,1)+U(IM1,J+1,1)+U(I,J+1,1))
          VSAVG(I,J)=.25*(V(IM1,J,1)+V(I,J,1)+V(IM1,J+1,1)+V(I,J+1,1))
        IM1=I
        END DO
        END DO
        CDM=.001d0

        CALL CALC_AMPK(LM)

        DO J=J_0,J_1
        DO I=1,IM
C**** SET SURFACE MOMENTUM TRANSFER TAU0
          TAUAVG(I,J)=CDM*WSAVG(I,J)**2
C**** SET LAYER THROUGH WHICH DRY CONVECTION MIXES TO 1
          DCLEV(I,J)=1.
C**** SET SURFACE SPECIFIC HUMIDITY FROM FIRST LAYER HUMIDITY
          QSAVG(I,J)=Q(I,J,1)
          QGAVG(I,J)=Q(I,J,1)
          TGVAVG(I,J)=T(I,J,1)
C**** SET RADIATION EQUILIBRIUM TEMPERATURES FROM LAYER LM TEMPERATURE
          DO K=1,LM_REQ
            RQT(K,I,J)=T(I,J,LM)
          END DO
C**** REPLACE TEMPERATURE BY POTENTIAL TEMPERATURE
          DO L=1,LM
            T(I,J,L)=T(I,J,L)/PK(L,I,J)
            TTOLD(L,I,J)=T(I,J,L)
            QTOLD(L,I,J)=Q(I,J,L)
          END DO
C**** initialize egcm to be used in ATURB.f
          DO L=1,LM
            egcm(l,i,j)=egcm_init_max/(float(l)**2)
            w2gcm(l,i,j)=egcm(l,i,j)*2.*by3
          END DO
        END DO
        END DO
C**** Initialize surface friction velocity
        DO ITYPE=1,4
        DO J=J_0,J_1
        DO I=1,IM
          USTAR_pbl(I,J,ITYPE)=WSAVG(I,J)*SQRT(CDM)
        END DO
        END DO
        END DO
C**** INITIALIZE VERTICAL SLOPES OF T,Q
        call tq_zmom_init(t,q,PMID,PEDN)
      END IF
C****
C**** I.C from possibly older/incomplete MODEL OUTPUT, ISTART=3-8
C****
      SELECT CASE (ISTART)
      CASE (3)               ! just general hints - not to be used as is
C**** Read what's there and substitute rest as needed (as above)
C**** To be implemented as needed. Sometimes it is safer to
C**** combine the ground layers into 2 layers (top 10cm and rest) and
C**** set   redoGH  to .true.  (after major changes in the GH code or
C**** after changing to a new horizontal grid)
C     redoGH=.TRUE.
C**** Set flag to initialise pbl/snow variables if obsolete or missing
C     iniPBL=.TRUE.  ; iniSNOW = .TRUE.
        go to 890            !  not implemented; stop model
C****
C**** I.C FROM FULL MODEL RESTART FILE (but re-initialise ocean)
C****
      CASE (4)
        call io_rsf(iu_AIC,IhrX,irsficno,ioerr)
        if (ioerr.eq.1) goto 800
        iniOCEAN = .TRUE. ! read in ocean ic
C****
C**** I.C FROM FULL MODEL RESTART FILE (but no tracers)
C****
      CASE (5)             ! this model's rsf file, no tracers
        call io_rsf(iu_AIC,IhrX,irsficnt,ioerr)
        if (ioerr.eq.1) goto 800
C****
C**** I.C FROM RESTART FILE that may not match land-ocean mask  ISTART=6
C****
      CASE (6)             ! converted model II' (B399) format (no snow)
        call io_rsf(iu_AIC,IhrX,irsficno,ioerr)
        if (ioerr.eq.1) goto 800
        iniSNOW = .TRUE.      ! extract snow data from first soil layer
        inipbl  = .TRUE.      ! initialise pbl profiles
        iniOCEAN = .TRUE.     ! read in ocean ic
        redoGH=.TRUE.
C****
C**** I.C FROM RESTART FILE WITH almost COMPLETE DATA    ISTART=7
C****
      CASE (7)             ! converted model II' (B399) format (no snow)
        call io_rsf(iu_AIC,IhrX,irsfic,ioerr)
        if (ioerr.eq.1) goto 800
        iniSNOW = .TRUE.      ! extract snow data from first soil layer
        iniOCEAN = .TRUE. ! read in ocean ic
C****
C****   Data from current type of RESTART FILE           ISTART=8
C****
      CASE (8)  ! no need to read SRHR,TRHR,FSF,TSFREZ,diag.arrays
        call io_rsf(iu_AIC,IhrX,irsfic,ioerr)
        iniSNOW = .TRUE.      ! extract snow data from first soil layer
        iniPBL=.TRUE.
        if (ioerr.eq.1) goto 800
      END SELECT
C**** Check consistency of starting time
      IF (ISTART.ge.3) THEN
        IF( (MOD(IHRI-IHRX,8760).ne.0) ) THEN
         WRITE (6,*) ' Difference in hours between ',
     *       'Starting date and Data date:',MOD(IHRI-IHRX,8760)
         WRITE (6,*) 'Please change HOURI,DATEI,MONTHI'
         call stop_model('INPUT: start date inconsistent with data',255)
        ENDIF
      END IF
C**** Set flag to initialise lake variables if they are not in I.C.
      IF (ISTART.lt.8) inilake=.TRUE.

      CALL CALC_AMPK(LM)
C****
!**** IRANDI seed for random perturbation of initial conditions (if/=0):
C****        tropospheric temperatures changed by at most 1 degree C
      IF (IRANDI.NE.0) THEN
        CALL RINIT (IRANDI)
        DO L=1,LS1-1
        call burn_random(n=im*(j_0-1))
        DO J=J_0,J_1
        DO I=1,IM
           TIJL=T(I,J,L)*PK(L,I,J)-1.+2*RANDU(X)
           T(I,J,L)=TIJL/PK(L,I,J)
        END DO
        END DO
        END DO
        IF (AM_I_ROOT())
     *       WRITE(6,*) 'Initial conditions were perturbed !!',IRANDI
      END IF
C**** Close "AIC" here if it was opened
      IF (ISTART.gt.1) call closeunit(iu_AIC)

      IF (AM_I_ROOT())
     *     WRITE(6,'(A,i3,1x,a4,i5,a3,i3,3x,a,i2/" ",a)')
     *  '0Model started on',datei,aMONTH(monthi),yeari,' Hr',houri,
     *  'ISTART =',ISTART,XLABEL(1:80)    ! report input file label
      XLABEL = RLABEL                     ! switch to rundeck label

      GO TO 600
C***********************************************************************
C****                                                               ****
C****                  RESTARTS: ISTART > 8                         ****
C****                                                               ****
C****   Current settings: 9 - from own model M-file                 ****
C****                    10 - from later of fort.1 or fort.2        ****
C****                    11 - from fort.1                           ****
C****                    12 - from fort.2                           ****
C****               13 & up - from earlier of fort.1 or fort.2      ****
C****                                                               ****
C***********************************************************************
  400 SELECT CASE (ISTART)
C****
C****   DATA FROM end-of-month RESTART FILE     ISTART=9
C****        mainly used for REPEATS and delayed EXTENSIONS
      CASE (1:9)                      !  diag.arrays are not read in
        call openunit("AIC",iu_AIC,.true.,.true.)
        if(istart.eq.9) call io_rsf(iu_AIC,Itime,irerun,ioerr)
#ifdef USE_FVCORE
        call system('cp AICfv  fv_internal_restart.dat')
        call system('cp AICdfv tendencies_checkpoint')
#endif
        if(istart.le.8) then         !  initial start of rad.forcing run
          call io_label(iu_AIC,Itime,ItimeX,irerun,ioerr)
          if (Kradia.gt.0) call io_rad (iu_AIC,irsfic,ioerr)
        end if
        call closeunit(iu_AIC)
        if (ioerr.eq.1) goto 800
        WRITE (6,'(A,I2,A,I11,A,A/)') '0Model restarted; ISTART=',
     *    ISTART,', TIME=',Itime,' ',XLABEL(1:80) ! sho input file label
        XLABEL = RLABEL                        ! switch to rundeck label

        CALL CALC_AMPK(LM)
C****
!**** IRANDI seed for random perturbation of current state (if/=0)
C****        tropospheric temperatures are changed by at most 1 degree C
        IF (IRANDI.ne.0 .and. Kradia.le.0) THEN
          CALL RINIT (IRANDI)
          DO L=1,LS1-1
          DO J=J_0,J_1
          DO I=1,IM
             TIJL=T(I,J,L)*PK(L,I,J)-1.+2*RANDU(X)
             T(I,J,L)=TIJL/PK(L,I,J)
          END DO
          END DO
          END DO
          IF (AM_I_ROOT())
     *         WRITE(6,*) 'Current temperatures were perturbed !!',IRANDI
        END IF
        TIMING = 0
        GO TO 500
C****
C**** RESTART ON DATA SETS 1 OR 2, ISTART=10 or more
C****
C**** CHOOSE DATA SET TO RESTART ON
      CASE (10,13:)
         Itime1=-1
         call openunit(rsf_file_name(1),iu_RSF,.true.,.true.)
         READ (iu_RSF,ERR=410) Itime1
         call closeunit(iu_RSF)
  410    continue !REWIND 1
         Itime2=-1
         call openunit(rsf_file_name(2),iu_RSF,.true.,.true.)
         READ (iu_RSF,ERR=420) Itime2
         call closeunit(iu_RSF)
  420    continue !REWIND 2
         IF (Itime1+Itime2.LE.-2.) GO TO 850
                               KDISK=1
         IF (Itime2.GT.Itime1) KDISK=2
         IF (ISTART.GE.13)     KDISK=3-KDISK
      CASE (11,12)
                               KDISK=ISTART-10
      END SELECT
  430 continue
      call openunit(rsf_file_name(KDISK),iu_RSF,.true.,.true.)
#ifdef USE_FVCORE
        write(suffix,'(i1)') kdisk
        call system('cp  fv.'// suffix // ' fv_internal_restart.dat')
        call system('cp dfv.'// suffix // ' tendencies_checkpoint')
#endif
      CALL HERE(__FILE__//'::io_rsf',__LINE__ + 10000*KDISK)
      call io_rsf(iu_RSF,Itime,ioread,ioerr)
      call closeunit(iu_RSF)
      if (ioerr.eq.1) then
         if (istart.gt.10) go to 850  ! no 2nd chance if istart/=10
         KDISK=3-KDISK                ! try the earlier restart file
         WRITE (6,'(A,I1,A,I1)')
     *     ' Read Error on fort.',3-kdisk,' trying fort.',kdisk
         ISTART=110
         go to 430
      end if
      if (AM_I_ROOT())
     * WRITE (6,'(A,I2,A,I11,A,A/)') '0RESTART DISK READ, UNIT',
     *   KDISK,', Time=',Itime,' ',XLABEL(1:80)

C**** Switch KDISK if the other file is (or may be) bad (istart>10)
C****     so both files will be fine after the next write execution
      IF (istart.gt.10) KDISK=3-KDISK
C**** Keep KDISK after reading from the later restart file, so that
C****     the same file is overwritten first; in case of trouble,
C****     the earlier restart file will still be available

  500 CONTINUE
C**** Get parameters we just read from rsf file. Only those
C**** parameters which we need in "INPUT" should be extracted here.
      if(is_set_param("DTsrc"))  call get_param( "DTsrc", DTsrc )
      if(is_set_param("DT"))     call get_param( "DT", DT )
      if(is_set_param("NMONAV")) call get_param( "NMONAV", NMONAV )
      if(is_set_param("Kradia")) call get_param( "Kradia", Kradia )

C***********************************************************************
C****                                                              *****
C****       INITIAL- AND RESTARTS: Final Initialization steps      *****
C****                                                              *****
C***********************************************************************
  600 CONTINUE

C**** initialize Lrunid (length of the identifying part of XLABEL)
C****
      lid1 = INDEX(XLABEL,'(') -1
      if (lid1.lt.1) lid1=17
      lid2 = INDEX(XLABEL,' ') -1
      if (lid2.lt.1) lid2=17
      LRUNID = min(lid1,lid2)
      IF (LRUNID.gt.16) call stop_model
     *     ('INPUT: Rundeck name too long. Shorten to 16 char or less'
     *     ,255)

C**** Update ItimeE only if YearE or IhourE is specified in the rundeck
C****
      if(timee.lt.0) timee=houre*nday/HR_IN_DAY
      IF(yearE.ge.0) ItimeE = (( (yearE-iyear1)*JDperY +
     *  JDendofM(monthE-1)+dateE-1 )*HR_IN_DAY )*NDAY/HR_IN_DAY + TIMEE
C**** Alternate (old) way of specifying end time
      if(IHOURE.gt.0) ItimeE=IHOURE*NDAY/HR_IN_DAY

C**** Check consistency of DTsrc (with NDAY) and dt (with NIdyn)
      if (is_set_param("DTsrc") .and. nint(sday/DTsrc).ne.NDAY) then
        if (AM_I_ROOT())
     *        write(6,*) 'DTsrc=',DTsrc,' has to stay at/be set to',SDAY/NDAY
        call stop_model('INPUT: DTsrc inappropriately set',255)
      end if
      DTsrc = SDAY/NDAY
      call set_param( "DTsrc", DTsrc, 'o' )   ! copy DTsrc into DB

      NIdyn=nint(dtsrc/dt)
#ifndef USE_FVCORE
C**** NIdyn=dtsrc/dt(dyn) has to be a multiple of 2
C****
      if(istart>0) then
        NIdyn = 2*nint(.5*dtsrc/dt)
        if (is_set_param("DT") .and. nint(DTsrc/dt).ne.NIdyn) then
          if (AM_I_ROOT())
     *        write(6,*) 'DT=',DT,' has to be changed to',DTsrc/NIdyn
          call stop_model('INPUT: DT inappropriately set',255)
        end if
      end if
#else
C**** need a clock to satisfy ESMF interfaces
      call getdte(itimei,nday,iyear1,YEARI,MONTHI,jday,DATEI,HOURI,amon)
      MINTI = nint(mod( mod(Itimei*hrday/Nday,hrday) * 60d0, 60d0))
      call getdte(itimee,nday,iyear1,YEARE,MONTHE,jday,DATEE,HOURE,amon)
      MINTE = nint(mod( mod(Itimee*hrday/Nday,hrday) * 60d0, 60d0))
      clock = init_app_clock( (/ YEARI, MONTHI, DATEI, HOURI, MINTI,0/),
     &                        (/ YEARE, MONTHE, DATEE, HOURE, MINTE,0/),
     &             interval = int(dt) )
#endif
      DT = DTsrc/NIdyn
      call set_param( "DT", DT, 'o' )         ! copy DT into DB

C**** NMONAV has to be 1(default),2,3,4,6,12, i.e. a factor of 12
      if (NMONAV.lt.1 .or. MOD(12,NMONAV).ne.0) then
        write (6,*) 'NMONAV has to be 1,2,3,4,6 or 12, not',NMONAV
        call stop_model('INPUT: nmonav inappropriately set',255)
      end if
      if (AM_I_ROOT())
     *     write (6,*) 'Diag. acc. period:',NMONAV,' month(s)'

C**** Updating Parameters: If any of them changed beyond this line
C**** use set_param(.., .., 'o') to update them in the database (DB)

C**** Get the rest of parameters from DB or put defaults to DB
      call init_Model

C**** Set julian date information
      call getdte(Itime,Nday,Iyear1,Jyear,Jmon,Jday,Jdate,Jhour,amon)
      call getdte(Itime0,Nday,iyear1,Jyear0,Jmon0,J,Jdate0,Jhour0,amon0)

C****
C**** READ IN TIME-INDEPENDENT ARRAYS
C****
      if (Kradia.le.0) then   !  full model
        CALL CALC_AMPK(LM)

C****   READ SPECIAL REGIONS FROM UNIT 29
        call openunit("REG",iu_REG,.true.,.true.)
        READ(iu_REG) TITREG,JREG,NAMREG
        IF (AM_I_ROOT())
     &       WRITE(6,*) ' read REGIONS from unit ',iu_REG,': ',TITREG
        call closeunit(iu_REG)
      end if  ! full model: Kradia le 0

#if (defined TRACERS_ON) || (defined TRACERS_OCEAN)
C**** Initialise tracer parameters and diagnostics
       call init_tracer
#endif
C**** READ IN LANDMASKS AND TOPOGRAPHIC DATA
C**** Note that FLAKE0 is read in only to provide initial values
C**** Actual array is set from restart file.
      call openunit("TOPO",iu_TOPO,.true.,.true.)
      CALL READT_PARALLEL(grid,iu_TOPO,NAMEUNIT(iu_TOPO),0,FOCEAN,1) ! Ocean fraction
      CALL READT_PARALLEL(grid,iu_TOPO,NAMEUNIT(iu_TOPO),0,FLAKE0,1) ! Orig. Lake fraction
      CALL READT_PARALLEL(grid,iu_TOPO,NAMEUNIT(iu_TOPO),0,FEARTH0,1) ! Earth frac. (no LI)
      CALL READT_PARALLEL(grid,iu_TOPO,NAMEUNIT(iu_TOPO),0,FLICE ,1) ! Land ice fraction
      CALL READT_PARALLEL(grid,iu_TOPO,NAMEUNIT(iu_TOPO),0,ZATMO ,1) ! Topography
      CALL READT_PARALLEL(grid,iu_TOPO,NAMEUNIT(iu_TOPO),0,HLAKE ,2) ! Lake Depths
      ZATMO(:,J_0:J_1) = ZATMO(:,J_0:J_1)*GRAV                  ! Geopotential
      call closeunit(iu_TOPO)

C**** Initialise some modules before finalising Land/Ocean/Lake/LI mask
C**** Initialize ice
      CALL init_ice(iniOCEAN,istart)
C**** Initialize lake variables (including river directions)
      CALL init_LAKES(inilake,istart)
C**** Initialize ocean variables
C****  KOCEAN = 1 => ocean heat transports/max. mixed layer depths
C****  KOCEAN = 0 => RSI/MSI factor
      CALL init_OCEAN(iniOCEAN,istart)
C**** Initialize ice dynamics code (if required)
      CALL init_icedyn(iniOCEAN)
C**** Initialize land ice (must come after oceans)
      CALL init_LI(istart)

C**** Make sure that constraints are satisfied by defining FLAND/FEARTH
C**** as residual terms. (deals with SP=>DP problem)
      DO J=J_0,J_1
      DO I=1,IMAXJ(J)
        IF (FOCEAN(I,J).gt.0) THEN
          FLAND(I,J)=1.-FOCEAN(I,J) ! Land fraction
          IF (FLAKE(I,J).gt.0) THEN
           IF (AM_I_ROOT()) WRITE(6,*)
     *            "Ocean and lake cannot co-exist in same grid box"
     *       ,i,j,FOCEAN(I,J),FLAKE(I,J)
            FLAKE(I,J)=0
          END IF
        ELSEIF (FLAKE(I,J).gt.0) THEN
          FLAND(I,J)=1.-FLAKE(I,J)
        ELSE
          FLAND(I,J)=1.
        END IF
C**** Ensure that no round off error effects land with ice and earth
        IF (FLICE(I,J)-FLAND(I,J).gt.-1d-4 .and. FLICE(I,J).gt.0) THEN
          FLICE(I,J)=FLAND(I,J)
          FEARTH(I,J)=0.
        ELSE
          FEARTH(I,J)=FLAND(I,J)-FLICE(I,J) ! Earth fraction
        END IF
      END DO
      END DO
      If (HAVE_SOUTH_POLE) Then
         FLAND(2:IM,1)=FLAND(1,1)
         FEARTH(2:IM,1)=FEARTH(1,1)
         FLICE(2:IM,1)=FLICE(1,1)
      End If
      If (HAVE_NORTH_POLE) Then
         FLAND(2:IM,JM)=FLAND(1,JM)
         FEARTH(2:IM,JM)=FEARTH(1,JM)
         FLICE(2:IM,JM)=FLICE(1,JM)
      End If
C****
C**** INITIALIZE GROUND HYDROLOGY ARRAYS (INCL. VEGETATION)
C**** Recompute Ground hydrology data if redoGH (new soils data)
C****
!!! hack: make sure that ISTART_kradia==0 if Kradia>0
!!! do we need it ? I.A.
      ISTART_kradia = ISTART
      if ( Kradia.gt.0 ) ISTART_kradia = 0
      CALL init_GH(DTsrc/NIsurf,redoGH,iniSNOW,ISTART_kradia, nl_soil)
#ifdef USE_ENT
      CALL init_module_ent(iniENT, Jday, Jyear, FOCEAN) !!! FEARTH)
#endif

      if (Kradia.gt.0) then   !  radiative forcing run
        !CALL init_GH(DTsrc/NIsurf,redoGH,iniSNOW,0)
        !CALL init_module_ent(iniENT,grid,jday,dxyp)
        CALL init_RAD(istart)
        if(istart.lt.0) CALL init_DIAG(0,num_acc_files) !post-processing
        if (AM_I_ROOT()) Then
           WRITE (6,INPUTZ)
           call print_param( 6 )
           WRITE (6,'(A14,4I4)') "IM,JM,LM,LS1=",IM,JM,LM,LS1
           WRITE (6,*) "PLbot=",PLbot
        end if
        if(istart.lt.0)
     &       CALL stop_model ('Terminated normally, istart<0',13)
        return
      end if                  !  Kradia>0; radiative forcing run
!      CALL init_GH(DTsrc/NIsurf,redoGH,iniSNOW,ISTART)
!      CALL init_module_ent(iniENT,grid,jday,dxyp)
C**** Initialize pbl (and read in file containing roughness length data)
      if(istart.gt.0) CALL init_pbl(iniPBL)
C****
C**** Initialize the use of gravity wave drag diagnostics
C****
      CALL init_GWDRAG
C
C**** Initialize nudging
#ifdef NUDGE_ON
      CALL NUDGE_INIT
#endif
#ifdef TRACERS_AMP
      CALL SETUP_CONFIG
      CALL SETUP_SPECIES_MAPS
      CALL SETUP_DP0
      CALL SETUP_AERO_MASS_MAP
      CALL SETUP_COAG_TENSORS
      CALL SETUP_DP0
      CALL SETUP_KIJ
      CALL SETUP_EMIS
      CALL SETUP_KCI
      CALL SETUP_NPFMASS
      CALL SETUP_DIAM
#endif
C****
      if(istart.gt.0) CALL RINIT (IRAND)
      CALL FFT0 (IM)
      CALL init_CLD
      CALL init_DIAG(istart,num_acc_files) ! initialize for accumulation
      CALL UPDTYPE
      if(istart.gt.0) CALL init_QUS(grid,im,jm,lm)
      if(istart.gt.0) CALL init_ATMDYN
      CALL init_RAD(istart)
      if (AM_I_ROOT()) then
         WRITE (6,INPUTZ)
         call print_param( 6 )
         WRITE (6,'(A7,12I6)') "IDACC=",(IDACC(I),I=1,12)
         WRITE (6,'(A14,4I4)') "IM,JM,LM,LS1=",IM,JM,LM,LS1
         WRITE (6,*) "PLbot=",PLbot
      end if
C****
      RETURN
C****
C**** TERMINATE BECAUSE OF IMPROPER PICK-UP
C****
  800 WRITE (6,'(A,I4/" ",A)')
     *  '0ERROR ENCOUNTERED READING AIC ISTART=', ISTART,XLABEL(1:80)
      call stop_model('INPUT: READ ERROR FOR AIC',255)
  830 WRITE(6,*) 'READ ERROR FOR GIC'
      call stop_model('INPUT: READ ERROR FOR GIC',255)
  850 WRITE (6,'(A)')
     *  '0ERRORS ON BOTH RESTART DATA SETS. TERMINATE THIS JOB'
      call stop_model('INPUT: ERRORS ON BOTH RESTART FILES',255)
  890 WRITE (6,'(A,I5)') '0INCORRECT VALUE OF ISTART',ISTART
      call stop_model('INPUT: ISTART-SPECIFICATION INVALID',255)
  900 write (6,*) 'Error in NAMELIST parameters'
      call stop_model('Error in NAMELIST parameters',255)
      END SUBROUTINE INPUT


      SUBROUTINE DAILY(end_of_day) 3,14
!@sum  DAILY performs daily tasks at end-of-day and maybe at (re)starts
!@auth Original Development Team
!@ver  1.0
!@calls constant:orbit, calc_ampk, getdte
      USE MODEL_COM, only : im,jm,lm,ls1,ptop,psf,p,q
     *     ,itime,itimei,iyear1,nday,jdpery,jdendofm
     *     ,jyear,jmon,jday,jdate,jhour,aMON,aMONTH,ftype
      USE GEOM, only : areag,dxyp,imaxj
      USE DYNAMICS, only : byAM
      USE RADPAR, only : ghgam,ghgyr2,ghgyr1
      USE RAD_COM, only : RSDIST,COSD,SIND, dh2o,H2ObyCH4,ghg_yr,
     *     omegt,obliq,eccn
#ifdef TRACERS_WATER
      USE TRACER_COM, only: trm,tr_wd_type,nwater,tr_H2ObyCH4,itime_tr0
     *     ,ntm
#endif
      USE DIAG_COM, only : aj=>aj_loc,j_h2och4
      USE DOMAIN_DECOMP, only : grid, GET, GLOBALSUM, AM_I_ROOT
      USE ATMDYN, only : CALC_AMPK
      IMPLICIT NONE
      REAL*8 DELTAP,PBAR,SMASS,LAM,xCH4,EDPY,VEDAY
      REAL*8 :: SPRESS(grid%J_STRT_HALO:grid%J_STOP_HALO)
      INTEGER i,j,l,iy
      LOGICAL, INTENT(IN) :: end_of_day
#ifdef TRACERS_WATER
      INTEGER n
#endif
c**** Extract domain decomposition info
      INTEGER :: J_0, J_1, J_0S, J_1S
      LOGICAL :: HAVE_SOUTH_POLE, HAVE_NORTH_POLE
      CALL GET(grid, J_STRT = J_0, J_STOP = J_1,
     &               J_STRT_SKP = J_0S, J_STOP_SKP = J_1S,
     &               HAVE_SOUTH_POLE = HAVE_SOUTH_POLE,
     &               HAVE_NORTH_POLE = HAVE_NORTH_POLE)


C**** Tasks to be done at end of day and at each start or restart
C****
C**** CALCULATE THE DAILY CALENDAR
C****
      call getdte(Itime,Nday,iyear1,Jyear,Jmon,Jday,Jdate,Jhour,amon)

C**** CALCULATE SOLAR ANGLES AND ORBIT POSITION
C**** This is for noon (GMT) for new day.

C**** The orbital calculation will need to vary depending on the kind
C**** of calendar adopted (i.e. a generic 365 day year, or a transient
C**** calendar including leap years etc.).  For transient calendars the
C**** JDAY passed to orbit needs to be adjusted to represent the number
C**** of days from Jan 1 2000AD.
c      EDPY=365.2425d0, VEDAY=79.3125d0  ! YR 2000AD
c      JDAY => JDAY + 365 * (JYEAR-2000) + appropriate number of leaps
C**** Default calculation (no leap, VE=Mar 21 hr 0)
      EDPY=365d0 ; VEDAY=79d0           ! Generic year
      CALL ORBIT (OBLIQ,ECCN,OMEGT,VEDAY,EDPY,REAL(JDAY,KIND=8)-.5
     *     ,RSDIST,SIND,COSD,LAM)

      IF (.not.(end_of_day.or.itime.eq.itimei)) RETURN

C**** Tasks to be done at end of day and at initial starts only
C****
C**** THE GLOBAL MEAN PRESSURE IS KEPT CONSTANT AT PSF MILLIBARS
C****
C**** CALCULATE THE CURRENT GLOBAL MEAN PRESSURE
      SMASS=0.
      DO J=J_0,J_1
        SPRESS(J)=0.
        DO I=1,IM
          SPRESS(J)=SPRESS(J)+P(I,J)
        END DO
        SPRESS(J) = SPRESS(J) * DXYP(J)
      END DO
      CALL GLOBALSUM(grid, SPRESS, SMASS, ALL=.TRUE.)
      PBAR=SMASS/AREAG+PTOP
C**** CORRECT PRESSURE FIELD FOR ANY LOSS OF MASS BY TRUNCATION ERROR
C****   except if it was just done (restart from itime=itimei)
      DELTAP=PSF-PBAR
      if(itime.eq.itimei .and. abs(deltap).lt.1.d-10) return
      P=P+DELTAP

      CALL CALC_AMPK(LS1-1)

      if (AM_I_ROOT()) then
         IF (ABS(DELTAP).gt.1d-6)
     *      WRITE (6,'(A25,F10.6/)') '0PRESSURE ADDED IN GMP IS',DELTAP
      end if

      IF (.not.end_of_day) RETURN

C**** Tasks to be done at end of day only
      if (H2ObyCH4.gt.0) then
C****   Add obs. H2O generated by CH4(*H2ObyCH4) using a 2 year lag
        iy = jyear - 2 - ghgyr1 + 1
        if (ghg_yr.gt.0) iy = ghg_yr - 2 - ghgyr1 + 1
        if (iy.lt.1) iy=1
        if (iy.gt.ghgyr2-ghgyr1+1) iy=ghgyr2-ghgyr1+1
        xCH4=ghgam(3,iy)*H2ObyCH4
c        If (AM_I_ROOT())
c     &    write(6,*) 'add in stratosphere: H2O gen. by CH4(ppm)=',xCH4

        do l=1,lm
        do j=J_0,J_1
        do i=1,imaxj(j)
          q(i,j,l)=q(i,j,l)+xCH4*dH2O(j,l,jmon)*byAM(l,i,j)
#ifdef TRACERS_WATER
C**** Add water to relevant tracers as well
          do n=1,ntm
            if (itime_tr0(n).le.itime) then
              select case (tr_wd_type(n))
              case (nWater)    ! water: add CH4-sourced water to tracers
                trm(i,j,l,n) = trm(i,j,l,n) +
     +                tr_H2ObyCH4(n)*xCH4*dH2O(j,l,jmon)*dxyp(j)
              end select
            end if
          end do
#endif
          aj(j,j_h2och4,:)=aj(j,j_h2och4,:)+
     +                       xCH4*dH2O(j,l,jmon)*ftype(:,i,j)
        end do
        end do
        If (HAVE_NORTH_POLE) q(2:im,jm,l)=q(1,jm,l)
        If (HAVE_SOUTH_POLE) q(2:im, 1,l)=q(1, 1,l)
#ifdef TRACERS_WATER
        do n=1,ntm
          If (HAVE_SOUTH_POLE) trm(2:im, 1,l,n)=trm(1, 1,l,n)
          If (HAVE_NORTH_POLE) trm(2:im,jm,l,n)=trm(1,jm,l,n)
        end do
#endif
        end do
      end if

      RETURN
      END SUBROUTINE DAILY


      SUBROUTINE CHECKT (SUBR) 17,20
!@sum  CHECKT Checks arrays for NaN/INF and reasonablness
!@auth Original Development Team
!@ver  1.0

C**** CHECKT IS TURNED ON BY SETTING QCHECK=.TRUE. IN NAMELIST
C**** REMEMBER TO SET QCHECK BACK TO .FALSE. AFTER THE ERRORS ARE
C**** CORRECTED.
      USE CONSTANT, only : tf
      USE MODEL_COM
      USE DYNAMICS, only : pk
      USE DOMAIN_DECOMP, only : grid, GET, AM_I_ROOT
      USE soil_drv, only : checke
      IMPLICIT NONE
      INTEGER I,J,L
!@var SUBR identifies where CHECK was called from
      CHARACTER*6, INTENT(IN) :: SUBR
c**** Extract domain decomposition info
      INTEGER :: J_0, J_1
      CALL GET(grid, J_STRT = J_0, J_STOP = J_1)


      IF (QCHECK) THEN
C**** Check all prog. arrays for Non-numbers
        CALL CHECK3(U,IM,JM,LM,SUBR,'u     ')
        CALL CHECK3(V,IM,JM,LM,SUBR,'v     ')
        CALL CHECK3(T,IM,JM,LM,SUBR,'t     ')
        CALL CHECK3(Q,IM,JM,LM,SUBR,'q     ')
        CALL CHECK3(P,IM,JM,1,SUBR,'p     ')
        CALL CHECK3(WM,IM,JM,LM,SUBR,'wm    ')

        DO J=J_0,J_1
        DO I=1,IM
          IF (Q(I,J,1).gt.1d-1)print*,SUBR," Q BIG ",i,j,Q(I,J,1:LS1)
          IF (T(I,J,1)*PK(1,I,J)-TF.gt.50.) print*,SUBR," T BIG ",i,j
     *         ,T(I,J,1:LS1)*PK(1:LS1,I,J)-TF
        END DO
        END DO
        DO L=1,LM
        DO J=J_0,J_1
        DO I=1,IM
          IF (Q(I,J,L).lt.0.) then
            print*,"After ",SUBR," Q < 0 ",i,j,Q(I,J,L)
            call stop_model('Q<0 in CHECKT',255)
          END IF
          IF (WM(I,J,L).lt.0.) then
            print*,"After ",SUBR," WM < 0 ",i,j,WM(I,J,L)
            call stop_model('WM<0 in CHECKT',255)
          END IF
        END DO
        END DO
        END DO
C**** Check PBL arrays
        CALL CHECKPBL(SUBR)
C**** Check Ocean arrays
        CALL CHECKO(SUBR)
C**** Check Ice arrays
        CALL CHECKI(SUBR)
C**** Check Lake arrays
        CALL CHECKL(SUBR)
C**** Check Earth arrays
       CALL CHECKE(SUBR)
#if (defined TRACERS_ON) || (defined TRACERS_OCEAN)
C**** check tracers
        CALL CHECKTR(SUBR)
#endif
      END IF

      RETURN
      END SUBROUTINE CHECKT



      subroutine read_options( qcrestart, ifile ) 1,3
!@sum reads options from the command line (for now only one option)
!@auth I. Aleinov
!@ver 1.0
      implicit none
!@var qcrestart true if "-r" is present
      logical, intent(inout) :: qcrestart
      character(*),intent(inout)  :: ifile
      character*80 arg,arg1

      do
        call nextarg( arg, 1 )
        if ( arg == "" ) exit          ! end of args
        select case (arg)
        case ("-r")
          qcrestart = .true.
        case ("-i")
          call nextarg( arg1, 0 )
          ifile=arg1
        ! new options can be included here
        case default
          print *,'Unknown option specified: ', arg
          print *,'Aborting...'
          call stop_model("Unknown option on a command line",255)
        end select
      enddo

      return
      end subroutine read_options



      subroutine print_restart_info 1,11
!@sum prints timing information needed to restart the model
!@auth I. Aleinov
!@ver 1.0
      USE MODEL_COM
      USE FILEMANAGER, only : openunit,closeunit
      use DOMAIN_DECOMP, only: AM_I_ROOT
      implicit none
      integer :: ItimeMax=-1, Itime1, Itime2, itm, ioerr1=-1, ioerr2=-1
      integer :: iu_rsf

      call openunit(rsf_file_name(1),iu_rsf,.true.)
      call io_label(iu_rsf,Itime1,itm,ioread,ioerr1)
      call closeunit(iu_rsf)
      call openunit(rsf_file_name(2),iu_rsf,.true.)
      call io_label(iu_rsf,Itime2,itm,ioread,ioerr2)
      call closeunit(iu_rsf)

      if ( ioerr1==-1 ) ItimeMax = Itime1
      if ( ioerr2==-1 ) ItimeMax = max( ItimeMax, Itime2 )

      if ( Itime < 0 )
     $     call stop_model("Could not read fort.1, fort.2",255)

      call getdte(
     &     ItimeMax,Nday,Iyear1,Jyear,Jmon,Jday,Jdate,Jhour,amon)
      if (AM_I_ROOT())
     &     write(6,"('QCRESTART_DATA: ',I10,1X,I2,'-',I2.2,'-',I4.4)")
     &     ItimeMax*24/Nday, Jmon, Jdate, Jyear

      return
      end subroutine print_restart_info