!WRF:DRIVER_LAYER:MAIN
!


PROGRAM ndown_em,92

   USE module_machine
   USE module_domain
   USE module_integrate
   USE module_driver_constants
   USE module_configure
   USE module_io_domain

   USE module_timing
   USE module_wrf_error
#ifdef DM_PARALLEL
   USE module_dm
#endif

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!new for bc
   USE module_bc
   USE module_big_step_utilities_em
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

   IMPLICIT NONE

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!new for bc
   INTEGER :: ids , ide , jds , jde , kds , kde
   INTEGER :: ims , ime , jms , jme , kms , kme
   INTEGER :: i , j , k
   INTEGER :: time_loop_max , time_loop
   INTEGER :: time_step_count_output
   INTEGER :: julyr , julday , iswater , map_proj
   INTEGER :: icnt

   REAL    :: dt , new_bdy_frq
   REAL    :: gmt , cen_lat , cen_lon , dx , dy , truelat1 , truelat2

   REAL , DIMENSION(:,:,:) , ALLOCATABLE :: ubdy3dtemp1 , vbdy3dtemp1 , tbdy3dtemp1 , pbdy3dtemp1 , qbdy3dtemp1
   REAL , DIMENSION(:,:  ) , ALLOCATABLE :: mbdy2dtemp1
   REAL , DIMENSION(:,:,:) , ALLOCATABLE :: ubdy3dtemp2 , vbdy3dtemp2 , tbdy3dtemp2 , pbdy3dtemp2 , qbdy3dtemp2
   REAL , DIMENSION(:,:  ) , ALLOCATABLE :: mbdy2dtemp2

   CHARACTER(LEN=19) :: start_date_char , current_date_char

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

   REAL    :: time

   INTEGER :: loop , levels_to_process

   TYPE (domain) , POINTER :: keep_grid, grid_ptr, null_domain, parent_grid , nested_grid
   TYPE (domain)           :: dummy
   TYPE (grid_config_rec_type)              :: config_flags
   INTEGER                 :: number_at_same_level
   INTEGER                 :: time_step_begin_restart

   INTEGER :: max_dom , domain_id , fid , fido, fidb , oid , idum1 , idum2 , ierr
   INTEGER :: status_next_var
   INTEGER :: debug_level
   LOGICAL :: input_from_file
   CHARACTER (LEN=19) :: date_string

#ifdef DM_PARALLEL
   INTEGER                 :: nbytes
   INTEGER, PARAMETER      :: configbuflen = 2*1024
   INTEGER                 :: configbuf( configbuflen )
   LOGICAL , EXTERNAL      :: wrf_dm_on_monitor
#endif

   CHARACTER (LEN=80)      :: inpname , outname , bdyname
   CHARACTER (LEN=80)      :: message

   !  Interface block for routine that passes pointers and needs to know that they
   !  are receiving pointers.

   INTERFACE

      SUBROUTINE med_interp_domain ( parent_grid , nested_grid )
         USE module_domain
         USE module_configure
         TYPE(domain), POINTER :: parent_grid , nested_grid
      END SUBROUTINE med_interp_domain

   END INTERFACE
#if 0
call opngks
#endif

   !  Define the name of this program (program_name defined in module_domain)

   program_name = "NDOWN_EM V1.2 PREPROCESSOR"

   !  Initialize the modules used by the WRF system.  Many of the CALLs made from the
   !  init_modules routine are NO-OPs.  Typical initializations are: the size of a 
   !  REAL, setting the file handles to a pre-use value, defining moisture and 
   !  chemistry indices, etc.

   CALL init_modules

   !  Get the NAMELIST data.  This is handled in the initial_config routine.  All of the
   !  NAMELIST input variables are assigned to the model_config_rec structure.  Below,
   !  note for parallel processing, only the monitor processor handles the raw Fortran
   !  I/O, and then broadcasts the info to each of the other nodes.

#ifdef DM_PARALLEL
   IF ( wrf_dm_on_monitor() ) THEN
     CALL initial_config
   ENDIF
   CALL get_config_as_buffer( configbuf, configbuflen, nbytes )
   CALL wrf_dm_bcast_bytes( configbuf, nbytes )
   CALL set_config_as_buffer( configbuf, configbuflen )
   CALL wrf_dm_initialize
#else
   CALL initial_config
