The goal of this study do design accurate vertical grid remapping
(vertical interpolation), which can be used in hybrid coordinate
(ALE-type) ocean models. Specific attention was paid to ability
of a scheme to maintain high-order accuracy on non-uniform grids;
to be monotonic; and to be able to maintain profile ("thermocline")
without diffusing or sharpening it over many periods of oscillatory
motion of the grid. 

   --> Overall the remapping procedure can be viewed as "inverse
       advection", i.e. grid moves, but profile should stand still.
       But it is equivalent to motion of profile with respect to the
      grid.


Several known and unknown scheme (SPLINES, PPM, WENO, etc...) were
studied and compared.

A brief manuscript (a PostScript file "remap.ps") and a lot of
graphics (NCAR Graphics gmetas) as well as all relevant FORTRAN
codes (useful to evaluate actual complexity and usability are
available at  

       http://www.atmos.ucla.edu/~alex/remapping

Just download file "remapping.tar.gz" (put it in a special
directory) uncompress it using and  untar it:

         gunzip remapping.tar
         tar xvf remapping.tar

Then read README file for further explanation.


Formulation of the problem:
=========== == === ========

Vertically nonuniform grid is generated via analytical function.
Movement (deformation of the grid) in time is also controlled by
making grid stretching parameter be dependent of time. 

Initial profile is set by TANH function.

As grid moves by one time step, data in remapped (interpolated)
from the "old" grid to "new". Once interpolation is done, the "old"
set grid-box averaged values is discarded, and during the next step
interpolation starts from the previously interpolated values.
And so on, up to 10000 times.  

Ideally the interpolated profile should be the same as original,
in practice it is not. The errors and long-term drifts caused by
different methods are compared.
 




            T O   S E E   T H E   R E S U L T S: 
            ===   =====   =====   ==============

These are several gmeta files here. Just do "idt gmeta_XXXXX" where
XXXXX = {PCONST, LINEAR, LINEAR_iterated, SLINE, PPM, WENO, QUARTIC}.

There are approximately 250 frames in each gmeta, so do fast forward
or animate. Two the most promising methods are WENO and QUARTIC.


What do you see:
==== == === ====

Blue staircase -- ACTUAL grid-box boundaries and grid-box averaged
            values shown at each moment.

Green continuous line -- the EXACT profile (drawn everywhere for
                                                     reference.)

Red line -- (either continuous WENO, QUARTIC or segments within each
            grid box continuous line, or red segments, LINEAR, PPM)
            profile as it is seen by the reconstruction algorithm.

White arrow (like mouse cursor) points to a selected grid-box
            interface (N/2-th interface). This is done to illustrate
            the amplitude of grid motion, which basically means that
            interfaces near the thermocline move well above and below
            it.

White time clock in the bottom right corner. Time is measured in
            periods and running from 0.00 to 200.00 (200.00 means
            200 periods). There are 50 time steps within each period 
            so that the field has been remapped 10000 times (TEN
            THOUSAND TIME STEPS) in each experiment.

           --> During the first 4 periods profile is plotted after
               each remapping update step, to illustrate exactly what
               is going on.

           --> After then only one frame per period is plotted to
               show long term effect (the actual calculation proceeds
               EXACTLY as before). This is to illustrate long-term
               effect.

             

The six remapXXX.F files are five different versions of remapping
procedure, their style and loop structure mimics the actual structure
of ROMS code: they are designed to work for subdomain of indix ranges
i,j = Istr:Iend,Jstr:Jend  which define a three dimensional block
within two dimensional partition. Of course, in all these experiments
Istr=Iend=Jstr=Jend=1, i.e. it is just a vertical column.

More information about each algorithm can be found in comments within
each file.

The specific versions are (gmeta_XXXX is the corresponding plot):


   remap0.F      Piecewise constant distribution is assumed in each
   gmeta_PCONST  grid box. This is similar to how it is done in first
                 order accurate upstream (donor cell) advection.
                 Highly diffusive.

   remap1.F      Monotonized (MINMOD slope) piecewise linear
   gmeta_LINEAR            distribution in each grid box. Similar
   gmeta_LINEAR_iterated   to van Leer, 1976 second-order advection
                           method. Can be iteratively enhanced (see
                 code associated with CPP-switch ENHANCE) to reduce
                 discontinuities of the reconstructed profile accross
                 grid-box interfaces. 
               --> Diffusive, but less than the previous one;
               --> Iterated version is much less diffusive.



   remap2S.F     Reconstruction by parabolic spline. This is just
   gmeta_SPLINE  a basic algorithms without any monotonicity
                 constraints. Accurate for smooth fields, but highly
                 ocsillatory otherwise.


   remap2PPM.F   Reconstruction is identical to PPM code of
   gmeta_PPM     Woodward -- Colella, 1984. This algorithm is
                 strictly monotonic. Continuity at interfaces
                 may be lost due to limiting.
 


   remap2W.F     Monotonized parabolic segment is constructed in
   gmeta_WENO    each grid box, which results in two candidate values
                 at each interface, one coming from each side.
                 The final interfacial value at each grid box is
                 then set to be a weighted sum of the two candidate
                 values with weights being inversely proportional to
                 a measure of quadratic variation of the field within
                 grid box.

                 Once interfacial values are finally computed,
                 parabolic distribution is assumed in each grid box

                -->  profile is always continuous across interfaces
                -->  "essentially non-oscillatory", strict
                   monotonicity is not guaranteed, but almost there.
 

   remap4.F      Parabolic WENO (same as in remap2W.F) enhances by
   gmeta_QUARTIC power-law reconciliation step. 

                 Profile in each grid box is then given by a quartic
                 polynomial.

                -->  continuity of both value and first derivative at
                     each interface;
                -->  "essentially non-oscillatory" is a sense similar
                     to above. 


Other files;

    main.F           simply drives and calls everything

    setup_grid.F     subroutine to generate grid

    setup_profile.F  subroutine to specify initial profile

    plot.F           call NCAR graphics routines to plot;

    Makefile

    phys_param.h
    set_global_definitions.h

Manuscript:
===========

    remap.ps   A PostScript file containing brief manuscript with
               relevant formulaes. Just to supplement the codes
               in order to understand what is going on. 


To reproduce the results:
== ========= === ========

   1. Edit makefile and adjust according to your computer setup: 

            CPP       path to C-preprocessor 
            FFLAGS
            LIBNCAR   location of NCAR graphics libraries.

   2. Type "make": it should compile, run and produce an example
                         of gmeta;

   3. Edit main.F: find CPP switch #define PCONST and select
            algorithm you want, then type "make" again.




          A D D I T I O N A L    I N F O R M A T I O N
          ===================    =====================

Meaning of selected variables:    (for simplicity horizontal
======= == ======== ==========     indices are suppressed here)

z_w(k) -- vertical coordinate of k-th interface; k=N corresponds
          to free surface; k=0 bottom; NOTE: z_w(k) is the same as 
          z_{k+1/2} in the manuscript. 

Hz(k)  -- height of grid box k (corresponds to H_k in the manuscript)
          ALWAYS       Hz(k)=z_w(k)-z_w(k-1) , k=1:N 

rho(k) -- k=1:N -- density (or whatever field) averahed within
          grid box grid-box Hz(k) [same as \overline\rho_k in the
          manuscript]; 

r(k)   -- k=0:N -- instantaneous value of density at the k-th
          interface [i.e. location z_w(k)] computed by reconstruction
          algorithm, [same as \rho_{k+1/2} in the manuscript];

d(k)   -- k=0:N -- instantaneous value first derivative at k-th 
          interface [i.e. location z_w(k)], computed by
          reconstruction , [same as d_{k+1/2} in the manuscript];

aL(k)  -- k=1:N left and right limits of parabolic segment defined
aR(k)     within grid box Hz(k) [same as a^L_k, a^R_k in Colella and
          Woodward, 1984], [corresponds to  \rho^L_k, \rho^R_k in the
          manuscript]; 

dL(k)  -- k=1:N left and right limits of first derivative of profile
dR(k)     (usually a parabola) defined within grid box Hz(k)



Vertical staggered grid indexing adopted here:
======== ========= ==== ======== ======= =====


z_w(N) --------------------------- r(N),d(N)       <-- surface
                       aR(N),dR(N)

        Hz(N), rho(N)
.....





                     aL(k+1),dR(k+1)
z_w(k) ----------------------------- r(k), d(k)     <--
                         aR(k),dR(k)                <--
                                                    <-- k-th
        Hz(k), rho(k)                               <-- Grid
                                                    <-- Box
                         aL(k),dL(k)                <--
z_w(k-1) --------------------------- r(k-1),d(k-1)  <--
                     aR(k-1),dR(k-1)

.......


         Hz(1), rho(1)

                            aL(1),dL(1)
z_w(k-1) ------------------------------ r(0),d(0)   <-- bottom




Code Optimization
==== ============

Because many algorithms presented here are complex and potentially
exepnsive, there was reasonable effort to optimize each code. By the
nature of slope-limited algorithms, "if" logical branches are
unavoidable, the following rules were followed to ensure efficiency
of execution:

       --> all loops are data-independent (==> vectorizable)

       --> since BOTH branches of an "if -- else -- endif" switch
           must be executed on a pipelined processor, all operations
           are moved outside the "if", leaving basically only
           assignments and negations;

       --> there are no nested "if" statements;

       --> avoid divisions, where possible.

       --> in some potentially too complex loops, software pipelining
           status was checked via "f77 -S"



 froopera
