GFDL - Geophysical Fluid Dynamics Laboratory

Skip to main content

The Hallberg Isopycnal Model (HIM)

by Robert Hallberg

Introduction


This program (HIM) simulates the ocean by numerically solving the Boussinesq primitive equations in isopycnal vertical coordinates and general orthogonal horizontal coordinates. These equations are horizontally discretized on an Arakawa C-grid. There are a range of options for the physical parameterizations, from those most appropriate to highly idealized models for studies of geophysical fluid dynamics to a rich suite of processes appropriate for realistic ocean simulations. The thermodynamic options range from an adiabatic model with fixed density layers to a model with temperature and salinity as state variables and using a full nonlinear equation of state. The uppermost few layers may be used to describe a bulk mixed layer, including the effects of penetrating shortwave radiation. Either a split- explicit time stepping scheme or a non-split scheme may be used for the dynamics, while the time stepping may be split (and use different numbers of steps to cover the same interval) for the forcing, the thermodynamics, and for the dynamics. Most of the numerics are second order accurate in space. HIM can run with an absurdly thin minimum layer thickness.

Details of the numerics and physical parameterizations are provided in the appropriate source files. Most of the available options are selected by the settings in init.h, although some (such as the equation of state) are selected by specifying which file to use in the make file (Makefile).

The file HIM.c contains the main time stepping loops. One time integration option for the dynamics uses a split explicit time stepping scheme to rapidly step the barotropic pressure and velocity fields. The barotropic velocities are averaged over the baroclinic time step before they are used to advect thickness and determine the baroclinic accelerations. At the end of every time step, the free surface height perturbation is determining by adding up the layer thicknesses; this perturbation is used to drive the free surface heights from the barotropic calculation and from the sum of the layer thicknesses toward each other over subsequent time steps. The barotropic and baroclinic velocities are synchronized as part of the vertical viscosity algorithm and be recalculating. the barotropic velocities from the baroclinic velocities each time step. This scheme is described in Hallberg, 1997, J. Comp. Phys. 135, 54-65.

The other time integration option uses a non-split time stepping scheme based on the 3-step third order Runge-Kutta scheme described in Matsuno, 1966, J. Met. Soc. Japan, 44, 85-88. For problems with more than a very few layers, this non-split scheme is much less efficient than the split scheme, but because it is much simpler and formally more accurate, it is useful to have to verify that temporal truncation errors are not significant.

There are a range of closure options available in HIM. Horizontal velocities are subject to a combination of horizontal biharmonic and Laplacian friction (based on a stress tensor formalism) and a vertical Fickian viscosity (perhaps using the kinematic viscosity of water). The horizontal viscosities may be constant, spatially varying or may be dynamically calculated using Smagorinsky's approach. A diapycnal diffusion of density and thermodynamic quantities is also allowed, but not required, as is horizontal diffusion of interface heights (akin to the Gent-McWilliams closure of geopotential coordinate models). The diapycnal mixing may use a fixed diffusivity or it may use the shear Richardson number dependent closure described in Hallberg (MWR, 2000). When there is diapycnal diffusion, it applies to momentum as well. As this is in addition to the vertical viscosity, the vertical Prandtl always exceeds 1.

HIM has a number of noteworthy debugging capabilities. Excessively large velocities are truncated and HIM will stop itself after a number of such instances to keep the model from crashing altogether, and the model state is output with a reported time of 9.9e9. This is useful in diagnosing failures, or (by accepting some truncations) it may be useful for getting the model past the adjustment from an ill-balanced initial condition. In addition, all of the accelerations in the columns with excessively large velocities may be directed to a text file. Parallelization errors may be diagnosed with the CHECK_PARALLEL option, whereby ostensibly identical model incarnations are run simultaneously on one and multiple processors and any differences are reported.

About 35 other files of source code and 6 header files must be used to make HIM work. A makefile is included to make compiling easy. Type "make HIM" to compile. Some run time input is required, but this is prompted for. It may be convenient to direct a small file containing the needed information to standard input, and direct the output to another file.

