Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into prepbufr_docs
Browse files Browse the repository at this point in the history
  • Loading branch information
braczka committed Feb 5, 2025
2 parents 2a11720 + f4b2a58 commit 645610d
Show file tree
Hide file tree
Showing 18 changed files with 576 additions and 799 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ test_beta_dist
test_kde_dist
test_window
test_force_bounds
test_parse_variables

# Directories to NOT IGNORE ... same as executable names
# as far as I know, these must be listed after the executables
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ individual files.

The changes are now listed with the most recent at the top.

**February 4 2025 :: Generic model_mod subroutine parse_variables. Tag v11.10.3**

- Creates two generalized subroutines that convert the table of state variables that is
read in from the &model_nml to a state_var_type: parse_variables and parse_variables_clamp
- Alternate versions for this subroutine were replaced with parse_variables in the
models MOM6, wrf_hydro, aether_lat-lon, cam-fv, cam-se, POP, and cice
- New dev test test_parse_variables added

**February 3 2025 :: Inflation documentation. Tag v11.10.2**

- Improved inflation documentation
Expand Down
67 changes: 62 additions & 5 deletions assimilation_code/modules/io/state_structure_mod.f90
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@ module state_structure_mod
!> The add_domain() call adds a 'domain' to the state. This may be a component in
!> the case of XCESM or another coupled model.
!>
!> There are three ways to add a domain (these are overloaded as add_domain):
!> There are four ways to add a domain (these are overloaded as add_domain):
!> * add_domain_blank. This takes model size as an argument.
!>
!> * add_domain_from_file. This takes a netcdf file and a list of variables
!>
!> * add_domain_from_state_type. This takes a netcdf file and a state_var_type,
!> which includes nvars, netcdf variable names, qtys (kinds),
!> clamp_values (optional), and updates
!>
!> * add_domain_from_spec. This makes a skeleton structure for a domain. Dimensions
!> for each variable must be added using add_dimension_to_variable(). This is intended
!> to be used to create netcdf output for models like bgrid_solo that are spun up.
Expand Down Expand Up @@ -68,6 +72,8 @@ module state_structure_mod

use sort_mod, only : index_sort

use default_model_mod, only : state_var_type

use netcdf

implicit none
Expand Down Expand Up @@ -240,8 +246,8 @@ module state_structure_mod
character(len=256) :: info_file = 'NULL'

! string identifying the manner in which the domain was created
! 'blank', 'file', or 'spec'
character(len=6) :: method = 'none'
! 'blank', 'file', 'state_type', or 'spec'
character(len=11) :: method = 'none'

end type domain_type

Expand Down Expand Up @@ -281,6 +287,7 @@ module state_structure_mod
module procedure add_domain_blank
module procedure add_domain_from_file
module procedure add_domain_from_spec
module procedure add_domain_from_state_type
end interface

interface get_index_start
Expand Down Expand Up @@ -313,8 +320,6 @@ module state_structure_mod
!> into the state_strucutre.
!>
!> Returns a dom_id that can be used to harvest information of a particular domain
!>
!> Does this need to be a function or a subroutine?


