Skip to content

Commit

Permalink
+Move MOM_scaling_check.F90 to MOM_unique_scales.F90
Browse files Browse the repository at this point in the history
  Renamed the framework module MOM_scaling_check.F90 to MOM_unique_scales.F90 to
help differentiate it from MOM_check_scaling.F90, and renamed the subroutine
check_scaling_factors() as check_scaling_uniqueness().  Also added
_Dimensional_consistency.dox to describe the dimensional consistency testing.
This commit should address the issues raised in the review of MOM6 PR #49.  All
answers and output are bitwise identical.
  • Loading branch information
Hallberg-NOAA authored and marshallward committed Feb 15, 2022
1 parent 56401b6 commit 75bf521
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 9 deletions.
6 changes: 3 additions & 3 deletions src/core/MOM_check_scaling.F90
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
!> This module is used to check the scaling factors used by the MOM6 ocean model
!> This module is used to check the dimensional scaling factors used by the MOM6 ocean model
module MOM_check_scaling

! This file is part of MOM6. See LICENSE.md for the license.

use MOM_error_handler, only : MOM_error, MOM_mesg, FATAL, WARNING, assert, MOM_get_verbosity
use MOM_scaling_check, only : check_scaling_factors, scales_to_powers
use MOM_unique_scales, only : check_scaling_uniqueness, scales_to_powers
use MOM_unit_scaling, only : unit_scale_type
use MOM_verticalGrid, only : verticalGrid_type

Expand Down Expand Up @@ -53,7 +53,7 @@ subroutine check_MOM6_scaling_factors(GV, US)
! This call records all the list of powers, the descriptions, and their weights.
call compose_dimension_list(ns, descriptions, weights)

call check_scaling_factors("MOM6", descriptions, weights, key, scale_pow2, max_pow)
call check_scaling_uniqueness("MOM6", descriptions, weights, key, scale_pow2, max_pow)

deallocate(weights)
deallocate(descriptions)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
!> This module is used to check the scaling factors used by the MOM6 ocean model
module MOM_scaling_check
!> This module provides tools that can be used to check the uniqueness of the dimensional
!! scaling factors used by the MOM6 ocean model or other models
module MOM_unique_scales

! This file is part of MOM6. See LICENSE.md for the license.

Expand All @@ -12,15 +13,15 @@ module MOM_scaling_check
! their mks counterparts with notation like "a velocity [Z T-1 ~> m s-1]". If the units
! vary with the Boussinesq approximation, the Boussinesq variant is given first.

public check_scaling_factors, scales_to_powers
public check_scaling_uniqueness, scales_to_powers

contains