Source File Subroutines


The ~35 source files contain the following subroutines:

    HIM.c
    step_HIM
    steps HIM over a specified interval of time.
    HIM_initialize
    calls initialize and does other initialization that does not warrant user modification.
    set_restart_fields
    is used to specify those fields that are written to and read from the restart file.
    calculate_surface_state
    determines the surface (mixed layer) properties of the current model state and packages pointers to these fields into an exported structure.
    HIM_checkparallel.c
    HIM_checkparallel.c is identical to HIM.c, except that it has a number of diagnostic calls to assess whether a parallel run is giving identical results to a single processor run.
    HIM_driver.c
    main
    is where HIM starts. Inside of main are the calls that set up the run, step the model, and orchestrate output and normal termination of the run.

Initial Condition, Forcing, and Domain Specification Routines


    initialize.c
    initialize
    does just that to all of the fields that are needed to specify the initial conditions of the model. initialize calls a number of other subroutines in initialize.c, each of which initializes a single field (or a few closely related fields) that are indicated by the subroutine name.
    initialize_output.c
    USER_set_output
    specifies what fields are output into which files and when, and whether they are averaged in time.
    USER_set_diagnostics
    specifies what diagnostic quantities are calculated.
    GetInputLines
    gets 4 controlling inputs from stdin, including the directories for I/O and the parameter specification file.
    write_grid_file
    writes out a file describing the model grid.
    surface_forcing.c
    set_forcing
    sets the current values of surface forcing fields.
    wind_forcing
    sets the current surface wind stresses.
    buoyancy_forcing
    sets the current surface heat, fresh water, buoyancy or other appropriate tracer fluxes.
    set_forcing_output
    sets up the output of any forcing fields.
    average_forcing
    accumulates time averages of indicated forcing fields.
    register_forcing_restarts
    is used to specify the forcing-related fields that are written to and read from the restart file.
    set_metrics.c
    set_metrics
    calculates the horizontal grid spacings and related metric fields, along with the grid point locations.
    initialize_masks
    initializes the land masks.

Principal Dynamic Routines


    CoriolisAdv.c
    CorAdCalc
    calculates the Coriolis and advective accelerations.
    PressureForce.c
    PressureForce
    calculates the pressure acceleration.
    register_compress
    is used to specify the reference profile of potential temperature and salinity that is used to compensate for compressibility.
    uncompress_e_rho
    makes internally consistent changes to profiles of interface height and density to offset compressibility and to minimize the non-solenoidal pressure gradient term.
    continuity.c, continuity_mpdata.c, or continuity_FCT.c
    continuity time steps the layer thicknesses.
    barotropic.c
    btstep
    time steps the linearized barotropic equations for use with the split explicit time stepping scheme.
    btcalc
    calculates the barotropic velocities from the layer velocities.
    barotropic_init
    initializes several split-related variables and calculates several static quantities for use by btstep.
    register_barotropic_restarts
    indicates those time splitting-related fields that are to be in the restart file.
    hor_visc.c
    horizontal_viscosity
    calculates the convergence of momentum due to Laplacian or biharmonic horizontal viscosity.
    set_up_hor_visc
    calculates combinations of metric coefficients and other static quantities used in horizontal_viscosity.
    vertvisc.c
    vertvisc
    changes the velocity due to vertical viscosity, including application of a surface stress and bottom drag.
    set_viscous_BBL
    determines the bottom boundary layer thickness and viscosity according to a linear or quadratic drag law.
    thickness_diffuse.c
    thickness_diffuse
    moves fluid adiabatically to horizontally diffuse interface heights.