#endif

   !  And here is an instance of using the information in the NAMELIST.  

   CALL get_debug_level ( debug_level )
   CALL set_wrf_debug_level ( debug_level )

   !  Allocated and configure the mother domain.  Since we are in the nesting down
   !  mode, we know a) we got a nest, and b) we only got 1 nest.

   NULLIFY( null_domain )

   CALL       wrf_message ( program_name )
   CALL       wrf_debug ( 100 , 'wrf: calling alloc_and_configure_domain coarse ' )
   CALL alloc_and_configure_domain ( domain_id  = 1 ,                  &
                                     local_time = 0 ,                  &
                                     grid       = head_grid ,          &
                                     parent     = null_domain ,        &
                                     kid        = -1                   )

   parent_grid => head_grid

   CALL       wrf_debug ( 100 , 'wrf: calling model_to_grid_config_rec ' )
   CALL model_to_grid_config_rec ( head_grid%id , model_config_rec , config_flags )
   CALL       wrf_debug ( 100 , 'wrf: calling set_scalar_indices_from_config ' )
   CALL set_scalar_indices_from_config ( head_grid%id , idum1, idum2 )

   !  Initialize the I/O for WRF.

   CALL       wrf_debug ( 100 , 'wrf: calling init_wrfio' )
   CALL init_wrfio

   !  Some of the configuration values may have been modified from the initial READ
   !  of the NAMELIST, so we re-broadcast the configuration records.

#ifdef DM_PARALLEL
   CALL get_config_as_buffer( configbuf, configbuflen, nbytes )
   CALL wrf_dm_bcast_bytes( configbuf, nbytes )
   CALL set_config_as_buffer( configbuf, configbuflen )
#endif

   !  Let's look at the time info available from the namelist.

   CALL get_time_step_count_output ( parent_grid%id , time_step_count_output )
   CALL get_dt                     ( parent_grid%id , dt                     )
   new_bdy_frq = time_step_count_output *  dt

   !  We need to current and starting dates for the output files.  The times need to be incremented
   !  so that the lateral BC files are not overwritten.

   WRITE ( start_date_char , FMT = '(I4.4,"-",I2.2,"-",I2.2,"_",I2.2,":",I2.2,":",I2.2)' ) &
           model_config_rec%start_year  (parent_grid%id) , &
           model_config_rec%start_month (parent_grid%id) , &
           model_config_rec%start_day   (parent_grid%id) , &
           model_config_rec%start_hour  (parent_grid%id) , &
           model_config_rec%start_minute(parent_grid%id) , &
           model_config_rec%start_second(parent_grid%id) 

   start_date        = start_date_char // '.0000' 

   !  Open the input data (wrfout_d01_000000) for reading.

   CALL wrf_debug          ( 100 , 'ndown_em main: calling open_r_dataset for wrfout' )
   CALL construct_filename ( inpname , 'wrfout' , head_grid%id , 2 , 0 , 6 )
   CALL open_r_dataset     ( fid, TRIM(inpname) , head_grid , config_flags , "DATASET=INPUT", ierr )
   IF ( ierr .NE. 0 ) THEN
      WRITE( wrf_err_message , FMT='(A,A,A,I8)' ) 'program ndown: error opening ',TRIM(inpname),' for reading ierr=',ierr
      CALL WRF_ERROR_FATAL ( wrf_err_message )
   ENDIF

   !  How many times in the input file (wrfout_d01_000000).

   time_loop_max = 0
   count_em_up : DO 
      CALL ext_ncd_get_next_time ( fid , date_string , status_next_var )
print *,'date/time = ',date_string
      IF ( status_next_var .EQ. 0 ) THEN
         time_loop_max = time_loop_max + 1
      ELSE
         EXIT count_em_up
      END IF
   END DO count_em_up
print *,'total time periods = ',time_loop_max

   !  There has to be a more elegant way to get to the beginning of the file, but this will do.

   CALL close_dataset      ( fid , config_flags , "DATASET=INPUT" )
   CALL open_r_dataset     ( fid, TRIM(inpname) , head_grid , config_flags , "DATASET=INPUT", ierr )
   IF ( ierr .NE. 0 ) THEN
      WRITE( wrf_err_message , FMT='(A,A,A,I8)' ) 'program ndown: error re-opening ',TRIM(inpname),' for reading ierr=',ierr
      CALL WRF_ERROR_FATAL ( wrf_err_message )
   ENDIF

   !  We know how many time periods to process (right now - all of them), we have the input data
   !  (re-)opened, so we begin.

   big_time_loop_thingy : DO time_loop = 1 , time_loop_max


