next up previous contents
Next: 7 Data Exchanged with Up: users_guide Previous: 5 Source Code Maintenance   Contents


6 Pseudo-Code

To understand the details of the Coupler's functionality, it is useful to have a
basic understanding of the computer code that is the Coupler. To that end, 
pseudo-code is shown below. If one wishes to modify the Coupler source code, it
is strongly recommended that one first study this section in conjunction with 
studying the source code file, main.F90. This should provide a good overview of
how the Coupler works; a necessary pre-requisite for successful code 
modification. The actual source code is 99.9% pure Fortran 90.

6.1 Variable Naming Convention

A variable naming convention has been adopted to help organize and identify
the literally hundreds of state and flux fields managed by the Coupler.
Understanding this naming convention is a prerequisite for understanding the
pseudo-code below.
State Variables
Model state variables are denoted Sx, where x denotes the corresponding
component model:

   * Sa = atm state variables, e.g. atm wind velocity
   * Si = ice state variables, e.g. ice temperature
   * Sl = lnd state variables, e.g. lnd albedo
   * So = ocn state variables, e.g. ocn SST
   * Ss = all surface states merged together, e.g. global surface temperature

Next, a suffix _x indicates what model grid the states reside on:

   * Sa_a: atm states on atm grid
   * Sa_o: atm states on ocn grid
Flux Fields
Input flux means fluxes given by the Coupler to a model. Output flux means
fluxes computed within a model and given to the Coupler. All input fluxes
for one model were either computed by the Coupler or were the output flux of
another model. In general, a given flux field between any two component
models may have been computed in one of three places: within either of the
two models or within the Coupler.

One function of the Coupler is to gather, merge, sum, and/or time-average
the various component flux fields from various sources and form a set of
complete input fluxes for each component model. This gathering and merging
process will generally involve mapping flux fields between various model
grids and combining like fields from several grids onto one grid. A
summation might be required, e.g., net heat flux = solar + latent + sensible
+ longwave. Also, for some flux fields the Coupler might be required to form
time-averaged quantities. Thus component fluxes are mapped, merged, summed,
and/or time-averaged by the Coupler in order to form complete input fluxes
for the models.

Flux fields are denoted Fxyz, where xy denotes the two model between which a
quantity is being fluxed, and z denotes the model which computed the flux
(i.e. it is an output flux of model z).

Component fluxes that are gathered, merged, summed, and/or time--averaged to
form the complete input fluxes are:

   * Faia = atm/ice flux, computed by atm, e.g. precipitation
   * Faii = atm/ice flux, computed by ice, e.g. sensible heat flux
   * Fala = atm/lnd flux, computed by atm, e.g. precipitation
   * Fall = atm/lnd flux, computed by lnd, e.g. sensible heat flux
   * Faoc = atm/ocn flux, computed by cpl, e.g. momentum flux
   * Faoa = atm/ocn flux, computed by atm, e.g. precipitation
   * Fioo = ice/ocn flux, computed by ocn, e.g. ice formed within the ocn
   * Fioi = ice/ocn flux, computed by ice, e.g. penetrating shortwave radiation
   * Flol = lnd/ocn flux, computed by lnd, e.g. river runoff

Complete input fluxes (an "a" prefix denotes a daily average):

   *  Faxx = all atm input fluxes: a map/merge/sum of: Faoc, Faii, Fall
   *  Flxx = all lnd input fluxes: a map/merge/sum of: Fala
   *  Foxx = all ocn input fluxes: a map/merge/sum of: Faoc, Faoa, Fioi, Flol
   * aFoxx = a time average of: Foxx
   *  Fixx = all ice input fluxes: a map/merge/sum of: Faia, Fioo

Finally, just like the state variables above, a suffix _x indicates what
model grid the fluxes reside on:

   * Faoa_a: atm/ocn fluxes, computed by the atm, on the atm grid
   * Faoa_o: atm/ocn fluxes, computed by the atm, on the ocn grid
Domain Maps
Mapping between domains is implemented by matrix multiplies.  Generally there
are different maps for state fields vs. flux fields, as state fields maps are
generally smoother (eg. bilinear) whereas flux field maps must be conservative
(eg. area averaging, aka Riemann sum integrals).  In the case of mapping between
identical domains, the map would be the identity map.  The necessary mapping 
matrices are:

   * map_Fa2i: map for fluxes, atm -> ice
   * map_Sa2i: map for states, atm -> ice
   * map_Fa2l: map for fluxes, atm -> lnd
   * map_Sa2l: map for states, atm -> lnd
   * map_Fa2o: map for fluxes, atm -> ocn
   * map_Sa2o: map for states, atm -> ocn
   * map_Fi2a: map for fluxes, ice -> atm
   * map_Si2a: map for states, ice -> atm

6.2 Main Program