Thermodynamic Routines


    diabatic_driver.c
    diabatic
    orchestrates the calculation of vertical advection and diffusion of momentum and tracers due to diapycnal mixing and mixed layer (or other diabatic) processes. mixedlayer, Calculate_Entrainment, apply_sponge, and any user-specified tracer column physics routines are all called by diabatic.
    diabatic_entrain.c
    Calculate_Entrainment
    calculates the diapycnal mass fluxes due to interior diapycnal mixing processes, which may include a Richardson number dependent entrainment.
    Calculate_Rino_flux
    estimates the Richardson number dependent entrainment in the absence of interactions between layers, from which the full interacting entrainment can be found.
    Estimate_u_h
    estimates what the velocities at thickness points will be after entrainment.
    mixed_layer.c
    mixed_layer
    implements a bulk mixed layer, including entrainment and detrainment, related advection of dynamically active tracers, and buffer layer splitting. The bulk mixed layer may consist of several layers.
    tracer.c
    register_tracer
    is called to indicate a field that is to be advected by advect_tracer and diffused by tracer_hordiff.
    advect_tracer
    does along-isopycnal advection of tracer fields.
    tracer_hordiff
    diffuses tracers along isopycnals.
    register_tracer_init_fn
    registers a user-specified tracer initialization subroutine.
    call_tracer_init_fns
    calls any user-specified tracer initialization subroutines that have been registered.
    register_tracer_column_fn
    registers a user-specified tracer column processes subroutine.
    call_tracer_column_fns
    calls any user-specified tracer column processes subroutines that have been registered.
    sponge.c
    apply_sponge
    damps fields back to reference profiles.
    initialize_sponge
    stores the damping rates and allocates the memory for the reference profiles.
    set_up_sponge_field
    registers reference profiles and associates them with the fields to be damped.
    eqn_of_state.c, eqn_of_state_linear.c, or eqn_of_state_UNESCO.c
    calculate_density
    calculates a list of densities at given potential temperatures, salinities and pressures.
    calculate_density_derivs
    calculates a list of the partial derivatives with temperature and salinity at the given potential temperatures, salinities and pressures.
    calculate_compress
    calculates a list of the compressibilities (partial derivatives of density with pressure) at the given potential temperatures, salinities and pressures.
    calculate_2_densities
    calculates a list of the densities at two specified reference pressures at the given potential temperatures and salinities.
    fit_compressibility.c
    fit_compressibility
    determines the best fit of compressibility with pressure using a fixed 5-coefficient functional form, based on a provided reference profile of potential temperature and salinity with depth. This fit is used in PressureForce.