!      CALL ext_ncd_get_next_time ( fid , date_string , status_next_var )
       CALL geth_newdate ( date_string , start_date_char , ( time_loop - 1 ) * NINT ( new_bdy_frq) )
print *,'-------->>>  Processing data: loop=',time_loop,'  date/time = ',date_string
      current_date_char = date_string
      current_date      = date_string // '.0000'
      start_date        = date_string // '.0000'

      CALL wrf_debug          ( 100 , 'wrf: calling input_history' )
      CALL input_history      ( fid , head_grid , config_flags )
      CALL wrf_debug          ( 100 , 'wrf: back from input_history' )

      !  Get the coarse grid info for later transfer to the fine grid domain.

      CALL wrf_get_dom_ti_integer ( fid , 'MAP_PROJ' , map_proj , 1 , icnt , ierr ) 
      CALL wrf_get_dom_ti_real    ( fid , 'DX'  , dx  , 1 , icnt , ierr ) 
      CALL wrf_get_dom_ti_real    ( fid , 'DY'  , dy  , 1 , icnt , ierr ) 
      CALL wrf_get_dom_ti_real    ( fid , 'CEN_LAT' , cen_lat , 1 , icnt , ierr ) 
      CALL wrf_get_dom_ti_real    ( fid , 'CEN_LON' , cen_lon , 1 , icnt , ierr ) 
      CALL wrf_get_dom_ti_real    ( fid , 'TRUELAT1' , truelat1 , 1 , icnt , ierr ) 
      CALL wrf_get_dom_ti_real    ( fid , 'TRUELAT2' , truelat2 , 1 , icnt , ierr ) 
      CALL wrf_get_dom_ti_real    ( fid , 'GMT' , gmt , 1 , icnt , ierr ) 
      CALL wrf_get_dom_ti_integer ( fid , 'JULYR' , julyr , 1 , icnt , ierr ) 
      CALL wrf_get_dom_ti_integer ( fid , 'JULDAY' , julday , 1 , icnt , ierr ) 
      CALL wrf_get_dom_ti_integer ( fid , 'ISWATER' , iswater , 1 , icnt , ierr ) 

      !  First time in, do this: allocate sapce for the fine grid, get the config flags, open the 
      !  wrfinput and wrfbdy files.  This COULD be done outside the time loop, I think, so check it
      !  out and move it up if you can.

      IF ( time_loop .EQ. 1 ) THEN

         CALL       wrf_message ( program_name )
         CALL       wrf_debug ( 100 , 'wrf: calling alloc_and_configure_domain fine ' )
         CALL alloc_and_configure_domain ( domain_id  = 2 ,                  &
                                           local_time = 0 ,                  &
                                           grid       = nested_grid ,        &
                                           parent     = parent_grid ,        &
                                           kid        = 1                   )
   
         CALL       wrf_debug ( 100 , 'wrf: calling model_to_grid_config_rec ' )
         CALL model_to_grid_config_rec ( nested_grid%id , model_config_rec , config_flags )
         CALL       wrf_debug ( 100 , 'wrf: calling set_scalar_indices_from_config ' )
         CALL set_scalar_indices_from_config ( nested_grid%id , idum1, idum2 )
   
         !  Generate an output file from this program, which will be an input file to WRF.

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! major kludge
print *,'kludge - stupid way to get 1d and consts into new grid'
nested_grid%em_fnm    = parent_grid%em_fnm
nested_grid%em_fnp    = parent_grid%em_fnp
nested_grid%em_rdnw   = parent_grid%em_rdnw
nested_grid%em_rdn    = parent_grid%em_rdn
nested_grid%em_dnw    = parent_grid%em_dnw
nested_grid%em_dn     = parent_grid%em_dn 
nested_grid%em_znu    = parent_grid%em_znu
nested_grid%em_znw    = parent_grid%em_znw