Notice that the Coupler code is configured for a particular time coordination 
scheme. Model time coordination involves two communication intervals, with the 
longer interval being an integer multiple of the shorter interval.  The 
atmosphere, ice, and land models communicate once per short interval while the 
ocean model communicates once per long interval.  Also, one day (24 hours) is
an integer multiple of the longer communication interval.  Typically the longer
interval is exactly one day, while the shorter interval is several hours or 
less.  While this configuration is hard-coded within the Coupler, its modular 
design facilitates code modifications to implement alternate configurations. A 
variety of time coordination schemes can be, and have been, implemented by 
rearranging subroutine calls at the highest level (within the main program), 
requiring a minimal amount of code modifications or new code.


   call initial       ! read input namelist

   call msg_atm_init  ! exchange spatial & temporal grid info with atm model
   call msg_ice_init  ! exchange spatial & temporal grid info with ice model
   call msg_lnd_init  ! exchange spatial & temporal grid info with lnd model
   call msg_ocn_init  ! exchange spatial & temporal grid info with ocn model

   !--- read restart file ---
   call restart ('read' , Sa_a , Faia_a , Fala_a , Faoa_a ,
   &                      Sl_l , Fall_l , Falo_l ,
   &                      Si_i , Faii_i , Fioi_i ,
   &                      So_o , Fioo_o ,aFoxx_o )

   m = ncpl_a/ncpl_o  ! determine number of atm messages per ocn message

   DO WHILE ( current_date < stop_date )

      DO n=0,ncpl_a-1

         !--- send tavg inputs to ocn, start new tavg summation ---
         if ( mod(n,m) == 0 ) then
            call msg_ocn_send (aFoxx_o)
            call tavg-zero    (aFoxx_o) ! start new time average
         end if

         !--- map atm states/fluxes to lnd, send msg to lnd ---
         call map (map_Sa2l,   Sa_a ,  Sa_l )
         call map (map_Fa2l, Fala_a ,Fala_l )
!lnds    call msg_lnd_send ( Fala_l ,  Sa_l  )

         !--- map atm states/fluxes to ice grid ---
         call map (map_Sa2i,   Sa_a ,   Sa_i )
         call map (map_Fa2i, Faia_a , Faia_i )

         !--- send msg to ice ---
!ices    call msg_ice_send ( Sa_i , So_i, Faia_i, Fioo_i )

         !--- prepare instantaneous ocn inputs ---
         call map (map_Sa2o,   Sa_a ,   Sa_o )
         call map (map_Fa2o, Faoa_a , Faoa_o )
         call map (map_Fl2o, Flol_l , Flol_o )
         call flux_solar ( Faoa_o, So_o, Faoc_o ) ! compute net short-wave

         !--- "send" msg to ocn (add instantaneous data to t-avg) ---
!ocns    call mrg_ocn  ( Faoa_o,  Faoc_o, Fioi_o, Flol_o, Foxx_o)
         call tavg-sum ( Foxx_o, aFoxx_o)

         !--- compute ocean albedos and Faoc fluxes ---
!ocnr    call flux_albedo ( So_o ) ! update ocn state ~ "receive"
         call flux_ao     ( Sa_o, So_o, Faoc_o )

         !--- map ocn states/fluxes to atm ---
         call map( map_Fo2a, Faoc_o, Faoc_a )
         call map( map_So2a,   So_o,   So_a )

!icer    !--- receive ice outputs ---
         call msg_ice_recv (Si_i ,Faii_i, Fioi_i )

         !--- map ice states/fluxes to atm & ocn grid ---
         call map (map_Fi2a, Faii_i, Faii_a )
         call map (map_Si2a,   Si_i,   Si_a )
         call map (map_Fi2o, Fioi_i, Fioi_o )
         call map (map_Si2o,   Si_i,   Si_o )

!lndr    !--- recv new lnd data ---
         call msg_lnd_recv (Sl_l, Fall_l, Flol_l )

         !--- map lnd states & fluxes to atm ---
         call map (map_Fl2a, Fall_l, Fall_a )
         call map (map_Sl2a,   Sl_l,   Sl_a )
         !--- merge atm states & fluxes ---
         call mrg_atm (Faii_a, Fall_a, Faoc_a, Faxx_a)
         call mrg_atm (  Si_a,   Sl_a,   So_a,   Ss_a)

!atms    !--- send data to atm ---
         call msg_atm_send (Faxx_a, Ss_a )

         !--- add data to history file ---
         call history ()

         if ( mod(n+1,m) == 0 ) then
            !--- receive ocn outputs ---
            call msg_ocn_recv (So_o , Fioo_o)

            !--- map ocn to ice ---
            call map (map_So2i,   So_o,   So_i )
            call map (map_Fo2i, Fioo_o, Fioo_i )

            !--- form tavg of ocn inputs summation---
            call tavg-avg(aFoxx_o,m)
         end if

!atmr    !--- recv msg from atm ---
         call msg_atm_recv (Sa_a, Faia_a, Fala_a, Faoa_a)
         !--- cpl, atm, ice, lnd have advanced part of one day ---
         sec = sec + 86400/ncpl_a
         call control()     ! reset stop, rest, hist control flags
      END DO

      !--- cpl & component models have advanced one day ---
      if (sec >= 86400) then
         eday = eday + 1  ! increment number of elapsed days
         sec  = 0
      end if
      call tcheck()    ! verify time coordination
      call control()   ! reset stop, rest, hist control flags

      !--- make a cpl restart file ---
      call restart ('write', Sa_a , Faia_a , Fala_a , Faoa_a ,
      &                      Sl_l , Fall_l , Falo_l ,
      &                      Si_i , Faii_i , Fioi_i ,
      &                      So_o , Fioo_o ,aFoxx_o )



   !--- send final msg to models & disconnect from msg-passing ---
   call msg_atm_final ()
   call msg_ice_final ()
   call msg_ocn_final ()
   call msg_lnd_final ()
   call msg_cpl_disconnect ()