NCAR CSM Flux Coupler, version 4.0 -- User's Guide         Table of Contents

7   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 Flux 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.F. 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 77.

 §7.1  Variable Naming Convention
 §7.2  Main Program

7.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 Flux 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:

Next, a suffix _x indicates what model grid the states reside on: 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:

Complete input fluxes (an "a" prefix denotes a daily average): Finally, just like the state variables above, a suffix _x indicates what model grid the fluxes reside on:

7.2   Main Program

Notice that the Flux Coupler code is configured for a particular time coordination scheme. Model time coordination occurs within a nested loop structure. The ocean model communicates with the coupler once per outer loop iteration, while the atmosphere, ice, and land models communicate once per inner loop iteration. Typically the outer loop corresponds to one day, while the inner loop corresponds to several hours or less. While this configuration is hard-coded within the coupler, it's 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 file), requiring a minimal amount of code modifications or new code.

      PROGRAM main 

      initial       ! read input namelist

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

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

      call restart ('read' , Sa_a , Faia_a , Fala_a , Faoa_a ,
     &                       Sl_l ,
     &                       Si_i , Fioi_i ,
     &                       So_o , Fioo_o ,aFoxx_o, runoff )

      while ( stop_date > current_date ) do

         do n=1,ncpl_a

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

            !--- prepare lnd input & send to lnd model ---
            call map_a2l (  Sa_a ,  Sa_l )
            call map_a2l (Fala_a ,Fala_l )
            call msg_lnd_send (Fala_l , Sa_l   )

            !--- deal with atm/ice fluxes (computed by cpl)  ---
            call map_a2i (Sa_a ,  Sa_i )
            call flux_ai (Sa_i  ,  Si_i ,Faic_i )
            call map_i2a (Faic_i ,Faic_a )
            call map_a2i (Faia_a ,Faia_i )

            !--- deal with atm/ocn fluxes (computed by cpl) ---
            call map_a2o (  Sa_a ,  Sa_o )
            call flux_ao (  Sa_o ,  So_o ,Faoc_o )
            call map_o2a (Faoc_o ,Faoc_a )
            call map_a2o (Faoa_a ,Faoa_o )

            !--- deal with atm/lnd fluxes (computed by lnd) ---
            call msg_lnd_recv (Sl_l , Fall_l , runoff)
            call map_l2a (Fall_l ,Fall_a )
            call map_l2a (Sl_l   ,Sl_a )

            !--- merge atm inputs & send to atm model ---
            call mrg_atm (Faic_a ,Fall_a ,Faoc_a ,Faxx_a)
            call mrg_atm (  Si_a ,  Sl_a ,  So_a ,  Ss_a)
            call msg_atm_send (Faxx_a ,  Ss_a )

            !--- adjust ice/ocn E~P balance over open ocn ---
            if (flx_epbal.ne.0) call flux_epbal()

            !--- deal with ice/ocn fluxes ---
            call map_i2o (Fioi_i ,Fioi_o )
            call map_o2i (Fioo_o ,Fioo_i )
            call map_o2i (  So_o ,  So_i )
            call flux_io (  Si_i ,  So_i ,Fioo_i ,Fioc_i )
            call map_i2o (Fioc_i ,Fioc_o )

            !--- merge ice inputs, send to ice ---
            call mrg_ice ( Faia_i , Faic_i , Fioo_i , Fioc_i, Faoa_o , Faoc_o , Fixx_i)
            call msg_ice_send ( Fixx_i )
       
            !--- merge *instantaneous* ocn inputs ---
            call mrg_ocn ( Faoa_o , Faoc_o , Fioi_o , Fioc_o, Foxx_o)

            !--- make a cpl history file, do diagnostics ---
            call history ()
            call diagnos ()

            !--- form tavg partial sum of ocn inputs ---
            call tavg-sum(Foxx_o,aFoxx_o)

            !--- receive atm,ice outputs ---
            call msg_ice_recv (Si_i ,Fioi_i )
            call msg_atm_recv (Sa_a ,Faia_a ,Fala_a ,Faoa_a)

            if ( mod(n,m).eq.0 ) then
              !--- receive ocn outputs ---
              call msg_ocn_recv (So_o , Fioo_o)
 
              !--- form tavg of ocn inputs ---
              call tavg-avg(aFoxx_o,m)
            end if

            !--- 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 ---
         eday = eday + 1  ! increment number of elapsed days
         sec  = 0
         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 ,
     &                            Si_i , Fioi_i ,
     &                            So_o , Fioo_o ,aFoxx_o, runoff )

      END DO
  999 CONTINUE

      !--- send final msg to models & disconnect from msg-passing ---
      call msg_atmf ()
      call msg_icef ()
      call msg_ocnf ()
      call msg_lndf ()
      call msg_cpld ()

      STOP - END OF PROGRAM


Fri 07 Aug 1998, 12:00:00