print *,'nested_grid%em_fnm    =', parent_grid%em_fnm
print *,'nested_grid%em_fnp    =', parent_grid%em_fnp
print *,'nested_grid%em_rdnw   =', parent_grid%em_rdnw
print *,'nested_grid%em_rdn    =', parent_grid%em_rdn
print *,'nested_grid%em_dnw    =', parent_grid%em_dnw
print *,'nested_grid%em_dn     =', parent_grid%em_dn 
print *,'nested_grid%em_znu    =', parent_grid%em_znu
print *,'nested_grid%em_znw    =', parent_grid%em_znw

nested_grid%zs        = parent_grid%zs
nested_grid%dzs       = parent_grid%dzs

nested_grid%p_top     = parent_grid%p_top
nested_grid%rdx       = parent_grid%rdx * 3.
nested_grid%rdy       = parent_grid%rdy * 3.
nested_grid%resm      = parent_grid%resm
nested_grid%zetatop   = parent_grid%zetatop
nested_grid%cf1       = parent_grid%cf1
nested_grid%cf2       = parent_grid%cf2
nested_grid%cf3       = parent_grid%cf3

print *,'nested_grid%zs        =', parent_grid%zs
print *,'nested_grid%dzs       =', parent_grid%dzs

print *,'nested_grid%p_top     =', parent_grid%p_top
print *,'nested_grid%rdx       =', parent_grid%rdx *3.
print *,'nested_grid%rdy       =', parent_grid%rdy * 3.
print *,'nested_grid%resm      =', parent_grid%resm
print *,'nested_grid%zetatop   =', parent_grid%zetatop
print *,'nested_grid%cf1       =', parent_grid%cf1
print *,'nested_grid%cf2       =', parent_grid%cf2
print *,'nested_grid%cf3       =', parent_grid%cf3

nested_grid%cfn       = parent_grid%cfn 
nested_grid%cfn1      = parent_grid%cfn1
nested_grid%epsts     = parent_grid%epsts
nested_grid%epsts     = parent_grid%epsts

print *,'nested_grid%cfn       =', parent_grid%cfn 
print *,'nested_grid%cfn1      =', parent_grid%cfn1
print *,'nested_grid%epsts     =', parent_grid%epsts
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
   
         CALL wrf_debug          ( 100 , 'ndown_em main: calling open_w_dataset for wrfinput' )
         CALL construct_filename1( outname , 'wrfinput' , nested_grid%id , 2 )
         CALL open_w_dataset     ( fido, TRIM(outname) , nested_grid , config_flags , output_model_input , "DATASET=INPUT", ierr )
         IF ( ierr .NE. 0 ) THEN
            WRITE( wrf_err_message , FMT='(A,A,A,I8)' ) 'program ndown: error opening ',TRIM(outname),' for reading ierr=',ierr
            CALL WRF_ERROR_FATAL ( wrf_err_message )
         ENDIF

         !  Various sizes that we need to be concerned about.

         ids = nested_grid%sd31
         ide = nested_grid%ed31
         kds = nested_grid%sd32
         kde = nested_grid%ed32
         jds = nested_grid%sd33
         jde = nested_grid%ed33

         ims = nested_grid%sm31
         ime = nested_grid%em31
         kms = nested_grid%sm32
         kme = nested_grid%em32
         jms = nested_grid%sm33
         jme = nested_grid%em33

         print *, ids , ide , jds , jde , kds , kde
         print *, ims , ime , jms , jme , kms , kme

         !  This is the space needed to save the current 3d data for use in computing
         !  the lateral boundary tendencies.

         ALLOCATE ( ubdy3dtemp1(ims:ime,kms:kme,jms:jme) )
         ALLOCATE ( vbdy3dtemp1(ims:ime,kms:kme,jms:jme) )
         ALLOCATE ( tbdy3dtemp1(ims:ime,kms:kme,jms:jme) )
         ALLOCATE ( pbdy3dtemp1(ims:ime,kms:kme,jms:jme) )
         ALLOCATE ( qbdy3dtemp1(ims:ime,kms:kme,jms:jme) )
         ALLOCATE ( mbdy2dtemp1(ims:ime,        jms:jme) )
         ALLOCATE ( ubdy3dtemp2(ims:ime,kms:kme,jms:jme) )
         ALLOCATE ( vbdy3dtemp2(ims:ime,kms:kme,jms:jme) )
         ALLOCATE ( tbdy3dtemp2(ims:ime,kms:kme,jms:jme) )
         ALLOCATE ( pbdy3dtemp2(ims:ime,kms:kme,jms:jme) )
         ALLOCATE ( qbdy3dtemp2(ims:ime,kms:kme,jms:jme) )
         ALLOCATE ( mbdy2dtemp2(ims:ime,        jms:jme) )

      END IF

      !  Do the interpolation.

      CALL med_interp_domain ( head_grid , nested_grid )

      !  Different things happen during the different time loops:
      !      first loop - write wrfinput file, close data set, copy files to holder arrays
      !      middle loops - diff 3d/2d arrays, compute and output bc
      !      last loop - diff 3d/2d arrays, compute and output bc, write wrfbdy file, close wrfbdy file

      IF ( time_loop .EQ. 1 ) THEN

         !  Output the first time period of the data.
   
         nested_grid%write_metadata = .TRUE.
         CALL output_model_input ( fido , nested_grid , config_flags , ierr )

         CALL wrf_put_dom_ti_integer ( fido , 'MAP_PROJ' , map_proj , 1 , ierr ) 