function add_domain_from_file(info_file, num_vars, var_names, kind_list, clamp_vals, update_list) result(dom_id)
Expand Down Expand Up @@ -365,6 +370,58 @@ function add_domain_from_file(info_file, num_vars, var_names, kind_list, clamp_v
end function add_domain_from_file


!-------------------------------------------------------------------------------
!> Given an info_file, reads in a state_var_type including nvars, netcdf
!> variable names, qtys (kinds), clamp values (optional), and updates into the
!> state_structure
!>
!> Returns a dom_id that can be used to harvest information of a particular domain


function add_domain_from_state_type(info_file, vars) result(dom_id)

character(len=*), intent(in) :: info_file
type(state_var_type), intent(in) :: vars
integer :: dom_id

integer :: ivar

! add to domains
call assert_below_max_num_domains('add_domain_from_state_type')
state%num_domains = state%num_domains + 1
!>@todo dom_id should be a handle.
dom_id = state%num_domains

! save information about the information file
state%domain(dom_id)%info_file = info_file
state%domain(dom_id)%method = 'state_type'

! set number of variables in this domain
state%domain(dom_id)%num_variables = vars%nvars

! load up the variable names
allocate(state%domain(dom_id)%variable(vars%nvars))

do ivar = 1, vars%nvars
state%domain(dom_id)%variable(ivar)%varname = vars%netcdf_var_names(ivar)
enddo

! load up variable id's and sizes
call load_state_variable_info(state%domain(dom_id),dom_id)

! load up the domain unique dimension info
call load_unique_dim_info(dom_id)

! load up any cf-conventions if they exist
call load_common_cf_conventions(state%domain(dom_id))

call set_dart_kinds(dom_id, vars%nvars, vars%qtys)
if (allocated(vars%clamp_values)) call set_clamping(dom_id, vars%nvars, vars%clamp_values)
call set_update_list(dom_id, vars%nvars, vars%updates)

end function add_domain_from_state_type


!-------------------------------------------------------------------------------
!> Defines a skeleton structure for the state structure. Dimension can be
!> added to variables with add_dimension_to_variable.
Expand Down
2 changes: 1 addition & 1 deletion conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
author = 'Data Assimilation Research Section'

# The full version, including alpha/beta/rc tags
release = '11.10.2'
release = '11.10.3'
root_doc = 'index'

# -- General configuration ---------------------------------------------------
Expand Down
85 changes: 85 additions & 0 deletions developer_tests/namelist/test_parse_variables.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
! 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_parse_variables

use utilities_mod, only : find_namelist_in_file, check_namelist_read, &
initialize_utilities, finalize_utilities
use types_mod, only : vtablenamelength, MISSING_R8, r8
use default_model_mod, only : parse_variables_clamp, parse_variables, &
state_var_type, &
MAX_STATE_VARIABLE_FIELDS_CLAMP, &
MAX_STATE_VARIABLE_FIELDS
use obs_kind_mod, only : QTY_SALINITY, QTY_POTENTIAL_TEMPERATURE, &
QTY_U_CURRENT_COMPONENT

use test ! fortran-testanything

implicit none

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

character(len=vtablenamelength) :: state_variables(MAX_STATE_VARIABLE_FIELDS) = ' '
character(len=vtablenamelength) :: state_variables_clamp(MAX_STATE_VARIABLE_FIELDS_CLAMP) = ' '

namelist /model_nml/ &
state_variables

namelist /model_nml_clamp/ &
state_variables_clamp

call initialize_utilities('test_parse_variables')

call plan(28)

! Using namelist entry WITHOUT clamping values

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

state_vars = parse_variables(state_variables)

call ok(state_vars%nvars == 3)
call ok(state_vars%netcdf_var_names(1) == 'SALT_CUR')
call ok(state_vars%netcdf_var_names(2) == 'TEMP_CUR')
call ok(state_vars%netcdf_var_names(3) == 'UVEL_CUR')
call ok(state_vars%qtys(1) == QTY_SALINITY)
call ok(state_vars%qtys(2) == QTY_POTENTIAL_TEMPERATURE)
call ok(state_vars%qtys(3) == QTY_U_CURRENT_COMPONENT)
call ok(allocated(state_vars_clamp%clamp_values) .eqv. .false.)
call ok(state_vars%updates(1) .eqv. .true.)
call ok(state_vars%updates(2) .eqv. .false.)
call ok(state_vars%updates(3) .eqv. .true.)

! Using namelist entry WITH clamping values

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')

state_vars_clamp = parse_variables_clamp(state_variables_clamp)

call ok(state_vars_clamp%nvars == 3)
call ok(state_vars_clamp%netcdf_var_names(1) == 'SALT_CUR')
call ok(state_vars_clamp%netcdf_var_names(2) == 'TEMP_CUR')
call ok(state_vars_clamp%netcdf_var_names(3) == 'UVEL_CUR')
call ok(state_vars_clamp%qtys(1) == QTY_SALINITY)
call ok(state_vars_clamp%qtys(2) == QTY_POTENTIAL_TEMPERATURE)
call ok(state_vars_clamp%qtys(3) == QTY_U_CURRENT_COMPONENT)
call ok(allocated(state_vars_clamp%clamp_values) .eqv. .true.)
call ok(state_vars_clamp%clamp_values(1,1) == 0.0_r8)
call ok(state_vars_clamp%clamp_values(1,2) == 0.0_r8)
call ok(state_vars_clamp%clamp_values(2,1) == 0.0_r8)
call ok(state_vars_clamp%clamp_values(2,2) == 0.0_r8)
call ok(state_vars_clamp%clamp_values(3,1) == 0.0_r8)
call ok(state_vars_clamp%clamp_values(3,2) == 0.0_r8)
call ok(state_vars_clamp%updates(1) .eqv. .true.)
call ok(state_vars_clamp%updates(2) .eqv. .false.)
call ok(state_vars_clamp%updates(3) .eqv. .true.)

call finalize_utilities()

end program test_parse_variables
67 changes: 67 additions & 0 deletions developer_tests/namelist/work/input.nml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
&model_nml_clamp
state_variables_clamp = 'SALT_CUR ', 'QTY_SALINITY', '0.0', '0.0', 'UPDATE',
'TEMP_CUR ', 'QTY_POTENTIAL_TEMPERATURE', '0.0', '0.0', 'NO_COPY_BACK',
'UVEL_CUR ', 'QTY_U_CURRENT_COMPONENT ', '0', '0.0', 'UPDATE',
/

&model_nml
state_variables = 'SALT_CUR ', 'QTY_SALINITY', 'UPDATE',
'TEMP_CUR ', 'QTY_POTENTIAL_TEMPERATURE', 'NO_COPY_BACK',
'UVEL_CUR ', 'QTY_U_CURRENT_COMPONENT ', '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"

serial_programs=(
test_parse_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 "$@"
Loading

0 comments on commit 645610d

Please sign in to comment.