Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generalized subroutine to read the state variables from the namelist (get_state_variables) #783

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
17f26ab
Making a generic subroutine to read model_nml:model_state_variables i…
mjs2369 Nov 12, 2024
179d34f
Adding a unit test for the state var table read
mjs2369 Nov 13, 2024
f18942e
Fixing file name for dev test
mjs2369 Nov 13, 2024
c0bb758
Changing the name of the subroutine to get_state_variables
mjs2369 Dec 10, 2024
1914a42
Changing the name of the dev test to better fit the subroutine name and
mjs2369 Dec 10, 2024
c168bbe
Removing MOM6 version of subroutine and making necessary adjustments
mjs2369 Dec 10, 2024
e82df2e
including other needed input.nml file for test
mjs2369 Dec 10, 2024
f177c69
Removing MPI from dev test
mjs2369 Dec 12, 2024
ccf37db
Adding an interface to create 2 distinct subroutines for get_state_va…
mjs2369 Dec 12, 2024
7381c2b
Updating MOM6 model_mod to use new interface
mjs2369 Dec 12, 2024
914468f
Replacing CAM-FV version of the routine with generic in default_model…
mjs2369 Dec 12, 2024
15e984f
Replacing CAM-SE version of the routine with generic in default_model…
mjs2369 Dec 12, 2024
6ed2022
Removing forgotten print statements from ca-fv model_mod
mjs2369 Dec 12, 2024
7336795
Using separate namelist groups in a single input.nml as opposed to us…
mjs2369 Dec 12, 2024
14352e1
Replacing WRF_HYDRO version of the routine with generic in default_mo…
mjs2369 Dec 12, 2024
4d996bd
WRF_HYDRO: Removing varibles that are no longer used due to changes
mjs2369 Dec 16, 2024
b1f0878
MOM6: Removing varibles that are no longer used due to changes
mjs2369 Dec 16, 2024
80a63e1
Replacing POP version of the routine with generic in default_model_mod
mjs2369 Dec 16, 2024
d76f1cb
Replacing aether_lat-lon version of the routine with generic in defau…
mjs2369 Dec 16, 2024
979a9cf
Replacing NOAH version of the routine with generic in default_model_mod
mjs2369 Dec 16, 2024
3e629cf
Replacing MITgcm_ocean version of the routine with generic in default…
mjs2369 Dec 16, 2024
0d759f3
Replacing CICE version of the routine with generic in default_model_mod
mjs2369 Dec 16, 2024
4d790b5
Fixing print statement in default_model_mod
mjs2369 Dec 17, 2024
83ad490
- Make function instead of subroutine
mjs2369 Jan 9, 2025
4da5986
Updating dev test; remove prints and test all components of the state…
mjs2369 Jan 9, 2025
022e6ba
Use parse_variables in the 3d template model_mod
mjs2369 Jan 9, 2025
87e21ba
Merge branch 'main' into get_state_variables
mjs2369 Jan 9, 2025
23c8d84
Fix typo in state_structure_mod.f90
mjs2369 Jan 9, 2025
ceeb76d
standard: .eqv. for logicals
hkershaw-brown Jan 13, 2025
e5057da
fix: use QTY_NAME rather than hardcoded number
hkershaw-brown Jan 13, 2025
b0c2a00
chore: add test_parse_variables program to gitignore
hkershaw-brown Jan 13, 2025
a4b10d6
Fix state_var_type%netcdf_var_names character length in default_model…
mjs2369 Jan 13, 2025
79cd8ea
Add needed trim to default_model_mod.f90
mjs2369 Jan 13, 2025
b66ee82
Making final adjustments and fixes to the dev test
mjs2369 Jan 13, 2025
d6bebae
Reverting the MITgcm_ocean model_mod to the original (cannot use the new
mjs2369 Jan 13, 2025
e78fbda
Adding the logic to use the default state variables if model_state_va…
mjs2369 Jan 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions developer_tests/namelist/test_get_state_variables.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
! DART software - Copyright UCAR. This open source software is provided
! by UCAR, "as is", without charge, subject to all terms of use at
! http://www.image.ucar.edu/DAReS/DART/DART_download

program test_get_state_variables

use utilities_mod, only : find_namelist_in_file, check_namelist_read
use mpi_utilities_mod, only : initialize_mpi_utilities, finalize_mpi_utilities
use types_mod, only : vtablenamelength, MISSING_R8
use default_model_mod, only : get_state_variables, state_var_type

use test ! fortran-testanything

implicit none

integer :: iunit, io
logical :: use_clamping
type(state_var_type) :: state_vars, state_vars_clamp

! DART state vector contents are specified in the input.nml:&model_nml namelist.
integer, parameter :: MAX_STATE_VARIABLES = 20
integer, parameter :: NUM_STATE_TABLE_COLUMNS = 3
character(len=vtablenamelength) :: state_variables(MAX_STATE_VARIABLES * NUM_STATE_TABLE_COLUMNS ) = ' '

namelist /model_nml_noclamp/ &
state_variables

namelist /model_nml_clamp/ &
state_variables

call initialize_mpi_utilities('test_get_state_variables')

call plan(10)

! Using namelist WITHOUT clamping values

call find_namelist_in_file('input.nml', 'model_nml_noclamp', iunit)
read(iunit, nml = model_nml_noclamp, iostat = io)
call check_namelist_read(iunit, io, 'model_nml_noclamp')

call get_state_variables(state_variables, MAX_STATE_VARIABLES, state_vars)

write(*,*) 'state_vars%nvars: ', state_vars%nvars
write(*,*) 'state_vars%netcdf_var_names: ', state_vars%netcdf_var_names
write(*,*) 'state_vars%qtys: ', state_vars%qtys
write(*,*) 'state_vars%updates: ', state_vars%updates
mjs2369 marked this conversation as resolved.
Show resolved Hide resolved

call ok(state_vars%nvars == 5) !OK
call ok(state_vars%netcdf_var_names(2) == '') !NOT OK
mjs2369 marked this conversation as resolved.
Show resolved Hide resolved
call ok(state_vars%qtys(3) == 20) !NOT OK
call ok(state_vars%updates(4) == .true.) !OK

! Using namelist file WITH clamping values
use_clamping = .true.

call find_namelist_in_file('input.nml', 'model_nml_clamp', iunit)
read(iunit, nml = model_nml_clamp, iostat = io)
call check_namelist_read(iunit, io, 'model_nml_clamp')

call get_state_variables(state_variables, MAX_STATE_VARIABLES, use_clamping, state_vars_clamp)

write(*,*) 'state_vars%nvars: ', state_vars_clamp%nvars
write(*,*) 'state_vars%netcdf_var_names: ', state_vars_clamp%netcdf_var_names
write(*,*) 'state_vars%qtys: ', state_vars_clamp%qtys
write(*,*) 'state_vars%clamp_values(:,1): ', state_vars_clamp%clamp_values(:, 1)
write(*,*) 'state_vars%clamp_values(:,2): ', state_vars_clamp%clamp_values(:, 2)
write(*,*) 'state_vars%updates: ', state_vars_clamp%updates
mjs2369 marked this conversation as resolved.
Show resolved Hide resolved

call ok(state_vars_clamp%nvars == 7) !NOT OK
call ok(state_vars_clamp%netcdf_var_names(2) == 'TEMP_CUR') !OK
call ok(state_vars_clamp%qtys(3) == 356) !OK
call ok(state_vars_clamp%clamp_values(1,1) == 99) !NOT OK
call ok(state_vars_clamp%clamp_values(5,2) == 0.0) !OK
call ok(state_vars_clamp%updates(4) == .false.) !NOT OK

call finalize_mpi_utilities()

end program test_get_state_variables
71 changes: 71 additions & 0 deletions developer_tests/namelist/work/input.nml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
&model_nml_clamp
state_variables = 'SALT_CUR ', 'QTY_SALINITY', '0.0', '0.0', 'UPDATE',
'TEMP_CUR ', 'QTY_POTENTIAL_TEMPERATURE', '0.0', '0.0', 'UPDATE',
'UVEL_CUR ', 'QTY_U_CURRENT_COMPONENT ', '0.0', '0.0', 'UPDATE',
'VVEL_CUR ', 'QTY_V_CURRENT_COMPONENT ', '0.0', '0.0', 'UPDATE',
'PSURF_CUR', 'QTY_SEA_SURFACE_PRESSURE ', '0.0', '0.0', 'UPDATE'
/

&model_nml_noclamp
state_variables = 'SALT_CUR ', 'QTY_SALINITY', 'UPDATE',
'TEMP_CUR ', 'QTY_POTENTIAL_TEMPERATURE', 'UPDATE',
'UVEL_CUR ', 'QTY_U_CURRENT_COMPONENT ', 'UPDATE',
'VVEL_CUR ', 'QTY_V_CURRENT_COMPONENT ', 'UPDATE',
'PSURF_CUR', 'QTY_SEA_SURFACE_PRESSURE ', 'UPDATE'
/

&utilities_nml
module_details = .false.
write_nml = 'none'
/

&preprocess_nml
input_obs_kind_mod_file = '../../../assimilation_code/modules/observations/DEFAULT_obs_kind_mod.F90'
quantity_files = '../../../assimilation_code/modules/observations/land_quantities_mod.f90',
'../../../assimilation_code/modules/observations/default_quantities_mod.f90'
'../../../assimilation_code/modules/observations/atmosphere_quantities_mod.f90'
'../../../assimilation_code/modules/observations/ocean_quantities_mod.f90'
output_obs_kind_mod_file = '../../../assimilation_code/modules/observations/obs_kind_mod.f90'
input_obs_def_mod_file = '../../../observations/forward_operators/DEFAULT_obs_def_mod.F90'
output_obs_def_mod_file = '../../../observations/forward_operators/obs_def_mod.f90'
input_files = '../../../observations/forward_operators/obs_def_AIRS_mod.f90',
'../../../observations/forward_operators/obs_def_AOD_mod.f90',
'../../../observations/forward_operators/obs_def_AURA_mod.f90',
'../../../observations/forward_operators/obs_def_COSMOS_mod.f90',
'../../../observations/forward_operators/obs_def_CO_Nadir_mod.f90',
'../../../observations/forward_operators/obs_def_GWD_mod.f90',
'../../../observations/forward_operators/obs_def_QuikSCAT_mod.f90',
'../../../observations/forward_operators/obs_def_SABER_mod.f90',
'../../../observations/forward_operators/obs_def_altimeter_mod.f90',
'../../../observations/forward_operators/obs_def_cloud_mod.f90',
'../../../observations/forward_operators/obs_def_dew_point_mod.f90',
'../../../observations/forward_operators/obs_def_dwl_mod.f90',
'../../../observations/forward_operators/obs_def_eval_mod.f90',
'../../../observations/forward_operators/obs_def_gps_mod.f90',
'../../../observations/forward_operators/obs_def_gts_mod.f90',
'../../../observations/forward_operators/obs_def_land_mod.f90',
'../../../observations/forward_operators/obs_def_metar_mod.f90',
'../../../observations/forward_operators/obs_def_ocean_mod.f90',
'../../../observations/forward_operators/obs_def_pe2lyr_mod.f90',
'../../../observations/forward_operators/obs_def_radar_mod.f90',
'../../../observations/forward_operators/obs_def_reanalysis_bufr_mod.f90',
'../../../observations/forward_operators/obs_def_rel_humidity_mod.f90',
'../../../observations/forward_operators/obs_def_sqg_mod.f90',
'../../../observations/forward_operators/obs_def_tower_mod.f90',
'../../../observations/forward_operators/obs_def_tpw_mod.f90',
'../../../observations/forward_operators/obs_def_upper_atm_mod.f90',
'../../../observations/forward_operators/obs_def_vortex_mod.f90',
'../../../observations/forward_operators/obs_def_wind_speed_mod.f90'
/

&mpi_utilities_nml
/

&obs_kind_nml
/

&ensemble_manager_nml
/

&state_vector_io_nml
/
43 changes: 43 additions & 0 deletions developer_tests/namelist/work/quickbuild.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash

# DART software - Copyright UCAR. This open source software is provided
# by UCAR, "as is", without charge, subject to all terms of use at
# http://www.image.ucar.edu/DAReS/DART/DART_download

main() {

export DART=$(git rev-parse --show-toplevel)
source "$DART"/build_templates/buildfunctions.sh

MODEL="none"
EXTRA="$DART"/models/template/threed_model_mod.f90
dev_test=1
TEST="namelist"
LOCATION="threed_sphere"

programs=(
test_get_state_variables
)


# quickbuild arguments
arguments "$@"

# clean the directory
\rm -f -- *.o *.mod Makefile .cppdefs

# build any NetCDF files from .cdl files
cdl_to_netcdf

# build and run preprocess before making any other DART executables
buildpreprocess

# build
buildit

# clean up
\rm -f -- *.o *.mod

}

main "$@"
106 changes: 10 additions & 96 deletions models/MITgcm_ocean/model_mod.f90
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ module model_mod
use random_seq_mod, only : random_seq_type, init_random_seq, random_gaussian

use default_model_mod, only : nc_write_model_vars, adv_1step, &
init_conditions => fail_init_conditions
init_conditions => fail_init_conditions, &
get_state_variables, state_var_type

use dart_time_io_mod, only : write_model_time

Expand Down Expand Up @@ -127,6 +128,8 @@ module model_mod
logical :: calendarDumps = .false.
logical :: pickupStrictlyMatch = .false.

logical, parameter :: use_clamping = .true.

NAMELIST /CAL_NML/ TheCalendar, startDate_1, startDate_2, calendarDumps

! FIXME: these namelists should probably be in a separate file, and only
Expand Down Expand Up @@ -285,7 +288,7 @@ module model_mod
integer, parameter :: VT_STATEINDX = 5 ! ... update (state) or not
integer, parameter :: MAX_STATE_VARIABLES = 20
integer, parameter :: NUM_STATE_TABLE_COLUMNS = 5
character(len=vtablenamelength) :: mitgcm_variables(NUM_STATE_TABLE_COLUMNS, MAX_STATE_VARIABLES ) = ' '
character(len=vtablenamelength) :: mitgcm_variables(NUM_STATE_TABLE_COLUMNS*MAX_STATE_VARIABLES ) = ' '
mjs2369 marked this conversation as resolved.
Show resolved Hide resolved

character(len=256) :: model_shape_file = ' '
integer :: assimilation_period_days = 7
Expand Down Expand Up @@ -317,7 +320,6 @@ module model_mod
end type MIT_meta_type

integer :: domain_id
integer :: nvars

contains

Expand All @@ -330,10 +332,7 @@ module model_mod

subroutine static_init_model()

character(len=vtablenamelength) :: var_names(MAX_STATE_VARIABLES) = ' '
integer :: quantity_list(MAX_STATE_VARIABLES) = MISSING_I
real(r8) :: clamp_vals(MAX_STATE_VARIABLES,2) = MISSING_R8
logical :: update_list(MAX_STATE_VARIABLES) = .FALSE.
type(state_var_type) :: state_vars

integer :: i, iunit, io
integer :: ss, dd
Expand Down Expand Up @@ -533,11 +532,11 @@ subroutine static_init_model()
if (do_output()) write( * , *) 'Using grid size : '
if (do_output()) write( * , *) ' Nx, Ny, Nz = ', Nx, Ny, Nz

call parse_variable_input(mitgcm_variables, model_shape_file, nvars, &
var_names, quantity_list, clamp_vals, update_list)
call get_state_variables(mitgcm_variables, MAX_STATE_VARIABLES, use_clamping, state_vars)

domain_id = add_domain(model_shape_file, nvars, &
var_names, quantity_list, clamp_vals, update_list )
domain_id = add_domain(model_shape_file, state_vars%nvars, &
state_vars%netcdf_var_names, state_vars%qtys, &
state_vars%clamp_values, state_vars%updates)

if (compress) then ! read in compressed coordinates

Expand Down Expand Up @@ -2050,91 +2049,6 @@ subroutine write_data_namelistfile
end subroutine write_data_namelistfile


!-----------------------------------------------------------------------
!>
!> Fill the array of requested variables, dart kinds, possible min/max
!> values and whether or not to update the field in the output file.
!>
!>@param state_variables the list of variables and kinds from model_mod_nml
!>@param ngood the number of variable/KIND pairs specified

subroutine parse_variable_input(state_variables, filename, ngood, &
var_names, quantity_list, clamp_vals, update_list)

character(len=*), intent(in) :: state_variables(:,:)
character(len=*), intent(in) :: filename
integer, intent(out) :: ngood
character(len=*), intent(out) :: var_names(:)
integer, intent(out) :: quantity_list(:)
real(r8), intent(out) :: clamp_vals(:,:)
logical, intent(out) :: update_list(:)

integer :: i
character(len=NF90_MAX_NAME) :: varname
character(len=NF90_MAX_NAME) :: dartstr
character(len=NF90_MAX_NAME) :: minvalstring
character(len=NF90_MAX_NAME) :: maxvalstring
character(len=NF90_MAX_NAME) :: updateable

ngood = 0
MyLoop : do i = 1, MAX_STATE_VARIABLES

varname = trim(state_variables(VT_VARNAMEINDX,i))
dartstr = trim(state_variables(VT_KINDINDX ,i))
minvalstring = trim(state_variables(VT_MINVALINDX ,i))
maxvalstring = trim(state_variables(VT_MAXVALINDX ,i))
updateable = trim(state_variables(VT_STATEINDX ,i))

if ( varname == ' ' .and. dartstr == ' ' ) exit MyLoop ! Found end of list.

if ( varname == ' ' .or. dartstr == ' ' ) then
string1 = 'model_nml:model "variables" not fully specified'
string2 = 'reading from "'//trim(filename)//'"'
call error_handler(E_ERR,'parse_variable_input:',string1,source,text2=string2)
endif

! Make sure DART quantity is valid

if( get_index_for_quantity(dartstr) < 0 ) then
write(string1,'(''there is no quantity <'',a,''> in obs_kind_mod.f90'')') trim(dartstr)
call error_handler(E_ERR,'parse_variable_input:',string1,source)
endif

call to_upper(minvalstring)
call to_upper(maxvalstring)
call to_upper(updateable)

var_names(i) = varname
quantity_list(i) = get_index_for_quantity(dartstr)
clamp_vals(i, 1) = string_to_real(minvalstring)
clamp_vals(i, 2) = string_to_real(maxvalstring)
update_list(i) = string_to_logical(updateable, 'UPDATE')

! Adjust clamping in case of log-transform
if (quantity_list(i) == QTY_NITRATE_CONCENTRATION ) call adjust_clamp(clamp_vals(i, 1))
if (quantity_list(i) == QTY_PHOSPHATE_CONCENTRATION ) call adjust_clamp(clamp_vals(i, 1))
if (quantity_list(i) == QTY_DISSOLVED_OXYGEN ) call adjust_clamp(clamp_vals(i, 1))
if (quantity_list(i) == QTY_PHYTOPLANKTON_BIOMASS ) call adjust_clamp(clamp_vals(i, 1))
if (quantity_list(i) == QTY_ALKALINITY ) call adjust_clamp(clamp_vals(i, 1))
if (quantity_list(i) == QTY_DISSOLVED_INORGANIC_CARBON) call adjust_clamp(clamp_vals(i, 1))
if (quantity_list(i) == QTY_DISSOLVED_ORGANIC_P ) call adjust_clamp(clamp_vals(i, 1))
if (quantity_list(i) == QTY_DISSOLVED_ORGANIC_NITROGEN) call adjust_clamp(clamp_vals(i, 1))
if (quantity_list(i) == QTY_DISSOLVED_INORGANIC_IRON ) call adjust_clamp(clamp_vals(i, 1))
if (quantity_list(i) == QTY_SURFACE_CHLOROPHYLL ) call adjust_clamp(clamp_vals(i, 1))

ngood = ngood + 1

enddo MyLoop

if (ngood == MAX_STATE_VARIABLES) then
string1 = 'WARNING: There is a possibility you need to increase ''MAX_STATE_VARIABLES'''
write(string2,'(''WARNING: you have specified at least '',i4,'' perhaps more.'')')ngood
call error_handler(E_MSG,'parse_variable_input:',string1,source,text2=string2)
endif

end subroutine parse_variable_input


!-----------------------------------------------------------------------
!>
!> We may choose to do a log transformation for the bgc tracers
Expand Down
Loading
Loading