!        CALL wrf_put_dom_ti_real    ( fido , 'DX'  , dx  , 1 , ierr ) 
!        CALL wrf_put_dom_ti_real    ( fido , 'DY'  , dy  , 1 , ierr ) 
         CALL wrf_put_dom_ti_real    ( fido , 'CEN_LAT' , cen_lat , 1 , ierr ) 
         CALL wrf_put_dom_ti_real    ( fido , 'CEN_LON' , cen_lon , 1 , ierr ) 
         CALL wrf_put_dom_ti_real    ( fido , 'TRUELAT1' , truelat1 , 1 , ierr ) 
         CALL wrf_put_dom_ti_real    ( fido , 'TRUELAT2' , truelat2 , 1 , ierr ) 
         CALL wrf_put_dom_ti_real    ( fido , 'GMT' , gmt , 1 , ierr ) 
         CALL wrf_put_dom_ti_integer ( fido , 'JULYR' , julyr , 1 , ierr ) 
         CALL wrf_put_dom_ti_integer ( fido , 'JULDAY' , julday , 1 , ierr ) 
         CALL wrf_put_dom_ti_integer ( fido , 'ISWATER' , iswater , 1 , ierr ) 
         
         !  Close the input (wrfout_d01_000000, for example) file.  That's right, the 
         !  input is an output file.  Who'd've thunk.
   
         CALL close_dataset      ( fido , config_flags , "DATASET=INPUT" )

         !  We need to save the 3d/2d data to compute a difference during the next loop.  Couple the
         !  3d fields with total mu (mub + mu_2) and the stagger-specific map scale factor.

         CALL couple ( nested_grid%em_mu_2 , nested_grid%em_mub , ubdy3dtemp1 , nested_grid%em_u_2                 , &
                       'u' , nested_grid%msfu , &
                       ids, ide, jds, jde, kds, kde, ims, ime, jms, jme, kms, kme, ids, ide, jds, jde, kds, kde )
         CALL couple ( nested_grid%em_mu_2 , nested_grid%em_mub , vbdy3dtemp1 , nested_grid%em_v_2                 , &
                       'v' , nested_grid%msfv , &
                       ids, ide, jds, jde, kds, kde, ims, ime, jms, jme, kms, kme, ids, ide, jds, jde, kds, kde )
         CALL couple ( nested_grid%em_mu_2 , nested_grid%em_mub , tbdy3dtemp1 , nested_grid%em_t_2                 , &
                       't' , nested_grid%msft , &
                       ids, ide, jds, jde, kds, kde, ims, ime, jms, jme, kms, kme, ids, ide, jds, jde, kds, kde )
         CALL couple ( nested_grid%em_mu_2 , nested_grid%em_mub , pbdy3dtemp1 , nested_grid%em_ph_2                , &
                       'w' , nested_grid%msft , &
                       ids, ide, jds, jde, kds, kde, ims, ime, jms, jme, kms, kme, ids, ide, jds, jde, kds, kde )
         CALL couple ( nested_grid%em_mu_2 , nested_grid%em_mub , qbdy3dtemp1 , nested_grid%moist_2(:,:,:,P_QV)    , &
                       't' , nested_grid%msft , &
                       ids, ide, jds, jde, kds, kde, ims, ime, jms, jme, kms, kme, ids, ide, jds, jde, kds, kde )
         mbdy2dtemp1 = nested_grid%em_mu_2

         !  There are 2 components to the lateral boundaries.  First, there is the starting
         !  point of this time period - just the outer few rows and columns.

         CALL stuff_bdy     ( ubdy3dtemp1 , nested_grid%em_u_b     , 'U' , ids , ide , jds , jde , kds , kde , &
                                                                           ims , ime , jms , jme , kms , kme )
         CALL stuff_bdy     ( vbdy3dtemp1 , nested_grid%em_v_b     , 'V' , ids , ide , jds , jde , kds , kde , &
                                                                           ims , ime , jms , jme , kms , kme )
         CALL stuff_bdy     ( tbdy3dtemp1 , nested_grid%em_t_b     , 'T' , ids , ide , jds , jde , kds , kde , &
                                                                           ims , ime , jms , jme , kms , kme )
         CALL stuff_bdy     ( pbdy3dtemp1 , nested_grid%em_ph_b    , 'W' , ids , ide , jds , jde , kds , kde , &
                                                                           ims , ime , jms , jme , kms , kme )
         CALL stuff_bdy     ( qbdy3dtemp1 , nested_grid%em_rqv_b   , 'T' , ids , ide , jds , jde , kds , kde , &
                                                                           ims , ime , jms , jme , kms , kme )
         CALL stuff_bdy2    ( mbdy2dtemp1 , nested_grid%em_mu_b    , 'T' , ids , ide , jds , jde , kds , kde , &
                                                                           ims , ime , jms , jme , kms , kme )


      ELSE IF ( ( time_loop .GT. 1 ) .AND. ( time_loop .LT. time_loop_max ) ) THEN

         CALL couple ( nested_grid%em_mu_2 , nested_grid%em_mub , ubdy3dtemp2 , nested_grid%em_u_2                 , &
                       'u' , nested_grid%msfu , &
                       ids, ide, jds, jde, kds, kde, ims, ime, jms, jme, kms, kme, ids, ide, jds, jde, kds, kde )
         CALL couple ( nested_grid%em_mu_2 , nested_grid%em_mub , vbdy3dtemp2 , nested_grid%em_v_2                 , &
                       'v' , nested_grid%msfv , &
                       ids, ide, jds, jde, kds, kde, ims, ime, jms, jme, kms, kme, ids, ide, jds, jde, kds, kde )
         CALL couple ( nested_grid%em_mu_2 , nested_grid%em_mub , tbdy3dtemp2 , nested_grid%em_t_2                 , &
                       't' , nested_grid%msft , &
                       ids, ide, jds, jde, kds, kde, ims, ime, jms, jme, kms, kme, ids, ide, jds, jde, kds, kde )
         CALL couple ( nested_grid%em_mu_2 , nested_grid%em_mub , pbdy3dtemp2 , nested_grid%em_ph_2                , &
                       'w' , nested_grid%msft , &
                       ids, ide, jds, jde, kds, kde, ims, ime, jms, jme, kms, kme, ids, ide, jds, jde, kds, kde )
         CALL couple ( nested_grid%em_mu_2 , nested_grid%em_mub , qbdy3dtemp2 , nested_grid%moist_2(:,:,:,P_QV)    , &
                       't' , nested_grid%msft , &
                       ids, ide, jds, jde, kds, kde, ims, ime, jms, jme, kms, kme, ids, ide, jds, jde, kds, kde )
         mbdy2dtemp2 = nested_grid%em_mu_2

         !  During all of the loops after the first loop, we first compute the boundary
         !  tendencies with the current data values and the previously save information
         !  stored in the *bdy3dtemp1 arrays.

         CALL stuff_bdytend ( ubdy3dtemp2 , ubdy3dtemp1 , new_bdy_frq , nested_grid%em_u_bt  , 'U' , &
                                                               ids , ide , jds , jde , kds , kde , &
                                                               ims , ime , jms , jme , kms , kme )
         CALL stuff_bdytend ( vbdy3dtemp2 , vbdy3dtemp1 , new_bdy_frq , nested_grid%em_v_bt  , 'V' , &
                                                               ids , ide , jds , jde , kds , kde , &
                                                               ims , ime , jms , jme , kms , kme )
         CALL stuff_bdytend ( tbdy3dtemp2 , tbdy3dtemp1 , new_bdy_frq , nested_grid%em_t_bt  , 'T' , &
                                                               ids , ide , jds , jde , kds , kde , &
                                                               ims , ime , jms , jme , kms , kme )
         CALL stuff_bdytend ( pbdy3dtemp2 , pbdy3dtemp1 , new_bdy_frq , nested_grid%em_ph_bt  , 'W' , &
                                                               ids , ide , jds , jde , kds , kde , &
                                                               ims , ime , jms , jme , kms , kme )
         CALL stuff_bdytend ( qbdy3dtemp2 , qbdy3dtemp1 , new_bdy_frq , nested_grid%em_rqv_bt , 'T' , &
                                                               ids , ide , jds , jde , kds , kde , &
                                                               ims , ime , jms , jme , kms , kme )
         CALL stuff_bdytend2( mbdy2dtemp2 , mbdy2dtemp1 , new_bdy_frq , nested_grid%em_mu_bt  , 'T' , &
                                                               ids , ide , jds , jde , kds , kde , &
                                                               ims , ime , jms , jme , kms , kme )
         IF ( time_loop .EQ. 2 ) THEN
   
            !  Generate an output file from this program, which will be an input file to WRF.

            nested_grid%write_metadata = .TRUE.
   
            CALL wrf_debug          ( 100 , 'ndown_em main: calling open_w_dataset for wrfbdy' )
            CALL construct_filename1( bdyname , 'wrfbdy' , nested_grid%id , 2 )
            CALL open_w_dataset     ( fidb, TRIM(bdyname) , nested_grid , config_flags , output_boundary , &
                                      "DATASET=BOUNDARY", ierr )
            IF ( ierr .NE. 0 ) THEN
               WRITE( wrf_err_message , FMT='(A,A,A,I8)' ) 'program ndown: error opening ',TRIM(bdyname),' for reading ierr=',ierr
               CALL WRF_ERROR_FATAL ( wrf_err_message )
            ENDIF

         ELSE

            nested_grid%write_metadata = .FALSE.

         END IF

         !  Both pieces of the boundary data are now available to be written.

         CALL output_boundary ( fidb , nested_grid , config_flags , ierr )
         IF ( time_loop .EQ. 2 ) THEN
            CALL wrf_put_dom_ti_real    ( fidb , 'BDYFRQ' , new_bdy_frq , 1 , ierr ) 
         END IF

         !  We need to save the 3d data to compute a difference during the next loop.  Couple the
         !  3d fields with total mu (mub + mu_2) and the stagger-specific map scale factor.
         !  We load up the boundary data again for use in the next loop.

         ubdy3dtemp1 = ubdy3dtemp2
         vbdy3dtemp1 = vbdy3dtemp2
         tbdy3dtemp1 = tbdy3dtemp2
         pbdy3dtemp1 = pbdy3dtemp2
         qbdy3dtemp1 = qbdy3dtemp2
         mbdy2dtemp1 = mbdy2dtemp2

         !  There are 2 components to the lateral boundaries.  First, there is the starting
         !  point of this time period - just the outer few rows and columns.

         CALL stuff_bdy     ( ubdy3dtemp1 , nested_grid%em_u_b     , 'U' , ids , ide , jds , jde , kds , kde , &
                                                                           ims , ime , jms , jme , kms , kme )
         CALL stuff_bdy     ( vbdy3dtemp1 , nested_grid%em_v_b     , 'V' , ids , ide , jds , jde , kds , kde , &
                                                                           ims , ime , jms , jme , kms , kme )
         CALL stuff_bdy     ( tbdy3dtemp1 , nested_grid%em_t_b     , 'T' , ids , ide , jds , jde , kds , kde , &
                                                                           ims , ime , jms , jme , kms , kme )
         CALL stuff_bdy     ( pbdy3dtemp1 , nested_grid%em_ph_b    , 'W' , ids , ide , jds , jde , kds , kde , &
                                                                           ims , ime , jms , jme , kms , kme )
         CALL stuff_bdy     ( qbdy3dtemp1 , nested_grid%em_rqv_b   , 'T' , ids , ide , jds , jde , kds , kde , &
                                                                           ims , ime , jms , jme , kms , kme )
         CALL stuff_bdy2    ( mbdy2dtemp1 , nested_grid%em_mu_b    , 'T' , ids , ide , jds , jde , kds , kde , &
                                                                           ims , ime , jms , jme , kms , kme )

      ELSE IF ( time_loop .EQ. time_loop_max ) THEN

         CALL couple ( nested_grid%em_mu_2 , nested_grid%em_mub , ubdy3dtemp2 , nested_grid%em_u_2                 , &
                       'u' , nested_grid%msfu , &
                       ids, ide, jds, jde, kds, kde, ims, ime, jms, jme, kms, kme, ids, ide, jds, jde, kds, kde )
         CALL couple ( nested_grid%em_mu_2 , nested_grid%em_mub , vbdy3dtemp2 , nested_grid%em_v_2                 , &
                       'v' , nested_grid%msfv , &
                       ids, ide, jds, jde, kds, kde, ims, ime, jms, jme, kms, kme, ids, ide, jds, jde, kds, kde )
         CALL couple ( nested_grid%em_mu_2 , nested_grid%em_mub , tbdy3dtemp2 , nested_grid%em_t_2                 , &
                       't' , nested_grid%msft , &
                       ids, ide, jds, jde, kds, kde, ims, ime, jms, jme, kms, kme, ids, ide, jds, jde, kds, kde )
         CALL couple ( nested_grid%em_mu_2 , nested_grid%em_mub , pbdy3dtemp2 , nested_grid%em_ph_2                , &
                       'w' , nested_grid%msft , &
                       ids, ide, jds, jde, kds, kde, ims, ime, jms, jme, kms, kme, ids, ide, jds, jde, kds, kde )
         CALL couple ( nested_grid%em_mu_2 , nested_grid%em_mub , qbdy3dtemp2 , nested_grid%moist_2(:,:,:,P_QV)    , &
                       't' , nested_grid%msft , &
                       ids, ide, jds, jde, kds, kde, ims, ime, jms, jme, kms, kme, ids, ide, jds, jde, kds, kde )
         mbdy2dtemp2 = nested_grid%em_mu_2

         !  During all of the loops after the first loop, we first compute the boundary
         !  tendencies with the current data values and the previously save information
         !  stored in the *bdy3dtemp1 arrays.

         CALL stuff_bdytend ( ubdy3dtemp2 , ubdy3dtemp1 , new_bdy_frq , nested_grid%em_u_bt  , 'U' , &
                                                               ids , ide , jds , jde , kds , kde , &
                                                               ims , ime , jms , jme , kms , kme )
         CALL stuff_bdytend ( vbdy3dtemp2 , vbdy3dtemp1 , new_bdy_frq , nested_grid%em_v_bt  , 'V' , &
                                                               ids , ide , jds , jde , kds , kde , &
                                                               ims , ime , jms , jme , kms , kme )
         CALL stuff_bdytend ( tbdy3dtemp2 , tbdy3dtemp1 , new_bdy_frq , nested_grid%em_t_bt  , 'T' , &
                                                               ids , ide , jds , jde , kds , kde , &
                                                               ims , ime , jms , jme , kms , kme )
         CALL stuff_bdytend ( pbdy3dtemp2 , pbdy3dtemp1 , new_bdy_frq , nested_grid%em_ph_bt  , 'W' , &
                                                               ids , ide , jds , jde , kds , kde , &
                                                               ims , ime , jms , jme , kms , kme )
         CALL stuff_bdytend ( qbdy3dtemp2 , qbdy3dtemp1 , new_bdy_frq , nested_grid%em_rqv_bt , 'T' , &
                                                               ids , ide , jds , jde , kds , kde , &
                                                               ims , ime , jms , jme , kms , kme )
         CALL stuff_bdytend2( mbdy2dtemp2 , mbdy2dtemp1 , new_bdy_frq , nested_grid%em_mu_bt  , 'T' , &
                                                               ids , ide , jds , jde , kds , kde , &
                                                               ims , ime , jms , jme , kms , kme )

         nested_grid%write_metadata = .FALSE.

         !  Both pieces of the boundary data are now available to be written.

         CALL output_boundary ( fidb , nested_grid , config_flags , ierr )

         !  Since this is the last time through here, we need to close the boundary file.

         CALL close_dataset ( fidb , config_flags , "DATASET=BOUNDARY" )


      END IF

      !  Process which time now?

   END DO big_time_loop_thingy

   STOP

END PROGRAM ndown_em