!> This subroutine does a checks whether the provided dimensional scaling factors give a unique
!! overall scaling for each of the combinations of units in description, and suggests a better
!! combination if it is not unique. However, this subroutine does nothing if the verbosity level
!! for this run is below 3.
subroutine check_scaling_factors(component, descs, weights, key, scales, max_powers)
subroutine check_scaling_uniqueness(component, descs, weights, key, scales, max_powers)
character(len=*), intent(in) :: component !< The name of the component (e.g., MOM6) to use in messages
character(len=*), intent(in) :: descs(:) !< The descriptions for each combination of units
integer, intent(in) :: weights(:) !< A list of the weights for each described combination
Expand Down Expand Up @@ -139,7 +140,7 @@ subroutine check_scaling_factors(component, descs, weights, key, scales, max_pow

endif

end subroutine check_scaling_factors
end subroutine check_scaling_uniqueness

!> Convert a unit scaling descriptor into an array of the dimensions of powers given in the key
subroutine encode_dim_powers(scaling, key, dim_powers)
Expand Down Expand Up @@ -350,4 +351,4 @@ function int_array_msg(array)
enddo
end function int_array_msg

end module MOM_scaling_check
end module MOM_unique_scales
85 changes: 85 additions & 0 deletions src/framework/_Dimensional_consistency.dox
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*! \page Dimensional_consistency Dimensional Consistency Testing

\section section_Dimensional_consistency Dimensional Consistency Testing

MOM6 uses a unique system for testing the dimensional consistency of all of
its expressions. The internal representations of dimensional variables are
rescaled by integer powers of 2 that depend on their units, with all input and
output being rescaled back to their original MKS units. By choosing different
powers of 2 for different units, the internal representations with different
units scale differently, so dimensionally inconsistent expressions will not
reproduce, but dimensionally inconsistent expressions give bitwise identical
results. So, for example, if horizontal lengths scale by a factor of 2^6=64,
and time is scaled by a factor of 2^4=16, horizontal velocities will scale by a
factor of 2^(6-4)=4. In this case, expressions that combine velocities, all
terms would scale by the same factor of 4. By contrast, if there were an
expression where a variable with units of length were added to one with the
units of a velocity, the results would scale inconsistently, and answers would
change with different scaling factors.

What makes these integer powers of 2 special is the way that floating point
numbers are written as an O(1) mantissa times 2 raised to an integer exponent
between +/-1024. Multiplication by an integer power of 2 is just an integer
shift in the exponent, so as long as the model is not rescaled by an overly
large factor to encounter overflows and the model is not relying on automatic
underflows being converted to 0, all floating point operations can be carried
with one scale, and then rescaled to obtain identical answers. MOM6 has the
option to explicitly handle all relevant cases of underflows, and it can be
demonstrated to give identical answers when each of its units are scaled by
factors ranging from 2^-140 ~= 7.2e-43 to 2^140 ~= 1.4e42.

When running with rescaling factors other than 2^0 = 1, there are some extra
array copies and multiplies of input fields or diagnostic output, so it is
slightly more efficient not to actively use the dimensional rescaling. For
production runs, we typically set all of the rescaling powers to 0, but for
debugging code problems, this rescaling can be an invaluable tool, especially
when combined with the very verbose runtime setting DEBUG=True in a MOM_input or
MOM_override file. Diffs of the output from runs with different scaling factors
readily highlights the earliest instances of differences, which can be used to
track down any dimensionally inconsistent expressions. Similarly, dimensional
inconsistencies in diagnostics is easily tracked down by comparing the output
from a pair of runs.

All real variables in MOM6 should have comments describing their purpose,
along with their rescaled units and their mks counterparts with notation like
"! A velocity [L T-1 ~> m s-1]". If the units vary with the Boussinesq
approximation, the Boussinesq variant is given first. When variables are read
in, their dimensions are usually specified with a 'scale=' optional argument on
the MOM_get_param or MOM_read_data call, while the unscaling of diagnostics is
specified with a 'conversion=' factor. In both cases, these arguments it next
to a text string specifying the variable's units, which can then be check easily
for self-consistency.

Currently in MOM6, the following dimensions have unique scaling, along with
the notation used to describe these variables in comments:

\li Time, scaled by 2^T_RESCALE_POWER, denoted as [T ~> s]
\li Horizontal length, scaled by 2^L_RESCALE_POWER, denoted as [L ~> m]
\li Vertical height, scaled by 2^Z_RESCALE_POWER, denoted as [Z ~> m]
\li Vertical thickness, scaled by 2^H_RESCALE_POWER, denoted as [H ~> m or kg m-2]
\li Density, scaled by 2^R_RESCALE_POWER, denoted as [R ~> kg m-3]
\li Enthalpy (or heat content), scaled by 2^Q_RESCALE_POWER, denoted as [Q ~> J kg-1]

These rescaling capabilities are also used by the SIS2 sea ice model, but it
does uses a non-Boussinesq mass scale of [R Z ~> kg m-2] for ice thicknesses,
rather than having a separate scaling factor (of [H ~> m or kg m-2]) that varies
between the Boussinesq and non-Boussinesq modes like MOM6 does. The actual
powers used in the scaling are specified separately for MOM6 and SIS2 and
need not be the same.

Each of these units can be scaled in separate test runs, or all of them can be
rescaled simultaneously. In the latter case, MOM_unique_scales.F90 provides
tools to evaluate whether the specific combinations of units used by a model
scale by unique powers, and it can suggest scaling factors that provides unique
combinations of rescaling factors for the dimensions being tested, using a
cost-function based on the frequency with which units are used in the model (and
specified inside of MOM_check_scaling.F90), with a cost going as the product of
the frequency of units that resolve to the same scaling factor.

A separate set of scaling factors could also be used for different chemical
tracer concentrations, for example. In this case, the tools in
MOM_unique_scales.F90 could still be used, but there would need to be a separate
equivalent of the unit_scaling_type with variables that are appropriate to the
units of the tracers.

*/

0 comments on commit 75bf521

Please sign in to comment.