|
!------------------------------------------------------------------------------- |
|
!> Check a variable for out of bounds and clamp or fail if needed. |
|
!> If the variable has clamping limits, this routine returns .TRUE. |
|
!> If the variable is unbounded, this routine returns .FALSE. |
|
!> The return value is not an indication of whether or not the values have |
|
!> actually been modified. |
|
!------------------------------------------------------------------------------- |
|
|
|
subroutine clamp_variable(dom_id, var_index, variable) |
|
|
|
integer, intent(in) :: dom_id ! domain id |
|
integer, intent(in) :: var_index ! variable index |
|
real(r8), intent(inout) :: variable(:) ! variable |
|
|
|
real(r8) :: minclamp, maxclamp, my_minmax(2) |
|
character(len=NF90_MAX_NAME) :: varname ! for informational log messages |
|
logical :: allow_missing ! used in CLM for state variables |
|
|
|
! if neither bound is set, return early |
|
minclamp = get_io_clamping_minval(dom_id, var_index) |
|
maxclamp = get_io_clamping_maxval(dom_id, var_index) |
|
|
|
if (minclamp == missing_r8 .and. maxclamp == missing_r8) return |
|
|
|
! if we get here, either the min, max or both have a clamping value. |
|
|
|
!>@todo this is what the code needs to be for CLM and any other |
|
! model that allows missing values in the state. right now that |
|
! is defined in assim_tools_mod but i don't think we can use it |
|
! because of circular module dependencies. it should be defined |
|
! maybe in filter? and set into some low level module (like types |
|
! or constants or options_mod so anyone can query it). |
|
! |
|
! if we allow missing values in the state (which jeff has never |
|
! liked because it makes the statistics funny), then these next |
|
! two lines need to be: |
|
allow_missing = get_missing_ok_status() |
|
|
|
if (allow_missing) then |
|
my_minmax(1) = minval(variable, mask=(variable /= missing_r8)) |
|
my_minmax(2) = maxval(variable, mask=(variable /= missing_r8)) |
|
else |
|
! get the min/max for this variable before we start |
|
my_minmax(1) = minval(variable) |
|
my_minmax(2) = maxval(variable) |
|
endif |
|
|
|
varname = get_variable_name(dom_id, var_index) |
|
|
|
! is lower bound set? |
|
if ( minclamp /= missing_r8 ) then ! missing_r8 is flag for no clamping |
|
if ( my_minmax(1) < minclamp ) then |
|
!>@todo again, if we're allowing missing in state, this has to be masked: |
|
if (allow_missing) then |
|
where(variable /= missing_r8) variable = max(minclamp, variable) |
|
else |
|
variable = max(minclamp, variable) |
|
endif |
|
|
|
! TJH TOO VERBOSE write(msgstring, *) trim(varname)// ' lower bound ', minclamp, ' min value ', my_minmax(1) |
|
! TJH TOO VERBOSE call error_handler(E_ALLMSG, 'clamp_variable', msgstring, & |
|
! TJH TOO VERBOSE source) |
|
endif |
|
endif ! min range set |
|
|
|
! is upper bound set? |
|
if ( maxclamp /= missing_r8 ) then ! missing_r8 is flag for no clamping |
|
if ( my_minmax(2) > maxclamp ) then |
|
!>@todo again, if we're allowing missing in state, this has to be masked: |
|
if (allow_missing) then |
|
where(variable /= missing_r8) variable = min(maxclamp, variable) |
|
else |
|
variable = min(maxclamp, variable) |
|
endif |
|
|
|
! TJH TOO VERBOSE write(msgstring, *) trim(varname)// ' upper bound ', maxclamp, ' max value ', my_minmax(2) |
|
! TJH TOO VERBOSE call error_handler(E_ALLMSG, 'clamp_variable', msgstring, & |
|
! TJH TOO VERBOSE source) |
|
endif |
|
|
|
endif ! max range set |
|
|
|
end subroutine clamp_variable |
|
|
|
|
|
|
|
!------------------------------------------------------------------------------- |
I don't think clamp_or_fail is used: ☠️
DART/models/wrf/model_mod.f90
Line 343 in 52e6e45
https://github.com/search?q=repo%3ANCAR%2FDART%20clamp_or_fail&type=code
clamp_or_fail not passed to state structure
No fail in
clamp_variableDART/assimilation_code/modules/io/direct_netcdf_mod.f90
Lines 1448 to 1534 in 52e6e45
Originally posted by @hkershaw-brown in #404 (comment)