Infrastructural Routines


    HIM_restart.c
    save_restart
    saves a restart file (or multiple files if they would otherwise be too large).
    register_restart_field
    is called to specify a field that is to written to and read from the restart file.
    restore_state
    reads the model state from output or restart files.
    query_initialized
    indicates whether a specific field or all restart fields have been read from the restart files.
    HIM_parser.c
    HIM_parser
    parses a parameter specification file with the same format as init.h to (possibly) change parameters at run time.
    HIM_sum_output.c
    write_energy
    writes the layer energies and masses and other spatially integrated quantities and monitors CPU time use.
    depth_list_setup
    generates a list of the volumes of fluid below various depths.
    HIM_field_output.c
    specify_saves_file
    sets up a file for output, including when and how frequently the file is to be written.
    set_up_save_field
    sets up a field to be saved and also perhaps to be averaged in time.
    save_fields
    saves all fields that are to be saved within the given time interval and indicates the next scheduled time that a field is to be saved.
    enable_averaging
    enables averaging for a time interval.
    disable_averaging
    disables the accumulation of averages.
    query_averaging_enabled
    indicates whether averaging is currently enabled.
    get_field_ref
    returns a reference integer for a field that is to be averaged, or 0 if it is not to be averaged.
    average_field
    accumulates the average of a field.
    timetype.c (Partial C implementation of the FMS time manager.)
    t_ge, t_gt, t_le, t_lt, t_eq, and t_ne
    make logical comparisons between times.
    t_plus
    adds two times together.
    t_minus
    finds the absolute value of the difference between times. (i.e. |t1-t2|)
    t_mult
    multiplies a time by an integer.
    t_div
    returns the real ratio of two times.
    t_div_int
    divides a time by an integer.
    t_interval
    finds the signed, real ratio of the interval between two times to a third time. (i.e. (t1-t2)/t3)
    double_to_time
    converts a real number to a time.
    time_to_double
    converts a time to a real number.
    HIM_io.c (Input/Output utility subroutines)
    create_file
    creates a new file, set up structures that are needed for subsequent output, and write the coordinates.
    reopen_file
    reopens an existing file for writing and set up structures that are needed for subsequent output.
    open_input_file
    opens the indicated file for reading only.
    close_file
    closes an open file.
    synch_file
    flushes the buffers for a file, completing all pending output.
    write_field
    writes a field to an open file.
    write_time
    writes a value of the time axis to an open file.
    Read_Field
    provides a simpler interface to read_field.
    read_field
    reads a field from an open file.
    read_time
    reads a time from an open file.
    name_output_file
    provides a name for an output file based on a name root and the time of the output.
    find_input_file
    finds a file that has been previously written by HIM and named by name_output_file and opens it for reading.
    handle_error
    writes an error code and quits.
    HIM_parallel.c (Parallelization utility subroutines)
    set_up_parallel
    starts parallel runs and calculates subdomain sizes and neighboring domains.
    pass_var
    passes a 3-D variable to neighboring processors or applies corresponding boundary conditions.
    pass_var_2d
    passes a 2-D variable to neighboring processors or applies corresponding boundary conditions.
    sum_fields
    sums fields across all processors.
    sum_int_fields
    sums integer fields across all processors.
    collect_double_fields
    collects a full layer of a field to processor 0.
    spread_string
    distributes a character string from processor 0.
    spread_double_vector
    distributes copies of a 1-D array from processor 0.
    check_field
    checks whether a field is identical on different processors, and reports any differences. This is useful for checking parallelization or for debugging coding changes that are not expected to change answers.
    quit
    causes all processors to stop execution.

Purely Diagnostic Routines


    diagnostics.c
    calculate_diagnostic_fields
    is used to calculate several diagnostic fields that are not naturally calculated elsewhere.
    register_time_deriv
    is used to register the information needed for diagnostically calculating a time derivative.
    calculate_derivs
    calculates any registered time derivatives.
    PointAccel.c
    write_u_accel
    writes a long list of zonal accelerations and related quantities for one column out to a file. This is typically called for diagnostic purposes from vertvisc when a zonal velocity exceeds the specified threshold.
    write_v_accel
    writes a long list of meridional accelerations and related quantities for one column out to a file. This is typically called for diagnostic purposes from vertvisc when a meridional velocity exceeds the specified threshold.

Header Files


In addition there are 5 header files:
    init.h
    sets various constants and parameters for the simulation.
    HIM.h
    contains the subroutine prototypes and the definitions of the following 6 structures:
    params (HIM_params) contains changeable simulation parameters.
    forcing (fluxes) contains pointers to surface forcing fields.
    surface (state) contains pointers to ocean surface fields.
    diag_fld (diag) contains pointers to diagnostic quantities.
    thermo_var_ptrs (tv) contains pointers to thermodynamic fields, such as potential temperature and salinity.
    bt_vars_ptrs (bt) contains pointers to variables related to the baroclinic/barotropic split time stepping.
    HIM_io.h
    contains the subroutine prototypes and structure definitions for I/O related subroutines.
    metrics.h
    contains the descriptions for a number of metric terms.
    hor_visc.h
    contains the descriptions for a number of metric-related fields that are only used by the horizontal viscosity.

Most simulations can be set up by modifying only the files init.h, initialize.c, and surface_forcing.c. In addition, the file initialize_output.c will commonly be modified to tailor the output to the needs of the question at hand. These altered files and the makefile might reside in the same directory as the executable file. All of the other (unaltered) source code should probably remain in some central directory. The makefile will, of course, need to reflect the locations of the desired source files.