From 0b24793ea0e57236714fb317a424b43b8f838ba1 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 14 Aug 2023 14:11:34 -0600 Subject: [PATCH 001/129] draft program to experiment with reading table values into corresponding types --- .../modules/assimilation/type_read_table.f90 | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 assimilation_code/modules/assimilation/type_read_table.f90 diff --git a/assimilation_code/modules/assimilation/type_read_table.f90 b/assimilation_code/modules/assimilation/type_read_table.f90 new file mode 100644 index 0000000000..f164221db3 --- /dev/null +++ b/assimilation_code/modules/assimilation/type_read_table.f90 @@ -0,0 +1,129 @@ +program read_table + +implicit none +type obs_error_info_type + logical :: bounded_below, bounded_above + real :: lower_bound, upper_bound +end type + +type probit_inflation_type + integer :: dist_type + logical :: bounded_below, bounded_above + real :: lower_bound, upper_bound +end type + +type probit_state_type + integer :: dist_type + logical :: bounded_below, bounded_above + real :: lower_bound, upper_bound +end type + +type probit_extended_state_type + integer :: dist_type + logical :: bounded_below, bounded_above + real :: lower_bound, upper_bound +end type + +type obs_inc_info_type + integer :: filter_kind + logical :: rectangular_quadrature, gaussian_likelihood_tails + logical :: sort_obs_inc, spread_restoration + logical :: bounded_below, bounded_above + real :: lower_bound, upper_bound +end type + +type qcf_table_data_type + type(obs_error_info_type) :: obs_error_info + type(probit_inflation_type) :: probit_inflation + type(probit_state_type) :: probit_state + type(probit_extended_state_type) :: probit_extended_state + type(obs_inc_info_type) :: obs_inc_info +end type + +! Reads in the QCEFF input options from tabular data file +!character(len=50), intent(in) :: qcf_table_filename +!real(r8), intent(out) :: qcf_table_data +!real, dimension(:, :), allocatable :: qcf_table_data_rows +type(qcf_table_data_type), allocatable :: qcf_table_data(:) +character(len=30), dimension(:), allocatable :: rowheaders !!!!! might need to change len=30 + +integer, parameter :: fileid = 10 !file identifier +character(len=30), parameter :: tester_QTY = 'QTY_GPSRO' +integer :: QTY_loc(1) + +!integer, parameter :: num_columns = 28 +integer :: nlines +integer :: io +integer :: numrows +integer :: row + +!real, dimension(1:num_columns, 1:num_rows) :: table_data +!integer :: table_data_1, table_data_2 +character(len=30), dimension(4) :: header1 +character(len=30), dimension(29) :: header2 +!variables for table values ^^^ + +open(unit=fileid, file='cam_qcf_table.dat') +nlines = 0 + +do !do loop to get number of rows (or QTY's) in the table + read(fileid,*,iostat=io) + if(io/=0) exit + nlines = nlines + 1 +end do +close(fileid) + +print*, nlines + +numrows = nlines - 2 +print *, 'numrows: ', numrows + +allocate(qcf_table_data(numrows)) +allocate(rowheaders(numrows)) +write(*,*) shape(qcf_table_data) + +open(unit=fileid, file='cam_qcf_table.dat') + +read(fileid, *) header1 +read(fileid, *) header2 !! skip the headers +Write(*, *) "header1: ", header1 +Write(*, *) "header2: ", header2 + +do row = 1, numrows + read(fileid, *) rowheaders(row), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & + qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & + qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & + qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & + qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & + qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & + qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & + qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & + qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & + qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & + qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & + qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound + + write(*, *) "rowheader(", row, "): ", rowheaders(row) + write(*, *) "qcf_table_data(", row, "): " + write(*, *) qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & + qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & + qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & + qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & + qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & + qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & + qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & + qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & + qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & + qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & + qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & + qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound +end do + +close(fileid) + +QTY_loc = findloc(rowheaders, tester_QTY) +write(*, *) 'findloc of GPSRO: ', QTY_loc(1) + +deallocate(qcf_table_data, rowheaders) + +end program read_table From 6746fa965821201bbee5d50136b83bc419b5778b Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 14 Aug 2023 14:18:48 -0600 Subject: [PATCH 002/129] prototype table data file that uses CAM-FV QTYs --- .../modules/assimilation/cam_qcf_table.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 assimilation_code/modules/assimilation/cam_qcf_table.txt diff --git a/assimilation_code/modules/assimilation/cam_qcf_table.txt b/assimilation_code/modules/assimilation/cam_qcf_table.txt new file mode 100644 index 0000000000..56e205a534 --- /dev/null +++ b/assimilation_code/modules/assimilation/cam_qcf_table.txt @@ -0,0 +1,10 @@ +QCF table version 1: +QTY bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound +QTY_U_WIND_COMPONENT, .false. .false. 3 4 5 .false. .false. 8 9 10 .false. .false. 13 14 15 .false. .false. 18 19 20 .false. .false. .false. .false. .false. .false. 27 28 +QTY_V_WIND_COMPONENT, .false. .false. 3 4 5 .false. .false. 8 9 10 .false. .false. 13 14 15 .false. .false. 18 19 20 .false. .false. .false. .false. .false. .false. 27 28 +QTY_SURFACE_PRESSURE .false. .false. 3 4 5 .false. .false. 8 9 10 .false. .false. 13 14 15 .false. .false. 18 19 20 .false. .false. .false. .false. .false. .false. 27 28 +QTY_TEMPERATURE .false. .false. 3 4 5 .false. .false. 8 9 10 .false. .false. 13 14 15 .false. .false. 18 19 20 .false. .false. .false. .false. .false. .false. 27 28 +QTY_SPECIFIC_HUMIDITY .false. .false. 3 4 5 .false. .false. 8 9 10 .false. .false. 13 14 15 .false. .false. 18 19 20 .false. .false. .false. .false. .false. .false. 27 28 +QTY_CLOUD_LIQUID_WATER .false. .false. 3 4 5 .false. .false. 8 9 10 .false. .false. 13 14 15 .false. .false. 18 19 20 .false. .false. .false. .false. .false. .false. 27 28 +QTY_CLOUD_ICE .false. .false. 3 4 5 .false. .false. 8 9 10 .false. .false. 13 14 15 .false. .false. 18 19 20 .false. .false. .false. .false. .false. .false. 27 28 +QTY_GPSRO .false. .false. 3 4 5 .false. .false. 8 9 10 .false. .false. 13 14 15 .false. .false. 18 19 20 .false. .false. .false. .false. .false. .false. 27 28 From eb62190bcad92b33c39de50a7f1f218481594287 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 14 Aug 2023 14:44:50 -0600 Subject: [PATCH 003/129] adding new subroutine init_qcf_table to return number of rows in table --- .../assimilation/algorithm_info_mod.f90 | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 7ea474c664..78c2f190ab 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -35,6 +35,7 @@ module algorithm_info_mod integer, parameter :: BOUNDED_NORMAL_RHF = 101 public :: obs_error_info, probit_dist_info, obs_inc_info, & + init_qcf_table, & EAKF, ENKF, BOUNDED_NORMAL_RHF, UNBOUNDED_RHF, GAMMA_FILTER ! Provides routines that give information about details of algorithms for @@ -238,4 +239,31 @@ end subroutine obs_inc_info !------------------------------------------------------------------------ + +subroutine init_qcf_table(qcf_table_filename, numrows) + +character(len=50), intent(in) :: qcf_table_filename +integer, intent(out) :: numrows !return value + +integer :: nlines +integer :: io +integer, parameter :: fileid = 10 !file identifier + +open(unit=fileid, file=qcf_table_filename) +nlines = 0 + +do !do loop to get number of rows (or QTY's) in the table + read(fileid,*,iostat=io) + if(io/=0) exit + nlines = nlines + 1 +end do +close(fileid) + +numrows = nlines - 2 +print *, 'numrows: ', numrows + +end subroutine init_qcf_table + +!------------------------------------------------------------------------ + end module algorithm_info_mod From 6d9b0139e562a8bed9cfe769a246262edda9d3bd Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 14 Aug 2023 15:25:08 -0600 Subject: [PATCH 004/129] Adding a new namelist variable to the assim_tools_nml --- .../modules/assimilation/assim_tools_mod.f90 | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index 72a01dc383..c73a02d31e 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -76,7 +76,7 @@ module assim_tools_mod use normal_distribution_mod, only : normal_cdf, inv_weighted_normal_cdf -use algorithm_info_mod, only : probit_dist_info, obs_inc_info +use algorithm_info_mod, only : probit_dist_info, obs_inc_info, init_qcf_table use gamma_distribution_mod, only : gamma_cdf, inv_gamma_cdf, gamma_mn_var_to_shape_scale, & gamma_gamma_prod @@ -143,6 +143,7 @@ module assim_tools_mod ! special_localization_obs_types -> Special treatment for the specified observation types ! special_localization_cutoffs -> Different cutoff value for each specified obs type ! +character(len = 129) :: qcf_table_filename = '' !not sure if the len should be 129 here, but it is consistent with other nml variables logical :: use_algorithm_info_mod = .true. integer :: filter_kind = 1 real(r8) :: cutoff = 0.2_r8 @@ -203,7 +204,7 @@ module assim_tools_mod ! compared to previous versions of this namelist item. logical :: distribute_mean = .false. -namelist / assim_tools_nml / use_algorithm_info_mod, & +namelist / assim_tools_nml / qcf_table_filename, use_algorithm_info_mod, & filter_kind, cutoff, sort_obs_inc, & spread_restoration, sampling_error_correction, & adaptive_localization_threshold, adaptive_cutoff_floor, & @@ -222,7 +223,7 @@ module assim_tools_mod subroutine assim_tools_init() -integer :: iunit, io, i, j +integer :: iunit, io, i, j, numrows integer :: num_special_cutoff, type_index logical :: cache_override = .false. @@ -313,6 +314,10 @@ subroutine assim_tools_init() call log_namelist_selections(num_special_cutoff, cache_override) +if(qcf_table_filename) then + call init_qcf_table(qcf_table_filename, numrows) +endif + end subroutine assim_tools_init !------------------------------------------------------------- From 5cca6962a345d803b8de48ad1ea0c2adcfcecd5e Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 14 Aug 2023 15:32:48 -0600 Subject: [PATCH 005/129] Adding QCF table type definitions to algorithm_info_mod --- .../assimilation/algorithm_info_mod.f90 | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 78c2f190ab..fb6a95c1f0 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -35,9 +35,51 @@ module algorithm_info_mod integer, parameter :: BOUNDED_NORMAL_RHF = 101 public :: obs_error_info, probit_dist_info, obs_inc_info, & - init_qcf_table, & + init_qcf_table, read_qcf_table, & + obs_error_info_type, probit_inflation_type, probit_state_type, & + probit_extended_state_type, obs_inc_info_type, qcf_table_data_type, & EAKF, ENKF, BOUNDED_NORMAL_RHF, UNBOUNDED_RHF, GAMMA_FILTER +!Creates the type definitions for the QCF table +type obs_error_info_type + logical :: bounded_below, bounded_above + real :: lower_bound, upper_bound +end type + +type probit_inflation_type + integer :: dist_type + logical :: bounded_below, bounded_above + real :: lower_bound, upper_bound +end type + +type probit_state_type + integer :: dist_type + logical :: bounded_below, bounded_above + real :: lower_bound, upper_bound +end type + +type probit_extended_state_type + integer :: dist_type + logical :: bounded_below, bounded_above + real :: lower_bound, upper_bound +end type + +type obs_inc_info_type + integer :: filter_kind + logical :: rectangular_quadrature, gaussian_likelihood_tails + logical :: sort_obs_inc, spread_restoration + logical :: bounded_below, bounded_above + real :: lower_bound, upper_bound +end type + +type qcf_table_data_type + type(obs_error_info_type) :: obs_error_info + type(probit_inflation_type) :: probit_inflation + type(probit_state_type) :: probit_state + type(probit_extended_state_type) :: probit_extended_state + type(obs_inc_info_type) :: obs_inc_info +end type + ! Provides routines that give information about details of algorithms for ! observation error sampling, observation increments, and the transformations ! for regression and inflation in probit space. @@ -266,4 +308,6 @@ end subroutine init_qcf_table !------------------------------------------------------------------------ + + end module algorithm_info_mod From ce942865e20105f2b81b8edfa7394cc72fcade7c Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 14 Aug 2023 15:38:16 -0600 Subject: [PATCH 006/129] adding type defs to use statement for algorithm_info_mod in assim_tools_mod --- assimilation_code/modules/assimilation/assim_tools_mod.f90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index c73a02d31e..1c1d6bc68e 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -76,7 +76,9 @@ module assim_tools_mod use normal_distribution_mod, only : normal_cdf, inv_weighted_normal_cdf -use algorithm_info_mod, only : probit_dist_info, obs_inc_info, init_qcf_table +use algorithm_info_mod, only : probit_dist_info, obs_inc_info, init_qcf_table, & + qcf_table_data_type, obs_error_info_type, obs_inc_info_type, & + probit_inflation_type, probit_state_type, probit_extended_state_type use gamma_distribution_mod, only : gamma_cdf, inv_gamma_cdf, gamma_mn_var_to_shape_scale, & gamma_gamma_prod From 51591c4cd420ccf2c478244344b574c7f54ae04e Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 14 Aug 2023 15:47:21 -0600 Subject: [PATCH 007/129] Adding allocatable variables for table data, allocating after determining size of table --- assimilation_code/modules/assimilation/assim_tools_mod.f90 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index 1c1d6bc68e..d29717c1f2 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -129,6 +129,9 @@ module assim_tools_mod character(len=*), parameter :: source = 'assim_tools_mod.f90' +type(qcf_table_data_type), allocatable :: qcf_table_data(:) +character(len=129), allocatable :: qcf_table_row_headers(:) !!!!! might need to change len=129 + !============================================================================ !---- namelist with default values @@ -318,6 +321,8 @@ subroutine assim_tools_init() if(qcf_table_filename) then call init_qcf_table(qcf_table_filename, numrows) + allocate(qcf_table_row_headers(numrows)) + allocate(qcf_table_data(numrows)) endif end subroutine assim_tools_init From 9821eefcb46dee21430e50744a7e751225728dc8 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 14 Aug 2023 16:12:59 -0600 Subject: [PATCH 008/129] New subroutine to read through the values in the QCF table and assign them to the variables in the qcf_table_data_type --- .../assimilation/algorithm_info_mod.f90 | 60 +++++++++++++++++++ .../modules/assimilation/assim_tools_mod.f90 | 3 +- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index fb6a95c1f0..8a795717e1 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -309,5 +309,65 @@ end subroutine init_qcf_table !------------------------------------------------------------------------ +subroutine read_qcf_table(qcf_table_filename, numrows, qcf_table_data, rowheaders) + +! Reads in the QCEFF input options from tabular data file + +character(len=129), intent(in) :: qcf_table_filename +integer, intent(in) :: numrows +type(qcf_table_data_type), intent(inout) :: qcf_table_data(:) +character(len=129), intent(inout) :: rowheaders(:) !!!!! might need to change len=129 + +integer, parameter :: fileid = 10 !file identifier +integer :: row + +character(len=129), dimension(4) :: header1 +character(len=129), dimension(29) :: header2 + +open(unit=fileid, file=qcf_table_filename) + +read(fileid, *) header1 +read(fileid, *) header2 !! skip the headers +write(*, *) "header1: ", header1 +write(*, *) "header2: ", header2 + +! read in table values directly to qcf_table_data type +do row = 1, numrows + read(fileid, *) rowheaders(row), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & + qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & + qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & + qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & + qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & + qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & + qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & + qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & + qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & + qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & + qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & + qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound + +! write to check values were correctly assigned + write(*, *) "rowheader(", row, "): ", rowheaders(row) + write(*, *) "qcf_table_data(", row, "): " + write(*, *) qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & + qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & + qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & + qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & + qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & + qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & + qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & + qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & + qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & + qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & + qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & + qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound +end do + +close(fileid) + + +end subroutine read_qcf_table + +!------------------------------------------------------------------------ end module algorithm_info_mod diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index d29717c1f2..1cc8d7a909 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -76,7 +76,7 @@ module assim_tools_mod use normal_distribution_mod, only : normal_cdf, inv_weighted_normal_cdf -use algorithm_info_mod, only : probit_dist_info, obs_inc_info, init_qcf_table, & +use algorithm_info_mod, only : probit_dist_info, obs_inc_info, init_qcf_table, read_qcf_table, & qcf_table_data_type, obs_error_info_type, obs_inc_info_type, & probit_inflation_type, probit_state_type, probit_extended_state_type @@ -323,6 +323,7 @@ subroutine assim_tools_init() call init_qcf_table(qcf_table_filename, numrows) allocate(qcf_table_row_headers(numrows)) allocate(qcf_table_data(numrows)) + call read_qcf_table(qcf_table_filename, numrows, qcf_table_data, qcf_table_row_headers) endif end subroutine assim_tools_init From 6c52bcf014582ee6a9b80b3b4b9f806e61c3e0e3 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 14 Aug 2023 16:47:08 -0600 Subject: [PATCH 009/129] Removing qcf table data types from assim_tools_mod and reorganizing so that these type structs are only used in algorithm_info_mod --- .../modules/assimilation/algorithm_info_mod.f90 | 17 +++++++++++++---- .../modules/assimilation/assim_tools_mod.f90 | 12 ++---------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 8a795717e1..521d5dca4f 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -80,6 +80,9 @@ module algorithm_info_mod type(obs_inc_info_type) :: obs_inc_info end type +type(qcf_table_data_type), allocatable :: qcf_table_data(:) +character(len=129), allocatable :: qcf_table_row_headers(:) !!!!! might need to change len=129 + ! Provides routines that give information about details of algorithms for ! observation error sampling, observation increments, and the transformations ! for regression and inflation in probit space. @@ -282,11 +285,11 @@ end subroutine obs_inc_info !------------------------------------------------------------------------ -subroutine init_qcf_table(qcf_table_filename, numrows) +subroutine init_qcf_table(qcf_table_filename) character(len=50), intent(in) :: qcf_table_filename -integer, intent(out) :: numrows !return value +integer :: numrows integer :: nlines integer :: io integer, parameter :: fileid = 10 !file identifier @@ -304,6 +307,11 @@ subroutine init_qcf_table(qcf_table_filename, numrows) numrows = nlines - 2 print *, 'numrows: ', numrows +allocate(qcf_table_data(numrows)) +allocate(rowheaders(numrows)) + +call read_qcf_table(qcf_table_filename, numrows, qcf_table_data, rowheaders) + end subroutine init_qcf_table !------------------------------------------------------------------------ @@ -315,8 +323,9 @@ subroutine read_qcf_table(qcf_table_filename, numrows, qcf_table_data, rowheader character(len=129), intent(in) :: qcf_table_filename integer, intent(in) :: numrows -type(qcf_table_data_type), intent(inout) :: qcf_table_data(:) -character(len=129), intent(inout) :: rowheaders(:) !!!!! might need to change len=129 + +type(qcf_table_data_type) :: qcf_table_data(:) +character(len=129) :: rowheaders(:) !!!!! might need to change len=129 integer, parameter :: fileid = 10 !file identifier integer :: row diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index 1cc8d7a909..d37556afcc 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -76,9 +76,7 @@ module assim_tools_mod use normal_distribution_mod, only : normal_cdf, inv_weighted_normal_cdf -use algorithm_info_mod, only : probit_dist_info, obs_inc_info, init_qcf_table, read_qcf_table, & - qcf_table_data_type, obs_error_info_type, obs_inc_info_type, & - probit_inflation_type, probit_state_type, probit_extended_state_type +use algorithm_info_mod, only : probit_dist_info, obs_inc_info, init_qcf_table, read_qcf_table use gamma_distribution_mod, only : gamma_cdf, inv_gamma_cdf, gamma_mn_var_to_shape_scale, & gamma_gamma_prod @@ -129,9 +127,6 @@ module assim_tools_mod character(len=*), parameter :: source = 'assim_tools_mod.f90' -type(qcf_table_data_type), allocatable :: qcf_table_data(:) -character(len=129), allocatable :: qcf_table_row_headers(:) !!!!! might need to change len=129 - !============================================================================ !---- namelist with default values @@ -320,10 +315,7 @@ subroutine assim_tools_init() call log_namelist_selections(num_special_cutoff, cache_override) if(qcf_table_filename) then - call init_qcf_table(qcf_table_filename, numrows) - allocate(qcf_table_row_headers(numrows)) - allocate(qcf_table_data(numrows)) - call read_qcf_table(qcf_table_filename, numrows, qcf_table_data, qcf_table_row_headers) + call init_qcf_table(qcf_table_filename) endif end subroutine assim_tools_init From a81234bef594e16f69f68dbd40be81260121d60d Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 14 Aug 2023 17:15:53 -0600 Subject: [PATCH 010/129] Fixing small inconsistencies/typos --- .../modules/assimilation/algorithm_info_mod.f90 | 6 +++--- assimilation_code/modules/assimilation/assim_tools_mod.f90 | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 521d5dca4f..77a35392c4 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -287,7 +287,7 @@ end subroutine obs_inc_info subroutine init_qcf_table(qcf_table_filename) -character(len=50), intent(in) :: qcf_table_filename +character(len=129), intent(in) :: qcf_table_filename integer :: numrows integer :: nlines @@ -308,9 +308,9 @@ subroutine init_qcf_table(qcf_table_filename) print *, 'numrows: ', numrows allocate(qcf_table_data(numrows)) -allocate(rowheaders(numrows)) +allocate(qcf_table_row_headers(numrows)) -call read_qcf_table(qcf_table_filename, numrows, qcf_table_data, rowheaders) +call read_qcf_table(qcf_table_filename, numrows, qcf_table_data, qcf_table_row_headers) end subroutine init_qcf_table diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index d37556afcc..608fe799a3 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -76,7 +76,7 @@ module assim_tools_mod use normal_distribution_mod, only : normal_cdf, inv_weighted_normal_cdf -use algorithm_info_mod, only : probit_dist_info, obs_inc_info, init_qcf_table, read_qcf_table +use algorithm_info_mod, only : probit_dist_info, obs_inc_info, init_qcf_table use gamma_distribution_mod, only : gamma_cdf, inv_gamma_cdf, gamma_mn_var_to_shape_scale, & gamma_gamma_prod @@ -314,7 +314,10 @@ subroutine assim_tools_init() call log_namelist_selections(num_special_cutoff, cache_override) -if(qcf_table_filename) then +write(*,*), "HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" +if(qcf_table_filename == '') then + write(*,*), "no qcf table in namelist" +else call init_qcf_table(qcf_table_filename) endif From ecacbe2ede660a73cc434ddfeeb46bec9469492d Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 14 Aug 2023 17:18:41 -0600 Subject: [PATCH 011/129] moving the location of draft program outside /assimilation_code/modules/assimilation --- .../modules/assimilation => qcf_table}/type_read_table.f90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename {assimilation_code/modules/assimilation => qcf_table}/type_read_table.f90 (97%) diff --git a/assimilation_code/modules/assimilation/type_read_table.f90 b/qcf_table/type_read_table.f90 similarity index 97% rename from assimilation_code/modules/assimilation/type_read_table.f90 rename to qcf_table/type_read_table.f90 index f164221db3..f7cd548acf 100644 --- a/assimilation_code/modules/assimilation/type_read_table.f90 +++ b/qcf_table/type_read_table.f90 @@ -45,7 +45,7 @@ program read_table !real(r8), intent(out) :: qcf_table_data !real, dimension(:, :), allocatable :: qcf_table_data_rows type(qcf_table_data_type), allocatable :: qcf_table_data(:) -character(len=30), dimension(:), allocatable :: rowheaders !!!!! might need to change len=30 +character(len=129), dimension(:), allocatable :: rowheaders !!!!! might need to change len=30 integer, parameter :: fileid = 10 !file identifier character(len=30), parameter :: tester_QTY = 'QTY_GPSRO' @@ -63,7 +63,7 @@ program read_table character(len=30), dimension(29) :: header2 !variables for table values ^^^ -open(unit=fileid, file='cam_qcf_table.dat') +open(unit=fileid, file='cam_qcf_table.txt') nlines = 0 do !do loop to get number of rows (or QTY's) in the table @@ -82,7 +82,7 @@ program read_table allocate(rowheaders(numrows)) write(*,*) shape(qcf_table_data) -open(unit=fileid, file='cam_qcf_table.dat') +open(unit=fileid, file='cam_qcf_table.txt') read(fileid, *) header1 read(fileid, *) header2 !! skip the headers From 4b5312f32ee378828b7c9d70ba6eabf68fd051e6 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 15 Aug 2023 15:14:06 -0600 Subject: [PATCH 012/129] Adding draft subroutine write_qcf_table to test that values are being read in correctly; removed rowheaders argument from subroutines where not needed --- .../assimilation/algorithm_info_mod.f90 | 96 ++++++++++++------- 1 file changed, 63 insertions(+), 33 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 77a35392c4..4f47c64e3f 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -155,6 +155,8 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & logical, intent(out) :: bounded_below, bounded_above real(r8), intent(out) :: lower_bound, upper_bound +integer :: QTY_loc(1) + ! Have input information about the kind of the state or observation being transformed ! along with additional logical info that indicates whether this is an observation ! or state variable and about whether the transformation is being done for inflation @@ -176,18 +178,19 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & if(is_inflation) then ! Case for inflation transformation - if(kind == QTY_STATE_VARIABLE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 - elseif(kind == QTY_TRACER_CONCENTRATION) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .true.; bounded_above = .false. - lower_bound = 0.0_r8; upper_bound = missing_r8 - elseif(kind == QTY_TRACER_SOURCE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .true.; bounded_above = .false. - lower_bound = 0.0_r8; upper_bound = missing_r8 +! if(kind == QTY_STATE_VARIABLE) then +! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION +! bounded_below = .false.; bounded_above = .false. +! lower_bound = missing_r8; upper_bound = missing_r8 +! elseif(kind == QTY_TRACER_CONCENTRATION) then +! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION +! bounded_below = .true.; bounded_above = .false. +! lower_bound = 0.0_r8; upper_bound = missing_r8 +! elseif(kind == QTY_TRACER_SOURCE) then +! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION +! bounded_below = .true.; bounded_above = .false. +! lower_bound = 0.0_r8; upper_bound = missing_r8 + if findloc else write(*, *) 'Illegal kind in obs_error_info' stop @@ -310,22 +313,21 @@ subroutine init_qcf_table(qcf_table_filename) allocate(qcf_table_data(numrows)) allocate(qcf_table_row_headers(numrows)) -call read_qcf_table(qcf_table_filename, numrows, qcf_table_data, qcf_table_row_headers) +call read_qcf_table(qcf_table_filename) end subroutine init_qcf_table !------------------------------------------------------------------------ -subroutine read_qcf_table(qcf_table_filename, numrows, qcf_table_data, rowheaders) +subroutine read_qcf_table(qcf_table_filename) ! Reads in the QCEFF input options from tabular data file character(len=129), intent(in) :: qcf_table_filename -integer, intent(in) :: numrows -type(qcf_table_data_type) :: qcf_table_data(:) -character(len=129) :: rowheaders(:) !!!!! might need to change len=129 +!type(qcf_table_data_type) :: qcf_table_data(:) +!character(len=129) :: rowheaders(:) !!!!! might need to change len=129 integer, parameter :: fileid = 10 !file identifier integer :: row @@ -341,8 +343,8 @@ subroutine read_qcf_table(qcf_table_filename, numrows, qcf_table_data, rowheader write(*, *) "header2: ", header2 ! read in table values directly to qcf_table_data type -do row = 1, numrows - read(fileid, *) rowheaders(row), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & +do row = 1, size(qcf_table_data) + read(fileid, *) qcf_table_row_headers(row), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & @@ -354,28 +356,56 @@ subroutine read_qcf_table(qcf_table_filename, numrows, qcf_table_data, rowheader qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound +end do + +close(fileid) + +call write_qcf_table() + +end subroutine read_qcf_table + +!------------------------------------------------------------------------ + + +subroutine write_qcf_table() ! write to check values were correctly assigned - write(*, *) "rowheader(", row, "): ", rowheaders(row) +! testing for findloc + +character(len=30), parameter :: tester_QTY = 'QTY_GPSRO' +integer :: QTY_loc(1) + +character(len=30), parameter :: tester_QTY0 = 'QTY_DUMMY' +integer :: QTY_loc0(1) + +integer :: row + +write(*,*), 'SIZE: ', size(qcf_table_data) + +do row = 1, size(qcf_table_data) + write(*, *) "qcf_table_row_headers(", row, "): ", qcf_table_row_headers(row) write(*, *) "qcf_table_data(", row, "): " write(*, *) qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & - qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & - qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & - qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & - qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & - qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & - qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & - qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & - qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & - qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & - qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound + qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & + qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & + qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & + qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & + qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & + qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & + qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & + qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & + qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & + qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & + qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound end do -close(fileid) +QTY_loc = findloc(qcf_table_row_headers, tester_QTY) +write(*, *) 'findloc of QTY_GPSRO: ', QTY_loc(1) +QTY_loc0 = findloc(qcf_table_row_headers, tester_QTY0) +write(*, *) 'findloc of invalid QTY (QTY_DUMMY): ', QTY_loc0(1) -end subroutine read_qcf_table +end subroutine write_qcf_table !------------------------------------------------------------------------ From e90f0498a9f8cbb4ab113bd6b02fa434fe3bbc9f Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 15 Aug 2023 16:06:58 -0600 Subject: [PATCH 013/129] replaicing conditionals and hardcoded values in probit_dist_info --- .../assimilation/algorithm_info_mod.f90 | 113 ++++++++++++------ 1 file changed, 74 insertions(+), 39 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 4f47c64e3f..c80f94ccde 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -176,8 +176,26 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & ! In the long run, may not have to have separate controls for each of the input possibilities ! However, for now these are things that need to be explored for science understanding -if(is_inflation) then +QTY_loc = findloc(qcf_table_row_headers, kind) +write(*, *) 'findloc of kind: ', QTY_loc(1) + +if (QTY_loc(1) == 0) then + write(*,*) 'QTY not in table!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + + !using default values here + dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION + bounded_below = .false.; bounded_above = .false. + lower_bound = missing_r8; upper_bound = missing_r8 + + elseif(is_inflation) then ! Case for inflation transformation + + dist_type = qcf_table_data(QTY_loc(1))%probit_inflation%dist_type + bounded_below = qcf_table_data(QTY_loc(1))%probit_inflation%bounded_below + bounded_above = qcf_table_data(QTY_loc(1))%probit_inflation%bounded_above + lower_bound = qcf_table_data(QTY_loc(1))%probit_inflation%lower_bound + upper_bound = qcf_table_data(QTY_loc(1))%probit_inflation%upper_bound + ! if(kind == QTY_STATE_VARIABLE) then ! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION ! bounded_below = .false.; bounded_above = .false. @@ -190,49 +208,66 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & ! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION ! bounded_below = .true.; bounded_above = .false. ! lower_bound = 0.0_r8; upper_bound = missing_r8 - if findloc - else - write(*, *) 'Illegal kind in obs_error_info' - stop - endif -elseif(is_state) then +! else +! write(*, *) 'Illegal kind in obs_error_info' +! stop +! endif + + elseif(is_state) then ! Case for state variable priors - if(kind == QTY_STATE_VARIABLE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 - elseif(kind == QTY_TRACER_CONCENTRATION) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .true.; bounded_above = .false. - lower_bound = 0.0_r8; upper_bound = missing_r8 - elseif(kind == QTY_TRACER_SOURCE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .true.; bounded_above = .false. - lower_bound = 0.0_r8; upper_bound = missing_r8 + + dist_type = qcf_table_data(QTY_loc(1))%probit_state%dist_type + bounded_below = qcf_table_data(QTY_loc(1))%probit_state%bounded_below + bounded_above = qcf_table_data(QTY_loc(1))%probit_state%bounded_above + lower_bound = qcf_table_data(QTY_loc(1))%probit_state%lower_bound + upper_bound = qcf_table_data(QTY_loc(1))%probit_state%upper_bound + + !if(kind == QTY_STATE_VARIABLE) then + ! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION + ! bounded_below = .false.; bounded_above = .false. + ! lower_bound = missing_r8; upper_bound = missing_r8 + ! elseif(kind == QTY_TRACER_CONCENTRATION) then + ! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION + ! bounded_below = .true.; bounded_above = .false. + ! lower_bound = 0.0_r8; upper_bound = missing_r8 +! elseif(kind == QTY_TRACER_SOURCE) then + ! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION + ! bounded_below = .true.; bounded_above = .false. + ! lower_bound = 0.0_r8; upper_bound = missing_r8 +! else +! write(*, *) 'Illegal kind in obs_error_info' + ! stop + ! endif + else - write(*, *) 'Illegal kind in obs_error_info' - stop - endif -else ! This case is for observation (extended state) priors - if(kind == QTY_STATE_VARIABLE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 - elseif(kind == QTY_TRACER_CONCENTRATION) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .true.; bounded_above = .false. - lower_bound = 0.0_r8; upper_bound = missing_r8 - elseif(kind == QTY_TRACER_SOURCE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .true.; bounded_above = .false. - lower_bound = 0.0_r8; upper_bound = missing_r8 - else - write(*, *) 'Illegal kind in obs_error_info' - stop - endif + + dist_type = qcf_table_data(QTY_loc(1))%probit_extended_state%dist_type + bounded_below = qcf_table_data(QTY_loc(1))%probit_extended_state%bounded_below + bounded_above = qcf_table_data(QTY_loc(1))%probit_extended_state%bounded_above + lower_bound = qcf_table_data(QTY_loc(1))%probit_extended_state%lower_bound + upper_bound = qcf_table_data(QTY_loc(1))%probit_extended_state%upper_bound + +! if(kind == QTY_STATE_VARIABLE) then +! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION +! bounded_below = .false.; bounded_above = .false. +! lower_bound = missing_r8; upper_bound = missing_r8 +! elseif(kind == QTY_TRACER_CONCENTRATION) then +! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION +! bounded_below = .true.; bounded_above = .false. +! lower_bound = 0.0_r8; upper_bound = missing_r8 +! elseif(kind == QTY_TRACER_SOURCE) then +! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION +! bounded_below = .true.; bounded_above = .false. +! lower_bound = 0.0_r8; upper_bound = missing_r8 +! else +! write(*, *) 'Illegal kind in obs_error_info' +! stop +! endif endif +write(*,*) dist_type, bounded_below, bounded_above, lower_bound, upper_bound + end subroutine probit_dist_info !------------------------------------------------------------------------ From 705d9b48d2291945d99e1a44a2ebdf814824f5a2 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 16 Aug 2023 14:26:13 -0600 Subject: [PATCH 014/129] using get_name_for_quantity to get generic quantity from integer index --- .../assimilation/algorithm_info_mod.f90 | 41 +++++++++++++++---- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index c80f94ccde..83937b807f 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -7,7 +7,8 @@ module algorithm_info_mod use types_mod, only : r8, i8, missing_r8 use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance -use obs_kind_mod, only : get_quantity_for_type_of_obs +use obs_kind_mod, only : get_quantity_for_type_of_obs, get_name_for_quantity + ! Get the QTY definitions that are needed (aka kind) use obs_kind_mod, only : QTY_STATE_VARIABLE, QTY_STATE_VAR_POWER, QTY_TRACER_CONCENTRATION, & @@ -156,6 +157,7 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & real(r8), intent(out) :: lower_bound, upper_bound integer :: QTY_loc(1) +character(len=129) :: kind_name ! Have input information about the kind of the state or observation being transformed ! along with additional logical info that indicates whether this is an observation @@ -176,13 +178,18 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & ! In the long run, may not have to have separate controls for each of the input possibilities ! However, for now these are things that need to be explored for science understanding -QTY_loc = findloc(qcf_table_row_headers, kind) -write(*, *) 'findloc of kind: ', QTY_loc(1) +!get actual name of QTY from integer index +kind_name = get_name_for_quantity(kind) +write(*,*) 'kind_name: ', kind_name + +!find location of QTY in qcf_table_data structure +QTY_loc = findloc(qcf_table_row_headers, kind_name) +write(*,*) 'findloc of kind: ', QTY_loc(1) if (QTY_loc(1) == 0) then write(*,*) 'QTY not in table!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' - !using default values here + !use default values dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION bounded_below = .false.; bounded_above = .false. lower_bound = missing_r8; upper_bound = missing_r8 @@ -190,10 +197,10 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & elseif(is_inflation) then ! Case for inflation transformation - dist_type = qcf_table_data(QTY_loc(1))%probit_inflation%dist_type + dist_type = qcf_table_data(QTY_loc(1))%probit_inflation%dist_type !dist_type has checks in transform_to_probit, transform_from_probit bounded_below = qcf_table_data(QTY_loc(1))%probit_inflation%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%probit_inflation%bounded_above - lower_bound = qcf_table_data(QTY_loc(1))%probit_inflation%lower_bound + lower_bound = qcf_table_data(QTY_loc(1))%probit_inflation%lower_bound !NEED TO ADD CHECKS THAT THESE ARE VALID VALUES upper_bound = qcf_table_data(QTY_loc(1))%probit_inflation%upper_bound ! if(kind == QTY_STATE_VARIABLE) then @@ -266,7 +273,7 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & ! endif endif -write(*,*) dist_type, bounded_below, bounded_above, lower_bound, upper_bound +write(*,*) 'probit_dist_info: ', dist_type, bounded_below, bounded_above, lower_bound, upper_bound end subroutine probit_dist_info @@ -291,6 +298,22 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ ! Temporary approach for setting the details of how to assimilate this observation ! This example is designed to reproduce the squared forward operator results from paper +!get actual name of QTY from integer index +kind_name = get_name_for_quantity(kind) +write(*,*) 'kind_name: ', kind_name + +!find location of QTY in qcf_table_data structure +QTY_loc = findloc(qcf_table_row_headers, kind_name) +write(*,*) 'findloc of kind: ', QTY_loc(1) + +if (QTY_loc(1) == 0) then + write(*,*) 'QTY not in table!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + + !use default values + dist_type = BOUNDED_NORMAL_RHF + bounded_below = .false.; bounded_above = .false. + lower_bound = missing_r8; upper_bound = missing_r8 + ! Set the observation increment details for each type of quantity if(obs_kind == QTY_STATE_VARIABLE) then @@ -372,8 +395,9 @@ subroutine read_qcf_table(qcf_table_filename) open(unit=fileid, file=qcf_table_filename) +! skip the headers read(fileid, *) header1 -read(fileid, *) header2 !! skip the headers +read(fileid, *) header2 write(*, *) "header1: ", header1 write(*, *) "header2: ", header2 @@ -404,6 +428,7 @@ end subroutine read_qcf_table subroutine write_qcf_table() +! DRAFT SUBROUTINE ! write to check values were correctly assigned ! testing for findloc From 9e1190f6bb9250240281e3cecbc5c6e6dbe1f783 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 16 Aug 2023 14:58:50 -0600 Subject: [PATCH 015/129] Replacing conditionals and hard coded values with qcf_table_data in obs_inc_info subroutine --- .../assimilation/algorithm_info_mod.f90 | 57 ++++++++++++------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 83937b807f..fe9d1c3e26 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -291,6 +291,9 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ logical, intent(inout) :: bounded_below, bounded_above real(r8), intent(inout) :: lower_bound, upper_bound +integer :: QTY_loc(1) +character(len=129) :: kind_name + ! The information arguments are all intent (inout). This means that if they are not set ! here, they retain the default values from the assim_tools_mod namelist. Bounds don't exist ! in that namelist, so default values are set in assim_tools_mod just before the call to here. @@ -299,7 +302,7 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ ! This example is designed to reproduce the squared forward operator results from paper !get actual name of QTY from integer index -kind_name = get_name_for_quantity(kind) +kind_name = get_name_for_quantity(obs_kind) write(*,*) 'kind_name: ', kind_name !find location of QTY in qcf_table_data structure @@ -310,32 +313,42 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ write(*,*) 'QTY not in table!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' !use default values - dist_type = BOUNDED_NORMAL_RHF - bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 - - -! Set the observation increment details for each type of quantity -if(obs_kind == QTY_STATE_VARIABLE) then filter_kind = BOUNDED_NORMAL_RHF bounded_below = .false.; bounded_above = .false. lower_bound = missing_r8; upper_bound = missing_r8 -elseif(obs_kind == QTY_TRACER_CONCENTRATION) then - filter_kind = BOUNDED_NORMAL_RHF - bounded_below = .true.; bounded_above = .false. - lower_bound = 0.0_r8; upper_bound = missing_r8 -elseif(obs_kind == QTY_TRACER_SOURCE) then - filter_kind = BOUNDED_NORMAL_RHF - bounded_below = .true.; bounded_above = .false. - lower_bound = 0.0_r8; upper_bound = missing_r8 -else - write(*, *) 'Illegal obs_kind in obs_error_info' - stop + sort_obs_inc = .false.; spread_restoration = .false. + ! Default settings for now for Icepack and tracer model tests (sort_obs_inc, spread_restoration) + + else + filter_kind = qcf_table_data(QTY_loc(1))%obs_inc_info%filter_kind !filter_kind has a check in obs_increment + sort_obs_inc = qcf_table_data(QTY_loc(1))%obs_inc_info%sort_obs_inc + spread_restoration = qcf_table_data(QTY_loc(1))%obs_inc_info%spread_restoration + bounded_below = qcf_table_data(QTY_loc(1))%obs_inc_info%bounded_below + bounded_above = qcf_table_data(QTY_loc(1))%obs_inc_info%bounded_above + lower_bound = qcf_table_data(QTY_loc(1))%obs_inc_info%lower_bound !NEED TO ADD CHECKS THAT THESE ARE VALID VALUES + upper_bound = qcf_table_data(QTY_loc(1))%obs_inc_info%upper_bound + endif -! Default settings for now for Icepack and tracer model tests -sort_obs_inc = .false. -spread_restoration = .false. +write(*,*) 'obs_inc_info: ', filter_kind, sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound + +! Set the observation increment details for each type of quantity +!if(obs_kind == QTY_STATE_VARIABLE) then +! filter_kind = BOUNDED_NORMAL_RHF +! bounded_below = .false.; bounded_above = .false. +! lower_bound = missing_r8; upper_bound = missing_r8 +!elseif(obs_kind == QTY_TRACER_CONCENTRATION) then +! filter_kind = BOUNDED_NORMAL_RHF +! bounded_below = .true.; bounded_above = .false. +! lower_bound = 0.0_r8; upper_bound = missing_r8 +!elseif(obs_kind == QTY_TRACER_SOURCE) then +! filter_kind = BOUNDED_NORMAL_RHF +! bounded_below = .true.; bounded_above = .false. +! lower_bound = 0.0_r8; upper_bound = missing_r8 +!else +! write(*, *) 'Illegal obs_kind in obs_error_info' +! stop +!endif ! Only need to set these two for options the original RHF implementation !!!rectangular_quadrature = .true. From 6a78ae7c198921093894d5c2200b984001153d33 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 16 Aug 2023 15:13:52 -0600 Subject: [PATCH 016/129] Replacing conditionals and hard coded values with qcf_table_data in obs_error_info subroutine --- .../assimilation/algorithm_info_mod.f90 | 50 +++++++++++++++---- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index fe9d1c3e26..da3260042e 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -109,6 +109,9 @@ subroutine obs_error_info(obs_def, error_variance, & integer(i8) :: state_var_index type(location_type) :: temp_loc +integer :: QTY_loc(1) +character(len=129) :: kind_name + ! Get the kind of the observation obs_type = get_obs_def_type_of_obs(obs_def) ! If it is negative, it is an identity obs @@ -122,21 +125,46 @@ subroutine obs_error_info(obs_def, error_variance, & ! Get the default error variance error_variance = get_obs_def_error_variance(obs_def) -! Set the observation error details for each type of quantity -if(obs_kind == QTY_STATE_VARIABLE) then +!get actual name of QTY from integer index +kind_name = get_name_for_quantity(obs_kind) +write(*,*) 'kind_name: ', kind_name + +!find location of QTY in qcf_table_data structure +QTY_loc = findloc(qcf_table_row_headers, kind_name) +write(*,*) 'findloc of kind: ', QTY_loc(1) + +if (QTY_loc(1) == 0) then + write(*,*) 'QTY not in table!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + + !use default values bounded_below = .false.; bounded_above = .false. lower_bound = missing_r8; upper_bound = missing_r8 -elseif(obs_kind == QTY_TRACER_CONCENTRATION) then - bounded_below = .true.; bounded_above = .false. - lower_bound = 0.0_r8; upper_bound = missing_r8 -elseif(obs_kind == QTY_TRACER_SOURCE) then - bounded_below = .true.; bounded_above = .false. - lower_bound = 0.0_r8; upper_bound = missing_r8 -else - write(*, *) 'Illegal obs_kind in obs_error_info' - stop + + else + bounded_below = qcf_table_data(QTY_loc(1))%obs_error_info%bounded_below + bounded_above = qcf_table_data(QTY_loc(1))%obs_error_info%bounded_above + lower_bound = qcf_table_data(QTY_loc(1))%obs_error_info%lower_bound !NEED TO ADD CHECKS THAT THESE ARE VALID VALUES + upper_bound = qcf_table_data(QTY_loc(1))%obs_error_info%upper_bound + endif +write(*,*) 'obs_error_info: ', bounded_below, bounded_above, lower_bound, upper_bound + +! Set the observation error details for each type of quantity +!if(obs_kind == QTY_STATE_VARIABLE) then +! bounded_below = .false.; bounded_above = .false. +! lower_bound = missing_r8; upper_bound = missing_r8 +!elseif(obs_kind == QTY_TRACER_CONCENTRATION) then +! bounded_below = .true.; bounded_above = .false. +! lower_bound = 0.0_r8; upper_bound = missing_r8 +!elseif(obs_kind == QTY_TRACER_SOURCE) then +! bounded_below = .true.; bounded_above = .false. +! lower_bound = 0.0_r8; upper_bound = missing_r8 +!else +! write(*, *) 'Illegal obs_kind in obs_error_info' +! stop +!endif + end subroutine obs_error_info From 0bb0db8d74c2d04490db520e822b057ad2c665da Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 16 Aug 2023 15:18:59 -0600 Subject: [PATCH 017/129] add subroutine to deallocate qcf table data structures --- .../modules/assimilation/algorithm_info_mod.f90 | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index da3260042e..ca8120ec0b 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -36,7 +36,7 @@ module algorithm_info_mod integer, parameter :: BOUNDED_NORMAL_RHF = 101 public :: obs_error_info, probit_dist_info, obs_inc_info, & - init_qcf_table, read_qcf_table, & + init_qcf_table, deallocate_qcf_table, & obs_error_info_type, probit_inflation_type, probit_state_type, & probit_extended_state_type, obs_inc_info_type, qcf_table_data_type, & EAKF, ENKF, BOUNDED_NORMAL_RHF, UNBOUNDED_RHF, GAMMA_FILTER @@ -510,4 +510,14 @@ end subroutine write_qcf_table !------------------------------------------------------------------------ + +subroutine deallocate_qcf_table() + +deallocate(qcf_table_data) +deallocate(qcf_table_row_headers) + +end subroutine deallocate_qcf_table + +!---------------------------------------------------------------------- + end module algorithm_info_mod From 0bc2492f4b940458442b187544b8ff945410e5ef Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Thu, 17 Aug 2023 11:25:34 -0600 Subject: [PATCH 018/129] making dealloc subroutine available to assim_tools_mod --- assimilation_code/modules/assimilation/assim_tools_mod.f90 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index 608fe799a3..b4f714eb93 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -76,7 +76,7 @@ module assim_tools_mod use normal_distribution_mod, only : normal_cdf, inv_weighted_normal_cdf -use algorithm_info_mod, only : probit_dist_info, obs_inc_info, init_qcf_table +use algorithm_info_mod, only : probit_dist_info, obs_inc_info, init_qcf_table, deallocate_qcf_table use gamma_distribution_mod, only : gamma_cdf, inv_gamma_cdf, gamma_mn_var_to_shape_scale, & gamma_gamma_prod @@ -314,7 +314,6 @@ subroutine assim_tools_init() call log_namelist_selections(num_special_cutoff, cache_override) -write(*,*), "HERE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" if(qcf_table_filename == '') then write(*,*), "no qcf table in namelist" else From 384bd30fd29df27120a26b3cb4780a0e0478df65 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Thu, 17 Aug 2023 13:28:52 -0600 Subject: [PATCH 019/129] removing comment blocks of old code --- .../assimilation/algorithm_info_mod.f90 | 95 +------------------ 1 file changed, 5 insertions(+), 90 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index ca8120ec0b..3eee46e986 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -95,6 +95,8 @@ module algorithm_info_mod contains !------------------------------------------------------------------------- + + subroutine obs_error_info(obs_def, error_variance, & bounded_below, bounded_above, lower_bound, upper_bound) @@ -134,7 +136,7 @@ subroutine obs_error_info(obs_def, error_variance, & write(*,*) 'findloc of kind: ', QTY_loc(1) if (QTY_loc(1) == 0) then - write(*,*) 'QTY not in table!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + write(*,*) 'QTY not in table, using default values' !use default values bounded_below = .false.; bounded_above = .false. @@ -150,24 +152,8 @@ subroutine obs_error_info(obs_def, error_variance, & write(*,*) 'obs_error_info: ', bounded_below, bounded_above, lower_bound, upper_bound -! Set the observation error details for each type of quantity -!if(obs_kind == QTY_STATE_VARIABLE) then -! bounded_below = .false.; bounded_above = .false. -! lower_bound = missing_r8; upper_bound = missing_r8 -!elseif(obs_kind == QTY_TRACER_CONCENTRATION) then -! bounded_below = .true.; bounded_above = .false. -! lower_bound = 0.0_r8; upper_bound = missing_r8 -!elseif(obs_kind == QTY_TRACER_SOURCE) then -! bounded_below = .true.; bounded_above = .false. -! lower_bound = 0.0_r8; upper_bound = missing_r8 -!else -! write(*, *) 'Illegal obs_kind in obs_error_info' -! stop -!endif - end subroutine obs_error_info - !------------------------------------------------------------------------- @@ -215,7 +201,7 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & write(*,*) 'findloc of kind: ', QTY_loc(1) if (QTY_loc(1) == 0) then - write(*,*) 'QTY not in table!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + write(*,*) 'QTY not in table, using default values' !use default values dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION @@ -231,23 +217,6 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & lower_bound = qcf_table_data(QTY_loc(1))%probit_inflation%lower_bound !NEED TO ADD CHECKS THAT THESE ARE VALID VALUES upper_bound = qcf_table_data(QTY_loc(1))%probit_inflation%upper_bound -! if(kind == QTY_STATE_VARIABLE) then -! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION -! bounded_below = .false.; bounded_above = .false. -! lower_bound = missing_r8; upper_bound = missing_r8 -! elseif(kind == QTY_TRACER_CONCENTRATION) then -! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION -! bounded_below = .true.; bounded_above = .false. -! lower_bound = 0.0_r8; upper_bound = missing_r8 -! elseif(kind == QTY_TRACER_SOURCE) then -! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION -! bounded_below = .true.; bounded_above = .false. -! lower_bound = 0.0_r8; upper_bound = missing_r8 -! else -! write(*, *) 'Illegal kind in obs_error_info' -! stop -! endif - elseif(is_state) then ! Case for state variable priors @@ -257,23 +226,6 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & lower_bound = qcf_table_data(QTY_loc(1))%probit_state%lower_bound upper_bound = qcf_table_data(QTY_loc(1))%probit_state%upper_bound - !if(kind == QTY_STATE_VARIABLE) then - ! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - ! bounded_below = .false.; bounded_above = .false. - ! lower_bound = missing_r8; upper_bound = missing_r8 - ! elseif(kind == QTY_TRACER_CONCENTRATION) then - ! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - ! bounded_below = .true.; bounded_above = .false. - ! lower_bound = 0.0_r8; upper_bound = missing_r8 -! elseif(kind == QTY_TRACER_SOURCE) then - ! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - ! bounded_below = .true.; bounded_above = .false. - ! lower_bound = 0.0_r8; upper_bound = missing_r8 -! else -! write(*, *) 'Illegal kind in obs_error_info' - ! stop - ! endif - else ! This case is for observation (extended state) priors @@ -283,22 +235,6 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & lower_bound = qcf_table_data(QTY_loc(1))%probit_extended_state%lower_bound upper_bound = qcf_table_data(QTY_loc(1))%probit_extended_state%upper_bound -! if(kind == QTY_STATE_VARIABLE) then -! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION -! bounded_below = .false.; bounded_above = .false. -! lower_bound = missing_r8; upper_bound = missing_r8 -! elseif(kind == QTY_TRACER_CONCENTRATION) then -! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION -! bounded_below = .true.; bounded_above = .false. -! lower_bound = 0.0_r8; upper_bound = missing_r8 -! elseif(kind == QTY_TRACER_SOURCE) then -! dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION -! bounded_below = .true.; bounded_above = .false. -! lower_bound = 0.0_r8; upper_bound = missing_r8 -! else -! write(*, *) 'Illegal kind in obs_error_info' -! stop -! endif endif write(*,*) 'probit_dist_info: ', dist_type, bounded_below, bounded_above, lower_bound, upper_bound @@ -338,7 +274,7 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ write(*,*) 'findloc of kind: ', QTY_loc(1) if (QTY_loc(1) == 0) then - write(*,*) 'QTY not in table!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' + write(*,*) 'QTY not in table, using default values' !use default values filter_kind = BOUNDED_NORMAL_RHF @@ -360,24 +296,6 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ write(*,*) 'obs_inc_info: ', filter_kind, sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound -! Set the observation increment details for each type of quantity -!if(obs_kind == QTY_STATE_VARIABLE) then -! filter_kind = BOUNDED_NORMAL_RHF -! bounded_below = .false.; bounded_above = .false. -! lower_bound = missing_r8; upper_bound = missing_r8 -!elseif(obs_kind == QTY_TRACER_CONCENTRATION) then -! filter_kind = BOUNDED_NORMAL_RHF -! bounded_below = .true.; bounded_above = .false. -! lower_bound = 0.0_r8; upper_bound = missing_r8 -!elseif(obs_kind == QTY_TRACER_SOURCE) then -! filter_kind = BOUNDED_NORMAL_RHF -! bounded_below = .true.; bounded_above = .false. -! lower_bound = 0.0_r8; upper_bound = missing_r8 -!else -! write(*, *) 'Illegal obs_kind in obs_error_info' -! stop -!endif - ! Only need to set these two for options the original RHF implementation !!!rectangular_quadrature = .true. !!!gaussian_likelihood_tails = .false. @@ -425,9 +343,6 @@ subroutine read_qcf_table(qcf_table_filename) character(len=129), intent(in) :: qcf_table_filename -!type(qcf_table_data_type) :: qcf_table_data(:) -!character(len=129) :: rowheaders(:) !!!!! might need to change len=129 - integer, parameter :: fileid = 10 !file identifier integer :: row From b5d27b2c5a7d72c5225b679aa587389c2a4f6734 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 21 Aug 2023 15:43:57 -0600 Subject: [PATCH 020/129] Adding call to deallocate routine, removing unused var and old commented code --- .../modules/assimilation/algorithm_info_mod.f90 | 6 ------ assimilation_code/modules/assimilation/assim_tools_mod.f90 | 7 +++++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 3eee46e986..d8e93391f0 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -9,12 +9,6 @@ module algorithm_info_mod use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance use obs_kind_mod, only : get_quantity_for_type_of_obs, get_name_for_quantity - -! Get the QTY definitions that are needed (aka kind) -use obs_kind_mod, only : QTY_STATE_VARIABLE, QTY_STATE_VAR_POWER, QTY_TRACER_CONCENTRATION, & - QTY_TRACER_SOURCE -! NOTE: Sadly, the QTY itself is not sufficient for the POWER because there is additional metadata - use assim_model_mod, only : get_state_meta_data use location_mod, only : location_type diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index b4f714eb93..d4bfa02b6a 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -223,7 +223,7 @@ module assim_tools_mod subroutine assim_tools_init() -integer :: iunit, io, i, j, numrows +integer :: iunit, io, i, j integer :: num_special_cutoff, type_index logical :: cache_override = .false. @@ -315,7 +315,7 @@ subroutine assim_tools_init() call log_namelist_selections(num_special_cutoff, cache_override) if(qcf_table_filename == '') then - write(*,*), "no qcf table in namelist" + write(*,*), "No QCF table in namelist, using default values for all QTYs" else call init_qcf_table(qcf_table_filename) endif @@ -903,6 +903,9 @@ subroutine filter_assim(ens_handle, obs_ens_handle, obs_seq, keys, & ! get rid of mpi window call free_mean_window() +! free qcf_table_data structures +call deallocate_qcf_table() + ! deallocate space deallocate(close_obs_dist, & my_obs_indx, & From fbfe5f383b79765daa874bf37e4549275968b082 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 21 Aug 2023 16:47:06 -0600 Subject: [PATCH 021/129] Fixing typo in subroutine names --- .../assimilation/algorithm_info_mod.f90 | 18 +++++++++--------- .../modules/assimilation/assim_tools_mod.f90 | 10 +++++----- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index d8e93391f0..b5fa43a560 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -30,7 +30,7 @@ module algorithm_info_mod integer, parameter :: BOUNDED_NORMAL_RHF = 101 public :: obs_error_info, probit_dist_info, obs_inc_info, & - init_qcf_table, deallocate_qcf_table, & + init_algorithm_info_mod, end_algorithm_info_mod, & obs_error_info_type, probit_inflation_type, probit_state_type, & probit_extended_state_type, obs_inc_info_type, qcf_table_data_type, & EAKF, ENKF, BOUNDED_NORMAL_RHF, UNBOUNDED_RHF, GAMMA_FILTER @@ -76,7 +76,7 @@ module algorithm_info_mod end type type(qcf_table_data_type), allocatable :: qcf_table_data(:) -character(len=129), allocatable :: qcf_table_row_headers(:) !!!!! might need to change len=129 +character(len=129), allocatable :: qcf_table_row_headers(:) ! Provides routines that give information about details of algorithms for ! observation error sampling, observation increments, and the transformations @@ -139,7 +139,7 @@ subroutine obs_error_info(obs_def, error_variance, & else bounded_below = qcf_table_data(QTY_loc(1))%obs_error_info%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%obs_error_info%bounded_above - lower_bound = qcf_table_data(QTY_loc(1))%obs_error_info%lower_bound !NEED TO ADD CHECKS THAT THESE ARE VALID VALUES + lower_bound = qcf_table_data(QTY_loc(1))%obs_error_info%lower_bound upper_bound = qcf_table_data(QTY_loc(1))%obs_error_info%upper_bound endif @@ -208,7 +208,7 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & dist_type = qcf_table_data(QTY_loc(1))%probit_inflation%dist_type !dist_type has checks in transform_to_probit, transform_from_probit bounded_below = qcf_table_data(QTY_loc(1))%probit_inflation%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%probit_inflation%bounded_above - lower_bound = qcf_table_data(QTY_loc(1))%probit_inflation%lower_bound !NEED TO ADD CHECKS THAT THESE ARE VALID VALUES + lower_bound = qcf_table_data(QTY_loc(1))%probit_inflation%lower_bound upper_bound = qcf_table_data(QTY_loc(1))%probit_inflation%upper_bound elseif(is_state) then @@ -283,7 +283,7 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ spread_restoration = qcf_table_data(QTY_loc(1))%obs_inc_info%spread_restoration bounded_below = qcf_table_data(QTY_loc(1))%obs_inc_info%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%obs_inc_info%bounded_above - lower_bound = qcf_table_data(QTY_loc(1))%obs_inc_info%lower_bound !NEED TO ADD CHECKS THAT THESE ARE VALID VALUES + lower_bound = qcf_table_data(QTY_loc(1))%obs_inc_info%lower_bound upper_bound = qcf_table_data(QTY_loc(1))%obs_inc_info%upper_bound endif @@ -299,7 +299,7 @@ end subroutine obs_inc_info !------------------------------------------------------------------------ -subroutine init_qcf_table(qcf_table_filename) +subroutine init_algorithm_info_mod(qcf_table_filename) character(len=129), intent(in) :: qcf_table_filename @@ -326,7 +326,7 @@ subroutine init_qcf_table(qcf_table_filename) call read_qcf_table(qcf_table_filename) -end subroutine init_qcf_table +end subroutine init_algorithm_info_mod !------------------------------------------------------------------------ @@ -420,12 +420,12 @@ end subroutine write_qcf_table !------------------------------------------------------------------------ -subroutine deallocate_qcf_table() +subroutine end_algorithm_info_mod() deallocate(qcf_table_data) deallocate(qcf_table_row_headers) -end subroutine deallocate_qcf_table +end subroutine end_algorithm_info_mod !---------------------------------------------------------------------- diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index d4bfa02b6a..393627be56 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -76,7 +76,7 @@ module assim_tools_mod use normal_distribution_mod, only : normal_cdf, inv_weighted_normal_cdf -use algorithm_info_mod, only : probit_dist_info, obs_inc_info, init_qcf_table, deallocate_qcf_table +use algorithm_info_mod, only : probit_dist_info, obs_inc_info, init_algorithm_info_mod, end_algorithm_info_mod use gamma_distribution_mod, only : gamma_cdf, inv_gamma_cdf, gamma_mn_var_to_shape_scale, & gamma_gamma_prod @@ -143,7 +143,7 @@ module assim_tools_mod ! special_localization_obs_types -> Special treatment for the specified observation types ! special_localization_cutoffs -> Different cutoff value for each specified obs type ! -character(len = 129) :: qcf_table_filename = '' !not sure if the len should be 129 here, but it is consistent with other nml variables +character(len = 129) :: qcf_table_filename = '' logical :: use_algorithm_info_mod = .true. integer :: filter_kind = 1 real(r8) :: cutoff = 0.2_r8 @@ -317,7 +317,7 @@ subroutine assim_tools_init() if(qcf_table_filename == '') then write(*,*), "No QCF table in namelist, using default values for all QTYs" else - call init_qcf_table(qcf_table_filename) + call init_algorithm_info_mod(qcf_table_filename) endif end subroutine assim_tools_init @@ -903,8 +903,8 @@ subroutine filter_assim(ens_handle, obs_ens_handle, obs_seq, keys, & ! get rid of mpi window call free_mean_window() -! free qcf_table_data structures -call deallocate_qcf_table() +! deallocate qcf_table_data structures +call end_algorithm_info_mod() ! deallocate space deallocate(close_obs_dist, & From 5a093b1b084889f7982c0c4c8d150238870915ca Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 22 Aug 2023 13:58:25 -0600 Subject: [PATCH 022/129] Moving the allocation and deallocation of qcf table data from assim_tools_mod to filter_main in filter_mod --- .../modules/assimilation/assim_tools_mod.f90 | 14 ++------------ .../modules/assimilation/filter_mod.f90 | 14 +++++++++++++- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index 393627be56..958e373201 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -76,7 +76,7 @@ module assim_tools_mod use normal_distribution_mod, only : normal_cdf, inv_weighted_normal_cdf -use algorithm_info_mod, only : probit_dist_info, obs_inc_info, init_algorithm_info_mod, end_algorithm_info_mod +use algorithm_info_mod, only : probit_dist_info, obs_inc_info use gamma_distribution_mod, only : gamma_cdf, inv_gamma_cdf, gamma_mn_var_to_shape_scale, & gamma_gamma_prod @@ -143,7 +143,6 @@ module assim_tools_mod ! special_localization_obs_types -> Special treatment for the specified observation types ! special_localization_cutoffs -> Different cutoff value for each specified obs type ! -character(len = 129) :: qcf_table_filename = '' logical :: use_algorithm_info_mod = .true. integer :: filter_kind = 1 real(r8) :: cutoff = 0.2_r8 @@ -204,7 +203,7 @@ module assim_tools_mod ! compared to previous versions of this namelist item. logical :: distribute_mean = .false. -namelist / assim_tools_nml / qcf_table_filename, use_algorithm_info_mod, & +namelist / assim_tools_nml / use_algorithm_info_mod, & filter_kind, cutoff, sort_obs_inc, & spread_restoration, sampling_error_correction, & adaptive_localization_threshold, adaptive_cutoff_floor, & @@ -314,12 +313,6 @@ subroutine assim_tools_init() call log_namelist_selections(num_special_cutoff, cache_override) -if(qcf_table_filename == '') then - write(*,*), "No QCF table in namelist, using default values for all QTYs" -else - call init_algorithm_info_mod(qcf_table_filename) -endif - end subroutine assim_tools_init !------------------------------------------------------------- @@ -903,9 +896,6 @@ subroutine filter_assim(ens_handle, obs_ens_handle, obs_seq, keys, & ! get rid of mpi window call free_mean_window() -! deallocate qcf_table_data structures -call end_algorithm_info_mod() - ! deallocate space deallocate(close_obs_dist, & my_obs_indx, & diff --git a/assimilation_code/modules/assimilation/filter_mod.f90 b/assimilation_code/modules/assimilation/filter_mod.f90 index 11e50c3038..0c4035b9a6 100644 --- a/assimilation_code/modules/assimilation/filter_mod.f90 +++ b/assimilation_code/modules/assimilation/filter_mod.f90 @@ -90,7 +90,7 @@ module filter_mod use probit_transform_mod, only : transform_to_probit, transform_from_probit -use algorithm_info_mod, only : probit_dist_info +use algorithm_info_mod, only : probit_dist_info, init_algorithm_info_mod, end_algorithm_info_mod use distribution_params_mod, only : distribution_params_type, NORMAL_DISTRIBUTION @@ -166,6 +166,7 @@ module filter_mod !---------------------------------------------------------------- ! Namelist input with default values ! +character(len = 129) :: qcf_table_filename = '' logical :: use_algorithm_info_mod = .true. integer :: async = 0, ens_size = 20 integer :: tasks_per_model_advance = 1 @@ -261,6 +262,7 @@ module filter_mod namelist /filter_nml/ async, & + qcf_table_filename, & use_algorithm_info_mod, & adv_ens_command, & ens_size, & @@ -1150,6 +1152,9 @@ subroutine filter_main() call end_assim_model() call trace_message('After end_model call') +! deallocate qcf_table_data structures +!call end_algorithm_info_mod() + call trace_message('Before ensemble and obs memory cleanup') call end_ensemble_manager(state_ens_handle) @@ -1268,6 +1273,13 @@ subroutine filter_initialize_modules_used() ! Initialize the obs sequence module call static_init_obs_sequence() +! Initialize algorothm_info_mod and read in QCF table data +if(qcf_table_filename == '') then + write(*,*) "No QCF table in namelist, using default values for all QTYs" +else + call init_algorithm_info_mod(qcf_table_filename) +endif + ! Initialize the model class data now that obs_sequence is all set up call static_init_assim_model() call state_vector_io_init() From 54f7ea090a60bf2f1148c5f3ad77472d75ec7b22 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 22 Aug 2023 14:38:47 -0600 Subject: [PATCH 023/129] uncommenting call to end_alg_info_mod --- assimilation_code/modules/assimilation/filter_mod.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assimilation_code/modules/assimilation/filter_mod.f90 b/assimilation_code/modules/assimilation/filter_mod.f90 index 0c4035b9a6..d967eb71e6 100644 --- a/assimilation_code/modules/assimilation/filter_mod.f90 +++ b/assimilation_code/modules/assimilation/filter_mod.f90 @@ -1153,7 +1153,7 @@ subroutine filter_main() call trace_message('After end_model call') ! deallocate qcf_table_data structures -!call end_algorithm_info_mod() +call end_algorithm_info_mod() call trace_message('Before ensemble and obs memory cleanup') call end_ensemble_manager(state_ens_handle) From 399d08d86c89945eb10b9dc3aa61bfd44ac8d40c Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 23 Aug 2023 15:28:06 -0600 Subject: [PATCH 024/129] moving call to init_algortihm_info_mod out of conditional --- .../modules/assimilation/filter_mod.f90 | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/assimilation_code/modules/assimilation/filter_mod.f90 b/assimilation_code/modules/assimilation/filter_mod.f90 index d967eb71e6..874a4cb1d5 100644 --- a/assimilation_code/modules/assimilation/filter_mod.f90 +++ b/assimilation_code/modules/assimilation/filter_mod.f90 @@ -166,7 +166,7 @@ module filter_mod !---------------------------------------------------------------- ! Namelist input with default values ! -character(len = 129) :: qcf_table_filename = '' +character(len = 129) :: qcf_table_filename = 'real_qcf_table.txt' !NEED TO REMOVE THIS LATER logical :: use_algorithm_info_mod = .true. integer :: async = 0, ens_size = 20 integer :: tasks_per_model_advance = 1 @@ -1273,17 +1273,14 @@ subroutine filter_initialize_modules_used() ! Initialize the obs sequence module call static_init_obs_sequence() -! Initialize algorothm_info_mod and read in QCF table data -if(qcf_table_filename == '') then - write(*,*) "No QCF table in namelist, using default values for all QTYs" -else - call init_algorithm_info_mod(qcf_table_filename) -endif - ! Initialize the model class data now that obs_sequence is all set up call static_init_assim_model() call state_vector_io_init() call initialize_qc() + +! Initialize algorothm_info_mod and read in QCF table data +call init_algorithm_info_mod(qcf_table_filename) + call trace_message('After filter_initialize_module_used call') end subroutine filter_initialize_modules_used From 2a1e7c522a1a7d8ab87475dd19a71c51a08c563f Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 23 Aug 2023 15:55:22 -0600 Subject: [PATCH 025/129] Reorganizing the subroutines so that init_algorithm_info_mod is at the top of algorithm_info_mod --- .../assimilation/algorithm_info_mod.f90 | 158 +++++++++--------- 1 file changed, 81 insertions(+), 77 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index b5fa43a560..027cf747eb 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -91,6 +91,87 @@ module algorithm_info_mod !------------------------------------------------------------------------- +subroutine init_algorithm_info_mod(qcf_table_filename) + +! Gets number of lines/QTYs in the QCF table, allocates space for the table data + +character(len=129), intent(in) :: qcf_table_filename + +integer :: numrows +integer :: nlines +integer :: io +integer, parameter :: fileid = 10 !file identifier + +write(*,*) 'filename: ', qcf_table_filename + +open(unit=fileid, file=qcf_table_filename) +nlines = 0 + +do !do loop to get number of rows (or QTY's) in the table + read(fileid,*,iostat=io) + if(io/=0) exit + nlines = nlines + 1 +end do +close(fileid) + +numrows = nlines - 2 +print *, 'numrows: ', numrows + +allocate(qcf_table_data(numrows)) +allocate(qcf_table_row_headers(numrows)) + +call read_qcf_table(qcf_table_filename) +call write_qcf_table() + +end subroutine init_algorithm_info_mod + +!------------------------------------------------------------------------ + + +subroutine read_qcf_table(qcf_table_filename) + +! Reads in the QCEFF input options from tabular data file + +character(len=129), intent(in) :: qcf_table_filename + +integer, parameter :: fileid = 10 !file identifier +integer :: row + +character(len=129), dimension(4) :: header1 +character(len=129), dimension(29) :: header2 + +write(*,*) 'filename: ', qcf_table_filename +open(unit=fileid, file=qcf_table_filename) + +! skip the headers +read(fileid, *) header1 +read(fileid, *) header2 +write(*, *) "header1: ", header1 +write(*, *) "header2: ", header2 + +! read in table values directly to qcf_table_data type +do row = 1, size(qcf_table_data) + read(fileid, *) qcf_table_row_headers(row), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & + qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & + qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & + qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & + qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & + qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & + qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & + qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & + qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & + qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & + qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & + qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound +end do + +close(fileid) + +end subroutine read_qcf_table + +!------------------------------------------------------------------------ + + subroutine obs_error_info(obs_def, error_variance, & bounded_below, bounded_above, lower_bound, upper_bound) @@ -299,83 +380,6 @@ end subroutine obs_inc_info !------------------------------------------------------------------------ -subroutine init_algorithm_info_mod(qcf_table_filename) - -character(len=129), intent(in) :: qcf_table_filename - -integer :: numrows -integer :: nlines -integer :: io -integer, parameter :: fileid = 10 !file identifier - -open(unit=fileid, file=qcf_table_filename) -nlines = 0 - -do !do loop to get number of rows (or QTY's) in the table - read(fileid,*,iostat=io) - if(io/=0) exit - nlines = nlines + 1 -end do -close(fileid) - -numrows = nlines - 2 -print *, 'numrows: ', numrows - -allocate(qcf_table_data(numrows)) -allocate(qcf_table_row_headers(numrows)) - -call read_qcf_table(qcf_table_filename) - -end subroutine init_algorithm_info_mod - -!------------------------------------------------------------------------ - - -subroutine read_qcf_table(qcf_table_filename) - -! Reads in the QCEFF input options from tabular data file - -character(len=129), intent(in) :: qcf_table_filename - -integer, parameter :: fileid = 10 !file identifier -integer :: row - -character(len=129), dimension(4) :: header1 -character(len=129), dimension(29) :: header2 - -open(unit=fileid, file=qcf_table_filename) - -! skip the headers -read(fileid, *) header1 -read(fileid, *) header2 -write(*, *) "header1: ", header1 -write(*, *) "header2: ", header2 - -! read in table values directly to qcf_table_data type -do row = 1, size(qcf_table_data) - read(fileid, *) qcf_table_row_headers(row), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & - qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & - qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & - qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & - qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & - qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & - qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & - qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & - qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & - qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & - qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound -end do - -close(fileid) - -call write_qcf_table() - -end subroutine read_qcf_table - -!------------------------------------------------------------------------ - - subroutine write_qcf_table() ! DRAFT SUBROUTINE From c93286aeb4385a8d71f84ba3b708abff0db2e287 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 23 Aug 2023 16:32:46 -0600 Subject: [PATCH 026/129] Adding qcf_table_listed logical and module_initialized checks --- .../assimilation/algorithm_info_mod.f90 | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 027cf747eb..c5b6ef965e 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -19,6 +19,9 @@ module algorithm_info_mod implicit none private +logical :: module_initialized = .false. +logical :: qcf_table_listed = .false. + ! Defining parameter strings for different observation space filters ! For now, retaining backwards compatibility in assim_tools_mod requires using ! these specific integer values and there is no point in using these in assim_tools. @@ -102,8 +105,17 @@ subroutine init_algorithm_info_mod(qcf_table_filename) integer :: io integer, parameter :: fileid = 10 !file identifier +if (module_initialized) return +module_initialized = .true. + write(*,*) 'filename: ', qcf_table_filename +if (qcf_table_filename == '') then + write(*,*) 'No QCF table file listed in namelist, using default values for all QTYs' + return +endif + +qcf_table_listed = .true. open(unit=fileid, file=qcf_table_filename) nlines = 0 @@ -140,6 +152,8 @@ subroutine read_qcf_table(qcf_table_filename) character(len=129), dimension(4) :: header1 character(len=129), dimension(29) :: header2 +if (.not. module_initialized) call init_algorithm_info_mod(qcf_table_filename) + write(*,*) 'filename: ', qcf_table_filename open(unit=fileid, file=qcf_table_filename) @@ -210,9 +224,12 @@ subroutine obs_error_info(obs_def, error_variance, & QTY_loc = findloc(qcf_table_row_headers, kind_name) write(*,*) 'findloc of kind: ', QTY_loc(1) -if (QTY_loc(1) == 0) then - write(*,*) 'QTY not in table, using default values' +!use default values if qcf_table_filename is not in namelist +if (.not. qcf_table_listed) then + bounded_below = .false.; bounded_above = .false. + lower_bound = missing_r8; upper_bound = missing_r8 +if (QTY_loc(1) == 0) then !use default values bounded_below = .false.; bounded_above = .false. lower_bound = missing_r8; upper_bound = missing_r8 @@ -429,6 +446,8 @@ subroutine end_algorithm_info_mod() deallocate(qcf_table_data) deallocate(qcf_table_row_headers) +module_initialized = .false. + end subroutine end_algorithm_info_mod !---------------------------------------------------------------------- From 39c9da1c4dc2ade87a6db79f8704d5aea0677bdf Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 23 Aug 2023 16:35:31 -0600 Subject: [PATCH 027/129] Moving location of qcf_table_listed check to before data access from findloc --- .../modules/assimilation/algorithm_info_mod.f90 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index c5b6ef965e..67a68d28e8 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -220,14 +220,16 @@ subroutine obs_error_info(obs_def, error_variance, & kind_name = get_name_for_quantity(obs_kind) write(*,*) 'kind_name: ', kind_name -!find location of QTY in qcf_table_data structure -QTY_loc = findloc(qcf_table_row_headers, kind_name) -write(*,*) 'findloc of kind: ', QTY_loc(1) - !use default values if qcf_table_filename is not in namelist if (.not. qcf_table_listed) then bounded_below = .false.; bounded_above = .false. lower_bound = missing_r8; upper_bound = missing_r8 + return +endif + +!find location of QTY in qcf_table_data structure +QTY_loc = findloc(qcf_table_row_headers, kind_name) +write(*,*) 'findloc of kind: ', QTY_loc(1) if (QTY_loc(1) == 0) then !use default values From 00e82ca2cc884cfd54afd8dd8d3c91c606cad59d Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 28 Aug 2023 16:17:50 -0600 Subject: [PATCH 028/129] Using error_handler from utilities_mod; adding check for correct table version --- .../assimilation/algorithm_info_mod.f90 | 44 ++++++++++++------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 67a68d28e8..e3afcfbda6 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -9,6 +9,8 @@ module algorithm_info_mod use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance use obs_kind_mod, only : get_quantity_for_type_of_obs, get_name_for_quantity +use utilities_mod, only : error_handler, E_ERR + use assim_model_mod, only : get_state_meta_data use location_mod, only : location_type @@ -19,6 +21,9 @@ module algorithm_info_mod implicit none private +character(len=512) :: errstring +character(len=*), parameter :: source = 'algorithm_info_mod.f90' + logical :: module_initialized = .false. logical :: qcf_table_listed = .false. @@ -154,14 +159,11 @@ subroutine read_qcf_table(qcf_table_filename) if (.not. module_initialized) call init_algorithm_info_mod(qcf_table_filename) -write(*,*) 'filename: ', qcf_table_filename open(unit=fileid, file=qcf_table_filename) -! skip the headers +! skip the headers, make sure user is using the correct table version read(fileid, *) header1 read(fileid, *) header2 -write(*, *) "header1: ", header1 -write(*, *) "header2: ", header2 ! read in table values directly to qcf_table_data type do row = 1, size(qcf_table_data) @@ -181,6 +183,8 @@ subroutine read_qcf_table(qcf_table_filename) close(fileid) +call assert_qcf_table_version(header1) + end subroutine read_qcf_table !------------------------------------------------------------------------ @@ -218,7 +222,6 @@ subroutine obs_error_info(obs_def, error_variance, & !get actual name of QTY from integer index kind_name = get_name_for_quantity(obs_kind) -write(*,*) 'kind_name: ', kind_name !use default values if qcf_table_filename is not in namelist if (.not. qcf_table_listed) then @@ -229,7 +232,6 @@ subroutine obs_error_info(obs_def, error_variance, & !find location of QTY in qcf_table_data structure QTY_loc = findloc(qcf_table_row_headers, kind_name) -write(*,*) 'findloc of kind: ', QTY_loc(1) if (QTY_loc(1) == 0) then !use default values @@ -244,8 +246,6 @@ subroutine obs_error_info(obs_def, error_variance, & endif -write(*,*) 'obs_error_info: ', bounded_below, bounded_above, lower_bound, upper_bound - end subroutine obs_error_info !------------------------------------------------------------------------- @@ -288,11 +288,9 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & !get actual name of QTY from integer index kind_name = get_name_for_quantity(kind) -write(*,*) 'kind_name: ', kind_name !find location of QTY in qcf_table_data structure QTY_loc = findloc(qcf_table_row_headers, kind_name) -write(*,*) 'findloc of kind: ', QTY_loc(1) if (QTY_loc(1) == 0) then write(*,*) 'QTY not in table, using default values' @@ -331,8 +329,6 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & endif -write(*,*) 'probit_dist_info: ', dist_type, bounded_below, bounded_above, lower_bound, upper_bound - end subroutine probit_dist_info !------------------------------------------------------------------------ @@ -361,11 +357,9 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ !get actual name of QTY from integer index kind_name = get_name_for_quantity(obs_kind) -write(*,*) 'kind_name: ', kind_name !find location of QTY in qcf_table_data structure QTY_loc = findloc(qcf_table_row_headers, kind_name) -write(*,*) 'findloc of kind: ', QTY_loc(1) if (QTY_loc(1) == 0) then write(*,*) 'QTY not in table, using default values' @@ -388,8 +382,6 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ endif -write(*,*) 'obs_inc_info: ', filter_kind, sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound - ! Only need to set these two for options the original RHF implementation !!!rectangular_quadrature = .true. !!!gaussian_likelihood_tails = .false. @@ -443,8 +435,28 @@ end subroutine write_qcf_table !------------------------------------------------------------------------ +subroutine assert_qcf_table_version(header) + +!subroutine to ensure the correct version of the QCF table is being used + +character(len=129), dimension(4), intent(in) :: header + +write(*,*) 'version: ', header(4) + +if (header(4) /= '1:') then + write(errstring,*) "Using outdated/incorrect version of the QCF table" + call error_handler(E_ERR, 'assert_qcf_table_version', errstring, source) +endif + +end subroutine assert_qcf_table_version + +!------------------------------------------------------------------------ + + subroutine end_algorithm_info_mod() +if (.not. module_initialized) return + deallocate(qcf_table_data) deallocate(qcf_table_row_headers) From 08b853c75eccf65ad7e14a4847032d7b5871cfe8 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 5 Sep 2023 14:26:24 -0600 Subject: [PATCH 029/129] adding qcf_table_file_listed logical to two remaining subrountines; work with log_qcf_info --- .../assimilation/algorithm_info_mod.f90 | 133 ++++++++++++++++-- 1 file changed, 120 insertions(+), 13 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index e3afcfbda6..c713467522 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -9,7 +9,7 @@ module algorithm_info_mod use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance use obs_kind_mod, only : get_quantity_for_type_of_obs, get_name_for_quantity -use utilities_mod, only : error_handler, E_ERR +use utilities_mod, only : error_handler, E_ALLMSG, E_ERR, E_MSG, log_it use assim_model_mod, only : get_state_meta_data use location_mod, only : location_type @@ -138,7 +138,11 @@ subroutine init_algorithm_info_mod(qcf_table_filename) allocate(qcf_table_row_headers(numrows)) call read_qcf_table(qcf_table_filename) +!call verify_qcf_table_data(qcf_table_filename, nlines) call write_qcf_table() +call log_qcf_table_data() + +!stop end subroutine init_algorithm_info_mod @@ -164,6 +168,8 @@ subroutine read_qcf_table(qcf_table_filename) ! skip the headers, make sure user is using the correct table version read(fileid, *) header1 read(fileid, *) header2 +write(*,*) 'header1: ', header1 +write(*,*) 'header2: ', header2 ! read in table values directly to qcf_table_data type do row = 1, size(qcf_table_data) @@ -220,9 +226,6 @@ subroutine obs_error_info(obs_def, error_variance, & ! Get the default error variance error_variance = get_obs_def_error_variance(obs_def) -!get actual name of QTY from integer index -kind_name = get_name_for_quantity(obs_kind) - !use default values if qcf_table_filename is not in namelist if (.not. qcf_table_listed) then bounded_below = .false.; bounded_above = .false. @@ -230,11 +233,14 @@ subroutine obs_error_info(obs_def, error_variance, & return endif +!get actual name of QTY from integer index +kind_name = get_name_for_quantity(obs_kind) + !find location of QTY in qcf_table_data structure QTY_loc = findloc(qcf_table_row_headers, kind_name) if (QTY_loc(1) == 0) then - !use default values + !use default values if QTY is not in table bounded_below = .false.; bounded_above = .false. lower_bound = missing_r8; upper_bound = missing_r8 @@ -286,6 +292,14 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & ! In the long run, may not have to have separate controls for each of the input possibilities ! However, for now these are things that need to be explored for science understanding +!use default values if qcf_table_filename is not in namelist +if (.not. qcf_table_listed) then + dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION + bounded_below = .false.; bounded_above = .false. + lower_bound = missing_r8; upper_bound = missing_r8 + return +endif + !get actual name of QTY from integer index kind_name = get_name_for_quantity(kind) @@ -293,9 +307,9 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & QTY_loc = findloc(qcf_table_row_headers, kind_name) if (QTY_loc(1) == 0) then - write(*,*) 'QTY not in table, using default values' + write(*,*) 'QTY not in table, using default values' !remove these writes on PR - !use default values + !use default values if QTY is not in table dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION bounded_below = .false.; bounded_above = .false. lower_bound = missing_r8; upper_bound = missing_r8 @@ -355,16 +369,27 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ ! Temporary approach for setting the details of how to assimilate this observation ! This example is designed to reproduce the squared forward operator results from paper +!use default values if qcf_table_filename is not in namelist +if (.not. qcf_table_listed) then + filter_kind = BOUNDED_NORMAL_RHF + bounded_below = .false.; bounded_above = .false. + lower_bound = missing_r8; upper_bound = missing_r8 + sort_obs_inc = .false.; spread_restoration = .false. + return +endif + !get actual name of QTY from integer index kind_name = get_name_for_quantity(obs_kind) +write(*,*) 'kind_name: ', kind_name !find location of QTY in qcf_table_data structure QTY_loc = findloc(qcf_table_row_headers, kind_name) +write(*,*) 'findloc of kind: ', QTY_loc(1) if (QTY_loc(1) == 0) then write(*,*) 'QTY not in table, using default values' - !use default values + !use default values if QTY is not in table filter_kind = BOUNDED_NORMAL_RHF bounded_below = .false.; bounded_above = .false. lower_bound = missing_r8; upper_bound = missing_r8 @@ -382,6 +407,8 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ endif +write(*,*) 'obs_inc_info: ', filter_kind, sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound + ! Only need to set these two for options the original RHF implementation !!!rectangular_quadrature = .true. !!!gaussian_likelihood_tails = .false. @@ -405,12 +432,10 @@ subroutine write_qcf_table() integer :: row -write(*,*), 'SIZE: ', size(qcf_table_data) - do row = 1, size(qcf_table_data) - write(*, *) "qcf_table_row_headers(", row, "): ", qcf_table_row_headers(row) - write(*, *) "qcf_table_data(", row, "): " - write(*, *) qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & + write(*,*) "qcf_table_row_headers(", row, "): ", qcf_table_row_headers(row) + write(*,*) "qcf_table_data(", row, "): " + write(*,*) qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & @@ -441,6 +466,10 @@ subroutine assert_qcf_table_version(header) character(len=129), dimension(4), intent(in) :: header +!if (.not. module_initialized) call init_algorithm_info_mod(qcf_table_filename) + +if (.not. qcf_table_listed) return + write(*,*) 'version: ', header(4) if (header(4) /= '1:') then @@ -453,6 +482,84 @@ end subroutine assert_qcf_table_version !------------------------------------------------------------------------ +subroutine verify_qcf_table_data(qcf_table_filename, nlines) + +!subroutine to ensure that the data in the QCF table is valid and in +!the correct formatthe right format and is correct size + +character(len=129), intent(in) :: qcf_table_filename +integer, intent(in) :: nlines + +character(len=500) :: table_rows(nlines) +integer, parameter :: fileid = 10 !file identifier +integer :: row + +if (.not. module_initialized) call init_algorithm_info_mod(qcf_table_filename) + +if (.not. qcf_table_listed) return + +open(unit=fileid, file=qcf_table_filename) + +do row = 1, nlines + read(fileid, '(A)') table_rows(row) + print *, 'full line:' + print *, table_rows(row) + print *, 'trimmed line:' + print *, trim(table_rows(row)) + print *, 'length', len_trim(table_rows(row)) +end do + +close(fileid) + +!if (size(qcf_table_row_headers) /= 2) then !NO, this needs to be table headers, not row +! write(errstring,*) 'Incorrect number of headers in the QCF table; ' , & +! 'ensure that the latest version of this table is ', & +! 'being used and is in the same format as the example' +! call error_handler(E_ERR, 'assert_qcf_table_version', errstring, source) +!endif + +end subroutine verify_qcf_table_data + +!------------------------------------------------------------------------ + + +subroutine log_qcf_table_data() + +!subroutine to write the data in QCF table to dart_log + +character(len=500) :: log_msg +integer :: row + +if (.not. qcf_table_listed) return + +do row = 1, size(qcf_table_data) + write(log_msg, *) "qcf_table_row_headers(", row, "): ", qcf_table_row_headers(row) + write(*,*) 'log_msg: ', log_msg + call log_it(log_msg) + write(log_msg, *) "qcf_table_data(", row, "): " + write(*,*) 'log_msg: ', log_msg + call log_it(log_msg) + write(log_msg, *) qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & + qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & + qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & + qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & + qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & + qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & + qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & + qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & + qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & + qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & + qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & + qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound + write(*,*) 'e_allmsg: ' + call error_handler(E_ALLMSG, 'write_qcf_table', log_msg, source) +end do + +end subroutine log_qcf_table_data + +!------------------------------------------------------------------------ + + subroutine end_algorithm_info_mod() if (.not. module_initialized) return From ff040866a18e8af67f51ca4dd19a4ed5928a2610 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 5 Sep 2023 15:16:37 -0600 Subject: [PATCH 030/129] commenting out prints; remove these lines later --- .../assimilation/algorithm_info_mod.f90 | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index c713467522..f09d3e1656 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -113,7 +113,7 @@ subroutine init_algorithm_info_mod(qcf_table_filename) if (module_initialized) return module_initialized = .true. -write(*,*) 'filename: ', qcf_table_filename +!write(*,*) 'filename: ', qcf_table_filename if (qcf_table_filename == '') then write(*,*) 'No QCF table file listed in namelist, using default values for all QTYs' @@ -132,14 +132,14 @@ subroutine init_algorithm_info_mod(qcf_table_filename) close(fileid) numrows = nlines - 2 -print *, 'numrows: ', numrows +!print *, 'numrows: ', numrows allocate(qcf_table_data(numrows)) allocate(qcf_table_row_headers(numrows)) call read_qcf_table(qcf_table_filename) !call verify_qcf_table_data(qcf_table_filename, nlines) -call write_qcf_table() +!call write_qcf_table() call log_qcf_table_data() !stop @@ -168,8 +168,8 @@ subroutine read_qcf_table(qcf_table_filename) ! skip the headers, make sure user is using the correct table version read(fileid, *) header1 read(fileid, *) header2 -write(*,*) 'header1: ', header1 -write(*,*) 'header2: ', header2 +!write(*,*) 'header1: ', header1 +!write(*,*) 'header2: ', header2 ! read in table values directly to qcf_table_data type do row = 1, size(qcf_table_data) @@ -307,7 +307,7 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & QTY_loc = findloc(qcf_table_row_headers, kind_name) if (QTY_loc(1) == 0) then - write(*,*) 'QTY not in table, using default values' !remove these writes on PR + ! write(*,*) 'QTY not in table, using default values' !remove these writes on PR !use default values if QTY is not in table dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION @@ -380,14 +380,14 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ !get actual name of QTY from integer index kind_name = get_name_for_quantity(obs_kind) -write(*,*) 'kind_name: ', kind_name +!write(*,*) 'kind_name: ', kind_name !find location of QTY in qcf_table_data structure QTY_loc = findloc(qcf_table_row_headers, kind_name) -write(*,*) 'findloc of kind: ', QTY_loc(1) +!write(*,*) 'findloc of kind: ', QTY_loc(1) if (QTY_loc(1) == 0) then - write(*,*) 'QTY not in table, using default values' + !write(*,*) 'QTY not in table, using default values' !use default values if QTY is not in table filter_kind = BOUNDED_NORMAL_RHF @@ -407,7 +407,7 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ endif -write(*,*) 'obs_inc_info: ', filter_kind, sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound +!write(*,*) 'obs_inc_info: ', filter_kind, sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound ! Only need to set these two for options the original RHF implementation !!!rectangular_quadrature = .true. @@ -470,7 +470,7 @@ subroutine assert_qcf_table_version(header) if (.not. qcf_table_listed) return -write(*,*) 'version: ', header(4) +!write(*,*) 'version: ', header(4) if (header(4) /= '1:') then write(errstring,*) "Using outdated/incorrect version of the QCF table" @@ -534,10 +534,10 @@ subroutine log_qcf_table_data() do row = 1, size(qcf_table_data) write(log_msg, *) "qcf_table_row_headers(", row, "): ", qcf_table_row_headers(row) - write(*,*) 'log_msg: ', log_msg + ! print *, 'log_msg: ', log_msg call log_it(log_msg) write(log_msg, *) "qcf_table_data(", row, "): " - write(*,*) 'log_msg: ', log_msg + ! print *, 'log_msg: ', log_msg call log_it(log_msg) write(log_msg, *) qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & @@ -551,7 +551,7 @@ subroutine log_qcf_table_data() qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound - write(*,*) 'e_allmsg: ' + ! print *, 'e_allmsg: ' call error_handler(E_ALLMSG, 'write_qcf_table', log_msg, source) end do From 7e921e00c7201ba4ef9421c94c651ed20366a29f Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 11 Sep 2023 12:43:37 -0600 Subject: [PATCH 031/129] Moving initialize_modules call to be after read of filter_nml --- assimilation_code/modules/assimilation/filter_mod.f90 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assimilation_code/modules/assimilation/filter_mod.f90 b/assimilation_code/modules/assimilation/filter_mod.f90 index 874a4cb1d5..c83a433a8a 100644 --- a/assimilation_code/modules/assimilation/filter_mod.f90 +++ b/assimilation_code/modules/assimilation/filter_mod.f90 @@ -166,7 +166,7 @@ module filter_mod !---------------------------------------------------------------- ! Namelist input with default values ! -character(len = 129) :: qcf_table_filename = 'real_qcf_table.txt' !NEED TO REMOVE THIS LATER +character(len = 129) :: qcf_table_filename = '' logical :: use_algorithm_info_mod = .true. integer :: async = 0, ens_size = 20 integer :: tasks_per_model_advance = 1 @@ -363,13 +363,13 @@ subroutine filter_main() real(r8), allocatable :: prior_qc_copy(:) -call filter_initialize_modules_used() ! static_init_model called in here - ! Read the namelist entry call find_namelist_in_file("input.nml", "filter_nml", iunit) read(iunit, nml = filter_nml, iostat = io) call check_namelist_read(iunit, io, "filter_nml") +call filter_initialize_modules_used() ! static_init_model called in here + ! Record the namelist values used for the run ... if (do_nml_file()) write(nmlfileunit, nml=filter_nml) if (do_nml_term()) write( * , nml=filter_nml) From 73ded1dff1e907108a68b4d97dd85b1af72ab556 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 11 Sep 2023 16:09:51 -0600 Subject: [PATCH 032/129] Adding check that all QTYs in the table exist in DART using get_index_for_quantity; adding checks that upper bounds are greater than lower bounds --- .../assimilation/algorithm_info_mod.f90 | 145 ++++++++---------- 1 file changed, 66 insertions(+), 79 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index f09d3e1656..1555ec5fdb 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -7,9 +7,9 @@ module algorithm_info_mod use types_mod, only : r8, i8, missing_r8 use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance -use obs_kind_mod, only : get_quantity_for_type_of_obs, get_name_for_quantity +use obs_kind_mod, only : get_quantity_for_type_of_obs, get_name_for_quantity, get_index_for_quantity -use utilities_mod, only : error_handler, E_ALLMSG, E_ERR, E_MSG, log_it +use utilities_mod, only : error_handler, E_ALLMSG, E_ERR, E_MSG, log_it, logfileunit use assim_model_mod, only : get_state_meta_data use location_mod, only : location_type @@ -21,6 +21,7 @@ module algorithm_info_mod implicit none private +character(len=2000) :: log_msg character(len=512) :: errstring character(len=*), parameter :: source = 'algorithm_info_mod.f90' @@ -39,8 +40,6 @@ module algorithm_info_mod public :: obs_error_info, probit_dist_info, obs_inc_info, & init_algorithm_info_mod, end_algorithm_info_mod, & - obs_error_info_type, probit_inflation_type, probit_state_type, & - probit_extended_state_type, obs_inc_info_type, qcf_table_data_type, & EAKF, ENKF, BOUNDED_NORMAL_RHF, UNBOUNDED_RHF, GAMMA_FILTER !Creates the type definitions for the QCF table @@ -83,8 +82,11 @@ module algorithm_info_mod type(obs_inc_info_type) :: obs_inc_info end type +character(len=129), dimension(4) :: header1 +character(len=129), dimension(29) :: header2 + +character(len=129), allocatable :: qcf_table_row_headers(:) type(qcf_table_data_type), allocatable :: qcf_table_data(:) -character(len=129), allocatable :: qcf_table_row_headers(:) ! Provides routines that give information about details of algorithms for ! observation error sampling, observation increments, and the transformations @@ -113,8 +115,6 @@ subroutine init_algorithm_info_mod(qcf_table_filename) if (module_initialized) return module_initialized = .true. -!write(*,*) 'filename: ', qcf_table_filename - if (qcf_table_filename == '') then write(*,*) 'No QCF table file listed in namelist, using default values for all QTYs' return @@ -124,7 +124,8 @@ subroutine init_algorithm_info_mod(qcf_table_filename) open(unit=fileid, file=qcf_table_filename) nlines = 0 -do !do loop to get number of rows (or QTY's) in the table +!do loop to get number of rows (or QTY's) in the table +do read(fileid,*,iostat=io) if(io/=0) exit nlines = nlines + 1 @@ -132,17 +133,17 @@ subroutine init_algorithm_info_mod(qcf_table_filename) close(fileid) numrows = nlines - 2 -!print *, 'numrows: ', numrows allocate(qcf_table_data(numrows)) allocate(qcf_table_row_headers(numrows)) call read_qcf_table(qcf_table_filename) -!call verify_qcf_table_data(qcf_table_filename, nlines) !call write_qcf_table() +call assert_qcf_table_version() +call verify_qcf_table_data() call log_qcf_table_data() -!stop +stop !FOR TESTING, REMOVE LATER end subroutine init_algorithm_info_mod @@ -158,9 +159,6 @@ subroutine read_qcf_table(qcf_table_filename) integer, parameter :: fileid = 10 !file identifier integer :: row -character(len=129), dimension(4) :: header1 -character(len=129), dimension(29) :: header2 - if (.not. module_initialized) call init_algorithm_info_mod(qcf_table_filename) open(unit=fileid, file=qcf_table_filename) @@ -168,8 +166,8 @@ subroutine read_qcf_table(qcf_table_filename) ! skip the headers, make sure user is using the correct table version read(fileid, *) header1 read(fileid, *) header2 -!write(*,*) 'header1: ', header1 -!write(*,*) 'header2: ', header2 +write(*,*) 'header1: ', header1 +write(*,*) 'header2: ', header2 ! read in table values directly to qcf_table_data type do row = 1, size(qcf_table_data) @@ -189,8 +187,6 @@ subroutine read_qcf_table(qcf_table_filename) close(fileid) -call assert_qcf_table_version(header1) - end subroutine read_qcf_table !------------------------------------------------------------------------ @@ -380,11 +376,9 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ !get actual name of QTY from integer index kind_name = get_name_for_quantity(obs_kind) -!write(*,*) 'kind_name: ', kind_name !find location of QTY in qcf_table_data structure QTY_loc = findloc(qcf_table_row_headers, kind_name) -!write(*,*) 'findloc of kind: ', QTY_loc(1) if (QTY_loc(1) == 0) then !write(*,*) 'QTY not in table, using default values' @@ -424,7 +418,7 @@ subroutine write_qcf_table() ! write to check values were correctly assigned ! testing for findloc -character(len=30), parameter :: tester_QTY = 'QTY_GPSRO' +character(len=30), parameter :: tester_QTY = 'QTY_STATE_VARIABLE' integer :: QTY_loc(1) character(len=30), parameter :: tester_QTY0 = 'QTY_DUMMY' @@ -450,7 +444,7 @@ subroutine write_qcf_table() end do QTY_loc = findloc(qcf_table_row_headers, tester_QTY) -write(*, *) 'findloc of QTY_GPSRO: ', QTY_loc(1) +write(*, *) 'findloc of QTY_STATE_VARIABLE: ', QTY_loc(1) QTY_loc0 = findloc(qcf_table_row_headers, tester_QTY0) write(*, *) 'findloc of invalid QTY (QTY_DUMMY): ', QTY_loc0(1) @@ -460,19 +454,11 @@ end subroutine write_qcf_table !------------------------------------------------------------------------ -subroutine assert_qcf_table_version(header) +subroutine assert_qcf_table_version() !subroutine to ensure the correct version of the QCF table is being used -character(len=129), dimension(4), intent(in) :: header - -!if (.not. module_initialized) call init_algorithm_info_mod(qcf_table_filename) - -if (.not. qcf_table_listed) return - -!write(*,*) 'version: ', header(4) - -if (header(4) /= '1:') then +if (header1(4) /= '1:') then write(errstring,*) "Using outdated/incorrect version of the QCF table" call error_handler(E_ERR, 'assert_qcf_table_version', errstring, source) endif @@ -482,41 +468,50 @@ end subroutine assert_qcf_table_version !------------------------------------------------------------------------ -subroutine verify_qcf_table_data(qcf_table_filename, nlines) - -!subroutine to ensure that the data in the QCF table is valid and in -!the correct formatthe right format and is correct size +subroutine verify_qcf_table_data() -character(len=129), intent(in) :: qcf_table_filename -integer, intent(in) :: nlines +!subroutine to ensure that the data in the QCF table is valid -character(len=500) :: table_rows(nlines) -integer, parameter :: fileid = 10 !file identifier +integer :: varid integer :: row -if (.not. module_initialized) call init_algorithm_info_mod(qcf_table_filename) +!if (.not. module_initialized) call init_algorithm_info_mod(qcf_table_filename) if (.not. qcf_table_listed) return -open(unit=fileid, file=qcf_table_filename) - -do row = 1, nlines - read(fileid, '(A)') table_rows(row) - print *, 'full line:' - print *, table_rows(row) - print *, 'trimmed line:' - print *, trim(table_rows(row)) - print *, 'length', len_trim(table_rows(row)) +!Checks that all bounds are valid; currently checks that the lower bound in less than the upper +!Here we could add more specific checks if we have known limits on the bounds +do row = 1, size(qcf_table_data) + if(qcf_table_data(row)%obs_error_info%lower_bound > qcf_table_data(row)%obs_error_info%upper_bound) then + write(errstring,*) "Invalid bounds in obs_error_info" + call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) + endif + if(qcf_table_data(row)%probit_inflation%lower_bound > qcf_table_data(row)%probit_inflation%upper_bound) then + write(errstring,*) "Invalid bounds in probit_inflation" + call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) + endif + if(qcf_table_data(row)%probit_state%lower_bound > qcf_table_data(row)%probit_state%upper_bound) then + write(errstring,*) "Invalid bounds in probit_state" + call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) + endif + if(qcf_table_data(row)%probit_extended_state%lower_bound > qcf_table_data(row)%probit_extended_state%upper_bound) then + write(errstring,*) "Invalid bounds in probit_extended_state" + call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) + endif + if(qcf_table_data(row)%obs_inc_info%lower_bound > qcf_table_data(row)%obs_inc_info%upper_bound) then + write(errstring,*) "Invalid bounds in obs_inc_info" + call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) + endif end do -close(fileid) - -!if (size(qcf_table_row_headers) /= 2) then !NO, this needs to be table headers, not row -! write(errstring,*) 'Incorrect number of headers in the QCF table; ' , & -! 'ensure that the latest version of this table is ', & -! 'being used and is in the same format as the example' -! call error_handler(E_ERR, 'assert_qcf_table_version', errstring, source) -!endif +!Ensures that all QTYs listed in the table exist in DART +do row = 1, size(qcf_table_data) + varid = get_index_for_quantity(qcf_table_row_headers(row)) + if(varid == -1) then + write(errstring,*) trim(qcf_table_row_headers(row)), " is not a valid DART QTY" + call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) + endif +end do end subroutine verify_qcf_table_data @@ -527,34 +522,26 @@ subroutine log_qcf_table_data() !subroutine to write the data in QCF table to dart_log -character(len=500) :: log_msg integer :: row if (.not. qcf_table_listed) return +!call error_handler(E_ALLMSG, 'log_qcf_table_data', log_msg, source) +!call log_it(log_msg) + +write(logfileunit, *) header1 +write(logfileunit, *) header2 + do row = 1, size(qcf_table_data) - write(log_msg, *) "qcf_table_row_headers(", row, "): ", qcf_table_row_headers(row) - ! print *, 'log_msg: ', log_msg - call log_it(log_msg) - write(log_msg, *) "qcf_table_data(", row, "): " - ! print *, 'log_msg: ', log_msg - call log_it(log_msg) - write(log_msg, *) qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & - qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & - qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & - qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & - qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & - qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & - qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & - qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & - qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & - qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & - qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound - ! print *, 'e_allmsg: ' - call error_handler(E_ALLMSG, 'write_qcf_table', log_msg, source) + write(*,*) qcf_table_row_headers(row), qcf_table_data(row) end do +!write(log_msg,*) qcf_table_data +!write(*, *) trim(log_msg) +!write(logfileunit, *) trim(log_msg) +!call log_it(trim(log_msg)) +!call error_handler(E_MSG, 'log_qcf_table_data', trim(log_msg), source) + end subroutine log_qcf_table_data !------------------------------------------------------------------------ From 61adbdc66af72ae60025d3ec8645485827d55154 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 11 Sep 2023 16:56:50 -0600 Subject: [PATCH 033/129] Replacing open and close of qcf_table file with open_file and close_file of utilities_mod - this fixes the issue with writing to the dart_log --- .../assimilation/algorithm_info_mod.f90 | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 1555ec5fdb..fbebef9cfb 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -9,7 +9,7 @@ module algorithm_info_mod use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance use obs_kind_mod, only : get_quantity_for_type_of_obs, get_name_for_quantity, get_index_for_quantity -use utilities_mod, only : error_handler, E_ALLMSG, E_ERR, E_MSG, log_it, logfileunit +use utilities_mod, only : error_handler, E_ALLMSG, E_ERR, E_MSG, log_it, logfileunit, open_file, close_file use assim_model_mod, only : get_state_meta_data use location_mod, only : location_type @@ -107,10 +107,11 @@ subroutine init_algorithm_info_mod(qcf_table_filename) character(len=129), intent(in) :: qcf_table_filename +integer :: fileid +integer :: io + integer :: numrows integer :: nlines -integer :: io -integer, parameter :: fileid = 10 !file identifier if (module_initialized) return module_initialized = .true. @@ -121,16 +122,18 @@ subroutine init_algorithm_info_mod(qcf_table_filename) endif qcf_table_listed = .true. -open(unit=fileid, file=qcf_table_filename) nlines = 0 +fileid = open_file(qcf_table_filename, 'formatted', 'read') + !do loop to get number of rows (or QTY's) in the table do read(fileid,*,iostat=io) if(io/=0) exit nlines = nlines + 1 end do -close(fileid) + +call close_file(fileid) numrows = nlines - 2 @@ -156,12 +159,12 @@ subroutine read_qcf_table(qcf_table_filename) character(len=129), intent(in) :: qcf_table_filename -integer, parameter :: fileid = 10 !file identifier +integer :: fileid integer :: row if (.not. module_initialized) call init_algorithm_info_mod(qcf_table_filename) -open(unit=fileid, file=qcf_table_filename) +fileid = open_file(qcf_table_filename, 'formatted', 'read') ! skip the headers, make sure user is using the correct table version read(fileid, *) header1 @@ -185,7 +188,7 @@ subroutine read_qcf_table(qcf_table_filename) qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound end do -close(fileid) +call close_file(fileid) end subroutine read_qcf_table From 58c61e4f1ae2d65762e2855dcac4224d5e231adf Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 11 Sep 2023 17:03:43 -0600 Subject: [PATCH 034/129] Making quotations consistent - using single quote only --- .../assimilation/algorithm_info_mod.f90 | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index fbebef9cfb..650c79f7a1 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -430,8 +430,8 @@ subroutine write_qcf_table() integer :: row do row = 1, size(qcf_table_data) - write(*,*) "qcf_table_row_headers(", row, "): ", qcf_table_row_headers(row) - write(*,*) "qcf_table_data(", row, "): " + write(*,*) 'qcf_table_row_headers(', row, '): ', qcf_table_row_headers(row) + write(*,*) 'qcf_table_data(', row, '): ' write(*,*) qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & @@ -462,7 +462,7 @@ subroutine assert_qcf_table_version() !subroutine to ensure the correct version of the QCF table is being used if (header1(4) /= '1:') then - write(errstring,*) "Using outdated/incorrect version of the QCF table" + write(errstring,*) 'Using outdated/incorrect version of the QCF table' call error_handler(E_ERR, 'assert_qcf_table_version', errstring, source) endif @@ -486,23 +486,23 @@ subroutine verify_qcf_table_data() !Here we could add more specific checks if we have known limits on the bounds do row = 1, size(qcf_table_data) if(qcf_table_data(row)%obs_error_info%lower_bound > qcf_table_data(row)%obs_error_info%upper_bound) then - write(errstring,*) "Invalid bounds in obs_error_info" + write(errstring,*) 'Invalid bounds in obs_error_info' call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) endif if(qcf_table_data(row)%probit_inflation%lower_bound > qcf_table_data(row)%probit_inflation%upper_bound) then - write(errstring,*) "Invalid bounds in probit_inflation" + write(errstring,*) 'Invalid bounds in probit_inflation' call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) endif if(qcf_table_data(row)%probit_state%lower_bound > qcf_table_data(row)%probit_state%upper_bound) then - write(errstring,*) "Invalid bounds in probit_state" + write(errstring,*) 'Invalid bounds in probit_state' call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) endif if(qcf_table_data(row)%probit_extended_state%lower_bound > qcf_table_data(row)%probit_extended_state%upper_bound) then - write(errstring,*) "Invalid bounds in probit_extended_state" + write(errstring,*) 'Invalid bounds in probit_extended_state' call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) endif if(qcf_table_data(row)%obs_inc_info%lower_bound > qcf_table_data(row)%obs_inc_info%upper_bound) then - write(errstring,*) "Invalid bounds in obs_inc_info" + write(errstring,*) 'Invalid bounds in obs_inc_info' call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) endif end do @@ -511,7 +511,7 @@ subroutine verify_qcf_table_data() do row = 1, size(qcf_table_data) varid = get_index_for_quantity(qcf_table_row_headers(row)) if(varid == -1) then - write(errstring,*) trim(qcf_table_row_headers(row)), " is not a valid DART QTY" + write(errstring,*) trim(qcf_table_row_headers(row)), ' is not a valid DART QTY' call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) endif end do From ef28acf4e69ca05105f965540e19efc3c2ade740 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 12 Sep 2023 15:07:22 -0600 Subject: [PATCH 035/129] Adding checks for duplicate QTYs in the table --- .../modules/assimilation/algorithm_info_mod.f90 | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 650c79f7a1..00b3ff651a 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -461,7 +461,7 @@ subroutine assert_qcf_table_version() !subroutine to ensure the correct version of the QCF table is being used -if (header1(4) /= '1:') then +if (header1(4) /= '1') then write(errstring,*) 'Using outdated/incorrect version of the QCF table' call error_handler(E_ERR, 'assert_qcf_table_version', errstring, source) endif @@ -516,6 +516,14 @@ subroutine verify_qcf_table_data() endif end do +!Ensures that there are no duplicate QTYs in the table +do row = 1, size(qcf_table_data) + if(count(qcf_table_row_headers==qcf_table_row_headers(row)) > 1) then + write(errstring,*) trim(qcf_table_row_headers(row)), ' has multiple entries in the table' + call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) + endif +end do + end subroutine verify_qcf_table_data !------------------------------------------------------------------------ From 5721aa7ba762ac9ded672f6af789156abee255e5 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 13 Sep 2023 12:51:03 -0600 Subject: [PATCH 036/129] Switching to real(r8); experimenting in the log_qcf_table subroutine --- .../assimilation/algorithm_info_mod.f90 | 65 ++++++++++++------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 00b3ff651a..5d215f6e2d 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -21,7 +21,6 @@ module algorithm_info_mod implicit none private -character(len=2000) :: log_msg character(len=512) :: errstring character(len=*), parameter :: source = 'algorithm_info_mod.f90' @@ -45,41 +44,41 @@ module algorithm_info_mod !Creates the type definitions for the QCF table type obs_error_info_type logical :: bounded_below, bounded_above - real :: lower_bound, upper_bound + real(r8) :: lower_bound, upper_bound end type type probit_inflation_type integer :: dist_type logical :: bounded_below, bounded_above - real :: lower_bound, upper_bound + real(r8) :: lower_bound, upper_bound end type type probit_state_type integer :: dist_type logical :: bounded_below, bounded_above - real :: lower_bound, upper_bound + real(r8) :: lower_bound, upper_bound end type type probit_extended_state_type integer :: dist_type logical :: bounded_below, bounded_above - real :: lower_bound, upper_bound + real(r8) :: lower_bound, upper_bound end type type obs_inc_info_type - integer :: filter_kind - logical :: rectangular_quadrature, gaussian_likelihood_tails - logical :: sort_obs_inc, spread_restoration - logical :: bounded_below, bounded_above - real :: lower_bound, upper_bound + integer :: filter_kind + logical :: rectangular_quadrature, gaussian_likelihood_tails + logical :: sort_obs_inc, spread_restoration + logical :: bounded_below, bounded_above + real(r8) :: lower_bound, upper_bound end type type qcf_table_data_type - type(obs_error_info_type) :: obs_error_info - type(probit_inflation_type) :: probit_inflation - type(probit_state_type) :: probit_state + type(obs_error_info_type) :: obs_error_info + type(probit_inflation_type) :: probit_inflation + type(probit_state_type) :: probit_state type(probit_extended_state_type) :: probit_extended_state - type(obs_inc_info_type) :: obs_inc_info + type(obs_inc_info_type) :: obs_inc_info end type character(len=129), dimension(4) :: header1 @@ -117,7 +116,8 @@ subroutine init_algorithm_info_mod(qcf_table_filename) module_initialized = .true. if (qcf_table_filename == '') then - write(*,*) 'No QCF table file listed in namelist, using default values for all QTYs' + write(errstring,*) 'No QCF table file listed in namelist, using default values for all QTYs' + call error_handler(E_MSG, 'init_algorithm_info_mod', errstring, source) return endif @@ -144,7 +144,7 @@ subroutine init_algorithm_info_mod(qcf_table_filename) !call write_qcf_table() call assert_qcf_table_version() call verify_qcf_table_data() -call log_qcf_table_data() +!call log_qcf_table_data() stop !FOR TESTING, REMOVE LATER @@ -169,8 +169,8 @@ subroutine read_qcf_table(qcf_table_filename) ! skip the headers, make sure user is using the correct table version read(fileid, *) header1 read(fileid, *) header2 -write(*,*) 'header1: ', header1 -write(*,*) 'header2: ', header2 +!write(*,*) 'header1: ', header1 +!write(*,*) 'header2: ', header2 ! read in table values directly to qcf_table_data type do row = 1, size(qcf_table_data) @@ -533,21 +533,40 @@ subroutine log_qcf_table_data() !subroutine to write the data in QCF table to dart_log +character(len=512) :: log_msg integer :: row +integer :: i if (.not. qcf_table_listed) return !call error_handler(E_ALLMSG, 'log_qcf_table_data', log_msg, source) !call log_it(log_msg) -write(logfileunit, *) header1 -write(logfileunit, *) header2 +!Write the headers to the dart_log and terminal -do row = 1, size(qcf_table_data) - write(*,*) qcf_table_row_headers(row), qcf_table_data(row) +!write(log_msg, *) trim(header1(1)) +do i = 1, size(header1) + write(*,*) trim(header1(i)) + write(log_msg,*) trim(header1(i)) + !log_msg = log_msg//trim(header1(i)) + ! call error_handler(E_MSG, 'log_qcf_table_data', trim(log_msg), source) + write(*, *) trim(log_msg) end do +write(*,*) 'log_msg: ', trim(log_msg) +!write(*,*) trim(log_msg) +!write(log_msg,*) header1 +!call error_handler(E_MSG, 'log_qcf_table_data', trim(log_msg), source) +!write(log_msg, *) header2 +!call error_handler(E_MSG, 'log_qcf_table_data', trim(log_msg), source) + +!Write the data to the dart_log and terminal +!do row = 1, size(qcf_table_data) +! write(log_msg,*) qcf_table_row_headers(row), qcf_table_data(row) +! call error_handler(E_MSG, 'log_qcf_table_data', trim(log_msg), source) +!end do -!write(log_msg,*) qcf_table_data +write(log_msg,*) qcf_table_data +write(*,*) 'log_msg: ', trim(log_msg) !write(*, *) trim(log_msg) !write(logfileunit, *) trim(log_msg) !call log_it(trim(log_msg)) From 9f4a6bd766be5942fc1fcf3bac2149e1d2371ee4 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 13 Sep 2023 17:49:45 -0600 Subject: [PATCH 037/129] reading in character strings from QCF table for filter_kind instead of ints --- .../assimilation/algorithm_info_mod.f90 | 55 +++++++++++++++++-- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 5d215f6e2d..42bdca1acf 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -9,7 +9,7 @@ module algorithm_info_mod use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance use obs_kind_mod, only : get_quantity_for_type_of_obs, get_name_for_quantity, get_index_for_quantity -use utilities_mod, only : error_handler, E_ALLMSG, E_ERR, E_MSG, log_it, logfileunit, open_file, close_file +use utilities_mod, only : error_handler, E_ALLMSG, E_ERR, E_MSG, log_it, logfileunit, open_file, close_file, to_upper use assim_model_mod, only : get_state_meta_data use location_mod, only : location_type @@ -66,7 +66,7 @@ module algorithm_info_mod end type type obs_inc_info_type - integer :: filter_kind + character(len=129) :: filter_kind logical :: rectangular_quadrature, gaussian_likelihood_tails logical :: sort_obs_inc, spread_restoration logical :: bounded_below, bounded_above @@ -141,12 +141,12 @@ subroutine init_algorithm_info_mod(qcf_table_filename) allocate(qcf_table_row_headers(numrows)) call read_qcf_table(qcf_table_filename) -!call write_qcf_table() +call write_qcf_table() call assert_qcf_table_version() call verify_qcf_table_data() !call log_qcf_table_data() -stop !FOR TESTING, REMOVE LATER +!stop !FOR TESTING, REMOVE LATER end subroutine init_algorithm_info_mod @@ -270,6 +270,7 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & real(r8), intent(out) :: lower_bound, upper_bound integer :: QTY_loc(1) +character(len=129) :: dist_type_string character(len=129) :: kind_name ! Have input information about the kind of the state or observation being transformed @@ -316,6 +317,8 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & elseif(is_inflation) then ! Case for inflation transformation +! dist_type_string = to_upper(qcf_table_data(QTY_loc(1))%probit_inflation%dist_type) + dist_type = qcf_table_data(QTY_loc(1))%probit_inflation%dist_type !dist_type has checks in transform_to_probit, transform_from_probit bounded_below = qcf_table_data(QTY_loc(1))%probit_inflation%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%probit_inflation%bounded_above @@ -361,6 +364,11 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ integer :: QTY_loc(1) character(len=129) :: kind_name +integer :: filter_kind_loc(1) +character(len=129), dimension(5) :: possible_filter_kinds +integer, dimension(5) :: possible_filter_kind_ints +character(len=129) :: filter_kind_string + ! The information arguments are all intent (inout). This means that if they are not set ! here, they retain the default values from the assim_tools_mod namelist. Bounds don't exist ! in that namelist, so default values are set in assim_tools_mod just before the call to here. @@ -368,6 +376,23 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ ! Temporary approach for setting the details of how to assimilate this observation ! This example is designed to reproduce the squared forward operator results from paper +! Fill array with possible filter_kind strings +possible_filter_kinds(1) = 'EAKF' +possible_filter_kinds(2) = 'ENKF' +possible_filter_kinds(3) = 'UNBOUNDED_RHF' +possible_filter_kinds(4) = 'GAMMA_FILTER' +possible_filter_kinds(5) = 'BOUNDED_NORMAL_RHF' +write(*,*) 'possible_filter_kinds' +write(*,*) possible_filter_kinds + +possible_filter_kind_ints(1) = 1 +possible_filter_kind_ints(2) = 2 +possible_filter_kind_ints(3) = 8 +possible_filter_kind_ints(4) = 11 +possible_filter_kind_ints(5) = 101 +write(*,*) 'possible_filter_kind_ints' +write(*,*) possible_filter_kind_ints + !use default values if qcf_table_filename is not in namelist if (.not. qcf_table_listed) then filter_kind = BOUNDED_NORMAL_RHF @@ -394,7 +419,25 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ ! Default settings for now for Icepack and tracer model tests (sort_obs_inc, spread_restoration) else - filter_kind = qcf_table_data(QTY_loc(1))%obs_inc_info%filter_kind !filter_kind has a check in obs_increment + + ! Comparing the filter_kind in string format to list of potential filter_kinds + filter_kind_string = qcf_table_data(QTY_loc(1))%obs_inc_info%filter_kind + write(*,*) 'filter_kind_string: ', filter_kind_string + call to_upper(filter_kind_string) + filter_kind_loc = findloc(possible_filter_kinds, trim(filter_kind_string)) + write(*,*) 'filter_kind_string: ', filter_kind_string + + if (filter_kind_loc(1) == 0) then + write(errstring, *) 'Invalid filter_kind' + call error_handler(E_ERR, 'obs_inc_info', errstring, source) + + else + filter_kind = possible_filter_kind_ints(filter_kind_loc(1)) + endif + +! if (filter_kind_string == + + ! filter_kind = qcf_table_data(QTY_loc(1))%obs_inc_info%filter_kind !filter_kind has a check in obs_increment sort_obs_inc = qcf_table_data(QTY_loc(1))%obs_inc_info%sort_obs_inc spread_restoration = qcf_table_data(QTY_loc(1))%obs_inc_info%spread_restoration bounded_below = qcf_table_data(QTY_loc(1))%obs_inc_info%bounded_below @@ -404,7 +447,7 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ endif -!write(*,*) 'obs_inc_info: ', filter_kind, sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound +write(*,*) 'obs_inc_info: ', filter_kind, sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound ! Only need to set these two for options the original RHF implementation !!!rectangular_quadrature = .true. From a1aa775ff1fbfa76b2881068bfee0416921f3fe5 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Thu, 14 Sep 2023 13:34:53 -0600 Subject: [PATCH 038/129] Reading in dist_type from the table as a character string instead of int --- .../assimilation/algorithm_info_mod.f90 | 99 ++++++++++++++++--- 1 file changed, 86 insertions(+), 13 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 42bdca1acf..43cf5a8714 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -48,19 +48,19 @@ module algorithm_info_mod end type type probit_inflation_type - integer :: dist_type + character(len=129) :: dist_type logical :: bounded_below, bounded_above real(r8) :: lower_bound, upper_bound end type type probit_state_type - integer :: dist_type + character(len=129) :: dist_type logical :: bounded_below, bounded_above real(r8) :: lower_bound, upper_bound end type type probit_extended_state_type - integer :: dist_type + character(len=129) :: dist_type logical :: bounded_below, bounded_above real(r8) :: lower_bound, upper_bound end type @@ -270,9 +270,13 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & real(r8), intent(out) :: lower_bound, upper_bound integer :: QTY_loc(1) -character(len=129) :: dist_type_string character(len=129) :: kind_name +integer :: dist_type_loc(1) +character(len=129), dimension(7) :: possible_dist_types +integer, dimension(7) :: possible_dist_type_ints +character(len=129) :: dist_type_string + ! Have input information about the kind of the state or observation being transformed ! along with additional logical info that indicates whether this is an observation ! or state variable and about whether the transformation is being done for inflation @@ -292,6 +296,27 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & ! In the long run, may not have to have separate controls for each of the input possibilities ! However, for now these are things that need to be explored for science understanding +! Fill arrays with possible dist_type strings and corresponding ints +possible_dist_types(1) = 'NORMAL_DISTRIBUTION ' +possible_dist_types(2) = 'BOUNDED_NORMAL_RH_DISTRIBUTION' +possible_dist_types(3) = 'GAMMA_DISTRIBUTION' +possible_dist_types(4) = 'BETA_DISTRIBUTION' +possible_dist_types(5) = 'LOG_NORMAL_DISTRIBUTION' +possible_dist_types(6) = 'UNIFORM_DISTRIBUTION ' +possible_dist_types(7) = 'PARTICLE_FILTER_DISTRIBUTION' +!write(*,*) 'possible_dist_types' +!write(*,*) possible_dist_types + +possible_dist_type_ints(1) = 1 +possible_dist_type_ints(2) = 2 +possible_dist_type_ints(3) = 3 +possible_dist_type_ints(4) = 4 +possible_dist_type_ints(5) = 5 +possible_dist_type_ints(6) = 6 +possible_dist_type_ints(7) = 7 +!write(*,*) 'possible_dist_type_ints' +!write(*,*) possible_dist_type_ints + !use default values if qcf_table_filename is not in namelist if (.not. qcf_table_listed) then dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION @@ -317,32 +342,80 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & elseif(is_inflation) then ! Case for inflation transformation -! dist_type_string = to_upper(qcf_table_data(QTY_loc(1))%probit_inflation%dist_type) + ! Comparing the dist_type in string format to list of potential dist_types + dist_type_string = qcf_table_data(QTY_loc(1))%probit_inflation%dist_type + ! write(*,*) 'dist_type_string: ', dist_type_string + call to_upper(dist_type_string) + dist_type_loc = findloc(possible_dist_types, trim(dist_type_string)) + ! write(*,*) 'dist_type_string: ', dist_type_string + + if (dist_type_loc(1) == 0) then + write(errstring, *) 'Invalid dist_type' + call error_handler(E_ERR, 'probit_dist_info', errstring, source) + + else + dist_type = possible_dist_type_ints(dist_type_loc(1)) + endif - dist_type = qcf_table_data(QTY_loc(1))%probit_inflation%dist_type !dist_type has checks in transform_to_probit, transform_from_probit bounded_below = qcf_table_data(QTY_loc(1))%probit_inflation%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%probit_inflation%bounded_above lower_bound = qcf_table_data(QTY_loc(1))%probit_inflation%lower_bound upper_bound = qcf_table_data(QTY_loc(1))%probit_inflation%upper_bound + write(*,*) 'probit_inflation: ', dist_type, bounded_below, bounded_above, lower_bound, upper_bound + elseif(is_state) then ! Case for state variable priors - dist_type = qcf_table_data(QTY_loc(1))%probit_state%dist_type + ! Comparing the dist_type in string format to list of potential dist_types + dist_type_string = qcf_table_data(QTY_loc(1))%probit_state%dist_type + write(*,*) 'dist_type_string: ', dist_type_string + call to_upper(dist_type_string) + dist_type_loc = findloc(possible_dist_types, trim(dist_type_string)) + write(*,*) 'dist_type_string: ', dist_type_string + + if (dist_type_loc(1) == 0) then + write(errstring, *) 'Invalid dist_type' + call error_handler(E_ERR, 'probit_dist_info', errstring, source) + + else + dist_type = possible_dist_type_ints(dist_type_loc(1)) + endif + + ! dist_type = qcf_table_data(QTY_loc(1))%probit_state%dist_type bounded_below = qcf_table_data(QTY_loc(1))%probit_state%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%probit_state%bounded_above lower_bound = qcf_table_data(QTY_loc(1))%probit_state%lower_bound upper_bound = qcf_table_data(QTY_loc(1))%probit_state%upper_bound + write(*,*) 'probit_state: ', dist_type, bounded_below, bounded_above, lower_bound, upper_bound + else ! This case is for observation (extended state) priors - dist_type = qcf_table_data(QTY_loc(1))%probit_extended_state%dist_type + ! Comparing the dist_type in string format to list of potential dist_types + dist_type_string = qcf_table_data(QTY_loc(1))%probit_extended_state%dist_type + write(*,*) 'dist_type_string: ', dist_type_string + call to_upper(dist_type_string) + dist_type_loc = findloc(possible_dist_types, trim(dist_type_string)) + write(*,*) 'dist_type_string: ', dist_type_string + + if (dist_type_loc(1) == 0) then + write(errstring, *) 'Invalid dist_type' + call error_handler(E_ERR, 'probit_dist_info', errstring, source) + + else + dist_type = possible_dist_type_ints(dist_type_loc(1)) + endif + + ! dist_type = qcf_table_data(QTY_loc(1))%probit_extended_state%dist_type bounded_below = qcf_table_data(QTY_loc(1))%probit_extended_state%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%probit_extended_state%bounded_above lower_bound = qcf_table_data(QTY_loc(1))%probit_extended_state%lower_bound upper_bound = qcf_table_data(QTY_loc(1))%probit_extended_state%upper_bound + write(*,*) 'probit_extended_state: ', dist_type, bounded_below, bounded_above, lower_bound, upper_bound + endif end subroutine probit_dist_info @@ -376,22 +449,22 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ ! Temporary approach for setting the details of how to assimilate this observation ! This example is designed to reproduce the squared forward operator results from paper -! Fill array with possible filter_kind strings +! Fill arrays with possible filter_kind strings and corresponding ints possible_filter_kinds(1) = 'EAKF' possible_filter_kinds(2) = 'ENKF' possible_filter_kinds(3) = 'UNBOUNDED_RHF' possible_filter_kinds(4) = 'GAMMA_FILTER' possible_filter_kinds(5) = 'BOUNDED_NORMAL_RHF' -write(*,*) 'possible_filter_kinds' -write(*,*) possible_filter_kinds +!write(*,*) 'possible_filter_kinds' +!write(*,*) possible_filter_kinds possible_filter_kind_ints(1) = 1 possible_filter_kind_ints(2) = 2 possible_filter_kind_ints(3) = 8 possible_filter_kind_ints(4) = 11 possible_filter_kind_ints(5) = 101 -write(*,*) 'possible_filter_kind_ints' -write(*,*) possible_filter_kind_ints +!write(*,*) 'possible_filter_kind_ints' +!write(*,*) possible_filter_kind_ints !use default values if qcf_table_filename is not in namelist if (.not. qcf_table_listed) then From a24743cfa30a7ea9f80a8ce6ce980b1d00a7649b Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 19 Sep 2023 17:14:57 -0600 Subject: [PATCH 039/129] Fixing log format; cleaning code --- .../assimilation/algorithm_info_mod.f90 | 199 +++++------------- .../modules/assimilation/filter_mod.nml | 1 + 2 files changed, 56 insertions(+), 144 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 43cf5a8714..750ecd2ba9 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -117,16 +117,15 @@ subroutine init_algorithm_info_mod(qcf_table_filename) if (qcf_table_filename == '') then write(errstring,*) 'No QCF table file listed in namelist, using default values for all QTYs' - call error_handler(E_MSG, 'init_algorithm_info_mod', errstring, source) + call error_handler(E_MSG, 'init_algorithm_info_mod:', errstring, source) return endif qcf_table_listed = .true. -nlines = 0 - -fileid = open_file(qcf_table_filename, 'formatted', 'read') +fileid = open_file(trim(qcf_table_filename), 'formatted', 'read') -!do loop to get number of rows (or QTY's) in the table +! Do loop to get number of rows (or QTY's) in the table +nlines = 0 do read(fileid,*,iostat=io) if(io/=0) exit @@ -141,12 +140,9 @@ subroutine init_algorithm_info_mod(qcf_table_filename) allocate(qcf_table_row_headers(numrows)) call read_qcf_table(qcf_table_filename) -call write_qcf_table() call assert_qcf_table_version() call verify_qcf_table_data() -!call log_qcf_table_data() - -!stop !FOR TESTING, REMOVE LATER +call log_qcf_table_data() end subroutine init_algorithm_info_mod @@ -164,13 +160,11 @@ subroutine read_qcf_table(qcf_table_filename) if (.not. module_initialized) call init_algorithm_info_mod(qcf_table_filename) -fileid = open_file(qcf_table_filename, 'formatted', 'read') +fileid = open_file(trim(qcf_table_filename), 'formatted', 'read') -! skip the headers, make sure user is using the correct table version +! skip the headers read(fileid, *) header1 read(fileid, *) header2 -!write(*,*) 'header1: ', header1 -!write(*,*) 'header2: ', header2 ! read in table values directly to qcf_table_data type do row = 1, size(qcf_table_data) @@ -304,8 +298,6 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & possible_dist_types(5) = 'LOG_NORMAL_DISTRIBUTION' possible_dist_types(6) = 'UNIFORM_DISTRIBUTION ' possible_dist_types(7) = 'PARTICLE_FILTER_DISTRIBUTION' -!write(*,*) 'possible_dist_types' -!write(*,*) possible_dist_types possible_dist_type_ints(1) = 1 possible_dist_type_ints(2) = 2 @@ -314,8 +306,6 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & possible_dist_type_ints(5) = 5 possible_dist_type_ints(6) = 6 possible_dist_type_ints(7) = 7 -!write(*,*) 'possible_dist_type_ints' -!write(*,*) possible_dist_type_ints !use default values if qcf_table_filename is not in namelist if (.not. qcf_table_listed) then @@ -332,8 +322,6 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & QTY_loc = findloc(qcf_table_row_headers, kind_name) if (QTY_loc(1) == 0) then - ! write(*,*) 'QTY not in table, using default values' !remove these writes on PR - !use default values if QTY is not in table dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION bounded_below = .false.; bounded_above = .false. @@ -344,14 +332,12 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & ! Comparing the dist_type in string format to list of potential dist_types dist_type_string = qcf_table_data(QTY_loc(1))%probit_inflation%dist_type - ! write(*,*) 'dist_type_string: ', dist_type_string call to_upper(dist_type_string) dist_type_loc = findloc(possible_dist_types, trim(dist_type_string)) - ! write(*,*) 'dist_type_string: ', dist_type_string if (dist_type_loc(1) == 0) then - write(errstring, *) 'Invalid dist_type' - call error_handler(E_ERR, 'probit_dist_info', errstring, source) + write(errstring, *) 'Invalid dist_type: ', trim(dist_type_string) + call error_handler(E_ERR, 'probit_dist_info:', errstring, source) else dist_type = possible_dist_type_ints(dist_type_loc(1)) @@ -362,60 +348,48 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & lower_bound = qcf_table_data(QTY_loc(1))%probit_inflation%lower_bound upper_bound = qcf_table_data(QTY_loc(1))%probit_inflation%upper_bound - write(*,*) 'probit_inflation: ', dist_type, bounded_below, bounded_above, lower_bound, upper_bound - elseif(is_state) then ! Case for state variable priors ! Comparing the dist_type in string format to list of potential dist_types dist_type_string = qcf_table_data(QTY_loc(1))%probit_state%dist_type - write(*,*) 'dist_type_string: ', dist_type_string call to_upper(dist_type_string) dist_type_loc = findloc(possible_dist_types, trim(dist_type_string)) - write(*,*) 'dist_type_string: ', dist_type_string if (dist_type_loc(1) == 0) then - write(errstring, *) 'Invalid dist_type' - call error_handler(E_ERR, 'probit_dist_info', errstring, source) + write(errstring, *) 'Invalid dist_type: ', trim(dist_type_string) + call error_handler(E_ERR, 'probit_dist_info:', errstring, source) else dist_type = possible_dist_type_ints(dist_type_loc(1)) endif - ! dist_type = qcf_table_data(QTY_loc(1))%probit_state%dist_type bounded_below = qcf_table_data(QTY_loc(1))%probit_state%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%probit_state%bounded_above lower_bound = qcf_table_data(QTY_loc(1))%probit_state%lower_bound upper_bound = qcf_table_data(QTY_loc(1))%probit_state%upper_bound - write(*,*) 'probit_state: ', dist_type, bounded_below, bounded_above, lower_bound, upper_bound - else ! This case is for observation (extended state) priors ! Comparing the dist_type in string format to list of potential dist_types dist_type_string = qcf_table_data(QTY_loc(1))%probit_extended_state%dist_type - write(*,*) 'dist_type_string: ', dist_type_string call to_upper(dist_type_string) dist_type_loc = findloc(possible_dist_types, trim(dist_type_string)) - write(*,*) 'dist_type_string: ', dist_type_string if (dist_type_loc(1) == 0) then - write(errstring, *) 'Invalid dist_type' - call error_handler(E_ERR, 'probit_dist_info', errstring, source) + write(errstring, *) 'Invalid dist_type: ', trim(dist_type_string) + call error_handler(E_ERR, 'probit_dist_info:', errstring, source) else dist_type = possible_dist_type_ints(dist_type_loc(1)) endif - ! dist_type = qcf_table_data(QTY_loc(1))%probit_extended_state%dist_type bounded_below = qcf_table_data(QTY_loc(1))%probit_extended_state%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%probit_extended_state%bounded_above lower_bound = qcf_table_data(QTY_loc(1))%probit_extended_state%lower_bound upper_bound = qcf_table_data(QTY_loc(1))%probit_extended_state%upper_bound - write(*,*) 'probit_extended_state: ', dist_type, bounded_below, bounded_above, lower_bound, upper_bound - endif end subroutine probit_dist_info @@ -455,16 +429,12 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ possible_filter_kinds(3) = 'UNBOUNDED_RHF' possible_filter_kinds(4) = 'GAMMA_FILTER' possible_filter_kinds(5) = 'BOUNDED_NORMAL_RHF' -!write(*,*) 'possible_filter_kinds' -!write(*,*) possible_filter_kinds possible_filter_kind_ints(1) = 1 possible_filter_kind_ints(2) = 2 possible_filter_kind_ints(3) = 8 possible_filter_kind_ints(4) = 11 possible_filter_kind_ints(5) = 101 -!write(*,*) 'possible_filter_kind_ints' -!write(*,*) possible_filter_kind_ints !use default values if qcf_table_filename is not in namelist if (.not. qcf_table_listed) then @@ -482,8 +452,6 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ QTY_loc = findloc(qcf_table_row_headers, kind_name) if (QTY_loc(1) == 0) then - !write(*,*) 'QTY not in table, using default values' - !use default values if QTY is not in table filter_kind = BOUNDED_NORMAL_RHF bounded_below = .false.; bounded_above = .false. @@ -495,22 +463,17 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ ! Comparing the filter_kind in string format to list of potential filter_kinds filter_kind_string = qcf_table_data(QTY_loc(1))%obs_inc_info%filter_kind - write(*,*) 'filter_kind_string: ', filter_kind_string call to_upper(filter_kind_string) filter_kind_loc = findloc(possible_filter_kinds, trim(filter_kind_string)) - write(*,*) 'filter_kind_string: ', filter_kind_string if (filter_kind_loc(1) == 0) then - write(errstring, *) 'Invalid filter_kind' - call error_handler(E_ERR, 'obs_inc_info', errstring, source) + write(errstring, *) 'Invalid filter_kind: ', trim(filter_kind_string) + call error_handler(E_ERR, 'obs_inc_info:', errstring, source) else filter_kind = possible_filter_kind_ints(filter_kind_loc(1)) endif -! if (filter_kind_string == - - ! filter_kind = qcf_table_data(QTY_loc(1))%obs_inc_info%filter_kind !filter_kind has a check in obs_increment sort_obs_inc = qcf_table_data(QTY_loc(1))%obs_inc_info%sort_obs_inc spread_restoration = qcf_table_data(QTY_loc(1))%obs_inc_info%spread_restoration bounded_below = qcf_table_data(QTY_loc(1))%obs_inc_info%bounded_below @@ -520,8 +483,6 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ endif -write(*,*) 'obs_inc_info: ', filter_kind, sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound - ! Only need to set these two for options the original RHF implementation !!!rectangular_quadrature = .true. !!!gaussian_likelihood_tails = .false. @@ -531,55 +492,13 @@ end subroutine obs_inc_info !------------------------------------------------------------------------ -subroutine write_qcf_table() - -! DRAFT SUBROUTINE -! write to check values were correctly assigned -! testing for findloc - -character(len=30), parameter :: tester_QTY = 'QTY_STATE_VARIABLE' -integer :: QTY_loc(1) - -character(len=30), parameter :: tester_QTY0 = 'QTY_DUMMY' -integer :: QTY_loc0(1) - -integer :: row - -do row = 1, size(qcf_table_data) - write(*,*) 'qcf_table_row_headers(', row, '): ', qcf_table_row_headers(row) - write(*,*) 'qcf_table_data(', row, '): ' - write(*,*) qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & - qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & - qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & - qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & - qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & - qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & - qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & - qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & - qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & - qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & - qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound -end do - -QTY_loc = findloc(qcf_table_row_headers, tester_QTY) -write(*, *) 'findloc of QTY_STATE_VARIABLE: ', QTY_loc(1) - -QTY_loc0 = findloc(qcf_table_row_headers, tester_QTY0) -write(*, *) 'findloc of invalid QTY (QTY_DUMMY): ', QTY_loc0(1) - -end subroutine write_qcf_table - -!------------------------------------------------------------------------ - - subroutine assert_qcf_table_version() -!subroutine to ensure the correct version of the QCF table is being used +! Subroutine to ensure the correct version of the QCF table is being used -if (header1(4) /= '1') then +if (trim(header1(4)) /= '1') then write(errstring,*) 'Using outdated/incorrect version of the QCF table' - call error_handler(E_ERR, 'assert_qcf_table_version', errstring, source) + call error_handler(E_ERR, 'assert_qcf_table_version:', errstring, source) endif end subroutine assert_qcf_table_version @@ -589,13 +508,11 @@ end subroutine assert_qcf_table_version subroutine verify_qcf_table_data() -!subroutine to ensure that the data in the QCF table is valid +! Subroutine to ensure that the data in the QCF table is valid integer :: varid integer :: row -!if (.not. module_initialized) call init_algorithm_info_mod(qcf_table_filename) - if (.not. qcf_table_listed) return !Checks that all bounds are valid; currently checks that the lower bound in less than the upper @@ -603,40 +520,40 @@ subroutine verify_qcf_table_data() do row = 1, size(qcf_table_data) if(qcf_table_data(row)%obs_error_info%lower_bound > qcf_table_data(row)%obs_error_info%upper_bound) then write(errstring,*) 'Invalid bounds in obs_error_info' - call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) + call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) endif if(qcf_table_data(row)%probit_inflation%lower_bound > qcf_table_data(row)%probit_inflation%upper_bound) then write(errstring,*) 'Invalid bounds in probit_inflation' - call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) + call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) endif if(qcf_table_data(row)%probit_state%lower_bound > qcf_table_data(row)%probit_state%upper_bound) then write(errstring,*) 'Invalid bounds in probit_state' - call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) + call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) endif if(qcf_table_data(row)%probit_extended_state%lower_bound > qcf_table_data(row)%probit_extended_state%upper_bound) then write(errstring,*) 'Invalid bounds in probit_extended_state' - call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) + call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) endif if(qcf_table_data(row)%obs_inc_info%lower_bound > qcf_table_data(row)%obs_inc_info%upper_bound) then write(errstring,*) 'Invalid bounds in obs_inc_info' - call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) + call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) endif end do !Ensures that all QTYs listed in the table exist in DART do row = 1, size(qcf_table_data) - varid = get_index_for_quantity(qcf_table_row_headers(row)) + varid = get_index_for_quantity(trim(qcf_table_row_headers(row))) if(varid == -1) then write(errstring,*) trim(qcf_table_row_headers(row)), ' is not a valid DART QTY' - call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) + call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) endif end do !Ensures that there are no duplicate QTYs in the table do row = 1, size(qcf_table_data) - if(count(qcf_table_row_headers==qcf_table_row_headers(row)) > 1) then + if(count(qcf_table_row_headers==trim(qcf_table_row_headers(row))) > 1) then write(errstring,*) trim(qcf_table_row_headers(row)), ' has multiple entries in the table' - call error_handler(E_ERR, 'verify_qcf_table_data', errstring, source) + call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) endif end do @@ -647,46 +564,40 @@ end subroutine verify_qcf_table_data subroutine log_qcf_table_data() -!subroutine to write the data in QCF table to dart_log - -character(len=512) :: log_msg +! Subroutine to write the data in QCF table to dart_log +character(len=2000) :: log_msg integer :: row -integer :: i if (.not. qcf_table_listed) return -!call error_handler(E_ALLMSG, 'log_qcf_table_data', log_msg, source) -!call log_it(log_msg) +call error_handler(E_MSG, '', '', source) !Writing blank line to log +call error_handler(E_MSG, 'log_qcf_table_data:', 'Logging the data in the QCF Table', source) + +! Write the table headers to the dart_log and terminal +write(log_msg, '(A4, A6, A9, A)') header1(:) +call error_handler(E_MSG, 'log_qcf_table_data:', trim(log_msg), source) -!Write the headers to the dart_log and terminal +write(log_msg,'(3A14, 2A12, 3(A10, 2A14, 2A12), A12, A23, A26, A13, A19, 2A14, 2A12)') header2(:) +call error_handler(E_MSG, 'log_qcf_table_data:', trim(log_msg), source) -!write(log_msg, *) trim(header1(1)) -do i = 1, size(header1) - write(*,*) trim(header1(i)) - write(log_msg,*) trim(header1(i)) - !log_msg = log_msg//trim(header1(i)) - ! call error_handler(E_MSG, 'log_qcf_table_data', trim(log_msg), source) - write(*, *) trim(log_msg) +! Write the table data to the dart_log and terminal +do row = 1, size(qcf_table_data) + write(log_msg, *) trim(qcf_table_row_headers(row)), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & + qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, trim(qcf_table_data(row)%probit_inflation%dist_type), & + qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & + qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, trim(qcf_table_data(row)%probit_state%dist_type), & + qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & + qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, trim(qcf_table_data(row)%probit_extended_state%dist_type), & + qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & + qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & + trim(qcf_table_data(row)%obs_inc_info%filter_kind), qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & + qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & + qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & + qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound +call error_handler(E_MSG, 'log_qcf_table_data:', trim(log_msg), source) end do -write(*,*) 'log_msg: ', trim(log_msg) -!write(*,*) trim(log_msg) -!write(log_msg,*) header1 -!call error_handler(E_MSG, 'log_qcf_table_data', trim(log_msg), source) -!write(log_msg, *) header2 -!call error_handler(E_MSG, 'log_qcf_table_data', trim(log_msg), source) - -!Write the data to the dart_log and terminal -!do row = 1, size(qcf_table_data) -! write(log_msg,*) qcf_table_row_headers(row), qcf_table_data(row) -! call error_handler(E_MSG, 'log_qcf_table_data', trim(log_msg), source) -!end do - -write(log_msg,*) qcf_table_data -write(*,*) 'log_msg: ', trim(log_msg) -!write(*, *) trim(log_msg) -!write(logfileunit, *) trim(log_msg) -!call log_it(trim(log_msg)) -!call error_handler(E_MSG, 'log_qcf_table_data', trim(log_msg), source) + +call error_handler(E_MSG, '', '', source) !Writing blank line to log end subroutine log_qcf_table_data diff --git a/assimilation_code/modules/assimilation/filter_mod.nml b/assimilation_code/modules/assimilation/filter_mod.nml index 362138fc5f..79611257bf 100644 --- a/assimilation_code/modules/assimilation/filter_mod.nml +++ b/assimilation_code/modules/assimilation/filter_mod.nml @@ -1,4 +1,5 @@ &filter_nml + qcf_table_filename = '' use_algorithm_info_mod = .true., single_file_in = .false., input_state_files = '' From fee096986f3b67f8d60d3bfc645743c01d697f01 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 25 Sep 2023 11:09:02 -0600 Subject: [PATCH 040/129] Removing unnecessary files --- .../modules/assimilation/cam_qcf_table.txt | 10 -- qcf_table/type_read_table.f90 | 129 ------------------ 2 files changed, 139 deletions(-) delete mode 100644 assimilation_code/modules/assimilation/cam_qcf_table.txt delete mode 100644 qcf_table/type_read_table.f90 diff --git a/assimilation_code/modules/assimilation/cam_qcf_table.txt b/assimilation_code/modules/assimilation/cam_qcf_table.txt deleted file mode 100644 index 56e205a534..0000000000 --- a/assimilation_code/modules/assimilation/cam_qcf_table.txt +++ /dev/null @@ -1,10 +0,0 @@ -QCF table version 1: -QTY bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound -QTY_U_WIND_COMPONENT, .false. .false. 3 4 5 .false. .false. 8 9 10 .false. .false. 13 14 15 .false. .false. 18 19 20 .false. .false. .false. .false. .false. .false. 27 28 -QTY_V_WIND_COMPONENT, .false. .false. 3 4 5 .false. .false. 8 9 10 .false. .false. 13 14 15 .false. .false. 18 19 20 .false. .false. .false. .false. .false. .false. 27 28 -QTY_SURFACE_PRESSURE .false. .false. 3 4 5 .false. .false. 8 9 10 .false. .false. 13 14 15 .false. .false. 18 19 20 .false. .false. .false. .false. .false. .false. 27 28 -QTY_TEMPERATURE .false. .false. 3 4 5 .false. .false. 8 9 10 .false. .false. 13 14 15 .false. .false. 18 19 20 .false. .false. .false. .false. .false. .false. 27 28 -QTY_SPECIFIC_HUMIDITY .false. .false. 3 4 5 .false. .false. 8 9 10 .false. .false. 13 14 15 .false. .false. 18 19 20 .false. .false. .false. .false. .false. .false. 27 28 -QTY_CLOUD_LIQUID_WATER .false. .false. 3 4 5 .false. .false. 8 9 10 .false. .false. 13 14 15 .false. .false. 18 19 20 .false. .false. .false. .false. .false. .false. 27 28 -QTY_CLOUD_ICE .false. .false. 3 4 5 .false. .false. 8 9 10 .false. .false. 13 14 15 .false. .false. 18 19 20 .false. .false. .false. .false. .false. .false. 27 28 -QTY_GPSRO .false. .false. 3 4 5 .false. .false. 8 9 10 .false. .false. 13 14 15 .false. .false. 18 19 20 .false. .false. .false. .false. .false. .false. 27 28 diff --git a/qcf_table/type_read_table.f90 b/qcf_table/type_read_table.f90 deleted file mode 100644 index f7cd548acf..0000000000 --- a/qcf_table/type_read_table.f90 +++ /dev/null @@ -1,129 +0,0 @@ -program read_table - -implicit none -type obs_error_info_type - logical :: bounded_below, bounded_above - real :: lower_bound, upper_bound -end type - -type probit_inflation_type - integer :: dist_type - logical :: bounded_below, bounded_above - real :: lower_bound, upper_bound -end type - -type probit_state_type - integer :: dist_type - logical :: bounded_below, bounded_above - real :: lower_bound, upper_bound -end type - -type probit_extended_state_type - integer :: dist_type - logical :: bounded_below, bounded_above - real :: lower_bound, upper_bound -end type - -type obs_inc_info_type - integer :: filter_kind - logical :: rectangular_quadrature, gaussian_likelihood_tails - logical :: sort_obs_inc, spread_restoration - logical :: bounded_below, bounded_above - real :: lower_bound, upper_bound -end type - -type qcf_table_data_type - type(obs_error_info_type) :: obs_error_info - type(probit_inflation_type) :: probit_inflation - type(probit_state_type) :: probit_state - type(probit_extended_state_type) :: probit_extended_state - type(obs_inc_info_type) :: obs_inc_info -end type - -! Reads in the QCEFF input options from tabular data file -!character(len=50), intent(in) :: qcf_table_filename -!real(r8), intent(out) :: qcf_table_data -!real, dimension(:, :), allocatable :: qcf_table_data_rows -type(qcf_table_data_type), allocatable :: qcf_table_data(:) -character(len=129), dimension(:), allocatable :: rowheaders !!!!! might need to change len=30 - -integer, parameter :: fileid = 10 !file identifier -character(len=30), parameter :: tester_QTY = 'QTY_GPSRO' -integer :: QTY_loc(1) - -!integer, parameter :: num_columns = 28 -integer :: nlines -integer :: io -integer :: numrows -integer :: row - -!real, dimension(1:num_columns, 1:num_rows) :: table_data -!integer :: table_data_1, table_data_2 -character(len=30), dimension(4) :: header1 -character(len=30), dimension(29) :: header2 -!variables for table values ^^^ - -open(unit=fileid, file='cam_qcf_table.txt') -nlines = 0 - -do !do loop to get number of rows (or QTY's) in the table - read(fileid,*,iostat=io) - if(io/=0) exit - nlines = nlines + 1 -end do -close(fileid) - -print*, nlines - -numrows = nlines - 2 -print *, 'numrows: ', numrows - -allocate(qcf_table_data(numrows)) -allocate(rowheaders(numrows)) -write(*,*) shape(qcf_table_data) - -open(unit=fileid, file='cam_qcf_table.txt') - -read(fileid, *) header1 -read(fileid, *) header2 !! skip the headers -Write(*, *) "header1: ", header1 -Write(*, *) "header2: ", header2 - -do row = 1, numrows - read(fileid, *) rowheaders(row), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & - qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & - qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & - qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & - qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & - qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & - qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & - qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & - qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & - qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & - qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound - - write(*, *) "rowheader(", row, "): ", rowheaders(row) - write(*, *) "qcf_table_data(", row, "): " - write(*, *) qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & - qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & - qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & - qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & - qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & - qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & - qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & - qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & - qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & - qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & - qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound -end do - -close(fileid) - -QTY_loc = findloc(rowheaders, tester_QTY) -write(*, *) 'findloc of GPSRO: ', QTY_loc(1) - -deallocate(qcf_table_data, rowheaders) - -end program read_table From b97ff55b8b3bef066f190f63f14228b295ced4bf Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 25 Sep 2023 11:15:38 -0600 Subject: [PATCH 041/129] Adding the yaml_to_table.py script and example yaml file qcf_table_template.yaml to the DART repo at /DART/assimilation_code/programs/qcf_table/. The location of these files in the repo may change --- .../qcf_table/qcf_table_template.yaml | 103 ++++++++++++++++++ .../programs/qcf_table/yaml_to_table.py | 77 +++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 assimilation_code/programs/qcf_table/qcf_table_template.yaml create mode 100644 assimilation_code/programs/qcf_table/yaml_to_table.py diff --git a/assimilation_code/programs/qcf_table/qcf_table_template.yaml b/assimilation_code/programs/qcf_table/qcf_table_template.yaml new file mode 100644 index 0000000000..c2a62d9eb5 --- /dev/null +++ b/assimilation_code/programs/qcf_table/qcf_table_template.yaml @@ -0,0 +1,103 @@ +QCF table version: 1 +QTY_TEMPLATE: + obs_error_info: + bounded_below + bounded_above + lower_bound + upper_bound + probit_inflation: + dist_type + bounded_below + bounded_above + lower_bound + upper_bound + probit_state: + dist_type + bounded_below + bounded_above + lower_bound + upper_bound + probit_extended_state: + dist_type + bounded_below + bounded_above + lower_bound + upper_bound + obs_inc_info: + filter_kind + rectangular_quadrature + gaussian_likelihood_tails + sort_obs_inc + spread_restoration + bounded_below + bounded_above + lower_bound + upper_bound +QTY_STATE_VARIABLE: + obs_error_info: + bounded_below: .false. + bounded_above: .false. + lower_bound: -888888.0 + upper_bound: -888888.0 + probit_inflation: + dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION + bounded_below: .false. + bounded_above: .false. + lower_bound: -888888.0 + upper_bound: -888888.0 + probit_state: + dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION + bounded_below: .false. + bounded_above: .false. + lower_bound: -888888.0 + upper_bound: -888888.0 + probit_extended_state: + dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION + bounded_below: .false. + bounded_above: .false. + lower_bound: -888888.0 + upper_bound: -888888.0 + obs_inc_info: + filter_kind: BOUNDED_NORMAL_RHF + rectangular_quadrature: .false. + gaussian_likelihood_tails: .false. + sort_obs_inc: .false. + spread_restoration: .false. + bounded_below: .false. + bounded_above: .false. + lower_bound: -888888.0 + upper_bound: -888888.0 +QTY_TRACER_SOURCE: + obs_error_info: + bounded_below: .false. + bounded_above: .false. + lower_bound: -888888.0 + upper_bound: -888888.0 + probit_inflation: + dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION + bounded_below: .false. + bounded_above: .false. + lower_bound: -888888.0 + upper_bound: -888888.0 + probit_state: + dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION + bounded_below: .false. + bounded_above: .false. + lower_bound: -888888.0 + upper_bound: -888888.0 + probit_extended_state: + dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION + bounded_below: .false. + bounded_above: .false. + lower_bound: -888888.0 + upper_bound: -888888.0 + obs_inc_info: + filter_kind: BOUNDED_NORMAL_RHF + rectangular_quadrature: .false. + gaussian_likelihood_tails: .false. + sort_obs_inc: .false. + spread_restoration: .false. + bounded_below: .false. + bounded_above: .false. + lower_bound: -888888.0 + upper_bound: -888888.0 diff --git a/assimilation_code/programs/qcf_table/yaml_to_table.py b/assimilation_code/programs/qcf_table/yaml_to_table.py new file mode 100644 index 0000000000..fc765e7c36 --- /dev/null +++ b/assimilation_code/programs/qcf_table/yaml_to_table.py @@ -0,0 +1,77 @@ +import yaml + +#Prompt user for name of input and output files +input_yaml = input('Please enter the name of your input yaml file (filename must end in ".yaml") OR press enter/return to use the default filename "qcf_table.yaml"\n') +output_txt = input('Please enter the name for the output file for the table (filename must end in ".txt") OR press enter/return to use the default filename "qcf_table.txt"\n') + +#Using deault names for input/output files if not specified +if (input_yaml == ''): + input_yaml = 'qcf_table.yaml' + +if (output_txt == ''): + output_txt = 'qcf_table.txt' + +#Open and load yaml file +with open(input_yaml) as file: + dict = yaml.safe_load(file) + + column_headers = list(dict.keys()) + column_data = list(dict.values()) + + obs_errror_info_header = dict['QTY_TEMPLATE']['obs_error_info'] + probit_inflation_header = dict['QTY_TEMPLATE']['probit_inflation'] + probit_state_header = dict['QTY_TEMPLATE']['probit_state'] + probit_extended_state_header = dict['QTY_TEMPLATE']['probit_extended_state'] + obs_inc_info_header = dict['QTY_TEMPLATE']['obs_inc_info'] + + f = open(output_txt, "w") + +#Write the table's headers to the output file + f.write(column_headers[0] + ": " + str(column_data[0]) + "\n") + + f.write(column_headers[1] + ": ") + for name in obs_errror_info_header: + f.write(name) + f.write(" ") + for name in probit_inflation_header: + f.write(name) + f.write(" ") + for name in probit_state_header: + f.write(name) + f.write(" ") + for name in probit_extended_state_header: + f.write(name) + f.write(" ") + for name in obs_inc_info_header: + f.write(name) + f.write("\n") + +#Writing table data to the output file + for i in range(2, len(column_headers)): + f.write(column_headers[i] + " ") + + obs_error_info = dict[column_headers[i]]['obs_error_info'].items() + for key, value in obs_error_info: + f.write(str(value) + " ") + + probit_inflation = dict[column_headers[i]]['probit_inflation'].items() + for key, value in probit_inflation: + f.write(str(value) + " ") + + probit_state = dict[column_headers[i]]['probit_state'].items() + for key, value in probit_state: + f.write(str(value) + " ") + + probit_extended_state = dict[column_headers[i]]['probit_extended_state'].items() + for key, value in probit_extended_state: + f.write(str(value) + " ") + + obs_inc_info = dict[column_headers[i]]['obs_inc_info'].items() + for key, value in obs_inc_info: + f.write(str(value) + " ") + + f.write("\n") + + f.close + +print('QCF table produced in ' + output_txt) From cba8c143912e176c5669b69b97be86f355ff3ed2 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 25 Sep 2023 11:20:49 -0600 Subject: [PATCH 042/129] Fixing deallocation by adding conditional to check if data types were allocated --- .../modules/assimilation/algorithm_info_mod.f90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 750ecd2ba9..47c8f3f844 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -607,12 +607,13 @@ end subroutine log_qcf_table_data subroutine end_algorithm_info_mod() if (.not. module_initialized) return +module_initialized = .false. + +if (.not. qcf_table_listed) return deallocate(qcf_table_data) deallocate(qcf_table_row_headers) -module_initialized = .false. - end subroutine end_algorithm_info_mod !---------------------------------------------------------------------- From eb6e97e9ae4c52bb1aff8aaf2b07d51005a4a36b Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 25 Sep 2023 15:42:22 -0600 Subject: [PATCH 043/129] Adjusting the YAML template file; removing trailing spaces from possible_dist_types strings --- .../assimilation/algorithm_info_mod.f90 | 4 +-- .../qcf_table/qcf_table_template.yaml | 34 ------------------- 2 files changed, 2 insertions(+), 36 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 47c8f3f844..dbe9027985 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -291,12 +291,12 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & ! However, for now these are things that need to be explored for science understanding ! Fill arrays with possible dist_type strings and corresponding ints -possible_dist_types(1) = 'NORMAL_DISTRIBUTION ' +possible_dist_types(1) = 'NORMAL_DISTRIBUTION' possible_dist_types(2) = 'BOUNDED_NORMAL_RH_DISTRIBUTION' possible_dist_types(3) = 'GAMMA_DISTRIBUTION' possible_dist_types(4) = 'BETA_DISTRIBUTION' possible_dist_types(5) = 'LOG_NORMAL_DISTRIBUTION' -possible_dist_types(6) = 'UNIFORM_DISTRIBUTION ' +possible_dist_types(6) = 'UNIFORM_DISTRIBUTION' possible_dist_types(7) = 'PARTICLE_FILTER_DISTRIBUTION' possible_dist_type_ints(1) = 1 diff --git a/assimilation_code/programs/qcf_table/qcf_table_template.yaml b/assimilation_code/programs/qcf_table/qcf_table_template.yaml index c2a62d9eb5..46b46358af 100644 --- a/assimilation_code/programs/qcf_table/qcf_table_template.yaml +++ b/assimilation_code/programs/qcf_table/qcf_table_template.yaml @@ -67,37 +67,3 @@ QTY_STATE_VARIABLE: bounded_above: .false. lower_bound: -888888.0 upper_bound: -888888.0 -QTY_TRACER_SOURCE: - obs_error_info: - bounded_below: .false. - bounded_above: .false. - lower_bound: -888888.0 - upper_bound: -888888.0 - probit_inflation: - dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below: .false. - bounded_above: .false. - lower_bound: -888888.0 - upper_bound: -888888.0 - probit_state: - dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below: .false. - bounded_above: .false. - lower_bound: -888888.0 - upper_bound: -888888.0 - probit_extended_state: - dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below: .false. - bounded_above: .false. - lower_bound: -888888.0 - upper_bound: -888888.0 - obs_inc_info: - filter_kind: BOUNDED_NORMAL_RHF - rectangular_quadrature: .false. - gaussian_likelihood_tails: .false. - sort_obs_inc: .false. - spread_restoration: .false. - bounded_below: .false. - bounded_above: .false. - lower_bound: -888888.0 - upper_bound: -888888.0 From 22931cf0a9eae29a2aad625728c8b00a84043140 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 25 Sep 2023 17:28:21 -0600 Subject: [PATCH 044/129] Adding documentaion file to repo --- guide/qcf_table.rst | 227 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 guide/qcf_table.rst diff --git a/guide/qcf_table.rst b/guide/qcf_table.rst new file mode 100644 index 0000000000..113bffee9a --- /dev/null +++ b/guide/qcf_table.rst @@ -0,0 +1,227 @@ +.. _QCF Table: + +############################################ +Using the QCF Table to Control Input Options +############################################ + +This file contains instructions for using an input table to set input options with the DART quantile conserving and probit transform filtering tools. +See the following link to learn more about these tools and how to use them: +https://docs.dart.ucar.edu/en/quantile_methods/models/lorenz_96_tracer_advection/work/readme.html + +Using this input table allows the user to specify the control options for the Quantile Conserving Filter (QCF), also known as the Quantile Conserving Ensemble Filtering Framework (QCEFF). The observation, state, and inflation variables are all included in this single table. + +The new quantile options are read in from the table at runtime and then set in the module algorithm_info_mod.f90 in the DART/assimilation_code/modules/assimilation directory. This module provides routines that give information about details of algorithms for observation error sampling, observation increments, and the transformations for regression and inflation in probit space. + +For individual QTYs in DART, the user can specify the options such as the bounds, distribution type, filter kind, etc. for the obs_error_info, probit_dist_info, and obs_inc_info subroutines in algorithm_info_mod.f90 + +If the user does not use a QCF input table with the DART quantile conserving and probit transform filtering tools, then the default values for these options will be used for all QTYs. + +Table Composition +----------------- +Each QTY is specified in its own column, having 28 total control options. +These control options are divided into 3 main groups, which are the options used for the obs_error_info, probit_dist_info, and obs_inc_info. However, the user is able to specify different values for probit inflation, probit state, and probit extended state, resulting in 5 total groupings for the control options. + +The obs_error_info subroutine computes information needed to compute error sample for this observation. +For obs_error_info the input options are the two bounds (lower and upper). + +The probit_dist_info subroutine computes the details of the probit transform. +From probit_dist_info, the values needed are the bounds and the distribution type. These can be different for all three cases (inflation, state, and extended_state). + +The obs_inc_info subrotuine sets the details of how to assimilate this observation. +From obs_inc_info, the bounds, plus the filter_kind, rectangular_quadrature, gaussian_likelihood_tails, sort_obs_inc, and spread_restoration are needed. However, rectangular_quadrature and gaussian_likelihood_tails are only applicable with RHF. + +Full list of options: +Obs_error_info: bounded_below, bounded_above, lower_bound, upper_bound [4 columns] +Probit_dist_info: dist_type, bounded_below, bounded_above, lower_bound, upper_bound (x3 for inflation, state, and observation (extended state) priors) [15 columns] +Obs_inc_info: filter_kind, rectangular_quadrature, gaussian_likelihood_tails, sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound [9 columns] + +Customizing the Table +--------------------- +The table can be customized by either editing a YAML file (which is then converted to a tabular data file in .txt format by a Python script) or a Google Sheet spreadsheet (which is then downloaded in .csv format). The specifics of how to manually edit both formats will be detailed in the following sections. + +Regardless of which of these formats are used, the table consists of two headers. The first states the version # of the table being used; the most recent version of the table needs to be used to ensure compatibilty with DART. The current version # is 1. The second header lists the full set of input options, or all 28 column names in other words. + +Generally, the user will add and fill in one row for each bounded QTY. If a QTY is not listed in the table, the default values will be used for all 28 options. Therefore, the user will only need to add rows for QTYs that use non-default values for any of the input options. ** + +The majority of the input options are read in as logicals, and will need to be written in the format of either 'F' or '.false.' These include bounded_below, bounded_above, rectangular_quadrature, gaussian_likelihood_tails, sort_obs_inc, and spread_restoration. + +The actual numerical values of the bounds are read in as real_r8 types. These can be specified as reals or integers in the table. + +dist_type and filter_kind are read in as strings, which the possible values for are listed below: + +dist_type: +NORMAL_DISTRIBUTION +BOUNDED_NORMAL_RH_DISTRIBUTION +GAMMA_DISTRIBUTION +BETA_DISTRIBUTION +LOG_NORMAL_DISTRIBUTION +UNIFORM_DISTRIBUTION +PARTICLE_FILTER_DISTRIBUTION + +filter_kind: +EAKF +ENKF +UNBOUNDED_RHF +GAMMA_FILTER +BOUNDED_NORMAL_RHF + +The default values for each of the options are listed below: +bounded_below = .false. +bounded_above = .false. +lower_bound = -888888 +upper_bound = -888888 +dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION +filter_kind = BOUNDED_NORMAL_RHF +rectangular_quadrature = .false. +gaussian_likelihood_tails = .false. +sort_obs_inc = .false. +spread_restoration = .false. + +Note that bounds set to -888888 are missing_r8 values. + +YAML File Usage +--------------- +This section will detail how to customize the qcf_table_template.yaml file and then utilize the yaml_to_table.py Python script to convert the YAML dictionary into a table in .txt format. + +First, the user needs to access YAML template file, located in DART/assimilation/programs/qcf_table/ +This template file is then to be copied into another file. You can name this anything, but the standard name is 'qcf_table.yaml'. + +.. code:: + cp qcf_table_template.yaml qcf_table.yaml + +The YAML file needs to match the formatting in qcf_table_template.yaml, which is as follows: + +:: + + QCF table version: 1 + QTY_TEMPLATE: + obs_error_info: + bounded_below + bounded_above + lower_bound + upper_bound + probit_inflation: + dist_type + bounded_below + bounded_above + lower_bound + upper_bound + probit_state: + dist_type + bounded_below + bounded_above + lower_bound + upper_bound + probit_extended_state: + dist_type + bounded_below + bounded_above + lower_bound + upper_bound + obs_inc_info: + filter_kind + rectangular_quadrature + gaussian_likelihood_tails + sort_obs_inc + spread_restoration + bounded_below + bounded_above + lower_bound + upper_bound + QTY_STATE_VARIABLE: + obs_error_info: + bounded_below: .false. + bounded_above: .false. + lower_bound: -888888.0 + upper_bound: -888888.0 + probit_inflation: + dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION + bounded_below: .false. + bounded_above: .false. + lower_bound: -888888.0 + upper_bound: -888888.0 + probit_state: + dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION + bounded_below: .false. + bounded_above: .false. + lower_bound: -888888.0 + upper_bound: -888888.0 + probit_extended_state: + dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION + bounded_below: .false. + bounded_above: .false. + lower_bound: -888888.0 + upper_bound: -888888.0 + obs_inc_info: + filter_kind: BOUNDED_NORMAL_RHF + rectangular_quadrature: .false. + gaussian_likelihood_tails: .false. + sort_obs_inc: .false. + spread_restoration: .false. + bounded_below: .false. + bounded_above: .false. + lower_bound: -888888.0 + upper_bound: -888888.0 + +To customize the YAML dictionary file, the user should change the name 'QTY_STATE_VARIABLE' to the name of the first QTY to be specified with non-default values. Edit the values for the vairables wanting to be changed, and leave the rest of the variables set to the default values. + +To add additional QTYs after this, simply copy the lines pertaining to first QTY, change the name of the QTY, and set the variables accordingly. + +To remove a QTY from the YAML dictionary, simply remove the lines it consists of. + +The user will then take their customized YAML file and pass it as input into a Python script. This will convert it into a text file contaning the table data. + +This script is located in DART/assimilation/programs/qcf_table/ + +To use the Python script on Derecho or Cheyenne, the user must first load the correct modules + +:: + + module load conda + conda activate npl + +Then run the python script. + +:: + + python3 yaml_to_table.py + +The user will be prompted to enter the name of the input YAML file and the name for the output text file name. +A table will be produced at the specified output filename. + +Copy or move this file to your working directory. + +Google Sheets Usage +------------------- +This section will detail how to customize the Google Sheets spreadsheet and then download the spreadsheet into a table in .csv format. + +Folow this link https://docs.google.com/spreadsheets/d/1SI4wHBXatLAAMfiMx3mUUC7x0fqz4lniKuM4_i5j6bM/edit#gid=0 to access the template spreadsheet. + +The QTYs listed in the template file (QTY_STATE_VARIABLE, QTY_TRACER_SOURCE) correspond to the lorenz_6_tracer_advection model and have the default values set for all variables. Make sure to remove these QTYs if you are not running an analagous model. ** + +Make a copy of the table by selecting 'File > Make a copy' from the menu bar. + +To customize the spreadsheet, click on the cell you want to edit and change the value of that cell. +To add a new QTY to the spreadsheet, simply copy the row of a listed QTY, change the QTY name, and edit the cells individually to set the control options. +To remove a QTY from the spreadsheet, select the row corresponding to that QTY. Then right click and choose "Delete Row" + +Ensure that there are no empty rows in between the QTYs listed in the spreadsheet. + +Download the spreadsheet as a .csv file by selecting 'File > Download > csv' from the menu bar. + +Google Sheets will append the name of the file with " - Sheet1.csv". For example a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv" +Rename this file to remove this append to ensure that there are no spaces in the filename. + +Copy or move this file to your working directory. + +Using the table in DART +----------------------- +Navigate to your working directory. + +Edit your namelist file (input.nml) +Add the item "qcf_table_filename = 'your_filename' to the &filter_nml section, replacing your_filename with the actual name of the file you want to use. +Remember that the default values will be used for all QTYs if no filename is listed here. + +Build and run filter normally. + +The data read from the QCF table used is written to the output file dart_log.out From 71d1190d590cd7e19c0f939192d6d3e25d78a08e Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 25 Sep 2023 19:02:05 -0600 Subject: [PATCH 045/129] Removing unused routines from utilities_mod use list --- assimilation_code/modules/assimilation/algorithm_info_mod.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index dbe9027985..2a01884641 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -9,7 +9,7 @@ module algorithm_info_mod use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance use obs_kind_mod, only : get_quantity_for_type_of_obs, get_name_for_quantity, get_index_for_quantity -use utilities_mod, only : error_handler, E_ALLMSG, E_ERR, E_MSG, log_it, logfileunit, open_file, close_file, to_upper +use utilities_mod, only : error_handler, E_ERR, E_MSG, open_file, close_file, to_upper use assim_model_mod, only : get_state_meta_data use location_mod, only : location_type From feb74c6f0c8c92732d1d3e4026fb40f22d69382d Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 25 Sep 2023 19:18:48 -0600 Subject: [PATCH 046/129] Adding &probit_transform_nml to input.nml files for lorenz 63 and 96 - this will allow for the build and run lorenz github actions to pass --- models/lorenz_63/work/input.nml | 13 +++++++++++-- models/lorenz_96/work/input.nml | 13 +++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/models/lorenz_63/work/input.nml b/models/lorenz_63/work/input.nml index 90504677f9..ab4a045d01 100644 --- a/models/lorenz_63/work/input.nml +++ b/models/lorenz_63/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -28,6 +34,8 @@ / &filter_nml + qcf_table_filename = '', + use_algorithm_info_mod = .true., single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' @@ -86,6 +94,7 @@ / &assim_tools_nml + use_algorithm_info_mod = .true., filter_kind = 1, cutoff = 1000000.0 sort_obs_inc = .false., @@ -138,9 +147,9 @@ &preprocess_nml overwrite_output = .true. 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' +output_obs_def_mod_file = './obs_def_mod.f90' input_obs_qty_mod_file = '../../../assimilation_code/modules/observations/DEFAULT_obs_kind_mod.F90' - output_obs_qty_mod_file = '../../../assimilation_code/modules/observations/obs_kind_mod.f90' +output_obs_qty_mod_file = './obs_kind_mod.f90' obs_type_files = '../../../observations/forward_operators/obs_def_1d_state_mod.f90' quantity_files = '../../../assimilation_code/modules/observations/oned_quantities_mod.f90' / diff --git a/models/lorenz_96/work/input.nml b/models/lorenz_96/work/input.nml index 39bbef5f02..03dceaf59c 100644 --- a/models/lorenz_96/work/input.nml +++ b/models/lorenz_96/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -28,6 +34,8 @@ / &filter_nml + qcf_table_filename = '', + use_algorithm_info_mod = .true., single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' @@ -86,6 +94,7 @@ / &assim_tools_nml + use_algorithm_info_mod = .true., filter_kind = 1, cutoff = 0.02, sort_obs_inc = .false., @@ -144,9 +153,9 @@ &preprocess_nml overwrite_output = .true. 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' +output_obs_def_mod_file = './obs_def_mod.f90' input_obs_qty_mod_file = '../../../assimilation_code/modules/observations/DEFAULT_obs_kind_mod.F90' - output_obs_qty_mod_file = '../../../assimilation_code/modules/observations/obs_kind_mod.f90' +output_obs_qty_mod_file = './obs_kind_mod.f90' obs_type_files = '../../../observations/forward_operators/obs_def_1d_state_mod.f90' quantity_files = '../../../assimilation_code/modules/observations/oned_quantities_mod.f90' / From 82aa5de4c99d344b4dbc4e48e4de9155475774a6 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 26 Sep 2023 12:43:53 -0600 Subject: [PATCH 047/129] Removing the use_algorithm_info_mod logical from assim_tools_mod and filter_mod --- .../modules/assimilation/assim_tools_mod.f90 | 12 +++++------- .../modules/assimilation/filter_mod.f90 | 15 +++------------ 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index 958e373201..b604807bac 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -143,7 +143,6 @@ module assim_tools_mod ! special_localization_obs_types -> Special treatment for the specified observation types ! special_localization_cutoffs -> Different cutoff value for each specified obs type ! -logical :: use_algorithm_info_mod = .true. integer :: filter_kind = 1 real(r8) :: cutoff = 0.2_r8 logical :: sort_obs_inc = .false. @@ -203,8 +202,7 @@ module assim_tools_mod ! compared to previous versions of this namelist item. logical :: distribute_mean = .false. -namelist / assim_tools_nml / use_algorithm_info_mod, & - filter_kind, cutoff, sort_obs_inc, & +namelist / assim_tools_nml / filter_kind, cutoff, sort_obs_inc, & spread_restoration, sampling_error_correction, & adaptive_localization_threshold, adaptive_cutoff_floor, & print_every_nth_obs, rectangular_quadrature, gaussian_likelihood_tails, & @@ -976,7 +974,8 @@ subroutine obs_increment(ens_in, ens_size, obs, obs_var, obs_kind, obs_inc, & !--------------------------begin algorithm_info control block----------------- ! More flexible abilities to control the observation space increments are ! available with this code block. It gets information about the increment method -! for the current observation is use_algorithm_info_mod is set to true in the namelist. +! for the current observation. + ! This is not an extensible mechanism for doing this as the number of ! obs increments distributions and associated information goes up ! Implications for sorting increments and for spread restoration need to be examined @@ -988,9 +987,8 @@ subroutine obs_increment(ens_in, ens_size, obs, obs_var, obs_kind, obs_inc, & bounded_below = .false.; lower_bound = 0.0_r8 bounded_above = .false.; upper_bound = 0.0_r8 -if(use_algorithm_info_mod) & - call obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_likelihood_tails, & - sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound) +call obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_likelihood_tails, & + sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound) ! Could add logic to check on sort being true when not needed. ! Could also add logic to limit the use of spread_restoration to EAKF. It will fail diff --git a/assimilation_code/modules/assimilation/filter_mod.f90 b/assimilation_code/modules/assimilation/filter_mod.f90 index c83a433a8a..1a4dbfe585 100644 --- a/assimilation_code/modules/assimilation/filter_mod.f90 +++ b/assimilation_code/modules/assimilation/filter_mod.f90 @@ -167,7 +167,6 @@ module filter_mod ! Namelist input with default values ! character(len = 129) :: qcf_table_filename = '' -logical :: use_algorithm_info_mod = .true. integer :: async = 0, ens_size = 20 integer :: tasks_per_model_advance = 1 ! if init_time_days and seconds are negative initial time is 0, 0 @@ -263,7 +262,6 @@ module filter_mod namelist /filter_nml/ async, & qcf_table_filename, & - use_algorithm_info_mod, & adv_ens_command, & ens_size, & tasks_per_model_advance, & @@ -1608,16 +1606,9 @@ subroutine filter_ensemble_inflate(ens_handle, inflate_copy, inflate, ENS_MEAN_C call get_state_meta_data(ens_handle%my_vars(j), my_state_loc, my_state_kind) ! Need to specify what kind of prior to use for each - ! Use default of untransformed if use_algorithm_info_mod is not true - if(use_algorithm_info_mod) then - call probit_dist_info(my_state_kind, .true., .true., dist_type, & - bounded_below, bounded_above, lower_bound, upper_bound) - else - ! Default is just a normal which does nothing - dist_type = NORMAL_DISTRIBUTION - bounded_below = .false. ; bounded_above = .false. - lower_bound = 0.0_r8; upper_bound = 0.0_r8 - endif + call probit_dist_info(my_state_kind, .true., .true., dist_type, & + bounded_below, bounded_above, lower_bound, upper_bound) + call transform_to_probit(grp_size, ens_handle%copies(grp_bot:grp_top, j), & dist_type, dist_params, probit_ens(1:grp_size), .false., & bounded_below, bounded_above, lower_bound, upper_bound) From 80cd9439a8539c17b3f407e5eec95d820a033aa5 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 26 Sep 2023 12:53:09 -0600 Subject: [PATCH 048/129] Fixing unintentional additions to lorenx 96 and 63 input.nml files; removing use_algorithm_info_mod nml option --- models/lorenz_63/work/input.nml | 6 ++---- models/lorenz_96/work/input.nml | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/models/lorenz_63/work/input.nml b/models/lorenz_63/work/input.nml index ab4a045d01..3ed5062322 100644 --- a/models/lorenz_63/work/input.nml +++ b/models/lorenz_63/work/input.nml @@ -35,7 +35,6 @@ &filter_nml qcf_table_filename = '', - use_algorithm_info_mod = .true., single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' @@ -94,7 +93,6 @@ / &assim_tools_nml - use_algorithm_info_mod = .true., filter_kind = 1, cutoff = 1000000.0 sort_obs_inc = .false., @@ -147,9 +145,9 @@ &preprocess_nml overwrite_output = .true. input_obs_def_mod_file = '../../../observations/forward_operators/DEFAULT_obs_def_mod.F90' -output_obs_def_mod_file = './obs_def_mod.f90' +output_obs_def_mod_file = '../../../observations/forward_operators/obs_def_mod.f90' input_obs_qty_mod_file = '../../../assimilation_code/modules/observations/DEFAULT_obs_kind_mod.F90' -output_obs_qty_mod_file = './obs_kind_mod.f90' +output_obs_qty_mod_file = '../../../assimilation_code/modules/observations/obs_kind_mod.f90' obs_type_files = '../../../observations/forward_operators/obs_def_1d_state_mod.f90' quantity_files = '../../../assimilation_code/modules/observations/oned_quantities_mod.f90' / diff --git a/models/lorenz_96/work/input.nml b/models/lorenz_96/work/input.nml index 03dceaf59c..8aa1ce99ad 100644 --- a/models/lorenz_96/work/input.nml +++ b/models/lorenz_96/work/input.nml @@ -35,7 +35,6 @@ &filter_nml qcf_table_filename = '', - use_algorithm_info_mod = .true., single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' @@ -94,7 +93,6 @@ / &assim_tools_nml - use_algorithm_info_mod = .true., filter_kind = 1, cutoff = 0.02, sort_obs_inc = .false., @@ -153,9 +151,9 @@ &preprocess_nml overwrite_output = .true. input_obs_def_mod_file = '../../../observations/forward_operators/DEFAULT_obs_def_mod.F90' -output_obs_def_mod_file = './obs_def_mod.f90' +output_obs_def_mod_file = '../../../observations/forward_operators/obs_def_mod.f90' input_obs_qty_mod_file = '../../../assimilation_code/modules/observations/DEFAULT_obs_kind_mod.F90' -output_obs_qty_mod_file = './obs_kind_mod.f90' +output_obs_qty_mod_file = '../../../assimilation_code/modules/observations/obs_kind_mod.f90' obs_type_files = '../../../observations/forward_operators/obs_def_1d_state_mod.f90' quantity_files = '../../../assimilation_code/modules/observations/oned_quantities_mod.f90' / From bf92ac4fe9a4c91dfbfba03ab6b9b352a7a71c68 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 26 Sep 2023 13:14:02 -0600 Subject: [PATCH 049/129] Adding spaces back in from unintentional removal --- models/lorenz_63/work/input.nml | 4 ++-- models/lorenz_96/work/input.nml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/models/lorenz_63/work/input.nml b/models/lorenz_63/work/input.nml index 3ed5062322..86a7e2e569 100644 --- a/models/lorenz_63/work/input.nml +++ b/models/lorenz_63/work/input.nml @@ -145,9 +145,9 @@ &preprocess_nml overwrite_output = .true. 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' + output_obs_def_mod_file = '../../../observations/forward_operators/obs_def_mod.f90' input_obs_qty_mod_file = '../../../assimilation_code/modules/observations/DEFAULT_obs_kind_mod.F90' -output_obs_qty_mod_file = '../../../assimilation_code/modules/observations/obs_kind_mod.f90' + output_obs_qty_mod_file = '../../../assimilation_code/modules/observations/obs_kind_mod.f90' obs_type_files = '../../../observations/forward_operators/obs_def_1d_state_mod.f90' quantity_files = '../../../assimilation_code/modules/observations/oned_quantities_mod.f90' / diff --git a/models/lorenz_96/work/input.nml b/models/lorenz_96/work/input.nml index 8aa1ce99ad..615ef8df5d 100644 --- a/models/lorenz_96/work/input.nml +++ b/models/lorenz_96/work/input.nml @@ -151,9 +151,9 @@ &preprocess_nml overwrite_output = .true. 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' + output_obs_def_mod_file = '../../../observations/forward_operators/obs_def_mod.f90' input_obs_qty_mod_file = '../../../assimilation_code/modules/observations/DEFAULT_obs_kind_mod.F90' -output_obs_qty_mod_file = '../../../assimilation_code/modules/observations/obs_kind_mod.f90' + output_obs_qty_mod_file = '../../../assimilation_code/modules/observations/obs_kind_mod.f90' obs_type_files = '../../../observations/forward_operators/obs_def_1d_state_mod.f90' quantity_files = '../../../assimilation_code/modules/observations/oned_quantities_mod.f90' / From f3d1826a640bd1d219e6f948cc9625616217df27 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 26 Sep 2023 15:54:31 -0600 Subject: [PATCH 050/129] Adding &probit_transform_nml and qcf_table_filename option to model's input.nml files (9var, am2, bgrid_solo) --- models/9var/work/input.nml | 7 +++++++ models/am2/work/input.nml | 7 +++++++ models/bgrid_solo/work/input.nml | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/models/9var/work/input.nml b/models/9var/work/input.nml index cfe617f0ce..168834b85a 100644 --- a/models/9var/work/input.nml +++ b/models/9var/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -32,6 +38,7 @@ # output_state_files = 'filter_output.nc' &filter_nml + qcf_table_filename = '' single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/am2/work/input.nml b/models/am2/work/input.nml index 5f453d01cd..171974666a 100644 --- a/models/am2/work/input.nml +++ b/models/am2/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &perfect_model_obs_nml start_from_restart = .true., output_restart = .true., @@ -22,6 +28,7 @@ / &filter_nml + qcf_table_filename = '' async = 2, adv_ens_command = "./advance_model.csh", ens_size = 10, diff --git a/models/bgrid_solo/work/input.nml b/models/bgrid_solo/work/input.nml index 9d65871b00..54e29e3f0b 100644 --- a/models/bgrid_solo/work/input.nml +++ b/models/bgrid_solo/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -28,6 +34,7 @@ / &filter_nml + qcf_table_filename = '' single_file_in = .true., input_state_files = 'filter_input.nc' input_state_file_list = '' From 78ccc5eefdba92b1a6138c80ee102347af1e2429 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 27 Sep 2023 15:51:34 -0600 Subject: [PATCH 051/129] Fixing missing commas in nml files --- models/9var/work/input.nml | 6 +++--- models/am2/work/input.nml | 6 +++--- models/bgrid_solo/work/input.nml | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/models/9var/work/input.nml b/models/9var/work/input.nml index 168834b85a..419aec1d3a 100644 --- a/models/9var/work/input.nml +++ b/models/9var/work/input.nml @@ -1,7 +1,7 @@ &probit_transform_nml fix_bound_violations = .false., - use_logit_instead_of_probit = .false. - do_inverse_check = .true. + use_logit_instead_of_probit = .false., + do_inverse_check = .true., / &perfect_model_obs_nml @@ -38,7 +38,7 @@ # output_state_files = 'filter_output.nc' &filter_nml - qcf_table_filename = '' + qcf_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/am2/work/input.nml b/models/am2/work/input.nml index 171974666a..83825dab00 100644 --- a/models/am2/work/input.nml +++ b/models/am2/work/input.nml @@ -1,7 +1,7 @@ &probit_transform_nml fix_bound_violations = .false., - use_logit_instead_of_probit = .false. - do_inverse_check = .true. + use_logit_instead_of_probit = .false., + do_inverse_check = .true., / &perfect_model_obs_nml @@ -28,7 +28,7 @@ / &filter_nml - qcf_table_filename = '' + qcf_table_filename = '', async = 2, adv_ens_command = "./advance_model.csh", ens_size = 10, diff --git a/models/bgrid_solo/work/input.nml b/models/bgrid_solo/work/input.nml index 54e29e3f0b..7311b0464e 100644 --- a/models/bgrid_solo/work/input.nml +++ b/models/bgrid_solo/work/input.nml @@ -1,7 +1,7 @@ &probit_transform_nml fix_bound_violations = .false., - use_logit_instead_of_probit = .false. - do_inverse_check = .true. + use_logit_instead_of_probit = .false., + do_inverse_check = .true., / &perfect_model_obs_nml @@ -34,7 +34,7 @@ / &filter_nml - qcf_table_filename = '' + qcf_table_filename = '', single_file_in = .true., input_state_files = 'filter_input.nc' input_state_file_list = '' From 64a9f74f751bd109f80225bf936283fde82ab520 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Thu, 28 Sep 2023 15:14:43 -0400 Subject: [PATCH 052/129] add test cases for reading qcf table --- .gitignore | 1 + developer_tests/qceff/test_table_read.f90 | 23 +++++++++++ developer_tests/qceff/work/input.nml | 28 +++++++++++++ developer_tests/qceff/work/qcf_table.txt | 3 ++ .../qceff/work/qcf_table_bad_qty.txt | 3 ++ .../qceff/work/qcf_table_broke.txt | 3 ++ .../qceff/work/qcf_table_extra_columns.txt | 3 ++ developer_tests/qceff/work/qcf_table_v2.txt | 3 ++ developer_tests/qceff/work/quickbuild.sh | 40 +++++++++++++++++++ 9 files changed, 107 insertions(+) create mode 100644 developer_tests/qceff/test_table_read.f90 create mode 100644 developer_tests/qceff/work/input.nml create mode 100644 developer_tests/qceff/work/qcf_table.txt create mode 100644 developer_tests/qceff/work/qcf_table_bad_qty.txt create mode 100644 developer_tests/qceff/work/qcf_table_broke.txt create mode 100644 developer_tests/qceff/work/qcf_table_extra_columns.txt create mode 100644 developer_tests/qceff/work/qcf_table_v2.txt create mode 100755 developer_tests/qceff/work/quickbuild.sh diff --git a/.gitignore b/.gitignore index cfbf4153d3..bf6ca1dcbd 100644 --- a/.gitignore +++ b/.gitignore @@ -189,6 +189,7 @@ stacktest obs_rwtest test_quad_irreg_interp test_quad_reg_interp +test_table_read # Directories to NOT IGNORE ... same as executable names # as far as I know, these must be listed after the executables diff --git a/developer_tests/qceff/test_table_read.f90 b/developer_tests/qceff/test_table_read.f90 new file mode 100644 index 0000000000..c9e97f4d1c --- /dev/null +++ b/developer_tests/qceff/test_table_read.f90 @@ -0,0 +1,23 @@ +program test_table_read + +use algorithm_info_mod, only : init_algorithm_info_mod, end_algorithm_info_mod +use utilities_mod, only : initialize_utilities + +implicit none + +character(len=129) :: qcf_table_filename + +call initialize_utilities('test_table_read') + +!n = command_argument_count() +call get_command_argument(1,qcf_table_filename) + + +!qcf_table_filename = 'qcf_table_v2.txt' + +call init_algorithm_info_mod(qcf_table_filename) + +call end_algorithm_info_mod() + + +end program test_table_read diff --git a/developer_tests/qceff/work/input.nml b/developer_tests/qceff/work/input.nml new file mode 100644 index 0000000000..ffa7155436 --- /dev/null +++ b/developer_tests/qceff/work/input.nml @@ -0,0 +1,28 @@ +&utilities_nml + TERMLEVEL = 1, + module_details = .false. + logfilename = 'dart_log.out' + / + +# pick a random set of inputs +&preprocess_nml + overwrite_output = .true. + input_obs_qty_mod_file = '../../../assimilation_code/modules/observations/DEFAULT_obs_kind_mod.F90' + output_obs_qty_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' + obs_type_files = '../../../observations/forward_operators/obs_def_reanalysis_bufr_mod.f90', + '../../../observations/forward_operators/obs_def_radar_mod.f90', + '../../../observations/forward_operators/obs_def_metar_mod.f90', + '../../../observations/forward_operators/obs_def_dew_point_mod.f90', + '../../../observations/forward_operators/obs_def_rel_humidity_mod.f90', + '../../../observations/forward_operators/obs_def_altimeter_mod.f90', + '../../../observations/forward_operators/obs_def_gps_mod.f90', + '../../../observations/forward_operators/obs_def_vortex_mod.f90', + '../../../observations/forward_operators/obs_def_gts_mod.f90', + '../../../observations/forward_operators/obs_def_QuikSCAT_mod.f90' + quantity_files = '../../../assimilation_code/modules/observations/default_quantities_mod.f90', + / + +&obs_kind_nml +/ diff --git a/developer_tests/qceff/work/qcf_table.txt b/developer_tests/qceff/work/qcf_table.txt new file mode 100644 index 0000000000..7d4f146540 --- /dev/null +++ b/developer_tests/qceff/work/qcf_table.txt @@ -0,0 +1,3 @@ +QCF table version: 1 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound +QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/qcf_table_bad_qty.txt b/developer_tests/qceff/work/qcf_table_bad_qty.txt new file mode 100644 index 0000000000..428e5fd6c5 --- /dev/null +++ b/developer_tests/qceff/work/qcf_table_bad_qty.txt @@ -0,0 +1,3 @@ +QCF table version: 1 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound +QTY_HAIRCUT .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/qcf_table_broke.txt b/developer_tests/qceff/work/qcf_table_broke.txt new file mode 100644 index 0000000000..cb78e95e49 --- /dev/null +++ b/developer_tests/qceff/work/qcf_table_broke.txt @@ -0,0 +1,3 @@ +QCF table version: 1 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound +QTY_STATE_VARIABLE .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/qcf_table_extra_columns.txt b/developer_tests/qceff/work/qcf_table_extra_columns.txt new file mode 100644 index 0000000000..d298573349 --- /dev/null +++ b/developer_tests/qceff/work/qcf_table_extra_columns.txt @@ -0,0 +1,3 @@ +QCF table version: 1 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound frog +QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 toad newt diff --git a/developer_tests/qceff/work/qcf_table_v2.txt b/developer_tests/qceff/work/qcf_table_v2.txt new file mode 100644 index 0000000000..0d1b5a46df --- /dev/null +++ b/developer_tests/qceff/work/qcf_table_v2.txt @@ -0,0 +1,3 @@ +QCF table version: 2 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound +QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/quickbuild.sh b/developer_tests/qceff/work/quickbuild.sh new file mode 100755 index 0000000000..81b1308494 --- /dev/null +++ b/developer_tests/qceff/work/quickbuild.sh @@ -0,0 +1,40 @@ +#!/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="qceff" +LOCATION="threed_sphere" + +serial_programs=( +test_table_read +) + +# quickbuild arguments +arguments "$@" + +# clean the directory +\rm -f -- *.o *.mod Makefile .cppdefs + +# build and run preprocess before making any other DART executables +buildpreprocess + +# build +buildit + +# clean up +\rm -f -- *.o *.mod + +} + +main "$@" From f9e490cd7cf6b4e26067554733bfbaa55ff0e78b Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Thu, 28 Sep 2023 16:35:50 -0400 Subject: [PATCH 053/129] test script to check return codes for various qcf_table cases --- developer_tests/qceff/test_table_read.f90 | 9 ++--- developer_tests/qceff/work/runall.sh | 40 +++++++++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) create mode 100755 developer_tests/qceff/work/runall.sh diff --git a/developer_tests/qceff/test_table_read.f90 b/developer_tests/qceff/test_table_read.f90 index c9e97f4d1c..aaaa279c2a 100644 --- a/developer_tests/qceff/test_table_read.f90 +++ b/developer_tests/qceff/test_table_read.f90 @@ -1,3 +1,8 @@ +! 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 + +! qcf_table_filename expected as command line arguement program test_table_read use algorithm_info_mod, only : init_algorithm_info_mod, end_algorithm_info_mod @@ -9,12 +14,8 @@ program test_table_read call initialize_utilities('test_table_read') -!n = command_argument_count() call get_command_argument(1,qcf_table_filename) - -!qcf_table_filename = 'qcf_table_v2.txt' - call init_algorithm_info_mod(qcf_table_filename) call end_algorithm_info_mod() diff --git a/developer_tests/qceff/work/runall.sh b/developer_tests/qceff/work/runall.sh new file mode 100755 index 0000000000..b9a4cf24ed --- /dev/null +++ b/developer_tests/qceff/work/runall.sh @@ -0,0 +1,40 @@ +#!/bin/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 + +# Usage: +# ./runall.sh +# ./runall.sh | grep FAIL +# ./runall.sh | grep PASS + + +should_pass () { +if [[ $? -ne 0 ]]; then + echo $1: "FAIL" +else + echo $1: "PASS" +fi +} + +should_fail () { +if [[ $? -eq 0 ]]; then + echo $1: "FAIL" +else + echo $1: "PASS" +fi +} + +./test_table_read ; should_pass "no table" + +./test_table_read qcf_table.txt /dev/null ; should_pass "correct v1 table" + +./test_table_read qcf_table_v2.txt /dev/null ; should_fail "detect wrong version" + +./test_table_read qcf_table_extra_columns.txt /dev/null ; should_pass "extra colums" + +./test_table_read qcf_table_bad_qty.txt /dev/null ; should_fail "bad qty" + +./test_table_read qcf_table_broke.txt /dev/null ; should_fail "bad value" + From d4de78956216394c2c5575bff1a6a5ea89edacd4 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Thu, 28 Sep 2023 16:38:55 -0400 Subject: [PATCH 054/129] remove stray /dev/null left in accidentally --- developer_tests/qceff/work/runall.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/developer_tests/qceff/work/runall.sh b/developer_tests/qceff/work/runall.sh index b9a4cf24ed..d47b7a2545 100755 --- a/developer_tests/qceff/work/runall.sh +++ b/developer_tests/qceff/work/runall.sh @@ -28,13 +28,13 @@ fi ./test_table_read ; should_pass "no table" -./test_table_read qcf_table.txt /dev/null ; should_pass "correct v1 table" +./test_table_read qcf_table.txt ; should_pass "correct v1 table" -./test_table_read qcf_table_v2.txt /dev/null ; should_fail "detect wrong version" +./test_table_read qcf_table_v2.txt ; should_fail "detect wrong version" -./test_table_read qcf_table_extra_columns.txt /dev/null ; should_pass "extra colums" +./test_table_read qcf_table_extra_columns.txt ; should_pass "extra colums" -./test_table_read qcf_table_bad_qty.txt /dev/null ; should_fail "bad qty" +./test_table_read qcf_table_bad_qty.txt ; should_fail "bad qty" -./test_table_read qcf_table_broke.txt /dev/null ; should_fail "bad value" +./test_table_read qcf_table_broke.txt ; should_fail "bad value" From 7733026a416e3f13b72b0824e206dcf8e3ac2cc5 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Thu, 28 Sep 2023 17:09:05 -0400 Subject: [PATCH 055/129] add tests for various bounds options currently the "lower bound only" test is failing because the upper < lower check happens always rather then only when you have two bounds --- developer_tests/qceff/work/qcf_table_duplicates.txt | 6 ++++++ developer_tests/qceff/work/qcf_table_lower_bound_only.txt | 6 ++++++ developer_tests/qceff/work/qcf_table_lower_gt_upper.txt | 6 ++++++ developer_tests/qceff/work/qcf_table_no_header.txt | 4 ++++ developer_tests/qceff/work/runall.sh | 5 +++++ 5 files changed, 27 insertions(+) create mode 100644 developer_tests/qceff/work/qcf_table_duplicates.txt create mode 100644 developer_tests/qceff/work/qcf_table_lower_bound_only.txt create mode 100644 developer_tests/qceff/work/qcf_table_lower_gt_upper.txt create mode 100644 developer_tests/qceff/work/qcf_table_no_header.txt diff --git a/developer_tests/qceff/work/qcf_table_duplicates.txt b/developer_tests/qceff/work/qcf_table_duplicates.txt new file mode 100644 index 0000000000..7ffddff61f --- /dev/null +++ b/developer_tests/qceff/work/qcf_table_duplicates.txt @@ -0,0 +1,6 @@ +QCF table version: 1 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound +QTY_VEGETATED_AREA_FRACTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_AQUIFER_WATER .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_SEAICE_SALINITY008 .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_VEGETATED_AREA_FRACTION .true. .false. 0 1000 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/qcf_table_lower_bound_only.txt b/developer_tests/qceff/work/qcf_table_lower_bound_only.txt new file mode 100644 index 0000000000..6f0fca4ee4 --- /dev/null +++ b/developer_tests/qceff/work/qcf_table_lower_bound_only.txt @@ -0,0 +1,6 @@ +QCF table version: 1 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound +QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_AQUIFER_WATER .true. .false. 0.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_SEAICE_SALINITY008 .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_VEGETATED_AREA_FRACTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/qcf_table_lower_gt_upper.txt b/developer_tests/qceff/work/qcf_table_lower_gt_upper.txt new file mode 100644 index 0000000000..6370c2cdd7 --- /dev/null +++ b/developer_tests/qceff/work/qcf_table_lower_gt_upper.txt @@ -0,0 +1,6 @@ +QCF table version: 1 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound +QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_AQUIFER_WATER .true. .true. 10.0 0.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_SEAICE_SALINITY008 .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_VEGETATED_AREA_FRACTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/qcf_table_no_header.txt b/developer_tests/qceff/work/qcf_table_no_header.txt new file mode 100644 index 0000000000..617379ffe0 --- /dev/null +++ b/developer_tests/qceff/work/qcf_table_no_header.txt @@ -0,0 +1,4 @@ +QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_AQUIFER_WATER .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_SEAICE_SALINITY008 .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_VEGETATED_AREA_FRACTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/runall.sh b/developer_tests/qceff/work/runall.sh index d47b7a2545..80b3fc87b1 100755 --- a/developer_tests/qceff/work/runall.sh +++ b/developer_tests/qceff/work/runall.sh @@ -38,3 +38,8 @@ fi ./test_table_read qcf_table_broke.txt ; should_fail "bad value" +./test_table_read qcf_table_no_header.txt ; should_fail "no header" + +./test_table_read qcf_table_lower_gt_upper.txt ; should_fail "upper bound less than lower" + +./test_table_read ./test_table_read qcf_table_lower_bound_only.txt ; should_pass "lower bound only" From 72717681d52a30c2b262a126df58e6dafff7038b Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Thu, 28 Sep 2023 17:14:26 -0400 Subject: [PATCH 056/129] test for bounds set to false, but bounds values in the table --- .../qceff/work/qcf_table_no_bounds_with_values.txt | 6 ++++++ developer_tests/qceff/work/runall.sh | 2 ++ 2 files changed, 8 insertions(+) create mode 100644 developer_tests/qceff/work/qcf_table_no_bounds_with_values.txt diff --git a/developer_tests/qceff/work/qcf_table_no_bounds_with_values.txt b/developer_tests/qceff/work/qcf_table_no_bounds_with_values.txt new file mode 100644 index 0000000000..32c8d4f8e9 --- /dev/null +++ b/developer_tests/qceff/work/qcf_table_no_bounds_with_values.txt @@ -0,0 +1,6 @@ +QCF table version: 1 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound +QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_AQUIFER_WATER .false. .false. 10.0 0.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_SEAICE_SALINITY008 .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_VEGETATED_AREA_FRACTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/runall.sh b/developer_tests/qceff/work/runall.sh index 80b3fc87b1..0588ec6d69 100755 --- a/developer_tests/qceff/work/runall.sh +++ b/developer_tests/qceff/work/runall.sh @@ -43,3 +43,5 @@ fi ./test_table_read qcf_table_lower_gt_upper.txt ; should_fail "upper bound less than lower" ./test_table_read ./test_table_read qcf_table_lower_bound_only.txt ; should_pass "lower bound only" + +./test_table_read qcf_table_no_bounds_with_values.txt ; should_pass "bounds false, values for bounds" From 23a60cfb5dde3691a81d3f4a2a4c0f447658ec76 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Fri, 29 Sep 2023 12:33:15 -0400 Subject: [PATCH 057/129] fix: need to check that a qty is bounded above and below before checking invalid bounds otherwise missing_r8 -88888 value for the upper bound is "less than" the lower bound --- .../assimilation/algorithm_info_mod.f90 | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 2a01884641..d235c289b4 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -518,26 +518,37 @@ subroutine verify_qcf_table_data() !Checks that all bounds are valid; currently checks that the lower bound in less than the upper !Here we could add more specific checks if we have known limits on the bounds do row = 1, size(qcf_table_data) - if(qcf_table_data(row)%obs_error_info%lower_bound > qcf_table_data(row)%obs_error_info%upper_bound) then - write(errstring,*) 'Invalid bounds in obs_error_info' - call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) - endif - if(qcf_table_data(row)%probit_inflation%lower_bound > qcf_table_data(row)%probit_inflation%upper_bound) then - write(errstring,*) 'Invalid bounds in probit_inflation' - call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) + + if (qcf_table_data(row)%obs_error_info%bounded_below .and. qcf_table_data(row)%obs_error_info%bounded_above) then + if(qcf_table_data(row)%obs_error_info%lower_bound > qcf_table_data(row)%obs_error_info%upper_bound) then + write(errstring,*) 'Invalid bounds in obs_error_info' + call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) + endif endif - if(qcf_table_data(row)%probit_state%lower_bound > qcf_table_data(row)%probit_state%upper_bound) then - write(errstring,*) 'Invalid bounds in probit_state' - call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) + if (qcf_table_data(row)%probit_inflation%bounded_below .and. qcf_table_data(row)%probit_inflation%bounded_above) then + if(qcf_table_data(row)%probit_inflation%lower_bound > qcf_table_data(row)%probit_inflation%upper_bound) then + write(errstring,*) 'Invalid bounds in probit_inflation' + call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) + endif endif - if(qcf_table_data(row)%probit_extended_state%lower_bound > qcf_table_data(row)%probit_extended_state%upper_bound) then - write(errstring,*) 'Invalid bounds in probit_extended_state' - call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) + if(qcf_table_data(row)%probit_state%bounded_below .and. qcf_table_data(row)%probit_state%bounded_above) then + if(qcf_table_data(row)%probit_state%lower_bound > qcf_table_data(row)%probit_state%upper_bound) then + write(errstring,*) 'Invalid bounds in probit_state' + call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) + endif endif - if(qcf_table_data(row)%obs_inc_info%lower_bound > qcf_table_data(row)%obs_inc_info%upper_bound) then - write(errstring,*) 'Invalid bounds in obs_inc_info' - call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) + if(qcf_table_data(row)%probit_extended_state%bounded_below .and. qcf_table_data(row)%probit_extended_state%bounded_above) then + if(qcf_table_data(row)%probit_extended_state%lower_bound > qcf_table_data(row)%probit_extended_state%upper_bound) then + write(errstring,*) 'Invalid bounds in probit_extended_state' + call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) + endif endif + if(qcf_table_data(row)%obs_inc_info%bounded_below .and. qcf_table_data(row)%obs_inc_info%bounded_above) then + if(qcf_table_data(row)%obs_inc_info%lower_bound > qcf_table_data(row)%obs_inc_info%upper_bound) then + write(errstring,*) 'Invalid bounds in obs_inc_info' + call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) + endif + endif end do !Ensures that all QTYs listed in the table exist in DART From 0960c676c5666856e43ed7993bf0de58dd0ed100 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Fri, 29 Sep 2023 13:45:07 -0400 Subject: [PATCH 058/129] fix: remove extra call to test_table read from runall.sh --- developer_tests/qceff/work/runall.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/developer_tests/qceff/work/runall.sh b/developer_tests/qceff/work/runall.sh index 0588ec6d69..4202947a4c 100755 --- a/developer_tests/qceff/work/runall.sh +++ b/developer_tests/qceff/work/runall.sh @@ -42,6 +42,6 @@ fi ./test_table_read qcf_table_lower_gt_upper.txt ; should_fail "upper bound less than lower" -./test_table_read ./test_table_read qcf_table_lower_bound_only.txt ; should_pass "lower bound only" +./test_table_read qcf_table_lower_bound_only.txt ; should_pass "lower bound only" ./test_table_read qcf_table_no_bounds_with_values.txt ; should_pass "bounds false, values for bounds" From aa03af1b3af0ef8cea2e3738261ad53258e2e737 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Mon, 2 Oct 2023 12:59:41 -0400 Subject: [PATCH 059/129] replace kind with qty kind is outdated terminolgy for quantity https://github.com/NCAR/DART/pull/545#issuecomment-1743365998 --- .../assimilation/algorithm_info_mod.f90 | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index d235c289b4..766ec4d6f8 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -199,21 +199,21 @@ subroutine obs_error_info(obs_def, error_variance, & logical, intent(out) :: bounded_below, bounded_above real(r8), intent(out) :: lower_bound, upper_bound -integer :: obs_type, obs_kind +integer :: obs_type, obs_qty integer(i8) :: state_var_index type(location_type) :: temp_loc integer :: QTY_loc(1) -character(len=129) :: kind_name +character(len=129) :: qty_name ! Get the kind of the observation obs_type = get_obs_def_type_of_obs(obs_def) ! If it is negative, it is an identity obs if(obs_type < 0) then state_var_index = -1 * obs_type - call get_state_meta_data(state_var_index, temp_loc, obs_kind) + call get_state_meta_data(state_var_index, temp_loc, obs_qty) else - obs_kind = get_quantity_for_type_of_obs(obs_type) + obs_qty = get_quantity_for_type_of_obs(obs_type) endif ! Get the default error variance @@ -227,10 +227,10 @@ subroutine obs_error_info(obs_def, error_variance, & endif !get actual name of QTY from integer index -kind_name = get_name_for_quantity(obs_kind) +qty_name = get_name_for_quantity(obs_qty) !find location of QTY in qcf_table_data structure -QTY_loc = findloc(qcf_table_row_headers, kind_name) +QTY_loc = findloc(qcf_table_row_headers, qty_name) if (QTY_loc(1) == 0) then !use default values if QTY is not in table @@ -264,7 +264,7 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & real(r8), intent(out) :: lower_bound, upper_bound integer :: QTY_loc(1) -character(len=129) :: kind_name +character(len=129) :: qty_name integer :: dist_type_loc(1) character(len=129), dimension(7) :: possible_dist_types @@ -316,10 +316,10 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & endif !get actual name of QTY from integer index -kind_name = get_name_for_quantity(kind) +qty_name = get_name_for_quantity(kind) !find location of QTY in qcf_table_data structure -QTY_loc = findloc(qcf_table_row_headers, kind_name) +QTY_loc = findloc(qcf_table_row_headers, qty_name) if (QTY_loc(1) == 0) then !use default values if QTY is not in table @@ -397,10 +397,10 @@ end subroutine probit_dist_info !------------------------------------------------------------------------ -subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_likelihood_tails, & +subroutine obs_inc_info(obs_qty, filter_kind, rectangular_quadrature, gaussian_likelihood_tails, & sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound) -integer, intent(in) :: obs_kind +integer, intent(in) :: obs_qty integer, intent(inout) :: filter_kind logical, intent(inout) :: rectangular_quadrature, gaussian_likelihood_tails logical, intent(inout) :: sort_obs_inc @@ -409,7 +409,7 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ real(r8), intent(inout) :: lower_bound, upper_bound integer :: QTY_loc(1) -character(len=129) :: kind_name +character(len=129) :: qty_name integer :: filter_kind_loc(1) character(len=129), dimension(5) :: possible_filter_kinds @@ -446,10 +446,10 @@ subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_ endif !get actual name of QTY from integer index -kind_name = get_name_for_quantity(obs_kind) +qty_name = get_name_for_quantity(obs_qty) !find location of QTY in qcf_table_data structure -QTY_loc = findloc(qcf_table_row_headers, kind_name) +QTY_loc = findloc(qcf_table_row_headers, qty_name) if (QTY_loc(1) == 0) then !use default values if QTY is not in table From fb53f565bc46a37cec5d09213a1879fe46eae09f Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Mon, 2 Oct 2023 14:12:53 -0400 Subject: [PATCH 060/129] add two tests for table read: incorrect filter kind, incorrect distribution Currently the algorithm_info_mod does not catch these on table read --- .../qceff/work/qcf_table_incorrect_distribution.txt | 3 +++ .../qceff/work/qcf_table_incorrect_filter_kind.txt | 3 +++ developer_tests/qceff/work/runall.sh | 4 ++++ 3 files changed, 10 insertions(+) create mode 100644 developer_tests/qceff/work/qcf_table_incorrect_distribution.txt create mode 100644 developer_tests/qceff/work/qcf_table_incorrect_filter_kind.txt diff --git a/developer_tests/qceff/work/qcf_table_incorrect_distribution.txt b/developer_tests/qceff/work/qcf_table_incorrect_distribution.txt new file mode 100644 index 0000000000..37decd57bf --- /dev/null +++ b/developer_tests/qceff/work/qcf_table_incorrect_distribution.txt @@ -0,0 +1,3 @@ +QCF table version: 1 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound +QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 POLAR_BEAR_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/qcf_table_incorrect_filter_kind.txt b/developer_tests/qceff/work/qcf_table_incorrect_filter_kind.txt new file mode 100644 index 0000000000..c1125c3360 --- /dev/null +++ b/developer_tests/qceff/work/qcf_table_incorrect_filter_kind.txt @@ -0,0 +1,3 @@ +QCF table version: 1 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound +QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 PENGUIN_FILTER .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/runall.sh b/developer_tests/qceff/work/runall.sh index 4202947a4c..62d42c3fc9 100755 --- a/developer_tests/qceff/work/runall.sh +++ b/developer_tests/qceff/work/runall.sh @@ -45,3 +45,7 @@ fi ./test_table_read qcf_table_lower_bound_only.txt ; should_pass "lower bound only" ./test_table_read qcf_table_no_bounds_with_values.txt ; should_pass "bounds false, values for bounds" + +./test_table_read qcf_table_incorrect_filter_kind.txt ; should_fail "incorrect filter_kind" + +./test_table_read qcf_table_incorrect_distribution.txt ; should_fail "incorrect distribution" From bcc657f263e4553ec3ea1668feec8a955c6efbea Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 3 Oct 2023 14:52:40 -0600 Subject: [PATCH 061/129] Fixing incorrect comments --- .../modules/assimilation/algorithm_info_mod.f90 | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 766ec4d6f8..7f213881ca 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -90,10 +90,6 @@ module algorithm_info_mod ! Provides routines that give information about details of algorithms for ! observation error sampling, observation increments, and the transformations ! for regression and inflation in probit space. -! For now, it is convenient to have these in a single module since several -! users will be developing their own problem specific versions of these -! subroutines. This will avoid constant merge conflicts as other parts of the -! assimilation code are updated. contains @@ -275,8 +271,9 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & ! along with additional logical info that indicates whether this is an observation ! or state variable and about whether the transformation is being done for inflation ! or for regress. -! Need to select the appropriate transform. At present, options are NORMAL_PRIOR -! which does nothing or BOUNDED_NORMAL_RH_PRIOR. +! Need to select the appropriate transform. At present, the options are NORMAL_DISTRIBUTION, +! BOUNDED_NORMAL_RH_DISTRIBUTION, GAMMA_DISTRIBUTION, BETA_DISTRIBUTION, LOG_NORMAL_DISTRIBUTION, +! UNIFORM_DISTRIBUTION, and PARTICLE_FILTER_DISTRIBUTION. ! If the BNRH is selected then information about the bounds must also be set. ! The two dimensional logical array 'bounded' is set to false for no bounds and true ! for bounded. the first element of the array is for the lower bound, the second for the upper. From 040b82d0c434ed5c91b227eb7d4dd0aa5c4a5ed2 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 3 Oct 2023 15:02:57 -0600 Subject: [PATCH 062/129] Using HEADER_LINES parameter to replace hardcoded number --- assimilation_code/modules/assimilation/algorithm_info_mod.f90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 7f213881ca..2ad60e3681 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -81,6 +81,7 @@ module algorithm_info_mod type(obs_inc_info_type) :: obs_inc_info end type +integer, parameter :: HEADER_LINES = 2 character(len=129), dimension(4) :: header1 character(len=129), dimension(29) :: header2 @@ -130,7 +131,7 @@ subroutine init_algorithm_info_mod(qcf_table_filename) call close_file(fileid) -numrows = nlines - 2 +numrows = nlines - HEADER_LINES allocate(qcf_table_data(numrows)) allocate(qcf_table_row_headers(numrows)) From d59e3c130f07d018ed5faad1f67e424c6fb70c32 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 3 Oct 2023 15:31:55 -0600 Subject: [PATCH 063/129] Changing the name of the logical qcf_table_listed to use_qty_defaults --- .../modules/assimilation/algorithm_info_mod.f90 | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 2ad60e3681..b1d2ad321c 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -25,7 +25,7 @@ module algorithm_info_mod character(len=*), parameter :: source = 'algorithm_info_mod.f90' logical :: module_initialized = .false. -logical :: qcf_table_listed = .false. +logical :: use_qty_defaults = .true. ! Defining parameter strings for different observation space filters ! For now, retaining backwards compatibility in assim_tools_mod requires using @@ -118,7 +118,7 @@ subroutine init_algorithm_info_mod(qcf_table_filename) return endif -qcf_table_listed = .true. +use_qty_defaults = .false. fileid = open_file(trim(qcf_table_filename), 'formatted', 'read') ! Do loop to get number of rows (or QTY's) in the table @@ -217,7 +217,7 @@ subroutine obs_error_info(obs_def, error_variance, & error_variance = get_obs_def_error_variance(obs_def) !use default values if qcf_table_filename is not in namelist -if (.not. qcf_table_listed) then +if (use_qty_defaults) then bounded_below = .false.; bounded_above = .false. lower_bound = missing_r8; upper_bound = missing_r8 return @@ -306,7 +306,7 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & possible_dist_type_ints(7) = 7 !use default values if qcf_table_filename is not in namelist -if (.not. qcf_table_listed) then +if (use_qty_defaults) then dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION bounded_below = .false.; bounded_above = .false. lower_bound = missing_r8; upper_bound = missing_r8 @@ -435,7 +435,7 @@ subroutine obs_inc_info(obs_qty, filter_kind, rectangular_quadrature, gaussian_l possible_filter_kind_ints(5) = 101 !use default values if qcf_table_filename is not in namelist -if (.not. qcf_table_listed) then +if (use_qty_defaults) then filter_kind = BOUNDED_NORMAL_RHF bounded_below = .false.; bounded_above = .false. lower_bound = missing_r8; upper_bound = missing_r8 @@ -511,7 +511,7 @@ subroutine verify_qcf_table_data() integer :: varid integer :: row -if (.not. qcf_table_listed) return +if (use_qty_defaults) return !Checks that all bounds are valid; currently checks that the lower bound in less than the upper !Here we could add more specific checks if we have known limits on the bounds @@ -577,7 +577,7 @@ subroutine log_qcf_table_data() character(len=2000) :: log_msg integer :: row -if (.not. qcf_table_listed) return +if (use_qty_defaults) return call error_handler(E_MSG, '', '', source) !Writing blank line to log call error_handler(E_MSG, 'log_qcf_table_data:', 'Logging the data in the QCF Table', source) @@ -618,7 +618,7 @@ subroutine end_algorithm_info_mod() if (.not. module_initialized) return module_initialized = .false. -if (.not. qcf_table_listed) return +if (use_qty_defaults) return deallocate(qcf_table_data) deallocate(qcf_table_row_headers) From d8addde6831f41f54eae5b449d7d7f8322bd9b69 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 3 Oct 2023 15:40:01 -0600 Subject: [PATCH 064/129] Changing the name of qcf_table_data_type to algorithm_info_type --- assimilation_code/modules/assimilation/algorithm_info_mod.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index b1d2ad321c..5ea50039b1 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -73,7 +73,7 @@ module algorithm_info_mod real(r8) :: lower_bound, upper_bound end type -type qcf_table_data_type +type algorithm_info_type type(obs_error_info_type) :: obs_error_info type(probit_inflation_type) :: probit_inflation type(probit_state_type) :: probit_state @@ -86,7 +86,7 @@ module algorithm_info_mod character(len=129), dimension(29) :: header2 character(len=129), allocatable :: qcf_table_row_headers(:) -type(qcf_table_data_type), allocatable :: qcf_table_data(:) +type(algorithm_info_type), allocatable :: qcf_table_data(:) ! Provides routines that give information about details of algorithms for ! observation error sampling, observation increments, and the transformations From 6a5fbb6126d472a48a449ab6f13ff671c59bfb41 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 3 Oct 2023 15:47:27 -0600 Subject: [PATCH 065/129] Removing old alternatives for algorithm_info_mod.f90 --- .../assimilation/all_eakf_algorithm_info_mod | 241 ------------------ .../assimilation/neg_algorithm_info_mod | 241 ------------------ .../assimilation/one_above_algorithm_info_mod | 241 ------------------ ...state_eakf_tracer_bnrhf_algorithm_info_mod | 241 ------------------ models/cam-fv/work/algorithm_info_mod.f90 | 216 ---------------- 5 files changed, 1180 deletions(-) delete mode 100644 assimilation_code/modules/assimilation/all_eakf_algorithm_info_mod delete mode 100644 assimilation_code/modules/assimilation/neg_algorithm_info_mod delete mode 100644 assimilation_code/modules/assimilation/one_above_algorithm_info_mod delete mode 100644 assimilation_code/modules/assimilation/state_eakf_tracer_bnrhf_algorithm_info_mod delete mode 100644 models/cam-fv/work/algorithm_info_mod.f90 diff --git a/assimilation_code/modules/assimilation/all_eakf_algorithm_info_mod b/assimilation_code/modules/assimilation/all_eakf_algorithm_info_mod deleted file mode 100644 index 37628cfb30..0000000000 --- a/assimilation_code/modules/assimilation/all_eakf_algorithm_info_mod +++ /dev/null @@ -1,241 +0,0 @@ -! 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 - -module algorithm_info_mod - -use types_mod, only : r8, i8 - -use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance -use obs_kind_mod, only : get_quantity_for_type_of_obs - -! Get the QTY definitions that are needed (aka kind) -use obs_kind_mod, only : QTY_STATE_VARIABLE, QTY_STATE_VAR_POWER, QTY_TRACER_CONCENTRATION, & - QTY_TRACER_SOURCE -! NOTE: Sadly, the QTY itself is not sufficient for the POWER because there is additional metadata - -use assim_model_mod, only : get_state_meta_data -use location_mod, only : location_type - -implicit none -private - -! Defining parameter strings for different observation space filters -! For now, retaining backwards compatibility in assim_tools_mod requires using -! these specific integer values and there is no point in using these in assim_tools. -! That will change if backwards compatibility is removed in the future. -integer, parameter :: EAKF = 1 -integer, parameter :: ENKF = 2 -integer, parameter :: UNBOUNDED_RHF = 8 -integer, parameter :: GAMMA_FILTER = 11 -integer, parameter :: BOUNDED_NORMAL_RHF = 101 - -! Defining parameter strings for different prior distributions that can be used for probit transform -integer, parameter :: NORMAL_PRIOR = 1 -integer, parameter :: BOUNDED_NORMAL_RH_PRIOR = 2 -integer, parameter :: GAMMA_PRIOR = 3 -integer, parameter :: BETA_PRIOR = 4 -integer, parameter :: LOG_NORMAL_PRIOR = 5 -integer, parameter :: UNIFORM_PRIOR = 6 - -public :: obs_error_info, probit_dist_info, obs_inc_info, & - EAKF, ENKF, BOUNDED_NORMAL_RHF, UNBOUNDED_RHF, GAMMA_FILTER, & - NORMAL_PRIOR, BOUNDED_NORMAL_RH_PRIOR, GAMMA_PRIOR, BETA_PRIOR, LOG_NORMAL_PRIOR, & - UNIFORM_PRIOR - -! Provides routines that give information about details of algorithms for -! observation error sampling, observation increments, and the transformations -! for regression and inflation in probit space. -! For now, it is convenient to have these in a single module since several -! users will be developing their own problem specific versions of these -! subroutines. This will avoid constant merge conflicts as other parts of the -! assimilation code are updated. - -contains - -!------------------------------------------------------------------------- -subroutine obs_error_info(obs_def, error_variance, bounded, bounds) - -! Computes information needed to compute error sample for this observation -! This is called by perfect_model_obs when generating noisy obs -type(obs_def_type), intent(in) :: obs_def -real(r8), intent(out) :: error_variance -logical, intent(out) :: bounded(2) -real(r8), intent(out) :: bounds(2) - -integer :: obs_type, obs_kind -integer(i8) :: state_var_index -type(location_type) :: temp_loc - -! Get the kind of the observation -obs_type = get_obs_def_type_of_obs(obs_def) -! If it is negative, it is an identity obs -if(obs_type < 0) then - state_var_index = -1 * obs_type - call get_state_meta_data(state_var_index, temp_loc, obs_kind) -else - obs_kind = get_quantity_for_type_of_obs(obs_type) -endif - -! Get the default error variance -error_variance = get_obs_def_error_variance(obs_def) - -! Set the observation error details for each type of quantity -if(obs_kind == QTY_STATE_VARIABLE) then - bounded = .false. -elseif(obs_kind == QTY_TRACER_CONCENTRATION) then - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 -elseif(obs_kind == QTY_TRACER_SOURCE) then - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 -else - write(*, *) 'Illegal obs_kind in obs_error_info' - stop -endif - -end subroutine obs_error_info - - -!------------------------------------------------------------------------- - - -subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & - bounded, bounds) - -! Computes the details of the probit transform for initial experiments -! with Molly - -integer, intent(in) :: kind -logical, intent(in) :: is_state ! True for state variable, false for obs -logical, intent(in) :: is_inflation ! True for inflation transform -integer, intent(out) :: dist_type -logical, intent(out) :: bounded(2) -real(r8), intent(out) :: bounds(2) - -! Have input information about the kind of the state or observation being transformed -! along with additional logical info that indicates whether this is an observation -! or state variable and about whether the transformation is being done for inflation -! or for regress. -! Need to select the appropriate transform. At present, options are NORMAL_PRIOR -! which does nothing or BOUNDED_NORMAL_RH_PRIOR. -! If the BNRH is selected then information about the bounds must also be set. -! The two dimensional logical array 'bounded' is set to false for no bounds and true -! for bounded. the first element of the array is for the lower bound, the second for the upper. -! If bounded is chosen, the corresponding bound value(s) must be set in the two dimensional -! real array 'bounds'. -! For example, if my_state_kind corresponds to a sea ice fraction then an appropriate choice -! would be: -! bounded(1) = .true.; bounded(2) = .true. -! bounds(1) = 0.0_r8; bounds(2) = 1.0_r8 - -! In the long run, may not have to have separate controls for each of the input possibilities -! However, for now these are things that need to be explored for science understanding - -if(is_inflation) then - ! Case for inflation transformation - if(kind == QTY_STATE_VARIABLE) then - dist_type = NORMAL_PRIOR - bounded = .false. - elseif(kind == QTY_TRACER_CONCENTRATION) then - dist_type = NORMAL_PRIOR - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 - elseif(kind == QTY_TRACER_SOURCE) then - dist_type = NORMAL_PRIOR - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 - else - write(*, *) 'Illegal kind in obs_error_info' - stop - endif -elseif(is_state) then - ! Case for state variable priors - if(kind == QTY_STATE_VARIABLE) then - dist_type = NORMAL_PRIOR - bounded = .false. - elseif(kind == QTY_TRACER_CONCENTRATION) then - dist_type = NORMAL_PRIOR - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 - elseif(kind == QTY_TRACER_SOURCE) then - dist_type = NORMAL_PRIOR - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 - else - write(*, *) 'Illegal kind in obs_error_info' - stop - endif -else - ! This case is for observation (extended state) priors - if(kind == QTY_STATE_VARIABLE) then - dist_type = NORMAL_PRIOR - bounded = .false. - elseif(kind == QTY_TRACER_CONCENTRATION) then - dist_type = NORMAL_PRIOR - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 - elseif(kind == QTY_TRACER_SOURCE) then - dist_type = NORMAL_PRIOR - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 - else - write(*, *) 'Illegal kind in obs_error_info' - stop - endif -endif - -end subroutine probit_dist_info - -!------------------------------------------------------------------------ - - -subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_likelihood_tails, & - sort_obs_inc, spread_restoration, bounded, bounds) - -integer, intent(in) :: obs_kind -integer, intent(inout) :: filter_kind -logical, intent(inout) :: rectangular_quadrature, gaussian_likelihood_tails -logical, intent(inout) :: sort_obs_inc -logical, intent(inout) :: spread_restoration -logical, intent(inout) :: bounded(2) -real(r8), intent(inout) :: bounds(2) - -! The information arguments are all intent (inout). This means that if they are not set -! here, they retain the default values from the assim_tools_mod namelist. Bounds don't exist -! in that namelist, so default values are set in assim_tools_mod just before the call to here. - -! Temporary approach for setting the details of how to assimilate this observation -! This example is designed to reproduce the squared forward operator results from paper - - -! Set the observation increment details for each type of quantity -if(obs_kind == QTY_STATE_VARIABLE) then - filter_kind = EAKF - bounded = .false. -elseif(obs_kind == QTY_TRACER_CONCENTRATION) then - filter_kind = EAKF - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 -elseif(obs_kind == QTY_TRACER_SOURCE) then - filter_kind = EAKF - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 -else - write(*, *) 'Illegal obs_kind in obs_error_info' - stop -endif - -! Default settings for now for Icepack and tracer model tests -sort_obs_inc = .false. -spread_restoration = .false. - -! Only need to set these two for options the original RHF implementation -!!!rectangular_quadrature = .true. -!!!gaussian_likelihood_tails = .false. - -end subroutine obs_inc_info - -!------------------------------------------------------------------------ - -end module algorithm_info_mod diff --git a/assimilation_code/modules/assimilation/neg_algorithm_info_mod b/assimilation_code/modules/assimilation/neg_algorithm_info_mod deleted file mode 100644 index b02a2290e3..0000000000 --- a/assimilation_code/modules/assimilation/neg_algorithm_info_mod +++ /dev/null @@ -1,241 +0,0 @@ -! 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 - -module algorithm_info_mod - -use types_mod, only : r8, i8, missing_r8 - -use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance -use obs_kind_mod, only : get_quantity_for_type_of_obs - -! Get the QTY definitions that are needed (aka kind) -use obs_kind_mod, only : QTY_STATE_VARIABLE, QTY_STATE_VAR_POWER, QTY_TRACER_CONCENTRATION, & - QTY_TRACER_SOURCE -! NOTE: Sadly, the QTY itself is not sufficient for the POWER because there is additional metadata - -use assim_model_mod, only : get_state_meta_data -use location_mod, only : location_type - -use distribution_params_mod, only : NORMAL_DISTRIBUTION, BOUNDED_NORMAL_RH_DISTRIBUTION, & - GAMMA_DISTRIBUTION, BETA_DISTRIBUTION, LOG_NORMAL_DISTRIBUTION, UNIFORM_DISTRIBUTION, & - PARTICLE_FILTER_DISTRIBUTION - -implicit none -private - -! Defining parameter strings for different observation space filters -! For now, retaining backwards compatibility in assim_tools_mod requires using -! these specific integer values and there is no point in using these in assim_tools. -! That will change if backwards compatibility is removed in the future. -integer, parameter :: EAKF = 1 -integer, parameter :: ENKF = 2 -integer, parameter :: UNBOUNDED_RHF = 8 -integer, parameter :: GAMMA_FILTER = 11 -integer, parameter :: BOUNDED_NORMAL_RHF = 101 - -public :: obs_error_info, probit_dist_info, obs_inc_info, & - EAKF, ENKF, BOUNDED_NORMAL_RHF, UNBOUNDED_RHF, GAMMA_FILTER - -! Provides routines that give information about details of algorithms for -! observation error sampling, observation increments, and the transformations -! for regression and inflation in probit space. -! For now, it is convenient to have these in a single module since several -! users will be developing their own problem specific versions of these -! subroutines. This will avoid constant merge conflicts as other parts of the -! assimilation code are updated. - -contains - -!------------------------------------------------------------------------- -subroutine obs_error_info(obs_def, error_variance, & - bounded_below, bounded_above, lower_bound, upper_bound) - -! Computes information needed to compute error sample for this observation -! This is called by perfect_model_obs when generating noisy obs -type(obs_def_type), intent(in) :: obs_def -real(r8), intent(out) :: error_variance -logical, intent(out) :: bounded_below, bounded_above -real(r8), intent(out) :: lower_bound, upper_bound - -integer :: obs_type, obs_kind -integer(i8) :: state_var_index -type(location_type) :: temp_loc - -! Get the kind of the observation -obs_type = get_obs_def_type_of_obs(obs_def) -! If it is negative, it is an identity obs -if(obs_type < 0) then - state_var_index = -1 * obs_type - call get_state_meta_data(state_var_index, temp_loc, obs_kind) -else - obs_kind = get_quantity_for_type_of_obs(obs_type) -endif - -! Get the default error variance -error_variance = get_obs_def_error_variance(obs_def) - -! Set the observation error details for each type of quantity -if(obs_kind == QTY_STATE_VARIABLE) then - bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 -elseif(obs_kind == QTY_TRACER_CONCENTRATION) then - bounded_below = .false.; bounded_above = .true. - lower_bound = missing_r8; upper_bound = 0.0_r8 -elseif(obs_kind == QTY_TRACER_SOURCE) then - bounded_below = .false.; bounded_above = .true. - lower_bound = missing_r8; upper_bound = 0.0_r8 -else - write(*, *) 'Illegal obs_kind in obs_error_info' - stop -endif - -end subroutine obs_error_info - - -!------------------------------------------------------------------------- - - -subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & - bounded_below, bounded_above, lower_bound, upper_bound) - -! Computes the details of the probit transform for initial experiments -! with Molly - -integer, intent(in) :: kind -logical, intent(in) :: is_state ! True for state variable, false for obs -logical, intent(in) :: is_inflation ! True for inflation transform -integer, intent(out) :: dist_type -logical, intent(out) :: bounded_below, bounded_above -real(r8), intent(out) :: lower_bound, upper_bound - -! Have input information about the kind of the state or observation being transformed -! along with additional logical info that indicates whether this is an observation -! or state variable and about whether the transformation is being done for inflation -! or for regress. -! Need to select the appropriate transform. At present, options are NORMAL_DISTRIBUTION -! which does nothing or BOUNDED_NORMAL_RH_DISTRIBUTION. -! If the BNRH is selected then information about the bounds must also be set. -! The two dimensional logical array 'bounded' is set to false for no bounds and true -! for bounded. the first element of the array is for the lower bound, the second for the upper. -! If bounded is chosen, the corresponding bound value(s) must be set in the two dimensional -! real array 'bounds'. -! For example, if my_state_kind corresponds to a sea ice fraction then an appropriate choice -! would be: -! bounded_below = .true.; bounded_above = .true. -! lower_bound = 0.0_r8; upper_bounds = 1.0_r8 - -! In the long run, may not have to have separate controls for each of the input possibilities -! However, for now these are things that need to be explored for science understanding - -if(is_inflation) then - ! Case for inflation transformation - if(kind == QTY_STATE_VARIABLE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 - elseif(kind == QTY_TRACER_CONCENTRATION) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .true. - lower_bound = missing_r8; upper_bound = 0.0_r8 - elseif(kind == QTY_TRACER_SOURCE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .true. - lower_bound = missing_r8; upper_bound = 0.0_r8 - else - write(*, *) 'Illegal kind in obs_error_info' - stop - endif -elseif(is_state) then - ! Case for state variable priors - if(kind == QTY_STATE_VARIABLE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 - elseif(kind == QTY_TRACER_CONCENTRATION) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .true. - lower_bound = missing_r8; upper_bound = 0.0_r8 - elseif(kind == QTY_TRACER_SOURCE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .true. - lower_bound = missing_r8; upper_bound = 0.0_r8 - else - write(*, *) 'Illegal kind in obs_error_info' - stop - endif -else - ! This case is for observation (extended state) priors - if(kind == QTY_STATE_VARIABLE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 - elseif(kind == QTY_TRACER_CONCENTRATION) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .true. - lower_bound = missing_r8; upper_bound = 0.0_r8 - elseif(kind == QTY_TRACER_SOURCE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .true. - lower_bound = missing_r8; upper_bound = 0.0_r8 - else - write(*, *) 'Illegal kind in obs_error_info' - stop - endif -endif - -end subroutine probit_dist_info - -!------------------------------------------------------------------------ - - -subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_likelihood_tails, & - sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound) - -integer, intent(in) :: obs_kind -integer, intent(inout) :: filter_kind -logical, intent(inout) :: rectangular_quadrature, gaussian_likelihood_tails -logical, intent(inout) :: sort_obs_inc -logical, intent(inout) :: spread_restoration -logical, intent(inout) :: bounded_below, bounded_above -real(r8), intent(inout) :: lower_bound, upper_bound - -! The information arguments are all intent (inout). This means that if they are not set -! here, they retain the default values from the assim_tools_mod namelist. Bounds don't exist -! in that namelist, so default values are set in assim_tools_mod just before the call to here. - -! Temporary approach for setting the details of how to assimilate this observation -! This example is designed to reproduce the squared forward operator results from paper - - -! Set the observation increment details for each type of quantity -if(obs_kind == QTY_STATE_VARIABLE) then - filter_kind = BOUNDED_NORMAL_RHF - bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 -elseif(obs_kind == QTY_TRACER_CONCENTRATION) then - filter_kind = BOUNDED_NORMAL_RHF - bounded_below = .false.; bounded_above = .true. - lower_bound = missing_r8; upper_bound = 0.0_r8 -elseif(obs_kind == QTY_TRACER_SOURCE) then - filter_kind = BOUNDED_NORMAL_RHF - bounded_below = .false.; bounded_above = .true. - lower_bound = missing_r8; upper_bound = 0.0_r8 -else - write(*, *) 'Illegal obs_kind in obs_error_info' - stop -endif - -! Default settings for now for Icepack and tracer model tests -sort_obs_inc = .false. -spread_restoration = .false. - -! Only need to set these two for options the original RHF implementation -!!!rectangular_quadrature = .true. -!!!gaussian_likelihood_tails = .false. - -end subroutine obs_inc_info - -!------------------------------------------------------------------------ - -end module algorithm_info_mod diff --git a/assimilation_code/modules/assimilation/one_above_algorithm_info_mod b/assimilation_code/modules/assimilation/one_above_algorithm_info_mod deleted file mode 100644 index f7e404bb3d..0000000000 --- a/assimilation_code/modules/assimilation/one_above_algorithm_info_mod +++ /dev/null @@ -1,241 +0,0 @@ -! 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 - -module algorithm_info_mod - -use types_mod, only : r8, i8, missing_r8 - -use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance -use obs_kind_mod, only : get_quantity_for_type_of_obs - -! Get the QTY definitions that are needed (aka kind) -use obs_kind_mod, only : QTY_STATE_VARIABLE, QTY_STATE_VAR_POWER, QTY_TRACER_CONCENTRATION, & - QTY_TRACER_SOURCE -! NOTE: Sadly, the QTY itself is not sufficient for the POWER because there is additional metadata - -use assim_model_mod, only : get_state_meta_data -use location_mod, only : location_type - -use distribution_params_mod, only : NORMAL_DISTRIBUTION, BOUNDED_NORMAL_RH_DISTRIBUTION, & - GAMMA_DISTRIBUTION, BETA_DISTRIBUTION, LOG_NORMAL_DISTRIBUTION, UNIFORM_DISTRIBUTION, & - PARTICLE_FILTER_DISTRIBUTION - -implicit none -private - -! Defining parameter strings for different observation space filters -! For now, retaining backwards compatibility in assim_tools_mod requires using -! these specific integer values and there is no point in using these in assim_tools. -! That will change if backwards compatibility is removed in the future. -integer, parameter :: EAKF = 1 -integer, parameter :: ENKF = 2 -integer, parameter :: UNBOUNDED_RHF = 8 -integer, parameter :: GAMMA_FILTER = 11 -integer, parameter :: BOUNDED_NORMAL_RHF = 101 - -public :: obs_error_info, probit_dist_info, obs_inc_info, & - EAKF, ENKF, BOUNDED_NORMAL_RHF, UNBOUNDED_RHF, GAMMA_FILTER - -! Provides routines that give information about details of algorithms for -! observation error sampling, observation increments, and the transformations -! for regression and inflation in probit space. -! For now, it is convenient to have these in a single module since several -! users will be developing their own problem specific versions of these -! subroutines. This will avoid constant merge conflicts as other parts of the -! assimilation code are updated. - -contains - -!------------------------------------------------------------------------- -subroutine obs_error_info(obs_def, error_variance, & - bounded_below, bounded_above, lower_bound, upper_bound) - -! Computes information needed to compute error sample for this observation -! This is called by perfect_model_obs when generating noisy obs -type(obs_def_type), intent(in) :: obs_def -real(r8), intent(out) :: error_variance -logical, intent(out) :: bounded_below, bounded_above -real(r8), intent(out) :: lower_bound, upper_bound - -integer :: obs_type, obs_kind -integer(i8) :: state_var_index -type(location_type) :: temp_loc - -! Get the kind of the observation -obs_type = get_obs_def_type_of_obs(obs_def) -! If it is negative, it is an identity obs -if(obs_type < 0) then - state_var_index = -1 * obs_type - call get_state_meta_data(state_var_index, temp_loc, obs_kind) -else - obs_kind = get_quantity_for_type_of_obs(obs_type) -endif - -! Get the default error variance -error_variance = get_obs_def_error_variance(obs_def) - -! Set the observation error details for each type of quantity -if(obs_kind == QTY_STATE_VARIABLE) then - bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 -elseif(obs_kind == QTY_TRACER_CONCENTRATION) then - bounded_below = .true.; bounded_above = .true. - lower_bound = -10.0_r8; upper_bound = 1.0_r8 -elseif(obs_kind == QTY_TRACER_SOURCE) then - bounded_below = .false.; bounded_above = .true. - lower_bound = missing_r8; upper_bound = 0.0_r8 -else - write(*, *) 'Illegal obs_kind in obs_error_info' - stop -endif - -end subroutine obs_error_info - - -!------------------------------------------------------------------------- - - -subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & - bounded_below, bounded_above, lower_bound, upper_bound) - -! Computes the details of the probit transform for initial experiments -! with Molly - -integer, intent(in) :: kind -logical, intent(in) :: is_state ! True for state variable, false for obs -logical, intent(in) :: is_inflation ! True for inflation transform -integer, intent(out) :: dist_type -logical, intent(out) :: bounded_below, bounded_above -real(r8), intent(out) :: lower_bound, upper_bound - -! Have input information about the kind of the state or observation being transformed -! along with additional logical info that indicates whether this is an observation -! or state variable and about whether the transformation is being done for inflation -! or for regress. -! Need to select the appropriate transform. At present, options are NORMAL_DISTRIBUTION -! which does nothing or BOUNDED_NORMAL_RH_DISTRIBUTION. -! If the BNRH is selected then information about the bounds must also be set. -! The two dimensional logical array 'bounded' is set to false for no bounds and true -! for bounded. the first element of the array is for the lower bound, the second for the upper. -! If bounded is chosen, the corresponding bound value(s) must be set in the two dimensional -! real array 'bounds'. -! For example, if my_state_kind corresponds to a sea ice fraction then an appropriate choice -! would be: -! bounded_below = .true.; bounded_above = .true. -! lower_bound = 0.0_r8; upper_bounds = 1.0_r8 - -! In the long run, may not have to have separate controls for each of the input possibilities -! However, for now these are things that need to be explored for science understanding - -if(is_inflation) then - ! Case for inflation transformation - if(kind == QTY_STATE_VARIABLE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 - elseif(kind == QTY_TRACER_CONCENTRATION) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .true.; bounded_above = .true. - lower_bound = -10.0_r8; upper_bound = 1.0_r8 - elseif(kind == QTY_TRACER_SOURCE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .true. - lower_bound = missing_r8; upper_bound = 0.0_r8 - else - write(*, *) 'Illegal kind in obs_error_info' - stop - endif -elseif(is_state) then - ! Case for state variable priors - if(kind == QTY_STATE_VARIABLE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 - elseif(kind == QTY_TRACER_CONCENTRATION) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .true.; bounded_above = .true. - lower_bound = -10.0_r8; upper_bound = 1.0_r8 - elseif(kind == QTY_TRACER_SOURCE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .true. - lower_bound = missing_r8; upper_bound = 0.0_r8 - else - write(*, *) 'Illegal kind in obs_error_info' - stop - endif -else - ! This case is for observation (extended state) priors - if(kind == QTY_STATE_VARIABLE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 - elseif(kind == QTY_TRACER_CONCENTRATION) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .true.; bounded_above = .true. - lower_bound = -10.0_r8; upper_bound = 1.0_r8 - elseif(kind == QTY_TRACER_SOURCE) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below = .false.; bounded_above = .true. - lower_bound = missing_r8; upper_bound = 0.0_r8 - else - write(*, *) 'Illegal kind in obs_error_info' - stop - endif -endif - -end subroutine probit_dist_info - -!------------------------------------------------------------------------ - - -subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_likelihood_tails, & - sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound) - -integer, intent(in) :: obs_kind -integer, intent(inout) :: filter_kind -logical, intent(inout) :: rectangular_quadrature, gaussian_likelihood_tails -logical, intent(inout) :: sort_obs_inc -logical, intent(inout) :: spread_restoration -logical, intent(inout) :: bounded_below, bounded_above -real(r8), intent(inout) :: lower_bound, upper_bound - -! The information arguments are all intent (inout). This means that if they are not set -! here, they retain the default values from the assim_tools_mod namelist. Bounds don't exist -! in that namelist, so default values are set in assim_tools_mod just before the call to here. - -! Temporary approach for setting the details of how to assimilate this observation -! This example is designed to reproduce the squared forward operator results from paper - - -! Set the observation increment details for each type of quantity -if(obs_kind == QTY_STATE_VARIABLE) then - filter_kind = BOUNDED_NORMAL_RHF - bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 -elseif(obs_kind == QTY_TRACER_CONCENTRATION) then - filter_kind = BOUNDED_NORMAL_RHF - bounded_below = .true.; bounded_above = .true. - lower_bound = -10.0_r8; upper_bound = 1.0_r8 -elseif(obs_kind == QTY_TRACER_SOURCE) then - filter_kind = BOUNDED_NORMAL_RHF - bounded_below = .false.; bounded_above = .true. - lower_bound = missing_r8; upper_bound = 0.0_r8 -else - write(*, *) 'Illegal obs_kind in obs_error_info' - stop -endif - -! Default settings for now for Icepack and tracer model tests -sort_obs_inc = .false. -spread_restoration = .false. - -! Only need to set these two for options the original RHF implementation -!!!rectangular_quadrature = .true. -!!!gaussian_likelihood_tails = .false. - -end subroutine obs_inc_info - -!------------------------------------------------------------------------ - -end module algorithm_info_mod diff --git a/assimilation_code/modules/assimilation/state_eakf_tracer_bnrhf_algorithm_info_mod b/assimilation_code/modules/assimilation/state_eakf_tracer_bnrhf_algorithm_info_mod deleted file mode 100644 index 6daf65ddf3..0000000000 --- a/assimilation_code/modules/assimilation/state_eakf_tracer_bnrhf_algorithm_info_mod +++ /dev/null @@ -1,241 +0,0 @@ -! 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 - -module algorithm_info_mod - -use types_mod, only : r8, i8 - -use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance -use obs_kind_mod, only : get_quantity_for_type_of_obs - -! Get the QTY definitions that are needed (aka kind) -use obs_kind_mod, only : QTY_STATE_VARIABLE, QTY_STATE_VAR_POWER, QTY_TRACER_CONCENTRATION, & - QTY_TRACER_SOURCE -! NOTE: Sadly, the QTY itself is not sufficient for the POWER because there is additional metadata - -use assim_model_mod, only : get_state_meta_data -use location_mod, only : location_type - -implicit none -private - -! Defining parameter strings for different observation space filters -! For now, retaining backwards compatibility in assim_tools_mod requires using -! these specific integer values and there is no point in using these in assim_tools. -! That will change if backwards compatibility is removed in the future. -integer, parameter :: EAKF = 1 -integer, parameter :: ENKF = 2 -integer, parameter :: UNBOUNDED_RHF = 8 -integer, parameter :: GAMMA_FILTER = 11 -integer, parameter :: BOUNDED_NORMAL_RHF = 101 - -! Defining parameter strings for different prior distributions that can be used for probit transform -integer, parameter :: NORMAL_PRIOR = 1 -integer, parameter :: BOUNDED_NORMAL_RH_PRIOR = 2 -integer, parameter :: GAMMA_PRIOR = 3 -integer, parameter :: BETA_PRIOR = 4 -integer, parameter :: LOG_NORMAL_PRIOR = 5 -integer, parameter :: UNIFORM_PRIOR = 6 - -public :: obs_error_info, probit_dist_info, obs_inc_info, & - EAKF, ENKF, BOUNDED_NORMAL_RHF, UNBOUNDED_RHF, GAMMA_FILTER, & - NORMAL_PRIOR, BOUNDED_NORMAL_RH_PRIOR, GAMMA_PRIOR, BETA_PRIOR, LOG_NORMAL_PRIOR, & - UNIFORM_PRIOR - -! Provides routines that give information about details of algorithms for -! observation error sampling, observation increments, and the transformations -! for regression and inflation in probit space. -! For now, it is convenient to have these in a single module since several -! users will be developing their own problem specific versions of these -! subroutines. This will avoid constant merge conflicts as other parts of the -! assimilation code are updated. - -contains - -!------------------------------------------------------------------------- -subroutine obs_error_info(obs_def, error_variance, bounded, bounds) - -! Computes information needed to compute error sample for this observation -! This is called by perfect_model_obs when generating noisy obs -type(obs_def_type), intent(in) :: obs_def -real(r8), intent(out) :: error_variance -logical, intent(out) :: bounded(2) -real(r8), intent(out) :: bounds(2) - -integer :: obs_type, obs_kind -integer(i8) :: state_var_index -type(location_type) :: temp_loc - -! Get the kind of the observation -obs_type = get_obs_def_type_of_obs(obs_def) -! If it is negative, it is an identity obs -if(obs_type < 0) then - state_var_index = -1 * obs_type - call get_state_meta_data(state_var_index, temp_loc, obs_kind) -else - obs_kind = get_quantity_for_type_of_obs(obs_type) -endif - -! Get the default error variance -error_variance = get_obs_def_error_variance(obs_def) - -! Set the observation error details for each type of quantity -if(obs_kind == QTY_STATE_VARIABLE) then - bounded = .false. -elseif(obs_kind == QTY_TRACER_CONCENTRATION) then - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 -elseif(obs_kind == QTY_TRACER_SOURCE) then - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 -else - write(*, *) 'Illegal obs_kind in obs_error_info' - stop -endif - -end subroutine obs_error_info - - -!------------------------------------------------------------------------- - - -subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & - bounded, bounds) - -! Computes the details of the probit transform for initial experiments -! with Molly - -integer, intent(in) :: kind -logical, intent(in) :: is_state ! True for state variable, false for obs -logical, intent(in) :: is_inflation ! True for inflation transform -integer, intent(out) :: dist_type -logical, intent(out) :: bounded(2) -real(r8), intent(out) :: bounds(2) - -! Have input information about the kind of the state or observation being transformed -! along with additional logical info that indicates whether this is an observation -! or state variable and about whether the transformation is being done for inflation -! or for regress. -! Need to select the appropriate transform. At present, options are NORMAL_PRIOR -! which does nothing or BOUNDED_NORMAL_RH_PRIOR. -! If the BNRH is selected then information about the bounds must also be set. -! The two dimensional logical array 'bounded' is set to false for no bounds and true -! for bounded. the first element of the array is for the lower bound, the second for the upper. -! If bounded is chosen, the corresponding bound value(s) must be set in the two dimensional -! real array 'bounds'. -! For example, if my_state_kind corresponds to a sea ice fraction then an appropriate choice -! would be: -! bounded(1) = .true.; bounded(2) = .true. -! bounds(1) = 0.0_r8; bounds(2) = 1.0_r8 - -! In the long run, may not have to have separate controls for each of the input possibilities -! However, for now these are things that need to be explored for science understanding - -if(is_inflation) then - ! Case for inflation transformation - if(kind == QTY_STATE_VARIABLE) then - dist_type = NORMAL_PRIOR - bounded = .false. - elseif(kind == QTY_TRACER_CONCENTRATION) then - dist_type = BOUNDED_NORMAL_RH_PRIOR - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 - elseif(kind == QTY_TRACER_SOURCE) then - dist_type = BOUNDED_NORMAL_RH_PRIOR - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 - else - write(*, *) 'Illegal kind in obs_error_info' - stop - endif -elseif(is_state) then - ! Case for state variable priors - if(kind == QTY_STATE_VARIABLE) then - dist_type = NORMAL_PRIOR - bounded = .false. - elseif(kind == QTY_TRACER_CONCENTRATION) then - dist_type = BOUNDED_NORMAL_RH_PRIOR - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 - elseif(kind == QTY_TRACER_SOURCE) then - dist_type = BOUNDED_NORMAL_RH_PRIOR - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 - else - write(*, *) 'Illegal kind in obs_error_info' - stop - endif -else - ! This case is for observation (extended state) priors - if(kind == QTY_STATE_VARIABLE) then - dist_type = NORMAL_PRIOR - bounded = .false. - elseif(kind == QTY_TRACER_CONCENTRATION) then - dist_type = BOUNDED_NORMAL_RH_PRIOR - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 - elseif(kind == QTY_TRACER_SOURCE) then - dist_type = BOUNDED_NORMAL_RH_PRIOR - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 - else - write(*, *) 'Illegal kind in obs_error_info' - stop - endif -endif - -end subroutine probit_dist_info - -!------------------------------------------------------------------------ - - -subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_likelihood_tails, & - sort_obs_inc, spread_restoration, bounded, bounds) - -integer, intent(in) :: obs_kind -integer, intent(inout) :: filter_kind -logical, intent(inout) :: rectangular_quadrature, gaussian_likelihood_tails -logical, intent(inout) :: sort_obs_inc -logical, intent(inout) :: spread_restoration -logical, intent(inout) :: bounded(2) -real(r8), intent(inout) :: bounds(2) - -! The information arguments are all intent (inout). This means that if they are not set -! here, they retain the default values from the assim_tools_mod namelist. Bounds don't exist -! in that namelist, so default values are set in assim_tools_mod just before the call to here. - -! Temporary approach for setting the details of how to assimilate this observation -! This example is designed to reproduce the squared forward operator results from paper - - -! Set the observation increment details for each type of quantity -if(obs_kind == QTY_STATE_VARIABLE) then - filter_kind = EAKF - bounded = .false. -elseif(obs_kind == QTY_TRACER_CONCENTRATION) then - filter_kind = BOUNDED_NORMAL_RHF - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 -elseif(obs_kind == QTY_TRACER_SOURCE) then - filter_kind = BOUNDED_NORMAL_RHF - bounded(1) = .true.; bounded(2) = .false. - bounds(1) = 0.0_r8; bounds(2) = 0.0_r8 -else - write(*, *) 'Illegal obs_kind in obs_error_info' - stop -endif - -! Default settings for now for Icepack and tracer model tests -sort_obs_inc = .false. -spread_restoration = .false. - -! Only need to set these two for options the original RHF implementation -!!!rectangular_quadrature = .true. -!!!gaussian_likelihood_tails = .false. - -end subroutine obs_inc_info - -!------------------------------------------------------------------------ - -end module algorithm_info_mod diff --git a/models/cam-fv/work/algorithm_info_mod.f90 b/models/cam-fv/work/algorithm_info_mod.f90 deleted file mode 100644 index 15bfcc3bc8..0000000000 --- a/models/cam-fv/work/algorithm_info_mod.f90 +++ /dev/null @@ -1,216 +0,0 @@ -! 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 - -module algorithm_info_mod - -use types_mod, only : r8, i8, missing_r8 - -use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance -use obs_kind_mod, only : get_quantity_for_type_of_obs - -! Get the QTY definitions that are needed (aka kind) -use obs_kind_mod, only : QTY_U_WIND_COMPONENT, QTY_V_WIND_COMPONENT, QTY_SURFACE_PRESSURE, & - QTY_TEMPERATURE, QTY_SPECIFIC_HUMIDITY, QTY_CLOUD_LIQUID_WATER, & - QTY_CLOUD_ICE, QTY_GPSRO - -use assim_model_mod, only : get_state_meta_data -use location_mod, only : location_type - -use distribution_params_mod, only : NORMAL_DISTRIBUTION, BOUNDED_NORMAL_RH_DISTRIBUTION, & - GAMMA_DISTRIBUTION, BETA_DISTRIBUTION, LOG_NORMAL_DISTRIBUTION, UNIFORM_DISTRIBUTION, & - PARTICLE_FILTER_DISTRIBUTION - -implicit none -private - -! Defining parameter strings for different observation space filters -! For now, retaining backwards compatibility in assim_tools_mod requires using -! these specific integer values and there is no point in using these in assim_tools. -! That will change if backwards compatibility is removed in the future. -integer, parameter :: EAKF = 1 -integer, parameter :: ENKF = 2 -integer, parameter :: UNBOUNDED_RHF = 8 -integer, parameter :: GAMMA_FILTER = 11 -integer, parameter :: BOUNDED_NORMAL_RHF = 101 - -public :: obs_error_info, probit_dist_info, obs_inc_info, & - EAKF, ENKF, BOUNDED_NORMAL_RHF, UNBOUNDED_RHF, GAMMA_FILTER - -! Provides routines that give information about details of algorithms for -! observation error sampling, observation increments, and the transformations -! for regression and inflation in probit space. -! For now, it is convenient to have these in a single module since several -! users will be developing their own problem specific versions of these -! subroutines. This will avoid constant merge conflicts as other parts of the -! assimilation code are updated. - -contains - -!------------------------------------------------------------------------- -subroutine obs_error_info(obs_def, error_variance, & - bounded_below, bounded_above, lower_bound, upper_bound) - -! Computes information needed to compute error sample for this observation -! This is called by perfect_model_obs when generating noisy obs -type(obs_def_type), intent(in) :: obs_def -real(r8), intent(out) :: error_variance -logical, intent(out) :: bounded_below, bounded_above -real(r8), intent(out) :: lower_bound, upper_bound - -integer :: obs_type, obs_kind -integer(i8) :: state_var_index -type(location_type) :: temp_loc - -! Get the kind of the observation -obs_type = get_obs_def_type_of_obs(obs_def) -! If it is negative, it is an identity obs -if(obs_type < 0) then - state_var_index = -1 * obs_type - call get_state_meta_data(state_var_index, temp_loc, obs_kind) -else - obs_kind = get_quantity_for_type_of_obs(obs_type) -endif - -! Get the default error variance -error_variance = get_obs_def_error_variance(obs_def) - -! Set the observation error details for each type of quantity -bounded_below = .false.; bounded_above = .false. -lower_bound = missing_r8; upper_bound = missing_r8 - -end subroutine obs_error_info - - -!------------------------------------------------------------------------- - - -subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & - bounded_below, bounded_above, lower_bound, upper_bound) - -! Computes the details of the probit transform for initial experiments -! with Molly - -integer, intent(in) :: kind -logical, intent(in) :: is_state ! True for state variable, false for obs -logical, intent(in) :: is_inflation ! True for inflation transform -integer, intent(out) :: dist_type -logical, intent(out) :: bounded_below, bounded_above -real(r8), intent(out) :: lower_bound, upper_bound - -! Have input information about the kind of the state or observation being transformed -! along with additional logical info that indicates whether this is an observation -! or state variable and about whether the transformation is being done for inflation -! or for regress. -! Need to select the appropriate transform. At present, options are NORMAL_PRIOR -! which does nothing or BOUNDED_NORMAL_RH_PRIOR. -! If the BNRH is selected then information about the bounds must also be set. -! The two dimensional logical array 'bounded' is set to false for no bounds and true -! for bounded. the first element of the array is for the lower bound, the second for the upper. -! If bounded is chosen, the corresponding bound value(s) must be set in the two dimensional -! real array 'bounds'. -! For example, if my_state_kind corresponds to a sea ice fraction then an appropriate choice -! would be: -! bounded_below = .true.; bounded_above = .true. -! lower_bound = 0.0_r8; upper_bounds = 1.0_r8 - -! In the long run, may not have to have separate controls for each of the input possibilities -! However, for now these are things that need to be explored for science understanding - -select case(kind) - case(QTY_U_WIND_COMPONENT, QTY_V_WIND_COMPONENT, QTY_SURFACE_PRESSURE, QTY_TEMPERATURE) - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION -! dist_type = NORMAL_PRIOR - bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 - -!-------------- - case(QTY_SPECIFIC_HUMIDITY) - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION -! dist_type = NORMAL_PRIOR -! bounded_below = .false.; bounded_above = .false. - bounded_below = .true.; bounded_above = .true. - lower_bound = 0.0_r8; upper_bound = 1.0_r8 - -!-------------- - case(QTY_CLOUD_LIQUID_WATER, QTY_CLOUD_ICE) - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION -! dist_type = NORMAL_PRIOR -! bound_below = .false.; bounded_above = .false. - bounded_below = .true.; bounded_above = .false. - lower_bound = 0.0_r8; upper_bound = missing_r8 - -!-------------- - case(QTY_GPSRO) - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION -! dist_type = NORMAL_PRIOR -! bounded_below = .false.; bounded_above = .false. - bounded_below = .true.; bounded_above = .false. - lower_bound = 0.0_r8; upper_bound = missing_r8 - -!-------------- - case DEFAULT - write(*, *) 'Unexpected QTY in algorithm_info_mod ', kind - stop -end select - -end subroutine probit_dist_info - -!------------------------------------------------------------------------ - - -subroutine obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_likelihood_tails, & - sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound) - -integer, intent(in) :: obs_kind -integer, intent(inout) :: filter_kind -logical, intent(inout) :: rectangular_quadrature, gaussian_likelihood_tails -logical, intent(inout) :: sort_obs_inc -logical, intent(inout) :: spread_restoration -logical, intent(inout) :: bounded_below, bounded_above -real(r8), intent(inout) :: lower_bound, upper_bound - -! The information arguments are all intent (inout). This means that if they are not set -! here, they retain the default values from the assim_tools_mod namelist. Bounds don't exist -! in that namelist, so default values are set in assim_tools_mod just before the call to here. - -! Temporary approach for setting the details of how to assimilate this observation -! This example is designed to reproduce the squared forward operator results from paper - -select case(obs_kind) - case(QTY_U_WIND_COMPONENT, QTY_V_WIND_COMPONENT, QTY_SURFACE_PRESSURE, QTY_TEMPERATURE) - ! Set the observation increment details for each type of quantity - filter_kind = BOUNDED_NORMAL_RHF - bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 - - case(QTY_GPSRO) - filter_kind = BOUNDED_NORMAL_RHF - bounded_below = .true.; bounded_above = .false. -! bounded_below = .false.; bounded_above = .false. - lower_bound = 0.0_r8; upper_bound = missing_r8 - - case(QTY_SPECIFIC_HUMIDITY) - filter_kind = BOUNDED_NORMAL_RHF - bounded_below = .true.; bounded_above = .true. -! bounded_below = .false.; bounded_above = .false. - lower_bound = 0.0_r8; upper_bound = 1.0_r8 - - case DEFAULT - write(*, *) 'Unexpected QTY in algorithm_info_mod ', obs_kind - stop -end select - -! Default settings for now for Icepack and tracer model tests -sort_obs_inc = .false. -spread_restoration = .false. - -! Only need to set these two for options the original RHF implementation -!!!rectangular_quadrature = .true. -!!!gaussian_likelihood_tails = .false. - -end subroutine obs_inc_info - -!------------------------------------------------------------------------ - -end module algorithm_info_mod From 320caed6dd342cb12c177926fe00bfc685340ce6 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 3 Oct 2023 17:48:01 -0600 Subject: [PATCH 066/129] Moving the conversions for dist_type and filter_kind from string to integer value to read_qcf_table, when the type is filled in --- .../assimilation/algorithm_info_mod.f90 | 196 +++++++++--------- 1 file changed, 96 insertions(+), 100 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 5ea50039b1..1749aa9e64 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -48,25 +48,25 @@ module algorithm_info_mod end type type probit_inflation_type - character(len=129) :: dist_type + integer :: dist_type logical :: bounded_below, bounded_above real(r8) :: lower_bound, upper_bound end type type probit_state_type - character(len=129) :: dist_type + integer :: dist_type logical :: bounded_below, bounded_above real(r8) :: lower_bound, upper_bound end type type probit_extended_state_type - character(len=129) :: dist_type + integer :: dist_type logical :: bounded_below, bounded_above real(r8) :: lower_bound, upper_bound end type type obs_inc_info_type - character(len=129) :: filter_kind + integer :: filter_kind logical :: rectangular_quadrature, gaussian_likelihood_tails logical :: sort_obs_inc, spread_restoration logical :: bounded_below, bounded_above @@ -88,6 +88,11 @@ module algorithm_info_mod character(len=129), allocatable :: qcf_table_row_headers(:) type(algorithm_info_type), allocatable :: qcf_table_data(:) +character(len=129) :: dist_type_string_probit_inflation +character(len=129) :: dist_type_string_probit_state +character(len=129) :: dist_type_string_probit_extended_state +character(len=129) :: filter_kind_string + ! Provides routines that give information about details of algorithms for ! observation error sampling, observation increments, and the transformations ! for regression and inflation in probit space. @@ -166,17 +171,92 @@ subroutine read_qcf_table(qcf_table_filename) ! read in table values directly to qcf_table_data type do row = 1, size(qcf_table_data) read(fileid, *) qcf_table_row_headers(row), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & - qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & + qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, dist_type_string_probit_inflation, & qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & - qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & + qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, dist_type_string_probit_state, & qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & - qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & + qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, dist_type_string_probit_extended_state, & qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & + filter_kind_string, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound + + ! Converting the distribution types (read in from table as a string) to its corresponding int value + if (trim(dist_type_string_probit_inflation) == 'NORMAL_DISTRIBUTION') then + qcf_table_data(row)%probit_inflation%dist_type = NORMAL_DISTRIBUTION + elseif (trim(dist_type_string_probit_inflation) == 'BOUNDED_NORMAL_RH_DISTRIBUTION') then + qcf_table_data(row)%probit_inflation%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION + elseif (trim(dist_type_string_probit_inflation) == 'GAMMA_DISTRIBUTION') then + qcf_table_data(row)%probit_inflation%dist_type = GAMMA_DISTRIBUTION + elseif (trim(dist_type_string_probit_inflation) == 'BETA_DISTRIBUTION') then + qcf_table_data(row)%probit_inflation%dist_type = BETA_DISTRIBUTION + elseif (trim(dist_type_string_probit_inflation) == 'LOG_NORMAL_DISTRIBUTION') then + qcf_table_data(row)%probit_inflation%dist_type = LOG_NORMAL_DISTRIBUTION + elseif (trim(dist_type_string_probit_inflation) == 'UNIFORM_DISTRIBUTION') then + qcf_table_data(row)%probit_inflation%dist_type = UNIFORM_DISTRIBUTION + elseif (trim(dist_type_string_probit_inflation) == 'PARTICLE_FILTER_DISTRIBUTION') then + qcf_table_data(row)%probit_inflation%dist_type = PARTICLE_FILTER_DISTRIBUTION + else + write(errstring, *) 'Invalid distribution type for probit inflation: ', trim(dist_type_string_probit_inflation) + call error_handler(E_ERR, 'read_qcf_table:', errstring, source) + endif + + if (trim(dist_type_string_probit_state) == 'NORMAL_DISTRIBUTION') then + qcf_table_data(row)%probit_state%dist_type = NORMAL_DISTRIBUTION + elseif (trim(dist_type_string_probit_state) == 'BOUNDED_NORMAL_RH_DISTRIBUTION') then + qcf_table_data(row)%probit_state%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION + elseif (trim(dist_type_string_probit_state) == 'GAMMA_DISTRIBUTION') then + qcf_table_data(row)%probit_state%dist_type = GAMMA_DISTRIBUTION + elseif (trim(dist_type_string_probit_state) == 'BETA_DISTRIBUTION') then + qcf_table_data(row)%probit_state%dist_type = BETA_DISTRIBUTION + elseif (trim(dist_type_string_probit_state) == 'LOG_NORMAL_DISTRIBUTION') then + qcf_table_data(row)%probit_state%dist_type = LOG_NORMAL_DISTRIBUTION + elseif (trim(dist_type_string_probit_state) == 'UNIFORM_DISTRIBUTION') then + qcf_table_data(row)%probit_state%dist_type = UNIFORM_DISTRIBUTION + elseif (trim(dist_type_string_probit_state) == 'PARTICLE_FILTER_DISTRIBUTION') then + qcf_table_data(row)%probit_state%dist_type = PARTICLE_FILTER_DISTRIBUTION + else + write(errstring, *) 'Invalid distribution type for probit state: ', trim(dist_type_string_probit_state) + call error_handler(E_ERR, 'read_qcf_table:', errstring, source) + endif + + if (trim(dist_type_string_probit_extended_state) == 'NORMAL_DISTRIBUTION') then + qcf_table_data(row)%probit_extended_state%dist_type = NORMAL_DISTRIBUTION + elseif (trim(dist_type_string_probit_extended_state) == 'BOUNDED_NORMAL_RH_DISTRIBUTION') then + qcf_table_data(row)%probit_extended_state%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION + elseif (trim(dist_type_string_probit_extended_state) == 'GAMMA_DISTRIBUTION') then + qcf_table_data(row)%probit_extended_state%dist_type = GAMMA_DISTRIBUTION + elseif (trim(dist_type_string_probit_extended_state) == 'BETA_DISTRIBUTION') then + qcf_table_data(row)%probit_extended_state%dist_type = BETA_DISTRIBUTION + elseif (trim(dist_type_string_probit_extended_state) == 'LOG_NORMAL_DISTRIBUTION') then + qcf_table_data(row)%probit_extended_state%dist_type = LOG_NORMAL_DISTRIBUTION + elseif (trim(dist_type_string_probit_extended_state) == 'UNIFORM_DISTRIBUTION') then + qcf_table_data(row)%probit_extended_state%dist_type = UNIFORM_DISTRIBUTION + elseif (trim(dist_type_string_probit_extended_state) == 'PARTICLE_FILTER_DISTRIBUTION') then + qcf_table_data(row)%probit_extended_state%dist_type = PARTICLE_FILTER_DISTRIBUTION + else + write(errstring, *) 'Invalid distribution type for probit extended state: ', trim(dist_type_string_probit_extended_state) + call error_handler(E_ERR, 'read_qcf_table:', errstring, source) + endif + + ! Converting the filter kind (read in from table as a string) to its corresponding int value + if (trim(filter_kind_string) == 'EAKF') then + qcf_table_data(row)%obs_inc_info%filter_kind = EAKF + elseif (trim(filter_kind_string) == 'ENKF') then + qcf_table_data(row)%obs_inc_info%filter_kind = ENKF + elseif (trim(filter_kind_string) == 'UNBOUNDED_RHF') then + qcf_table_data(row)%obs_inc_info%filter_kind = UNBOUNDED_RHF + elseif (trim(filter_kind_string) == 'GAMMA_FILTER') then + qcf_table_data(row)%obs_inc_info%filter_kind = GAMMA_FILTER + elseif (trim(filter_kind_string) == 'BOUNDED_NORMAL_RHF') then + qcf_table_data(row)%obs_inc_info%filter_kind = BOUNDED_NORMAL_RHF + else + write(errstring, *) 'Invalid filter kind: ', trim(filter_kind_string) + call error_handler(E_ERR, 'read_qcf_table:', errstring, source) + endif + end do call close_file(fileid) @@ -264,9 +344,6 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & character(len=129) :: qty_name integer :: dist_type_loc(1) -character(len=129), dimension(7) :: possible_dist_types -integer, dimension(7) :: possible_dist_type_ints -character(len=129) :: dist_type_string ! Have input information about the kind of the state or observation being transformed ! along with additional logical info that indicates whether this is an observation @@ -288,23 +365,6 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & ! In the long run, may not have to have separate controls for each of the input possibilities ! However, for now these are things that need to be explored for science understanding -! Fill arrays with possible dist_type strings and corresponding ints -possible_dist_types(1) = 'NORMAL_DISTRIBUTION' -possible_dist_types(2) = 'BOUNDED_NORMAL_RH_DISTRIBUTION' -possible_dist_types(3) = 'GAMMA_DISTRIBUTION' -possible_dist_types(4) = 'BETA_DISTRIBUTION' -possible_dist_types(5) = 'LOG_NORMAL_DISTRIBUTION' -possible_dist_types(6) = 'UNIFORM_DISTRIBUTION' -possible_dist_types(7) = 'PARTICLE_FILTER_DISTRIBUTION' - -possible_dist_type_ints(1) = 1 -possible_dist_type_ints(2) = 2 -possible_dist_type_ints(3) = 3 -possible_dist_type_ints(4) = 4 -possible_dist_type_ints(5) = 5 -possible_dist_type_ints(6) = 6 -possible_dist_type_ints(7) = 7 - !use default values if qcf_table_filename is not in namelist if (use_qty_defaults) then dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION @@ -328,19 +388,7 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & elseif(is_inflation) then ! Case for inflation transformation - ! Comparing the dist_type in string format to list of potential dist_types - dist_type_string = qcf_table_data(QTY_loc(1))%probit_inflation%dist_type - call to_upper(dist_type_string) - dist_type_loc = findloc(possible_dist_types, trim(dist_type_string)) - - if (dist_type_loc(1) == 0) then - write(errstring, *) 'Invalid dist_type: ', trim(dist_type_string) - call error_handler(E_ERR, 'probit_dist_info:', errstring, source) - - else - dist_type = possible_dist_type_ints(dist_type_loc(1)) - endif - + dist_type = qcf_table_data(QTY_loc(1))%probit_inflation%dist_type bounded_below = qcf_table_data(QTY_loc(1))%probit_inflation%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%probit_inflation%bounded_above lower_bound = qcf_table_data(QTY_loc(1))%probit_inflation%lower_bound @@ -349,19 +397,7 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & elseif(is_state) then ! Case for state variable priors - ! Comparing the dist_type in string format to list of potential dist_types - dist_type_string = qcf_table_data(QTY_loc(1))%probit_state%dist_type - call to_upper(dist_type_string) - dist_type_loc = findloc(possible_dist_types, trim(dist_type_string)) - - if (dist_type_loc(1) == 0) then - write(errstring, *) 'Invalid dist_type: ', trim(dist_type_string) - call error_handler(E_ERR, 'probit_dist_info:', errstring, source) - - else - dist_type = possible_dist_type_ints(dist_type_loc(1)) - endif - + dist_type = qcf_table_data(QTY_loc(1))%probit_state%dist_type bounded_below = qcf_table_data(QTY_loc(1))%probit_state%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%probit_state%bounded_above lower_bound = qcf_table_data(QTY_loc(1))%probit_state%lower_bound @@ -370,19 +406,7 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & else ! This case is for observation (extended state) priors - ! Comparing the dist_type in string format to list of potential dist_types - dist_type_string = qcf_table_data(QTY_loc(1))%probit_extended_state%dist_type - call to_upper(dist_type_string) - dist_type_loc = findloc(possible_dist_types, trim(dist_type_string)) - - if (dist_type_loc(1) == 0) then - write(errstring, *) 'Invalid dist_type: ', trim(dist_type_string) - call error_handler(E_ERR, 'probit_dist_info:', errstring, source) - - else - dist_type = possible_dist_type_ints(dist_type_loc(1)) - endif - + dist_type = qcf_table_data(QTY_loc(1))%probit_extended_state%dist_type bounded_below = qcf_table_data(QTY_loc(1))%probit_extended_state%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%probit_extended_state%bounded_above lower_bound = qcf_table_data(QTY_loc(1))%probit_extended_state%lower_bound @@ -410,9 +434,6 @@ subroutine obs_inc_info(obs_qty, filter_kind, rectangular_quadrature, gaussian_l character(len=129) :: qty_name integer :: filter_kind_loc(1) -character(len=129), dimension(5) :: possible_filter_kinds -integer, dimension(5) :: possible_filter_kind_ints -character(len=129) :: filter_kind_string ! The information arguments are all intent (inout). This means that if they are not set ! here, they retain the default values from the assim_tools_mod namelist. Bounds don't exist @@ -421,19 +442,6 @@ subroutine obs_inc_info(obs_qty, filter_kind, rectangular_quadrature, gaussian_l ! Temporary approach for setting the details of how to assimilate this observation ! This example is designed to reproduce the squared forward operator results from paper -! Fill arrays with possible filter_kind strings and corresponding ints -possible_filter_kinds(1) = 'EAKF' -possible_filter_kinds(2) = 'ENKF' -possible_filter_kinds(3) = 'UNBOUNDED_RHF' -possible_filter_kinds(4) = 'GAMMA_FILTER' -possible_filter_kinds(5) = 'BOUNDED_NORMAL_RHF' - -possible_filter_kind_ints(1) = 1 -possible_filter_kind_ints(2) = 2 -possible_filter_kind_ints(3) = 8 -possible_filter_kind_ints(4) = 11 -possible_filter_kind_ints(5) = 101 - !use default values if qcf_table_filename is not in namelist if (use_qty_defaults) then filter_kind = BOUNDED_NORMAL_RHF @@ -459,19 +467,7 @@ subroutine obs_inc_info(obs_qty, filter_kind, rectangular_quadrature, gaussian_l else - ! Comparing the filter_kind in string format to list of potential filter_kinds - filter_kind_string = qcf_table_data(QTY_loc(1))%obs_inc_info%filter_kind - call to_upper(filter_kind_string) - filter_kind_loc = findloc(possible_filter_kinds, trim(filter_kind_string)) - - if (filter_kind_loc(1) == 0) then - write(errstring, *) 'Invalid filter_kind: ', trim(filter_kind_string) - call error_handler(E_ERR, 'obs_inc_info:', errstring, source) - - else - filter_kind = possible_filter_kind_ints(filter_kind_loc(1)) - endif - + filter_kind = qcf_table_data(QTY_loc(1))%obs_inc_info%filter_kind sort_obs_inc = qcf_table_data(QTY_loc(1))%obs_inc_info%sort_obs_inc spread_restoration = qcf_table_data(QTY_loc(1))%obs_inc_info%spread_restoration bounded_below = qcf_table_data(QTY_loc(1))%obs_inc_info%bounded_below @@ -592,14 +588,14 @@ subroutine log_qcf_table_data() ! Write the table data to the dart_log and terminal do row = 1, size(qcf_table_data) write(log_msg, *) trim(qcf_table_row_headers(row)), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & - qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, trim(qcf_table_data(row)%probit_inflation%dist_type), & + qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & - qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, trim(qcf_table_data(row)%probit_state%dist_type), & + qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & - qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, trim(qcf_table_data(row)%probit_extended_state%dist_type), & + qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - trim(qcf_table_data(row)%obs_inc_info%filter_kind), qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & + qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound From b46a922aacd9f2226d15eccb0de22368196f9078 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 3 Oct 2023 17:57:09 -0600 Subject: [PATCH 067/129] removing python script for yaml files - will be moved to a separate pull request --- .../qcf_table/qcf_table_template.yaml | 69 ----------------- .../programs/qcf_table/yaml_to_table.py | 77 ------------------- 2 files changed, 146 deletions(-) delete mode 100644 assimilation_code/programs/qcf_table/qcf_table_template.yaml delete mode 100644 assimilation_code/programs/qcf_table/yaml_to_table.py diff --git a/assimilation_code/programs/qcf_table/qcf_table_template.yaml b/assimilation_code/programs/qcf_table/qcf_table_template.yaml deleted file mode 100644 index 46b46358af..0000000000 --- a/assimilation_code/programs/qcf_table/qcf_table_template.yaml +++ /dev/null @@ -1,69 +0,0 @@ -QCF table version: 1 -QTY_TEMPLATE: - obs_error_info: - bounded_below - bounded_above - lower_bound - upper_bound - probit_inflation: - dist_type - bounded_below - bounded_above - lower_bound - upper_bound - probit_state: - dist_type - bounded_below - bounded_above - lower_bound - upper_bound - probit_extended_state: - dist_type - bounded_below - bounded_above - lower_bound - upper_bound - obs_inc_info: - filter_kind - rectangular_quadrature - gaussian_likelihood_tails - sort_obs_inc - spread_restoration - bounded_below - bounded_above - lower_bound - upper_bound -QTY_STATE_VARIABLE: - obs_error_info: - bounded_below: .false. - bounded_above: .false. - lower_bound: -888888.0 - upper_bound: -888888.0 - probit_inflation: - dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below: .false. - bounded_above: .false. - lower_bound: -888888.0 - upper_bound: -888888.0 - probit_state: - dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below: .false. - bounded_above: .false. - lower_bound: -888888.0 - upper_bound: -888888.0 - probit_extended_state: - dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below: .false. - bounded_above: .false. - lower_bound: -888888.0 - upper_bound: -888888.0 - obs_inc_info: - filter_kind: BOUNDED_NORMAL_RHF - rectangular_quadrature: .false. - gaussian_likelihood_tails: .false. - sort_obs_inc: .false. - spread_restoration: .false. - bounded_below: .false. - bounded_above: .false. - lower_bound: -888888.0 - upper_bound: -888888.0 diff --git a/assimilation_code/programs/qcf_table/yaml_to_table.py b/assimilation_code/programs/qcf_table/yaml_to_table.py deleted file mode 100644 index fc765e7c36..0000000000 --- a/assimilation_code/programs/qcf_table/yaml_to_table.py +++ /dev/null @@ -1,77 +0,0 @@ -import yaml - -#Prompt user for name of input and output files -input_yaml = input('Please enter the name of your input yaml file (filename must end in ".yaml") OR press enter/return to use the default filename "qcf_table.yaml"\n') -output_txt = input('Please enter the name for the output file for the table (filename must end in ".txt") OR press enter/return to use the default filename "qcf_table.txt"\n') - -#Using deault names for input/output files if not specified -if (input_yaml == ''): - input_yaml = 'qcf_table.yaml' - -if (output_txt == ''): - output_txt = 'qcf_table.txt' - -#Open and load yaml file -with open(input_yaml) as file: - dict = yaml.safe_load(file) - - column_headers = list(dict.keys()) - column_data = list(dict.values()) - - obs_errror_info_header = dict['QTY_TEMPLATE']['obs_error_info'] - probit_inflation_header = dict['QTY_TEMPLATE']['probit_inflation'] - probit_state_header = dict['QTY_TEMPLATE']['probit_state'] - probit_extended_state_header = dict['QTY_TEMPLATE']['probit_extended_state'] - obs_inc_info_header = dict['QTY_TEMPLATE']['obs_inc_info'] - - f = open(output_txt, "w") - -#Write the table's headers to the output file - f.write(column_headers[0] + ": " + str(column_data[0]) + "\n") - - f.write(column_headers[1] + ": ") - for name in obs_errror_info_header: - f.write(name) - f.write(" ") - for name in probit_inflation_header: - f.write(name) - f.write(" ") - for name in probit_state_header: - f.write(name) - f.write(" ") - for name in probit_extended_state_header: - f.write(name) - f.write(" ") - for name in obs_inc_info_header: - f.write(name) - f.write("\n") - -#Writing table data to the output file - for i in range(2, len(column_headers)): - f.write(column_headers[i] + " ") - - obs_error_info = dict[column_headers[i]]['obs_error_info'].items() - for key, value in obs_error_info: - f.write(str(value) + " ") - - probit_inflation = dict[column_headers[i]]['probit_inflation'].items() - for key, value in probit_inflation: - f.write(str(value) + " ") - - probit_state = dict[column_headers[i]]['probit_state'].items() - for key, value in probit_state: - f.write(str(value) + " ") - - probit_extended_state = dict[column_headers[i]]['probit_extended_state'].items() - for key, value in probit_extended_state: - f.write(str(value) + " ") - - obs_inc_info = dict[column_headers[i]]['obs_inc_info'].items() - for key, value in obs_inc_info: - f.write(str(value) + " ") - - f.write("\n") - - f.close - -print('QCF table produced in ' + output_txt) From f2d20b78577eaf1b45a9e4b98f90749ca71b2a3b Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 4 Oct 2023 11:19:11 -0600 Subject: [PATCH 068/129] Changing the name of qcf_table_row_headers to specified_qtys --- .../assimilation/algorithm_info_mod.f90 | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 1749aa9e64..3ad3b401f1 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -85,7 +85,7 @@ module algorithm_info_mod character(len=129), dimension(4) :: header1 character(len=129), dimension(29) :: header2 -character(len=129), allocatable :: qcf_table_row_headers(:) +character(len=129), allocatable :: specified_qtys(:) type(algorithm_info_type), allocatable :: qcf_table_data(:) character(len=129) :: dist_type_string_probit_inflation @@ -138,8 +138,8 @@ subroutine init_algorithm_info_mod(qcf_table_filename) numrows = nlines - HEADER_LINES +allocate(specified_qtys(numrows)) allocate(qcf_table_data(numrows)) -allocate(qcf_table_row_headers(numrows)) call read_qcf_table(qcf_table_filename) call assert_qcf_table_version() @@ -170,7 +170,7 @@ subroutine read_qcf_table(qcf_table_filename) ! read in table values directly to qcf_table_data type do row = 1, size(qcf_table_data) - read(fileid, *) qcf_table_row_headers(row), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & + read(fileid, *) specified_qtys(row), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, dist_type_string_probit_inflation, & qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, dist_type_string_probit_state, & @@ -307,7 +307,7 @@ subroutine obs_error_info(obs_def, error_variance, & qty_name = get_name_for_quantity(obs_qty) !find location of QTY in qcf_table_data structure -QTY_loc = findloc(qcf_table_row_headers, qty_name) +QTY_loc = findloc(specified_qtys, qty_name) if (QTY_loc(1) == 0) then !use default values if QTY is not in table @@ -343,8 +343,6 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & integer :: QTY_loc(1) character(len=129) :: qty_name -integer :: dist_type_loc(1) - ! Have input information about the kind of the state or observation being transformed ! along with additional logical info that indicates whether this is an observation ! or state variable and about whether the transformation is being done for inflation @@ -377,7 +375,7 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & qty_name = get_name_for_quantity(kind) !find location of QTY in qcf_table_data structure -QTY_loc = findloc(qcf_table_row_headers, qty_name) +QTY_loc = findloc(specified_qtys, qty_name) if (QTY_loc(1) == 0) then !use default values if QTY is not in table @@ -433,8 +431,6 @@ subroutine obs_inc_info(obs_qty, filter_kind, rectangular_quadrature, gaussian_l integer :: QTY_loc(1) character(len=129) :: qty_name -integer :: filter_kind_loc(1) - ! The information arguments are all intent (inout). This means that if they are not set ! here, they retain the default values from the assim_tools_mod namelist. Bounds don't exist ! in that namelist, so default values are set in assim_tools_mod just before the call to here. @@ -455,7 +451,7 @@ subroutine obs_inc_info(obs_qty, filter_kind, rectangular_quadrature, gaussian_l qty_name = get_name_for_quantity(obs_qty) !find location of QTY in qcf_table_data structure -QTY_loc = findloc(qcf_table_row_headers, qty_name) +QTY_loc = findloc(specified_qtys, qty_name) if (QTY_loc(1) == 0) then !use default values if QTY is not in table @@ -547,17 +543,17 @@ subroutine verify_qcf_table_data() !Ensures that all QTYs listed in the table exist in DART do row = 1, size(qcf_table_data) - varid = get_index_for_quantity(trim(qcf_table_row_headers(row))) + varid = get_index_for_quantity(trim(specified_qtys(row))) if(varid == -1) then - write(errstring,*) trim(qcf_table_row_headers(row)), ' is not a valid DART QTY' + write(errstring,*) trim(specified_qtys(row)), ' is not a valid DART QTY' call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) endif end do !Ensures that there are no duplicate QTYs in the table do row = 1, size(qcf_table_data) - if(count(qcf_table_row_headers==trim(qcf_table_row_headers(row))) > 1) then - write(errstring,*) trim(qcf_table_row_headers(row)), ' has multiple entries in the table' + if(count(specified_qtys==trim(specified_qtys(row))) > 1) then + write(errstring,*) trim(specified_qtys(row)), ' has multiple entries in the table' call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) endif end do @@ -587,7 +583,7 @@ subroutine log_qcf_table_data() ! Write the table data to the dart_log and terminal do row = 1, size(qcf_table_data) - write(log_msg, *) trim(qcf_table_row_headers(row)), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & + write(log_msg, *) trim(specified_qtys(row)), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & @@ -616,8 +612,8 @@ subroutine end_algorithm_info_mod() if (use_qty_defaults) return +deallocate(specified_qtys) deallocate(qcf_table_data) -deallocate(qcf_table_row_headers) end subroutine end_algorithm_info_mod From 5f41368273c7aeef7bdecc357e3c107897b155d2 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 4 Oct 2023 15:56:51 -0600 Subject: [PATCH 069/129] Adding &probit_transform_nml to remaining model input.nml files --- models/FESOM/work/input.nml | 7 +++++++ models/LMDZ/work/input.nml | 7 +++++++ models/MITgcm_annulus/work/input.nml | 7 +++++++ models/MOM6/work/input.nml | 7 +++++++ models/NAAPS/work/input.nml | 7 +++++++ models/NCOMMAS/work/input.nml | 7 +++++++ models/POP/work/input.nml | 7 +++++++ models/ROMS/work/input.nml | 7 +++++++ models/cam-fv/work/input.nml | 9 ++++----- models/cam-se/work/input.nml | 7 +++++++ models/cice/work/input.nml | 7 +++++++ models/clm/work/input.nml | 7 +++++++ models/cm1/work/input.nml | 7 +++++++ .../coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml | 7 +++++++ models/dynamo/work/input.nml | 7 +++++++ models/forced_barot/work/input.nml | 7 +++++++ models/forced_lorenz_96/work/input.nml | 7 +++++++ models/gitm/work/input.nml | 6 ++++++ models/ikeda/work/input.nml | 7 +++++++ models/lorenz_04/work/input.nml | 7 +++++++ models/lorenz_84/work/input.nml | 7 +++++++ models/lorenz_96_2scale/work/input.nml | 7 +++++++ models/lorenz_96_tracer_advection/work/input.nml | 9 +++++++-- models/mpas_atm/work/input.nml | 7 +++++++ models/mpas_ocn/work/input.nml | 7 +++++++ models/noah/work/input.nml | 7 +++++++ models/null_model/work/input.nml | 7 +++++++ models/pe2lyr/work/input.nml | 7 +++++++ models/rose/work/input.nml | 7 +++++++ models/simple_advection/work/input.nml | 7 +++++++ models/sqg/work/input.nml | 7 +++++++ models/template/work/oned_input.nml | 7 +++++++ models/template/work/threed_input.nml | 7 +++++++ models/tiegcm/work/input.nml | 7 +++++++ models/wrf/work/input.nml | 7 +++++++ models/wrf_hydro/work/input.nml | 7 +++++++ 36 files changed, 248 insertions(+), 7 deletions(-) diff --git a/models/FESOM/work/input.nml b/models/FESOM/work/input.nml index 5334abff8c..140d14cf67 100644 --- a/models/FESOM/work/input.nml +++ b/models/FESOM/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false. + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &perfect_model_obs_nml read_input_state_from_file = .true. input_state_files = "ENS01.2009.oce.nc" @@ -31,6 +37,7 @@ # state by specifying the 'input' stage. &filter_nml + qcf_table_filename = '' async = 5 adv_ens_command = "advance_model_script.die" ens_size = 3 diff --git a/models/LMDZ/work/input.nml b/models/LMDZ/work/input.nml index edbf8617c5..f6df9b80e2 100644 --- a/models/LMDZ/work/input.nml +++ b/models/LMDZ/work/input.nml @@ -1,4 +1,11 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &filter_nml + qcf_table_filename = '', async = 2, adv_ens_command = "./advance_model.csh", ens_size = 40, diff --git a/models/MITgcm_annulus/work/input.nml b/models/MITgcm_annulus/work/input.nml index b7301418ea..39d36c0d19 100644 --- a/models/MITgcm_annulus/work/input.nml +++ b/models/MITgcm_annulus/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml start_from_restart = .false., output_restart = .true., @@ -22,6 +28,7 @@ / &filter_nml + qcf_table_filename = '', async = 0, adv_ens_command = "../shell_scripts/advance_model.csh", ens_size = 20, diff --git a/models/MOM6/work/input.nml b/models/MOM6/work/input.nml index 860e574da4..eeaa2a3b3b 100644 --- a/models/MOM6/work/input.nml +++ b/models/MOM6/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -28,6 +34,7 @@ / &filter_nml + qcf_table_filename = '', single_file_in = .false., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/NAAPS/work/input.nml b/models/NAAPS/work/input.nml index 13f65c076f..e7b0145b05 100644 --- a/models/NAAPS/work/input.nml +++ b/models/NAAPS/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false. + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &assim_tools_nml filter_kind = 1 cutoff = 0.03 @@ -123,6 +129,7 @@ &filter_nml + qcf_table_filename = '' async = 0 adv_ens_command = "./advance_model.csh" ens_size = 20 diff --git a/models/NCOMMAS/work/input.nml b/models/NCOMMAS/work/input.nml index 79a7b30c8e..20313f87e9 100644 --- a/models/NCOMMAS/work/input.nml +++ b/models/NCOMMAS/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml start_from_restart = .true., output_restart = .true., @@ -24,6 +30,7 @@ &filter_nml + qcf_table_filename = '', async = 4, adv_ens_command = "../shell_scripts/advance_model.csh", ens_size = 20, diff --git a/models/POP/work/input.nml b/models/POP/work/input.nml index 8863032412..2e2406f0c8 100644 --- a/models/POP/work/input.nml +++ b/models/POP/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false. + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &perfect_model_obs_nml read_input_state_from_file = .true. single_file_in = .false. @@ -28,6 +34,7 @@ / &filter_nml + qcf_table_filename = '' async = 0 adv_ens_command = 'no_CESM_advance_script' ens_size = 3 diff --git a/models/ROMS/work/input.nml b/models/ROMS/work/input.nml index 349bf35dcf..ec9c4b6ab9 100644 --- a/models/ROMS/work/input.nml +++ b/models/ROMS/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false. + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &perfect_model_obs_nml read_input_state_from_file = .true. single_file_in = .false. @@ -29,6 +35,7 @@ &filter_nml + qcf_table_filename = '' async = 0 adv_ens_command = "DART_trying_to_advance_ROMS_not_supported" ens_size = 3 diff --git a/models/cam-fv/work/input.nml b/models/cam-fv/work/input.nml index 8c6d2abbba..5c57299780 100644 --- a/models/cam-fv/work/input.nml +++ b/models/cam-fv/work/input.nml @@ -33,14 +33,14 @@ ! inf_sd_from_restart inflation restart files from the values in inf*_initial ! if needed. -&quantile_distributions_nml - fix_bound_violations = .true., +&probit_transform_nml + fix_bound_violations = .false. use_logit_instead_of_probit = .false. - do_inverse_check = .false. + do_inverse_check = .true. / &filter_nml - use_algorithm_info_mod = .true. + qcf_table_filename = '' input_state_file_list = 'cam_init_files' input_state_files = '' single_file_in = .false. @@ -360,7 +360,6 @@ &assim_tools_nml - use_algorithm_info_mod = .true. filter_kind = 1 cutoff = 0.15 sort_obs_inc = .false. diff --git a/models/cam-se/work/input.nml b/models/cam-se/work/input.nml index 52dc5ca5a5..c0d85dd32a 100644 --- a/models/cam-se/work/input.nml +++ b/models/cam-se/work/input.nml @@ -28,7 +28,14 @@ ! inf_sd_from_restart inflation restart files from the values in inf*_initial ! if needed. +&probit_transform_nml + fix_bound_violations = .false. + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &filter_nml + qcf_table_filename = '' input_state_files = '' input_state_file_list = 'cam_init_files' single_file_in = .false. diff --git a/models/cice/work/input.nml b/models/cice/work/input.nml index 9fe096838a..4b51f3cdc9 100644 --- a/models/cice/work/input.nml +++ b/models/cice/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false. + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &perfect_model_obs_nml read_input_state_from_file = .true. write_output_state_to_file = .true. @@ -22,6 +28,7 @@ / &filter_nml + qcf_table_filename = '' async = 0 adv_ens_command = "no_advance_script" ens_size = 6 diff --git a/models/clm/work/input.nml b/models/clm/work/input.nml index daa8fb4d98..ee6dec2901 100644 --- a/models/clm/work/input.nml +++ b/models/clm/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false. + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &perfect_model_obs_nml read_input_state_from_file = .true. write_output_state_to_file = .false. @@ -25,6 +31,7 @@ &filter_nml + qcf_table_filename = '' allow_missing_clm = .true. perturb_from_single_instance = .FALSE. perturbation_amplitude = 0.2 diff --git a/models/cm1/work/input.nml b/models/cm1/work/input.nml index 218f34f536..fedba1cb38 100644 --- a/models/cm1/work/input.nml +++ b/models/cm1/work/input.nml @@ -2,7 +2,14 @@ ! For high-resolution models with large DART states, ! use 'distributed_state = .true.' +&probit_transform_nml + fix_bound_violations = .false. + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &filter_nml + qcf_table_filename = '' async = 2 adv_ens_command = 'advance_model.csh' input_state_file_list = 'input_filelist.txt' diff --git a/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml b/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml index 5636b43894..0eda864c17 100644 --- a/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml +++ b/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false. + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &perfect_model_obs_nml start_from_restart = .true., output_restart = .true., @@ -17,6 +23,7 @@ / &filter_nml + qcf_table_filename = '' async = 4, adv_ens_command = "./advance_wrapper.sh", ens_size = 16, diff --git a/models/dynamo/work/input.nml b/models/dynamo/work/input.nml index c3c0921059..dc87e3fe8f 100644 --- a/models/dynamo/work/input.nml +++ b/models/dynamo/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml start_from_restart = .false., output_restart = .true., @@ -22,6 +28,7 @@ / &filter_nml + qcf_table_filename = '', async = 2, adv_ens_command = "./advance_model.ksh", ens_size = 20, diff --git a/models/forced_barot/work/input.nml b/models/forced_barot/work/input.nml index 2ad26c71b6..289947ac7e 100644 --- a/models/forced_barot/work/input.nml +++ b/models/forced_barot/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml start_from_restart = .true., output_restart = .true., @@ -22,6 +28,7 @@ / &filter_nml + qcf_table_filename = '', async = 0, adv_ens_command = "./advance_model.csh", ens_size = 20, diff --git a/models/forced_lorenz_96/work/input.nml b/models/forced_lorenz_96/work/input.nml index e11a177c5e..94ffe130ee 100644 --- a/models/forced_lorenz_96/work/input.nml +++ b/models/forced_lorenz_96/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -30,6 +36,7 @@ # stages_to_write = 'preassim', 'postassim', 'output' &filter_nml + qcf_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/gitm/work/input.nml b/models/gitm/work/input.nml index f3afac2137..04f0dc17ea 100644 --- a/models/gitm/work/input.nml +++ b/models/gitm/work/input.nml @@ -1,5 +1,11 @@ +&probit_transform_nml + fix_bound_violations = .false. + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / &filter_nml + qcf_table_filename = '' input_state_files = '' input_state_file_list = 'gitm_input_files.txt' single_file_in = .false. diff --git a/models/ikeda/work/input.nml b/models/ikeda/work/input.nml index 57f57246c3..cdb6258774 100644 --- a/models/ikeda/work/input.nml +++ b/models/ikeda/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml read_input_state_from_file = .false., single_file_in = .true. @@ -28,6 +34,7 @@ / &filter_nml + qcf_table_filename = '', single_file_in = .true., input_state_files = 'filter_input.nc' input_state_file_list = '' diff --git a/models/lorenz_04/work/input.nml b/models/lorenz_04/work/input.nml index 19b372df2a..eb33f422f6 100644 --- a/models/lorenz_04/work/input.nml +++ b/models/lorenz_04/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -32,6 +38,7 @@ # output_state_files = 'filter_output.nc' &filter_nml + qcf_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/lorenz_84/work/input.nml b/models/lorenz_84/work/input.nml index 6634c45d1f..41abcd15aa 100644 --- a/models/lorenz_84/work/input.nml +++ b/models/lorenz_84/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -32,6 +38,7 @@ # output_state_files = 'filter_output.nc' &filter_nml + qcf_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/lorenz_96_2scale/work/input.nml b/models/lorenz_96_2scale/work/input.nml index e7edc3fa92..5c02f9afa7 100644 --- a/models/lorenz_96_2scale/work/input.nml +++ b/models/lorenz_96_2scale/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -32,6 +38,7 @@ # output_state_files = 'filter_output.nc' &filter_nml + qcf_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/lorenz_96_tracer_advection/work/input.nml b/models/lorenz_96_tracer_advection/work/input.nml index bbbe929578..164c2444e2 100644 --- a/models/lorenz_96_tracer_advection/work/input.nml +++ b/models/lorenz_96_tracer_advection/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml use_algorithm_info_mod = .true., read_input_state_from_file = .false., @@ -29,7 +35,7 @@ / &filter_nml - use_algorithm_info_mod = .true., + qcf_table_filename = '', single_file_in = .true., input_state_files = 'perfect_input.nc' input_state_file_list = '' @@ -94,7 +100,6 @@ / &assim_tools_nml - use_algorithm_info_mod = .true., filter_kind = 1, cutoff = 1000000.0 sort_obs_inc = .false., diff --git a/models/mpas_atm/work/input.nml b/models/mpas_atm/work/input.nml index 67869b6174..7444c9f3b9 100644 --- a/models/mpas_atm/work/input.nml +++ b/models/mpas_atm/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false. + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &perfect_model_obs_nml read_input_state_from_file = .true. single_file_in = .false. @@ -28,6 +34,7 @@ / &filter_nml + qcf_table_filename = '' async = 0 adv_ens_command = './advance_model.csh' ens_size = 3 diff --git a/models/mpas_ocn/work/input.nml b/models/mpas_ocn/work/input.nml index a3b35c0cfb..dd54fdb788 100644 --- a/models/mpas_ocn/work/input.nml +++ b/models/mpas_ocn/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml start_from_restart = .true., output_restart = .true., @@ -22,6 +28,7 @@ / &filter_nml + qcf_table_filename = '', async = 2, adv_ens_command = "../shell_scripts/advance_model.csh", ens_size = 3, diff --git a/models/noah/work/input.nml b/models/noah/work/input.nml index 86f921a95a..cfc027ac68 100644 --- a/models/noah/work/input.nml +++ b/models/noah/work/input.nml @@ -1,5 +1,11 @@ # This namelist is for both NOAH and NOAH-MP +&probit_transform_nml + fix_bound_violations = .false. + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &model_nml lsm_model_choice = 'noahMP_36' domain_shapefiles = 'RESTART.2003051600_DOMAIN1_01' @@ -49,6 +55,7 @@ &filter_nml + qcf_table_filename = '' input_state_file_list = 'input_file_list.txt' perturb_from_single_instance = .false. init_time_days = -1 diff --git a/models/null_model/work/input.nml b/models/null_model/work/input.nml index c3e8905428..5ab448764c 100644 --- a/models/null_model/work/input.nml +++ b/models/null_model/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -28,6 +34,7 @@ / &filter_nml + qcf_table_filename = '', single_file_in = .true., input_state_files = 'filter_input.nc' input_state_file_list = '' diff --git a/models/pe2lyr/work/input.nml b/models/pe2lyr/work/input.nml index ddfc37e57b..ab7c31f1dd 100644 --- a/models/pe2lyr/work/input.nml +++ b/models/pe2lyr/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml start_from_restart = .true., output_restart = .true., @@ -22,6 +28,7 @@ / &filter_nml + qcf_table_filename = '', async = 0, adv_ens_command = "./advance_model.csh", ens_size = 20, diff --git a/models/rose/work/input.nml b/models/rose/work/input.nml index 786486552b..0b0baca301 100644 --- a/models/rose/work/input.nml +++ b/models/rose/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml start_from_restart = .false., output_restart = .true., @@ -22,6 +28,7 @@ / &filter_nml + qcf_table_filename = '', async = 2, adv_ens_command = "../shell_scripts/advance_model.csh", ens_size = 20, diff --git a/models/simple_advection/work/input.nml b/models/simple_advection/work/input.nml index 13f84b1220..1a1f25aaf7 100644 --- a/models/simple_advection/work/input.nml +++ b/models/simple_advection/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false. + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &perfect_model_obs_nml read_input_state_from_file = .true. single_file_in = .true. @@ -32,6 +38,7 @@ # output_state_files = 'filter_output.nc' &filter_nml + qcf_table_filename = '' single_file_in = .true. input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/sqg/work/input.nml b/models/sqg/work/input.nml index 62b0acaee3..fe4a2c9c2b 100644 --- a/models/sqg/work/input.nml +++ b/models/sqg/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml start_from_restart = .true., output_restart = .true., @@ -30,6 +36,7 @@ / &filter_nml + qcf_table_filename = '', async = 0, adv_ens_command = "model called as a subroutine", ens_size = 25, diff --git a/models/template/work/oned_input.nml b/models/template/work/oned_input.nml index 66b5a07bb8..42ec36bf15 100644 --- a/models/template/work/oned_input.nml +++ b/models/template/work/oned_input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -28,6 +34,7 @@ / &filter_nml + qcf_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/template/work/threed_input.nml b/models/template/work/threed_input.nml index 90608b10f6..cd962d5fe1 100644 --- a/models/template/work/threed_input.nml +++ b/models/template/work/threed_input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -28,6 +34,7 @@ / &filter_nml + qcf_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/tiegcm/work/input.nml b/models/tiegcm/work/input.nml index c92d64e746..bdffe30be7 100644 --- a/models/tiegcm/work/input.nml +++ b/models/tiegcm/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &quality_control_nml / @@ -38,6 +44,7 @@ # output_state_file_list = 'out_restart_p_files.txt', 'out_secondary_files.txt', 'out_f10.7.txt' &filter_nml + qcf_table_filename = '', single_file_in = .false., input_state_files = '' input_state_file_list = 'restart_p_files.txt', 'secondary_files.txt' diff --git a/models/wrf/work/input.nml b/models/wrf/work/input.nml index 30b6f0cad0..d1165099f2 100644 --- a/models/wrf/work/input.nml +++ b/models/wrf/work/input.nml @@ -1,3 +1,9 @@ +&probit_transform_nml + fix_bound_violations = .false., + use_logit_instead_of_probit = .false., + do_inverse_check = .true., + / + &perfect_model_obs_nml read_input_state_from_file = .true. single_file_in = .false. @@ -28,6 +34,7 @@ / &filter_nml + qcf_table_filename = '', async = 0, adv_ens_command = "../shell_scripts/advance_model.csh", ens_size = 3, diff --git a/models/wrf_hydro/work/input.nml b/models/wrf_hydro/work/input.nml index 8b22e40e68..fb02247d26 100644 --- a/models/wrf_hydro/work/input.nml +++ b/models/wrf_hydro/work/input.nml @@ -7,6 +7,12 @@ # domain_order = 'hydro', 'parameters' # domain_shapefiles = 'restart.hydro.nc', 'parameters.nc' +&probit_transform_nml + fix_bound_violations = .false. + use_logit_instead_of_probit = .false. + do_inverse_check = .true. + / + &model_nml assimilation_period_days = 0 assimilation_period_seconds = 3600 @@ -71,6 +77,7 @@ # output_state_file_list = 'hydro_file_list.txt' &filter_nml + qcf_table_filename = '' input_state_file_list = 'hydro_file_list.txt' single_file_in = .false. init_time_days = -1, From 46dbd969ee59462e376ffcdd132872fd055a71b0 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Thu, 5 Oct 2023 10:26:13 -0400 Subject: [PATCH 070/129] chore: pin requirements for readthedocs --- .readthedocs.yaml | 4 ++++ guide/requirements.txt | 2 ++ 2 files changed, 6 insertions(+) create mode 100644 guide/requirements.txt diff --git a/.readthedocs.yaml b/.readthedocs.yaml index cdd5a58e67..9e1ea1d8cf 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -11,3 +11,7 @@ build: sphinx: configuration: conf.py + +python: + install: + - requirements: guide/requirements.txt diff --git a/guide/requirements.txt b/guide/requirements.txt new file mode 100644 index 0000000000..254085495f --- /dev/null +++ b/guide/requirements.txt @@ -0,0 +1,2 @@ +Sphinx==6.2.1 +sphinx-rtd-theme==1.2.2 From 42bec457d2185c2f7f5cf9c05614343bee94a515 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 9 Oct 2023 16:50:54 -0600 Subject: [PATCH 071/129] Removing rectangular_quadtrature and gaussian_likelihood_tails from the QCF table and obs_inc_info --- .../assimilation/algorithm_info_mod.f90 | 20 ++++++------------- .../modules/assimilation/assim_tools_mod.f90 | 4 ++-- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 3ad3b401f1..f61d99f022 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -67,7 +67,6 @@ module algorithm_info_mod type obs_inc_info_type integer :: filter_kind - logical :: rectangular_quadrature, gaussian_likelihood_tails logical :: sort_obs_inc, spread_restoration logical :: bounded_below, bounded_above real(r8) :: lower_bound, upper_bound @@ -83,7 +82,7 @@ module algorithm_info_mod integer, parameter :: HEADER_LINES = 2 character(len=129), dimension(4) :: header1 -character(len=129), dimension(29) :: header2 +character(len=129), dimension(27) :: header2 character(len=129), allocatable :: specified_qtys(:) type(algorithm_info_type), allocatable :: qcf_table_data(:) @@ -178,9 +177,8 @@ subroutine read_qcf_table(qcf_table_filename) qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, dist_type_string_probit_extended_state, & qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - filter_kind_string, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & - qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & - qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & + filter_kind_string, qcf_table_data(row)%obs_inc_info%sort_obs_inc, qcf_table_data(row)%obs_inc_info%spread_restoration, & + qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound ! Converting the distribution types (read in from table as a string) to its corresponding int value @@ -417,12 +415,11 @@ end subroutine probit_dist_info !------------------------------------------------------------------------ -subroutine obs_inc_info(obs_qty, filter_kind, rectangular_quadrature, gaussian_likelihood_tails, & - sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound) +subroutine obs_inc_info(obs_qty, filter_kind, sort_obs_inc, spread_restoration, & + bounded_below, bounded_above, lower_bound, upper_bound) integer, intent(in) :: obs_qty integer, intent(inout) :: filter_kind -logical, intent(inout) :: rectangular_quadrature, gaussian_likelihood_tails logical, intent(inout) :: sort_obs_inc logical, intent(inout) :: spread_restoration logical, intent(inout) :: bounded_below, bounded_above @@ -473,10 +470,6 @@ subroutine obs_inc_info(obs_qty, filter_kind, rectangular_quadrature, gaussian_l endif -! Only need to set these two for options the original RHF implementation -!!!rectangular_quadrature = .true. -!!!gaussian_likelihood_tails = .false. - end subroutine obs_inc_info !------------------------------------------------------------------------ @@ -591,8 +584,7 @@ subroutine log_qcf_table_data() qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%rectangular_quadrature, & - qcf_table_data(row)%obs_inc_info%gaussian_likelihood_tails, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & + qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound call error_handler(E_MSG, 'log_qcf_table_data:', trim(log_msg), source) diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index b604807bac..9a8c8c4144 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -987,8 +987,8 @@ subroutine obs_increment(ens_in, ens_size, obs, obs_var, obs_kind, obs_inc, & bounded_below = .false.; lower_bound = 0.0_r8 bounded_above = .false.; upper_bound = 0.0_r8 -call obs_inc_info(obs_kind, filter_kind, rectangular_quadrature, gaussian_likelihood_tails, & - sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound) +call obs_inc_info(obs_kind, filter_kind, sort_obs_inc, spread_restoration, & + bounded_below, bounded_above, lower_bound, upper_bound) ! Could add logic to check on sort being true when not needed. ! Could also add logic to limit the use of spread_restoration to EAKF. It will fail From 55e4c6ef57c83e992820d4d89dbf964d2a89d3fc Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 10 Oct 2023 15:01:06 -0600 Subject: [PATCH 072/129] Removed sort_obs_inc from the QCF table; removed code related to the sort_obs_inc logical from filter_assim and obs_increment in assim_tools_mod.f90 and obs_inc_info in algorithm_info_mod.f90 --- .../assimilation/algorithm_info_mod.f90 | 21 +++++------ .../modules/assimilation/assim_tools_mod.f90 | 35 ++----------------- 2 files changed, 11 insertions(+), 45 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index f61d99f022..5f6f6d3742 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -67,7 +67,7 @@ module algorithm_info_mod type obs_inc_info_type integer :: filter_kind - logical :: sort_obs_inc, spread_restoration + logical :: spread_restoration logical :: bounded_below, bounded_above real(r8) :: lower_bound, upper_bound end type @@ -82,7 +82,7 @@ module algorithm_info_mod integer, parameter :: HEADER_LINES = 2 character(len=129), dimension(4) :: header1 -character(len=129), dimension(27) :: header2 +character(len=129), dimension(26) :: header2 character(len=129), allocatable :: specified_qtys(:) type(algorithm_info_type), allocatable :: qcf_table_data(:) @@ -177,7 +177,7 @@ subroutine read_qcf_table(qcf_table_filename) qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, dist_type_string_probit_extended_state, & qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - filter_kind_string, qcf_table_data(row)%obs_inc_info%sort_obs_inc, qcf_table_data(row)%obs_inc_info%spread_restoration, & + filter_kind_string, qcf_table_data(row)%obs_inc_info%spread_restoration, & qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound @@ -415,12 +415,11 @@ end subroutine probit_dist_info !------------------------------------------------------------------------ -subroutine obs_inc_info(obs_qty, filter_kind, sort_obs_inc, spread_restoration, & +subroutine obs_inc_info(obs_qty, filter_kind, spread_restoration, & bounded_below, bounded_above, lower_bound, upper_bound) integer, intent(in) :: obs_qty integer, intent(inout) :: filter_kind -logical, intent(inout) :: sort_obs_inc logical, intent(inout) :: spread_restoration logical, intent(inout) :: bounded_below, bounded_above real(r8), intent(inout) :: lower_bound, upper_bound @@ -440,7 +439,7 @@ subroutine obs_inc_info(obs_qty, filter_kind, sort_obs_inc, spread_restoration, filter_kind = BOUNDED_NORMAL_RHF bounded_below = .false.; bounded_above = .false. lower_bound = missing_r8; upper_bound = missing_r8 - sort_obs_inc = .false.; spread_restoration = .false. + spread_restoration = .false. return endif @@ -455,13 +454,12 @@ subroutine obs_inc_info(obs_qty, filter_kind, sort_obs_inc, spread_restoration, filter_kind = BOUNDED_NORMAL_RHF bounded_below = .false.; bounded_above = .false. lower_bound = missing_r8; upper_bound = missing_r8 - sort_obs_inc = .false.; spread_restoration = .false. - ! Default settings for now for Icepack and tracer model tests (sort_obs_inc, spread_restoration) + spread_restoration = .false. + ! Default settings for now for Icepack and tracer model tests (spread_restoration) else filter_kind = qcf_table_data(QTY_loc(1))%obs_inc_info%filter_kind - sort_obs_inc = qcf_table_data(QTY_loc(1))%obs_inc_info%sort_obs_inc spread_restoration = qcf_table_data(QTY_loc(1))%obs_inc_info%spread_restoration bounded_below = qcf_table_data(QTY_loc(1))%obs_inc_info%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%obs_inc_info%bounded_above @@ -584,9 +582,8 @@ subroutine log_qcf_table_data() qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%sort_obs_inc, & - qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & - qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound + qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, & + qcf_table_data(row)%obs_inc_info%bounded_above, qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound call error_handler(E_MSG, 'log_qcf_table_data:', trim(log_msg), source) end do diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index 9a8c8c4144..d3ed0d3549 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -145,7 +145,7 @@ module assim_tools_mod ! integer :: filter_kind = 1 real(r8) :: cutoff = 0.2_r8 -logical :: sort_obs_inc = .false. +logical :: sort_obs_inc = .true. logical :: spread_restoration = .false. logical :: sampling_error_correction = .false. integer :: adaptive_localization_threshold = -1 @@ -421,22 +421,6 @@ subroutine filter_assim(ens_handle, obs_ens_handle, obs_seq, keys, & ! Need to give create_mean_window the mean copy call create_mean_window(ens_handle, ENS_MEAN_COPY, distribute_mean) -! filter kinds 1 and 8 return sorted increments, however non-deterministic -! inflation can scramble these. the sort is expensive, so help users get better -! performance by rejecting namelist combinations that do unneeded work. -if (sort_obs_inc) then - if(deterministic_inflate(inflate) .and. ((filter_kind == 1) .or. (filter_kind == 8))) then - write(msgstring, *) 'With a deterministic filter [assim_tools_nml:filter_kind = ',filter_kind,']' - write(msgstring2, *) 'and deterministic inflation [filter_nml:inf_deterministic = .TRUE.]' - write(msgstring3, *) 'assim_tools_nml:sort_obs_inc = .TRUE. is not needed and is expensive.' - call error_handler(E_MSG,'', '') ! whitespace - call error_handler(E_MSG,'WARNING filter_assim:', msgstring, source, & - text2=msgstring2,text3=msgstring3) - call error_handler(E_MSG,'', '') ! whitespace - sort_obs_inc = .FALSE. - endif -endif - ! Open the localization diagnostics file if(output_localization_diagnostics .and. my_task_id() == 0) & localization_unit = open_file(localization_diagnostics_file, action = 'append') @@ -987,7 +971,7 @@ subroutine obs_increment(ens_in, ens_size, obs, obs_var, obs_kind, obs_inc, & bounded_below = .false.; lower_bound = 0.0_r8 bounded_above = .false.; upper_bound = 0.0_r8 -call obs_inc_info(obs_kind, filter_kind, sort_obs_inc, spread_restoration, & +call obs_inc_info(obs_kind, filter_kind, spread_restoration, & bounded_below, bounded_above, lower_bound, upper_bound) ! Could add logic to check on sort being true when not needed. @@ -1082,21 +1066,6 @@ subroutine obs_increment(ens_in, ens_size, obs, obs_var, obs_kind, obs_inc, & ! Add in the extra increments if doing observation space covariance inflation if(do_obs_inflate(inflate)) obs_inc = obs_inc + inflate_inc -! To minimize regression errors, may want to sort to minimize increments -! This makes sense for any of the non-deterministic algorithms -! By doing it here, can take care of both standard non-deterministic updates -! plus non-deterministic obs space covariance inflation. This is expensive, so -! don't use it if it's not needed. -if (sort_obs_inc) then - new_val = ens_in + obs_inc - ! Sorting to make increments as small as possible - call index_sort(ens_in, ens_index, ens_size) - call index_sort(new_val, new_index, ens_size) - do i = 1, ens_size - obs_inc(ens_index(i)) = new_val(new_index(i)) - ens_in(ens_index(i)) - end do -endif - ! Get the net change in spread if obs space inflation was used if(do_obs_inflate(inflate)) net_a = net_a * sqrt(my_cov_inflate) From b0a941c24c69145eec2472958273b0bcee3529e6 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 17 Oct 2023 10:55:53 -0600 Subject: [PATCH 073/129] Adding the code for sort_obs_inc into obs_increment_enkf --- .../modules/assimilation/assim_tools_mod.f90 | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index d3ed0d3549..b93e7eeca5 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -1326,7 +1326,8 @@ subroutine obs_increment_enkf(ens, ens_size, prior_var, obs, obs_var, obs_inc) real(r8) :: obs_var_inv, prior_var_inv, new_var, new_mean(ens_size) ! real(r8) :: sx, s_x2 real(r8) :: temp_mean, temp_obs(ens_size) -integer :: i +real(r8) :: new_val(ens_size) +integer :: i, ens_index(ens_size), new_index(ens_size) ! Compute mt_rinv_y (obs error normalized by variance) obs_var_inv = 1.0_r8 / obs_var @@ -1355,6 +1356,21 @@ subroutine obs_increment_enkf(ens, ens_size, prior_var, obs, obs_var, obs_inc) temp_mean = sum(temp_obs) / ens_size temp_obs(:) = temp_obs(:) - temp_mean + obs +! To minimize regression errors, may want to sort to minimize increments +! This makes sense for any of the non-deterministic algorithms +! By doing it here, can take care of both standard non-deterministic updates +! plus non-deterministic obs space covariance inflation. This is expensive, so +! don't use it if it's not needed. +if (sort_obs_inc) then + new_val = ens + obs_inc + ! Sorting to make increments as small as possible + call index_sort(ens, ens_index, ens_size) + call index_sort(new_val, new_index, ens_size) + do i = 1, ens_size + obs_inc(ens_index(i)) = new_val(new_index(i)) - ens(ens_index(i)) + end do +endif + ! Loop through pairs of priors and obs and compute new mean do i = 1, ens_size new_mean(i) = new_var * (prior_var_inv * ens(i) + temp_obs(i) / obs_var) From fb045f70083a88e9e158c1489cbd48d46fca8ff4 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 17 Oct 2023 11:46:45 -0600 Subject: [PATCH 074/129] Logging the dist_type and filter_kind in their string formats instead of ints --- .../assimilation/algorithm_info_mod.f90 | 90 ++++++++++--------- 1 file changed, 47 insertions(+), 43 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 5f6f6d3742..a0339d1930 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -87,10 +87,10 @@ module algorithm_info_mod character(len=129), allocatable :: specified_qtys(:) type(algorithm_info_type), allocatable :: qcf_table_data(:) -character(len=129) :: dist_type_string_probit_inflation -character(len=129) :: dist_type_string_probit_state -character(len=129) :: dist_type_string_probit_extended_state -character(len=129) :: filter_kind_string +character(len=129), allocatable :: dist_type_string_probit_inflation(:) +character(len=129), allocatable :: dist_type_string_probit_state(:) +character(len=129), allocatable :: dist_type_string_probit_extended_state(:) +character(len=129), allocatable :: filter_kind_string(:) ! Provides routines that give information about details of algorithms for ! observation error sampling, observation increments, and the transformations @@ -139,6 +139,10 @@ subroutine init_algorithm_info_mod(qcf_table_filename) allocate(specified_qtys(numrows)) allocate(qcf_table_data(numrows)) +allocate(dist_type_string_probit_inflation(numrows)) +allocate(dist_type_string_probit_state(numrows)) +allocate(dist_type_string_probit_extended_state(numrows)) +allocate(filter_kind_string(numrows)) call read_qcf_table(qcf_table_filename) call assert_qcf_table_version() @@ -149,7 +153,7 @@ end subroutine init_algorithm_info_mod !------------------------------------------------------------------------ - + subroutine read_qcf_table(qcf_table_filename) ! Reads in the QCEFF input options from tabular data file @@ -170,88 +174,88 @@ subroutine read_qcf_table(qcf_table_filename) ! read in table values directly to qcf_table_data type do row = 1, size(qcf_table_data) read(fileid, *) specified_qtys(row), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & - qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, dist_type_string_probit_inflation, & + qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, dist_type_string_probit_inflation(row), & qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & - qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, dist_type_string_probit_state, & + qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, dist_type_string_probit_state(row), & qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & - qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, dist_type_string_probit_extended_state, & + qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, dist_type_string_probit_extended_state(row), & qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - filter_kind_string, qcf_table_data(row)%obs_inc_info%spread_restoration, & + filter_kind_string(row), qcf_table_data(row)%obs_inc_info%spread_restoration, & qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound ! Converting the distribution types (read in from table as a string) to its corresponding int value - if (trim(dist_type_string_probit_inflation) == 'NORMAL_DISTRIBUTION') then + if (trim(dist_type_string_probit_inflation(row)) == 'NORMAL_DISTRIBUTION') then qcf_table_data(row)%probit_inflation%dist_type = NORMAL_DISTRIBUTION - elseif (trim(dist_type_string_probit_inflation) == 'BOUNDED_NORMAL_RH_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_inflation(row)) == 'BOUNDED_NORMAL_RH_DISTRIBUTION') then qcf_table_data(row)%probit_inflation%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - elseif (trim(dist_type_string_probit_inflation) == 'GAMMA_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_inflation(row)) == 'GAMMA_DISTRIBUTION') then qcf_table_data(row)%probit_inflation%dist_type = GAMMA_DISTRIBUTION - elseif (trim(dist_type_string_probit_inflation) == 'BETA_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_inflation(row)) == 'BETA_DISTRIBUTION') then qcf_table_data(row)%probit_inflation%dist_type = BETA_DISTRIBUTION - elseif (trim(dist_type_string_probit_inflation) == 'LOG_NORMAL_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_inflation(row)) == 'LOG_NORMAL_DISTRIBUTION') then qcf_table_data(row)%probit_inflation%dist_type = LOG_NORMAL_DISTRIBUTION - elseif (trim(dist_type_string_probit_inflation) == 'UNIFORM_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_inflation(row)) == 'UNIFORM_DISTRIBUTION') then qcf_table_data(row)%probit_inflation%dist_type = UNIFORM_DISTRIBUTION - elseif (trim(dist_type_string_probit_inflation) == 'PARTICLE_FILTER_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_inflation(row)) == 'PARTICLE_FILTER_DISTRIBUTION') then qcf_table_data(row)%probit_inflation%dist_type = PARTICLE_FILTER_DISTRIBUTION else - write(errstring, *) 'Invalid distribution type for probit inflation: ', trim(dist_type_string_probit_inflation) + write(errstring, *) 'Invalid distribution type for probit inflation: ', trim(dist_type_string_probit_inflation(row)) call error_handler(E_ERR, 'read_qcf_table:', errstring, source) endif - if (trim(dist_type_string_probit_state) == 'NORMAL_DISTRIBUTION') then + if (trim(dist_type_string_probit_state(row)) == 'NORMAL_DISTRIBUTION') then qcf_table_data(row)%probit_state%dist_type = NORMAL_DISTRIBUTION - elseif (trim(dist_type_string_probit_state) == 'BOUNDED_NORMAL_RH_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_state(row)) == 'BOUNDED_NORMAL_RH_DISTRIBUTION') then qcf_table_data(row)%probit_state%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - elseif (trim(dist_type_string_probit_state) == 'GAMMA_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_state(row)) == 'GAMMA_DISTRIBUTION') then qcf_table_data(row)%probit_state%dist_type = GAMMA_DISTRIBUTION - elseif (trim(dist_type_string_probit_state) == 'BETA_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_state(row)) == 'BETA_DISTRIBUTION') then qcf_table_data(row)%probit_state%dist_type = BETA_DISTRIBUTION - elseif (trim(dist_type_string_probit_state) == 'LOG_NORMAL_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_state(row)) == 'LOG_NORMAL_DISTRIBUTION') then qcf_table_data(row)%probit_state%dist_type = LOG_NORMAL_DISTRIBUTION - elseif (trim(dist_type_string_probit_state) == 'UNIFORM_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_state(row)) == 'UNIFORM_DISTRIBUTION') then qcf_table_data(row)%probit_state%dist_type = UNIFORM_DISTRIBUTION - elseif (trim(dist_type_string_probit_state) == 'PARTICLE_FILTER_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_state(row)) == 'PARTICLE_FILTER_DISTRIBUTION') then qcf_table_data(row)%probit_state%dist_type = PARTICLE_FILTER_DISTRIBUTION else - write(errstring, *) 'Invalid distribution type for probit state: ', trim(dist_type_string_probit_state) + write(errstring, *) 'Invalid distribution type for probit state: ', trim(dist_type_string_probit_state(row)) call error_handler(E_ERR, 'read_qcf_table:', errstring, source) endif - if (trim(dist_type_string_probit_extended_state) == 'NORMAL_DISTRIBUTION') then + if (trim(dist_type_string_probit_extended_state(row)) == 'NORMAL_DISTRIBUTION') then qcf_table_data(row)%probit_extended_state%dist_type = NORMAL_DISTRIBUTION - elseif (trim(dist_type_string_probit_extended_state) == 'BOUNDED_NORMAL_RH_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_extended_state(row)) == 'BOUNDED_NORMAL_RH_DISTRIBUTION') then qcf_table_data(row)%probit_extended_state%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - elseif (trim(dist_type_string_probit_extended_state) == 'GAMMA_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_extended_state(row)) == 'GAMMA_DISTRIBUTION') then qcf_table_data(row)%probit_extended_state%dist_type = GAMMA_DISTRIBUTION - elseif (trim(dist_type_string_probit_extended_state) == 'BETA_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_extended_state(row)) == 'BETA_DISTRIBUTION') then qcf_table_data(row)%probit_extended_state%dist_type = BETA_DISTRIBUTION - elseif (trim(dist_type_string_probit_extended_state) == 'LOG_NORMAL_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_extended_state(row)) == 'LOG_NORMAL_DISTRIBUTION') then qcf_table_data(row)%probit_extended_state%dist_type = LOG_NORMAL_DISTRIBUTION - elseif (trim(dist_type_string_probit_extended_state) == 'UNIFORM_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_extended_state(row)) == 'UNIFORM_DISTRIBUTION') then qcf_table_data(row)%probit_extended_state%dist_type = UNIFORM_DISTRIBUTION - elseif (trim(dist_type_string_probit_extended_state) == 'PARTICLE_FILTER_DISTRIBUTION') then + elseif (trim(dist_type_string_probit_extended_state(row)) == 'PARTICLE_FILTER_DISTRIBUTION') then qcf_table_data(row)%probit_extended_state%dist_type = PARTICLE_FILTER_DISTRIBUTION else - write(errstring, *) 'Invalid distribution type for probit extended state: ', trim(dist_type_string_probit_extended_state) + write(errstring, *) 'Invalid distribution type for probit extended state: ', trim(dist_type_string_probit_extended_state(row)) call error_handler(E_ERR, 'read_qcf_table:', errstring, source) endif ! Converting the filter kind (read in from table as a string) to its corresponding int value - if (trim(filter_kind_string) == 'EAKF') then + if (trim(filter_kind_string(row)) == 'EAKF') then qcf_table_data(row)%obs_inc_info%filter_kind = EAKF - elseif (trim(filter_kind_string) == 'ENKF') then + elseif (trim(filter_kind_string(row)) == 'ENKF') then qcf_table_data(row)%obs_inc_info%filter_kind = ENKF - elseif (trim(filter_kind_string) == 'UNBOUNDED_RHF') then + elseif (trim(filter_kind_string(row)) == 'UNBOUNDED_RHF') then qcf_table_data(row)%obs_inc_info%filter_kind = UNBOUNDED_RHF - elseif (trim(filter_kind_string) == 'GAMMA_FILTER') then + elseif (trim(filter_kind_string(row)) == 'GAMMA_FILTER') then qcf_table_data(row)%obs_inc_info%filter_kind = GAMMA_FILTER - elseif (trim(filter_kind_string) == 'BOUNDED_NORMAL_RHF') then + elseif (trim(filter_kind_string(row)) == 'BOUNDED_NORMAL_RHF') then qcf_table_data(row)%obs_inc_info%filter_kind = BOUNDED_NORMAL_RHF else - write(errstring, *) 'Invalid filter kind: ', trim(filter_kind_string) + write(errstring, *) 'Invalid filter kind: ', trim(filter_kind_string(row)) call error_handler(E_ERR, 'read_qcf_table:', errstring, source) endif @@ -575,14 +579,14 @@ subroutine log_qcf_table_data() ! Write the table data to the dart_log and terminal do row = 1, size(qcf_table_data) write(log_msg, *) trim(specified_qtys(row)), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & - qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, qcf_table_data(row)%probit_inflation%dist_type, & + qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, trim(dist_type_string_probit_inflation(row)), & qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & - qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, qcf_table_data(row)%probit_state%dist_type, & + qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, trim(dist_type_string_probit_state(row)), & qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & - qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, qcf_table_data(row)%probit_extended_state%dist_type, & + qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, trim(dist_type_string_probit_extended_state(row)), & qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - qcf_table_data(row)%obs_inc_info%filter_kind, qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, & + trim(filter_kind_string(row)), qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, & qcf_table_data(row)%obs_inc_info%bounded_above, qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound call error_handler(E_MSG, 'log_qcf_table_data:', trim(log_msg), source) end do From 85ecf530251650112c87d9e932d6066fc0f20b3b Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 17 Oct 2023 16:56:22 -0600 Subject: [PATCH 075/129] Updating the documentationc- adding info on the QCF and probit transform tools to DART's main documentation page; removing outdated docs for using these tools --- guide/qcf_probit.rst | 98 ++++++++ guide/qcf_table.rst | 227 ------------------- index.rst | 41 +++- models/lorenz_96_tracer_advection/readme.rst | 143 ------------ 4 files changed, 138 insertions(+), 371 deletions(-) create mode 100644 guide/qcf_probit.rst delete mode 100644 guide/qcf_table.rst delete mode 100644 models/lorenz_96_tracer_advection/readme.rst diff --git a/guide/qcf_probit.rst b/guide/qcf_probit.rst new file mode 100644 index 0000000000..f411f476f7 --- /dev/null +++ b/guide/qcf_probit.rst @@ -0,0 +1,98 @@ +.. _QCF: + +######################################################## +Quantile Conserving and Probit Transform Filtering Tools +######################################################## + +This file contains instructions for using the DART Quantile Conserving Filters (QCF), also known as the Quantile Conserving Ensemble Filtering Framework (QCEFF), and probit transform filtering tools. + +The DART development team (dart@ucar.edu) would be happy to hear about your experiences and is anxious to build scientific collaborations using these new capabilities. + +The user can include an input table allows the user to specify the control options for these tools. The observation, state, and inflation variables are all included in this single table. + +The new quantile options are read in from the table at runtime and then set in the module algorithm_info_mod.f90 in the DART/assimilation_code/modules/assimilation directory. This module provides routines that give information about details of algorithms for observation error sampling, observation increments, and the transformations for regression and inflation in probit space. + +For individual QTYs in DART, the user can specify the options such as the bounds, distribution type, filter kind, etc. for the obs_error_info, probit_dist_info, and obs_inc_info subroutines in algorithm_info_mod.f90 + +If the user does not use a QCF input table with the DART quantile conserving and probit transform filtering tools, then the default values for these options will be used for all QTYs. + +Table Composition +----------------- +The table consists of two headers. The first states the version # of the table being used; the most recent version of the table needs to be used to ensure compatibilty with DART. The current version # is 1. The second header lists the full set of input options, or all 25 column names in other words. + +Each QTY is specified in its own column, having 25 total control options. +These control options are divided into 3 main groups, which are the options used for the obs_error_info, probit_dist_info, and obs_inc_info. However, the user is able to specify different values for probit inflation, probit state, and probit extended state, resulting in 5 total groupings for the control options. + +The obs_error_info subroutine computes information needed to compute error sample for this observation. +For obs_error_info the input options are the two bounds (lower and upper). + +The probit_dist_info subroutine computes the details of the probit transform. +From probit_dist_info, the values needed are the bounds and the distribution type. These can be different for all three cases (inflation, state, and extended_state). + +The obs_inc_info subrotuine sets the details of how to assimilate this observation. +From obs_inc_info, the bounds, plus the filter_kind and spread_restoration are needed. + +Full list of options: +Obs_error_info: bounded_below, bounded_above, lower_bound, upper_bound [4 columns] +Probit_dist_info: dist_type, bounded_below, bounded_above, lower_bound, upper_bound (x3 for inflation, state, and observation (extended state) priors) [15 columns] +Obs_inc_info: filter_kind, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound [6 columns] + +Customizing the Table +--------------------- +The table can be customized by editing a Google Sheet spreadsheet (which is then downloaded in .csv format). Folow this link https://docs.google.com/spreadsheets/d/1SI4wHBXatLAAMfiMx3mUUC7x0fqz4lniKuM4_i5j6bM/edit#gid=0 to access the template spreadsheet. + +The user will add and fill in one row for each bounded QTY they want to specify. If a QTY is not listed in the table, the default values will be used for all 25 options. Therefore, the user will only need to add rows for QTYs that use non-default values for any of the input options. + +The default values for each of the options are listed below: +bounded_below = .false. +bounded_above = .false. +lower_bound = -888888 +upper_bound = -888888 +dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION +filter_kind = BOUNDED_NORMAL_RHF +spread_restoration = .false. + +Note that bounds set to -888888 are missing_r8 values. + +The following input options are read in as logicals, and will need to be written in the format of either 'F' or '.false.' These include bounded_below, bounded_above, and spread_restoration. + +The actual numerical values of the bounds are read in as real_r8 types. These can be specified as reals or integers in the table. + +dist_type and filter_kind are read in as strings. The possible values for these variables are listed below: + +dist_type: +NORMAL_DISTRIBUTION, BOUNDED_NORMAL_RH_DISTRIBUTION, GAMMA_DISTRIBUTION, BETA_DISTRIBUTION, LOG_NORMAL_DISTRIBUTION, UNIFORM_DISTRIBUTION, PARTICLE_FILTER_DISTRIBUTION + +filter_kind: +EAKF, ENKF, UNBOUNDED_RHF, GAMMA_FILTER, BOUNDED_NORMAL_RHF + +Make a copy of the table by selecting 'File > Make a copy' from the menu bar. + +To customize the spreadsheet, click on the cell you want to edit and change the value of that cell. +To add a new QTY to the spreadsheet, copy row 3 of the table into the next available row, change ``QTY_TEMPLATE`` to the name of the QTY to specify, and edit the cells individually to set the control options. +To remove a QTY from the spreadsheet, select the row number corresponding to that QTY. Then right click and choose "Delete Row" +Make sure to remove the row for ``QTY_TEMPLATE`` when you have finished adding all of the specified QTYs to the table. + +Ensure that there are no empty rows in between the QTYs listed in the spreadsheet. + +Download the spreadsheet as a .csv file by selecting 'File > Download > csv' from the menu bar. + +Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv" +Rename this file to remove this addition to ensure that there are no spaces in the filename. + +Copy or move this file to your working directory (/DART/models/model_name/work). + +Using the table in DART +----------------------- +Navigate to your working directory (/DART/models/model_name/work). + +Switch to the quantile_methods branch of DART: +``git checkout quantile_methods`` + +Edit your namelist file (input.nml): +Add the name of the QCF table file in between the quotes of ``qcf_table_filename = ''`` in the &filter_nml section. +Remember that the default values will be used for all QTYs if no filename is listed here. + +Build and run filter normally. + +The data that is read from in the QCF table is written to the output file dart_log.out diff --git a/guide/qcf_table.rst b/guide/qcf_table.rst deleted file mode 100644 index 113bffee9a..0000000000 --- a/guide/qcf_table.rst +++ /dev/null @@ -1,227 +0,0 @@ -.. _QCF Table: - -############################################ -Using the QCF Table to Control Input Options -############################################ - -This file contains instructions for using an input table to set input options with the DART quantile conserving and probit transform filtering tools. -See the following link to learn more about these tools and how to use them: -https://docs.dart.ucar.edu/en/quantile_methods/models/lorenz_96_tracer_advection/work/readme.html - -Using this input table allows the user to specify the control options for the Quantile Conserving Filter (QCF), also known as the Quantile Conserving Ensemble Filtering Framework (QCEFF). The observation, state, and inflation variables are all included in this single table. - -The new quantile options are read in from the table at runtime and then set in the module algorithm_info_mod.f90 in the DART/assimilation_code/modules/assimilation directory. This module provides routines that give information about details of algorithms for observation error sampling, observation increments, and the transformations for regression and inflation in probit space. - -For individual QTYs in DART, the user can specify the options such as the bounds, distribution type, filter kind, etc. for the obs_error_info, probit_dist_info, and obs_inc_info subroutines in algorithm_info_mod.f90 - -If the user does not use a QCF input table with the DART quantile conserving and probit transform filtering tools, then the default values for these options will be used for all QTYs. - -Table Composition ------------------ -Each QTY is specified in its own column, having 28 total control options. -These control options are divided into 3 main groups, which are the options used for the obs_error_info, probit_dist_info, and obs_inc_info. However, the user is able to specify different values for probit inflation, probit state, and probit extended state, resulting in 5 total groupings for the control options. - -The obs_error_info subroutine computes information needed to compute error sample for this observation. -For obs_error_info the input options are the two bounds (lower and upper). - -The probit_dist_info subroutine computes the details of the probit transform. -From probit_dist_info, the values needed are the bounds and the distribution type. These can be different for all three cases (inflation, state, and extended_state). - -The obs_inc_info subrotuine sets the details of how to assimilate this observation. -From obs_inc_info, the bounds, plus the filter_kind, rectangular_quadrature, gaussian_likelihood_tails, sort_obs_inc, and spread_restoration are needed. However, rectangular_quadrature and gaussian_likelihood_tails are only applicable with RHF. - -Full list of options: -Obs_error_info: bounded_below, bounded_above, lower_bound, upper_bound [4 columns] -Probit_dist_info: dist_type, bounded_below, bounded_above, lower_bound, upper_bound (x3 for inflation, state, and observation (extended state) priors) [15 columns] -Obs_inc_info: filter_kind, rectangular_quadrature, gaussian_likelihood_tails, sort_obs_inc, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound [9 columns] - -Customizing the Table ---------------------- -The table can be customized by either editing a YAML file (which is then converted to a tabular data file in .txt format by a Python script) or a Google Sheet spreadsheet (which is then downloaded in .csv format). The specifics of how to manually edit both formats will be detailed in the following sections. - -Regardless of which of these formats are used, the table consists of two headers. The first states the version # of the table being used; the most recent version of the table needs to be used to ensure compatibilty with DART. The current version # is 1. The second header lists the full set of input options, or all 28 column names in other words. - -Generally, the user will add and fill in one row for each bounded QTY. If a QTY is not listed in the table, the default values will be used for all 28 options. Therefore, the user will only need to add rows for QTYs that use non-default values for any of the input options. ** - -The majority of the input options are read in as logicals, and will need to be written in the format of either 'F' or '.false.' These include bounded_below, bounded_above, rectangular_quadrature, gaussian_likelihood_tails, sort_obs_inc, and spread_restoration. - -The actual numerical values of the bounds are read in as real_r8 types. These can be specified as reals or integers in the table. - -dist_type and filter_kind are read in as strings, which the possible values for are listed below: - -dist_type: -NORMAL_DISTRIBUTION -BOUNDED_NORMAL_RH_DISTRIBUTION -GAMMA_DISTRIBUTION -BETA_DISTRIBUTION -LOG_NORMAL_DISTRIBUTION -UNIFORM_DISTRIBUTION -PARTICLE_FILTER_DISTRIBUTION - -filter_kind: -EAKF -ENKF -UNBOUNDED_RHF -GAMMA_FILTER -BOUNDED_NORMAL_RHF - -The default values for each of the options are listed below: -bounded_below = .false. -bounded_above = .false. -lower_bound = -888888 -upper_bound = -888888 -dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION -filter_kind = BOUNDED_NORMAL_RHF -rectangular_quadrature = .false. -gaussian_likelihood_tails = .false. -sort_obs_inc = .false. -spread_restoration = .false. - -Note that bounds set to -888888 are missing_r8 values. - -YAML File Usage ---------------- -This section will detail how to customize the qcf_table_template.yaml file and then utilize the yaml_to_table.py Python script to convert the YAML dictionary into a table in .txt format. - -First, the user needs to access YAML template file, located in DART/assimilation/programs/qcf_table/ -This template file is then to be copied into another file. You can name this anything, but the standard name is 'qcf_table.yaml'. - -.. code:: - cp qcf_table_template.yaml qcf_table.yaml - -The YAML file needs to match the formatting in qcf_table_template.yaml, which is as follows: - -:: - - QCF table version: 1 - QTY_TEMPLATE: - obs_error_info: - bounded_below - bounded_above - lower_bound - upper_bound - probit_inflation: - dist_type - bounded_below - bounded_above - lower_bound - upper_bound - probit_state: - dist_type - bounded_below - bounded_above - lower_bound - upper_bound - probit_extended_state: - dist_type - bounded_below - bounded_above - lower_bound - upper_bound - obs_inc_info: - filter_kind - rectangular_quadrature - gaussian_likelihood_tails - sort_obs_inc - spread_restoration - bounded_below - bounded_above - lower_bound - upper_bound - QTY_STATE_VARIABLE: - obs_error_info: - bounded_below: .false. - bounded_above: .false. - lower_bound: -888888.0 - upper_bound: -888888.0 - probit_inflation: - dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below: .false. - bounded_above: .false. - lower_bound: -888888.0 - upper_bound: -888888.0 - probit_state: - dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below: .false. - bounded_above: .false. - lower_bound: -888888.0 - upper_bound: -888888.0 - probit_extended_state: - dist_type: BOUNDED_NORMAL_RH_DISTRIBUTION - bounded_below: .false. - bounded_above: .false. - lower_bound: -888888.0 - upper_bound: -888888.0 - obs_inc_info: - filter_kind: BOUNDED_NORMAL_RHF - rectangular_quadrature: .false. - gaussian_likelihood_tails: .false. - sort_obs_inc: .false. - spread_restoration: .false. - bounded_below: .false. - bounded_above: .false. - lower_bound: -888888.0 - upper_bound: -888888.0 - -To customize the YAML dictionary file, the user should change the name 'QTY_STATE_VARIABLE' to the name of the first QTY to be specified with non-default values. Edit the values for the vairables wanting to be changed, and leave the rest of the variables set to the default values. - -To add additional QTYs after this, simply copy the lines pertaining to first QTY, change the name of the QTY, and set the variables accordingly. - -To remove a QTY from the YAML dictionary, simply remove the lines it consists of. - -The user will then take their customized YAML file and pass it as input into a Python script. This will convert it into a text file contaning the table data. - -This script is located in DART/assimilation/programs/qcf_table/ - -To use the Python script on Derecho or Cheyenne, the user must first load the correct modules - -:: - - module load conda - conda activate npl - -Then run the python script. - -:: - - python3 yaml_to_table.py - -The user will be prompted to enter the name of the input YAML file and the name for the output text file name. -A table will be produced at the specified output filename. - -Copy or move this file to your working directory. - -Google Sheets Usage -------------------- -This section will detail how to customize the Google Sheets spreadsheet and then download the spreadsheet into a table in .csv format. - -Folow this link https://docs.google.com/spreadsheets/d/1SI4wHBXatLAAMfiMx3mUUC7x0fqz4lniKuM4_i5j6bM/edit#gid=0 to access the template spreadsheet. - -The QTYs listed in the template file (QTY_STATE_VARIABLE, QTY_TRACER_SOURCE) correspond to the lorenz_6_tracer_advection model and have the default values set for all variables. Make sure to remove these QTYs if you are not running an analagous model. ** - -Make a copy of the table by selecting 'File > Make a copy' from the menu bar. - -To customize the spreadsheet, click on the cell you want to edit and change the value of that cell. -To add a new QTY to the spreadsheet, simply copy the row of a listed QTY, change the QTY name, and edit the cells individually to set the control options. -To remove a QTY from the spreadsheet, select the row corresponding to that QTY. Then right click and choose "Delete Row" - -Ensure that there are no empty rows in between the QTYs listed in the spreadsheet. - -Download the spreadsheet as a .csv file by selecting 'File > Download > csv' from the menu bar. - -Google Sheets will append the name of the file with " - Sheet1.csv". For example a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv" -Rename this file to remove this append to ensure that there are no spaces in the filename. - -Copy or move this file to your working directory. - -Using the table in DART ------------------------ -Navigate to your working directory. - -Edit your namelist file (input.nml) -Add the item "qcf_table_filename = 'your_filename' to the &filter_nml section, replacing your_filename with the actual name of the file you want to use. -Remember that the default values will be used for all QTYs if no filename is listed here. - -Build and run filter normally. - -The data read from the QCF table used is written to the output file dart_log.out diff --git a/index.rst b/index.rst index 1aedcc7f87..618da47cfc 100644 --- a/index.rst +++ b/index.rst @@ -62,6 +62,45 @@ These tools are intended for use by the full range of geosciencies community: beginners and experts; students and teachers; national centers and university research labs. +Nonlinear and Non-Gaussian Data Assimilation Capabilities in DART +----------------------------------------------------------------- +The default DART algorithms assume a normal distribution to compute ensemble increments +for the observed quantity (this is the ensemble adjustment Kalman filter, or EAKF) and +then linearly regresses the observation increments onto each state variable. + +DART’s newest and innovative capability, the Quantile Conserving Filters (QCF), provide a +very general method of computing increments for the prior ensemble of an observed quantity +and allow for the use of quantile conserving ensemble filters that can assume arbitrary +distributions for the prior and the observation error. Quantile conserving filters are +especially useful for bounded quantities like tracer concentrations, depths of things like +snow or ice, and estimating model parameters that have a restricted range. + +While Quantile Conserving Filters lead to significant improvements in analysis estimates for +observed variables, those improvements can be lost when using standard linear regression of +observation increments to update other state variables. Therefore, DART also includes new +functionality to use probit-transformed quantile regression methods that allow much more general +regression for computing state increments. Doing the regression of observation quantile increments +in a probit-transformed, bivariate, quantile space guarantees that the posterior ensembles +for state variables also have all the advantages of the observation space quantile conserving +posteriors. For example, if state variables are bounded, then posterior ensembles will respect +the bounds. The posterior ensembles also respect other aspects of the continuous prior distributions. + +Inflation and localization, methods that improve the quality of ensemble DA, can also negate the +advantages of the quantile conserving method. However, both localization and inflation can be done +in the probit-transformed quantile space. + +Combining these new methods can significantly improve data assimilation for non-Gaussian quantities +in Earth system models by extending the capabilities of ensemble DA to general non-Gaussian and +nonlinear distributions. Transformative improvements in DA can result for many applications. The +largest improvements are found for bounded variables like tracer concentrations, snow and ice depth, +soil moisture, and similar quantities in other parts of the Earth system. Model parameters can also be +estimated with DA and large improvements can occur for bounded parameters. Variables that have distinctly +non-Gaussian prior distributions can also see large improvements. Examples can include atmospheric +quantities like moisture and cloud amount in the presence of convection, and many land surface variables. + +The instructions to use these tools can be found on this page: +:doc:`Quantile Conserving and Probit Transform Filtering Tools ` + Organization of the documentation --------------------------------- @@ -230,7 +269,7 @@ References guide/downloading-dart guide/compiling-dart guide/verifying-installation - models/lorenz_96_tracer_advection/work/readme + guide/qcf_probit.rst .. toctree:: :maxdepth: 2 diff --git a/models/lorenz_96_tracer_advection/readme.rst b/models/lorenz_96_tracer_advection/readme.rst deleted file mode 100644 index 417f82d903..0000000000 --- a/models/lorenz_96_tracer_advection/readme.rst +++ /dev/null @@ -1,143 +0,0 @@ -Lorenz 96 Tracer Advection -========================== - -Overview --------- - -The Lorenz 96 Tracer Advection model combines the Lorenz 96 model with an -upstream semi-Lagrangian method. This simulates the advection of tracer -particles from any source(s) by the Lorenz 96 variables (here serving as wind). - -The Lorenz 96 model was first described by Edward Lorenz during a seminar at -the European Centre for Medium-Range Weather Forecasts in the Autumn of 1995, -the proceedings of which were published as Lorenz (1996) [1]_ the following -year, hence the model is commonly referred to as Lorenz 96. - -Lorenz and Emmanuel (1998) [2]_ describe the model as: - - ... consisting of 40 ordinary differential equations, with the dependent - variables representing values of some atmospheric quantity at 40 sites spaced - equally about a latitude circle. The equations contain quadratic, linear, and - constant terms representing advection, dissipation, and external forcing. - Numerical integration indicates that small errors (differences between - solutions) tend to double in about 2 days. Localized errors tend to spread - eastward as they grow, encircling the globe after about 14 days. - - We have chosen a model with :math:`J` variables, denoted by: - - .. math:: - - X_1, ... , X_j; - - in most of our experiments we have let :math:`J = 40`. The governing - equations are: - - .. math:: - - dX_j/dt=(X_{j+1}-X_{j-2})X_{j-1}-X_j+F (1) - - for: - - .. math:: - - j=1,...,J. - - To make Eq. (1) meaningful for all values of *j* we define: - - .. math:: - - X_{-1}=X_{J-1}, X_0=X_J, \& X_{J+1}=X_1, - - so that the variables form a cyclic chain, and may be looked at as values of - some unspecified scalar meteorological quantity, perhaps vorticity or - temperature, at *J* equally spaced sites extending around a latitude circle. - Nothing will simulate the atmosphere's latitudinal or vertical extent. - -In this model we are using the Semi-Lagrangian Scheme to model how tracer particles -get distributed upstream across the grids by the Lorenz 96 winds - -|Plot of 1D Semi-Lagrangian Method| - -The figure above describes the implementation of the Semi-Lagrangian scheme in a -one dimensional array. The tracer particle in the figure lands on a predefined grid -point at t\ :sup:`n+1`. The trajectory of this tracer particle is then integrated -backwards by one time step to time t\ :sup:`n`, often landing between grid points. -Then, due to advection without diffusion, the concentration of tracer at time - t\ :sup:`n+1` is simply the concentration of tracer at time t\ :sup:`n`, which -can be determined by interpolating concentrations of the surrounding grids [3]_. - -Once the coupled Lorenz 96 and semi-Lagrangian is run with a source of strength -100 units/s and location at grid point one (with exponential sinks present in -all grid points), the time evolution is as depicted below: - -|Plot of Lorenz 96 Tracer Advection| - -For Lorenz 96 Tracer Advection, DART advances the model, gets the model state and -metadata describing this state, finds state variables that are close to a given -location, and does spatial interpolation for model state variables. - -Namelist --------- - -The ``&model_nml`` namelist is read from the ``input.nml`` file. Namelists -start with an ampersand ``&`` and terminate with a slash ``/``. Character -strings that contain a ``/`` must be enclosed in quotes to prevent them from -prematurely terminating the namelist. - -.. code-block:: fortran - - &model_nml - model_size = 120, - forcing = 8.00, - delta_t = 0.05, - time_step_days = 0, - time_step_seconds = 3600 - / - -Description of each namelist entry -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -+-------------------+----------+-------------------------------------+ -| Item | Type | Description | -+===================+==========+=====================================+ -| model_size | integer | Total number of items in the state | -| | | vector. | -| | | The first third of the state vector | -| | | describes winds, the second third | -| | | describes tracer concentration, and | -| | | the final third of the state vector | -| | | describes the location strength of | -| | | sources. | -+-------------------+----------+-------------------------------------+ -| forcing | real(r8) | Forcing, F, for model. | -+-------------------+----------+-------------------------------------+ -| delta_t | real(r8) | Non-dimensional timestep. This is | -| | | mapped to the dimensional timestep | -| | | specified by time_step_days and | -| | | time_step_seconds. | -+-------------------+----------+-------------------------------------+ -| time_step_days | integer | Number of days for dimensional | -| | | timestep, mapped to delta_t. | -+-------------------+----------+-------------------------------------+ -| time_step_seconds | integer | Number of seconds for dimensional | -| | | timestep, mapped to delta_t. | -+-------------------+----------+-------------------------------------+ - -References ----------- - -.. [1] Lorenz, Edward N., 1996: Predictability: A Problem Partly Solved. - *Seminar on Predictability.* **1**, ECMWF, Reading, Berkshire, UK, 1-18. - -.. [2] Lorenz, Edward N., and Kerry A. Emanuel, 1998: Optimal Sites for - Supplementary Weather Observations: Simulations with a Small Model. - *Journal of the Atmospheric Sciences*, **55**, 399-414, - `doi:10.1175/1520-0469(1998)055\<0399:OSFSWO\>2.0.CO;2 - 2.0.CO;2>`__ - -.. [3] Cushman-Roisin, Benoit, and Jean-Marie Beckers. 2011. - Introduction to Geophysical Fluid Dynamics: Volume 101: Physical - and Numerical Aspects. 2nd ed. San Diego, CA: Academic Press. - -.. |Plot of 1D Semi-Lagrangian Method| image:: images/Semi_lag.png -.. |Plot of Lorenz 96 Tracer Advection| image:: images/lorenz_96_tracer_advection.gif From 5573b6de1a5928ce1cd5d50b40a35268863f2c56 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 17 Oct 2023 17:09:19 -0600 Subject: [PATCH 076/129] Fixing the link to the QCF doc page --- index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.rst b/index.rst index 618da47cfc..99d2fbfd0a 100644 --- a/index.rst +++ b/index.rst @@ -99,7 +99,7 @@ non-Gaussian prior distributions can also see large improvements. Examples can i quantities like moisture and cloud amount in the presence of convection, and many land surface variables. The instructions to use these tools can be found on this page: -:doc:`Quantile Conserving and Probit Transform Filtering Tools ` +:ref:`QCF` Organization of the documentation --------------------------------- From bd1aa8512669d15c1f2243b5e8faaf9a18e159bf Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 18 Oct 2023 11:38:15 -0600 Subject: [PATCH 077/129] Fixing some typos in the documentation --- index.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/index.rst b/index.rst index 99d2fbfd0a..fa63356f3b 100644 --- a/index.rst +++ b/index.rst @@ -68,10 +68,11 @@ The default DART algorithms assume a normal distribution to compute ensemble inc for the observed quantity (this is the ensemble adjustment Kalman filter, or EAKF) and then linearly regresses the observation increments onto each state variable. -DART’s newest and innovative capability, the Quantile Conserving Filters (QCF), provide a +DART’s newest and innovative capability, the Quantile Conserving Filters (QCF), also known +as the Quantile Conserving Ensemble Filtering Framework (QCEFF), provide a very general method of computing increments for the prior ensemble of an observed quantity -and allow for the use of quantile conserving ensemble filters that can assume arbitrary -distributions for the prior and the observation error. Quantile conserving filters are +by allowing the use of quantile conserving ensemble filters that can assume arbitrary +distributions for the prior and the observation error. Quantile Conserving Filters are especially useful for bounded quantities like tracer concentrations, depths of things like snow or ice, and estimating model parameters that have a restricted range. @@ -86,8 +87,8 @@ posteriors. For example, if state variables are bounded, then posterior ensemble the bounds. The posterior ensembles also respect other aspects of the continuous prior distributions. Inflation and localization, methods that improve the quality of ensemble DA, can also negate the -advantages of the quantile conserving method. However, both localization and inflation can be done -in the probit-transformed quantile space. +advantages of the quantile conserving method. For this reason, both localization and inflation can be done +in the probit-transformed quantile space as well. Combining these new methods can significantly improve data assimilation for non-Gaussian quantities in Earth system models by extending the capabilities of ensemble DA to general non-Gaussian and From 17fb9edf2230d323a0540489253a1dba4f537b76 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 18 Oct 2023 11:59:45 -0600 Subject: [PATCH 078/129] Revoving global filter_kind from assim_tools_mod and &assim_tools_nml; making args for obs_inc_info intent(out) --- .../assimilation/algorithm_info_mod.f90 | 8 ++-- .../modules/assimilation/assim_tools_mod.f90 | 37 +------------------ 2 files changed, 6 insertions(+), 39 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index a0339d1930..ba32e5b177 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -82,7 +82,7 @@ module algorithm_info_mod integer, parameter :: HEADER_LINES = 2 character(len=129), dimension(4) :: header1 -character(len=129), dimension(26) :: header2 +character(len=129), dimension(26) :: header2 ! Number of table columns plus 1 character(len=129), allocatable :: specified_qtys(:) type(algorithm_info_type), allocatable :: qcf_table_data(:) @@ -423,10 +423,10 @@ subroutine obs_inc_info(obs_qty, filter_kind, spread_restoration, & bounded_below, bounded_above, lower_bound, upper_bound) integer, intent(in) :: obs_qty -integer, intent(inout) :: filter_kind +integer, intent(out) :: filter_kind logical, intent(inout) :: spread_restoration -logical, intent(inout) :: bounded_below, bounded_above -real(r8), intent(inout) :: lower_bound, upper_bound +logical, intent(out) :: bounded_below, bounded_above +real(r8), intent(out) :: lower_bound, upper_bound integer :: QTY_loc(1) character(len=129) :: qty_name diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index b93e7eeca5..16f9d54994 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -143,7 +143,6 @@ module assim_tools_mod ! special_localization_obs_types -> Special treatment for the specified observation types ! special_localization_cutoffs -> Different cutoff value for each specified obs type ! -integer :: filter_kind = 1 real(r8) :: cutoff = 0.2_r8 logical :: sort_obs_inc = .true. logical :: spread_restoration = .false. @@ -202,7 +201,7 @@ module assim_tools_mod ! compared to previous versions of this namelist item. logical :: distribute_mean = .false. -namelist / assim_tools_nml / filter_kind, cutoff, sort_obs_inc, & +namelist / assim_tools_nml / cutoff, sort_obs_inc, & spread_restoration, sampling_error_correction, & adaptive_localization_threshold, adaptive_cutoff_floor, & print_every_nth_obs, rectangular_quadrature, gaussian_likelihood_tails, & @@ -247,12 +246,6 @@ subroutine assim_tools_init() ! Note null_win_mod.f90 ignores distibute_mean. if (task_count() == 1) distribute_mean = .true. -! FOR NOW, can only do spread restoration with filter option 1 (need to extend this) -if(spread_restoration .and. .not. filter_kind == 1) then - write(msgstring, *) 'cannot combine spread_restoration and filter_kind ', filter_kind - call error_handler(E_ERR,'assim_tools_init:', msgstring, source) -endif - ! allocate a list in all cases - even the ones where there is only ! a single cutoff value. note that in spite of the name these ! are specific types (e.g. RADIOSONDE_TEMPERATURE, AIRCRAFT_TEMPERATURE) @@ -922,6 +915,7 @@ subroutine obs_increment(ens_in, ens_size, obs, obs_var, obs_kind, obs_inc, & ! Declarations for bounded rank histogram filter real(r8) :: likelihood(ens_size), like_sum +integer :: filter_kind logical :: bounded_below, bounded_above real(r8) :: lower_bound, upper_bound @@ -2489,33 +2483,6 @@ subroutine log_namelist_selections(num_special_cutoff, cache_override) integer :: i -select case (filter_kind) - case (1) - msgstring = 'Ensemble Adjustment Kalman Filter (EAKF)' - case (2) - msgstring = 'Ensemble Kalman Filter (ENKF)' - case (3) - msgstring = 'Kernel filter' - case (4) - msgstring = 'observation space particle filter' - case (5) - msgstring = 'random draw from posterior' - case (6) - msgstring = 'deterministic draw from posterior with fixed kurtosis' - case (7) - msgstring = 'Boxcar' - case (8) - msgstring = 'Rank Histogram Filter' - case (11) - msgstring = 'Gamma Filter' - case (101) - msgstring = 'Bounded Rank Histogram Filter' - case default - call error_handler(E_ERR, 'assim_tools_init:', 'illegal filter_kind value, valid values are 1-8', & - source) -end select -call error_handler(E_MSG, 'assim_tools_init:', 'Selected filter type is '//trim(msgstring)) - if (adjust_obs_impact) then call allocate_impact_table(obs_impact_table) call read_impact_table(obs_impact_filename, obs_impact_table, allow_any_impact_values, "allow_any_impact_values") From 4d15ff8d25a341d64abfa066c72f2dccd92af198 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 18 Oct 2023 14:27:58 -0600 Subject: [PATCH 079/129] Removing filter_kind from all input.nml files in the &assim_tools_mod section --- models/9var/work/input.nml | 1 - models/FESOM/work/input.nml | 1 - models/LMDZ/work/input.nml | 1 - models/MITgcm_annulus/work/input.nml | 1 - models/MITgcm_ocean/work/input.nml | 2 -- models/MOM6/work/input.nml | 1 - models/NAAPS/work/input.nml | 1 - models/NCOMMAS/work/input.nml | 1 - models/POP/work/input.nml | 1 - models/ROMS/work/input.nml | 1 - models/am2/work/input.nml | 1 - models/bgrid_solo/work/input.nml | 1 - models/cam-fv/work/input.nml | 1 - models/cam-se/work/input.nml | 1 - models/cice/work/input.nml | 1 - models/clm/work/input.nml | 1 - models/cm1/work/input.nml | 1 - models/dynamo/work/input.nml | 1 - models/forced_barot/work/input.nml | 1 - models/forced_lorenz_96/work/input.nml | 1 - models/gitm/work/input.nml | 1 - models/ikeda/work/input.nml | 1 - models/lorenz_04/work/input.nml | 1 - models/lorenz_63/work/input.nml | 1 - models/lorenz_84/work/input.nml | 1 - models/lorenz_96/work/input.nml | 1 - models/lorenz_96_2scale/work/input.nml | 1 - models/lorenz_96_tracer_advection/work/input.nml | 1 - models/mpas_atm/work/input.nml | 1 - models/mpas_ocn/work/input.nml | 1 - models/noah/work/input.nml | 1 - models/null_model/work/input.nml | 1 - models/pe2lyr/work/input.nml | 1 - models/rose/work/input.nml | 1 - models/simple_advection/work/input.nml | 1 - models/sqg/work/input.nml | 1 - models/template/work/oned_input.nml | 1 - models/template/work/threed_input.nml | 1 - models/tiegcm/work/input.nml | 1 - models/wrf/work/input.nml | 1 - models/wrf_hydro/work/input.nml | 2 -- 41 files changed, 43 deletions(-) diff --git a/models/9var/work/input.nml b/models/9var/work/input.nml index 419aec1d3a..fccc09cf31 100644 --- a/models/9var/work/input.nml +++ b/models/9var/work/input.nml @@ -96,7 +96,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 1000000.0, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/FESOM/work/input.nml b/models/FESOM/work/input.nml index 140d14cf67..80d0e09c4f 100644 --- a/models/FESOM/work/input.nml +++ b/models/FESOM/work/input.nml @@ -94,7 +94,6 @@ / &assim_tools_nml - filter_kind = 1 cutoff = 0.005 sort_obs_inc = .false. spread_restoration = .false. diff --git a/models/LMDZ/work/input.nml b/models/LMDZ/work/input.nml index f6df9b80e2..440eb8a9ee 100644 --- a/models/LMDZ/work/input.nml +++ b/models/LMDZ/work/input.nml @@ -81,7 +81,6 @@ perturbation_amplitude = 0.2 / &assim_tools_nml - filter_kind = 1, cutoff = 0.2, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/MITgcm_annulus/work/input.nml b/models/MITgcm_annulus/work/input.nml index 39d36c0d19..065a524d74 100644 --- a/models/MITgcm_annulus/work/input.nml +++ b/models/MITgcm_annulus/work/input.nml @@ -81,7 +81,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 0.15, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/MITgcm_ocean/work/input.nml b/models/MITgcm_ocean/work/input.nml index 9bc7844826..46211431fe 100644 --- a/models/MITgcm_ocean/work/input.nml +++ b/models/MITgcm_ocean/work/input.nml @@ -78,7 +78,6 @@ # enabling sampling error correction is generally beneficial # the default file is in assimilation_code/programs/gen_sampling_err_table/work # -# With a deterministic filter (filter_kind == 1 or 8) # and a deterministic inflation (filter_nml:inf_deterministic == .true.) # sort_obs_inc is not needed and is expensive. Should be .false. # @@ -86,7 +85,6 @@ # in both lists, the same number of items &assim_tools_nml - filter_kind = 1 cutoff = 0.025 distribute_mean = .false. sort_obs_inc = .false. diff --git a/models/MOM6/work/input.nml b/models/MOM6/work/input.nml index eeaa2a3b3b..867191e4bf 100644 --- a/models/MOM6/work/input.nml +++ b/models/MOM6/work/input.nml @@ -93,7 +93,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 1000000.0 sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/NAAPS/work/input.nml b/models/NAAPS/work/input.nml index e7b0145b05..00425d2245 100644 --- a/models/NAAPS/work/input.nml +++ b/models/NAAPS/work/input.nml @@ -5,7 +5,6 @@ / &assim_tools_nml - filter_kind = 1 cutoff = 0.03 sort_obs_inc = .false. spread_restoration = .false. diff --git a/models/NCOMMAS/work/input.nml b/models/NCOMMAS/work/input.nml index 20313f87e9..52c176a737 100644 --- a/models/NCOMMAS/work/input.nml +++ b/models/NCOMMAS/work/input.nml @@ -80,7 +80,6 @@ # cutoff of 0.03 (radians) is about 200km &assim_tools_nml - filter_kind = 1, cutoff = 0.20, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/POP/work/input.nml b/models/POP/work/input.nml index 2e2406f0c8..a1eb9e0dab 100644 --- a/models/POP/work/input.nml +++ b/models/POP/work/input.nml @@ -95,7 +95,6 @@ # if running a smaller pop case, use false to run faster. # &assim_tools_nml - filter_kind = 1 cutoff = 0.20 sort_obs_inc = .false. spread_restoration = .false. diff --git a/models/ROMS/work/input.nml b/models/ROMS/work/input.nml index ec9c4b6ab9..9120b6e916 100644 --- a/models/ROMS/work/input.nml +++ b/models/ROMS/work/input.nml @@ -94,7 +94,6 @@ &assim_tools_nml - filter_kind = 1 cutoff = 0.02 sort_obs_inc = .false. spread_restoration = .false. diff --git a/models/am2/work/input.nml b/models/am2/work/input.nml index 83825dab00..58d0b3dee2 100644 --- a/models/am2/work/input.nml +++ b/models/am2/work/input.nml @@ -79,7 +79,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 0.2, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/bgrid_solo/work/input.nml b/models/bgrid_solo/work/input.nml index 7311b0464e..f85cd5b2a6 100644 --- a/models/bgrid_solo/work/input.nml +++ b/models/bgrid_solo/work/input.nml @@ -99,7 +99,6 @@ &assim_tools_nml - filter_kind = 1, cutoff = 0.20, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/cam-fv/work/input.nml b/models/cam-fv/work/input.nml index 5c57299780..8a8ae3d10a 100644 --- a/models/cam-fv/work/input.nml +++ b/models/cam-fv/work/input.nml @@ -360,7 +360,6 @@ &assim_tools_nml - filter_kind = 1 cutoff = 0.15 sort_obs_inc = .false. spread_restoration = .false. diff --git a/models/cam-se/work/input.nml b/models/cam-se/work/input.nml index c0d85dd32a..6b9a561b68 100644 --- a/models/cam-se/work/input.nml +++ b/models/cam-se/work/input.nml @@ -351,7 +351,6 @@ &assim_tools_nml - filter_kind = 1 cutoff = 0.15 sort_obs_inc = .false. spread_restoration = .false. diff --git a/models/cice/work/input.nml b/models/cice/work/input.nml index 4b51f3cdc9..c78fd038a4 100644 --- a/models/cice/work/input.nml +++ b/models/cice/work/input.nml @@ -83,7 +83,6 @@ # cutoff of 0.03 (radians) is about 200km &assim_tools_nml - filter_kind = 1 cutoff = 0.05 sort_obs_inc = .false. spread_restoration = .false. diff --git a/models/clm/work/input.nml b/models/clm/work/input.nml index ee6dec2901..cb46cab1ff 100644 --- a/models/clm/work/input.nml +++ b/models/clm/work/input.nml @@ -121,7 +121,6 @@ # cutoff of 0.03 (radians) is about 200km &assim_tools_nml - filter_kind = 1 cutoff = 0.05 sort_obs_inc = .false. spread_restoration = .false. diff --git a/models/cm1/work/input.nml b/models/cm1/work/input.nml index fedba1cb38..b0a6d5cef0 100644 --- a/models/cm1/work/input.nml +++ b/models/cm1/work/input.nml @@ -257,7 +257,6 @@ &assim_tools_nml adaptive_localization_threshold = -1 cutoff = 15000.0 - filter_kind = 1 print_every_nth_obs = 100 rectangular_quadrature = .true. sampling_error_correction = .false. diff --git a/models/dynamo/work/input.nml b/models/dynamo/work/input.nml index dc87e3fe8f..3add1a1c6e 100644 --- a/models/dynamo/work/input.nml +++ b/models/dynamo/work/input.nml @@ -81,7 +81,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 0.00001, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/forced_barot/work/input.nml b/models/forced_barot/work/input.nml index 289947ac7e..aed880c7b4 100644 --- a/models/forced_barot/work/input.nml +++ b/models/forced_barot/work/input.nml @@ -83,7 +83,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 0.02, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/forced_lorenz_96/work/input.nml b/models/forced_lorenz_96/work/input.nml index 94ffe130ee..537d7aec4e 100644 --- a/models/forced_lorenz_96/work/input.nml +++ b/models/forced_lorenz_96/work/input.nml @@ -94,7 +94,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 1000000.0, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/gitm/work/input.nml b/models/gitm/work/input.nml index 04f0dc17ea..70156882d0 100644 --- a/models/gitm/work/input.nml +++ b/models/gitm/work/input.nml @@ -90,7 +90,6 @@ # cutoff of 0.03 (radians) is about 200km &assim_tools_nml - filter_kind = 1, cutoff = 0.60, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/ikeda/work/input.nml b/models/ikeda/work/input.nml index cdb6258774..51d0d15c50 100644 --- a/models/ikeda/work/input.nml +++ b/models/ikeda/work/input.nml @@ -93,7 +93,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 1000000.0, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/lorenz_04/work/input.nml b/models/lorenz_04/work/input.nml index eb33f422f6..7d2f85fc02 100644 --- a/models/lorenz_04/work/input.nml +++ b/models/lorenz_04/work/input.nml @@ -91,7 +91,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 1000000.0, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/lorenz_63/work/input.nml b/models/lorenz_63/work/input.nml index 86a7e2e569..da3f873619 100644 --- a/models/lorenz_63/work/input.nml +++ b/models/lorenz_63/work/input.nml @@ -93,7 +93,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 1000000.0 sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/lorenz_84/work/input.nml b/models/lorenz_84/work/input.nml index 41abcd15aa..40276b9994 100644 --- a/models/lorenz_84/work/input.nml +++ b/models/lorenz_84/work/input.nml @@ -96,7 +96,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 1000000.0, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/lorenz_96/work/input.nml b/models/lorenz_96/work/input.nml index 615ef8df5d..49b3244f1d 100644 --- a/models/lorenz_96/work/input.nml +++ b/models/lorenz_96/work/input.nml @@ -93,7 +93,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 0.02, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/lorenz_96_2scale/work/input.nml b/models/lorenz_96_2scale/work/input.nml index 5c02f9afa7..bf1468237c 100644 --- a/models/lorenz_96_2scale/work/input.nml +++ b/models/lorenz_96_2scale/work/input.nml @@ -92,7 +92,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 1000000.0, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/lorenz_96_tracer_advection/work/input.nml b/models/lorenz_96_tracer_advection/work/input.nml index 164c2444e2..bb5353fc67 100644 --- a/models/lorenz_96_tracer_advection/work/input.nml +++ b/models/lorenz_96_tracer_advection/work/input.nml @@ -100,7 +100,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 1000000.0 sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/mpas_atm/work/input.nml b/models/mpas_atm/work/input.nml index 7444c9f3b9..bfbe13f568 100644 --- a/models/mpas_atm/work/input.nml +++ b/models/mpas_atm/work/input.nml @@ -99,7 +99,6 @@ / &assim_tools_nml - filter_kind = 1 cutoff = 0.10 distribute_mean = .false. convert_all_obs_verticals_first = .true. diff --git a/models/mpas_ocn/work/input.nml b/models/mpas_ocn/work/input.nml index dd54fdb788..f11d657cda 100644 --- a/models/mpas_ocn/work/input.nml +++ b/models/mpas_ocn/work/input.nml @@ -81,7 +81,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 1000000.0, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/noah/work/input.nml b/models/noah/work/input.nml index cfc027ac68..c5e48d8429 100644 --- a/models/noah/work/input.nml +++ b/models/noah/work/input.nml @@ -122,7 +122,6 @@ # cutoff = 0.06 (radians) is about 400 km &assim_tools_nml - filter_kind = 1 cutoff = 0.05 sort_obs_inc = .false. spread_restoration = .false. diff --git a/models/null_model/work/input.nml b/models/null_model/work/input.nml index 5ab448764c..f5282c3b22 100644 --- a/models/null_model/work/input.nml +++ b/models/null_model/work/input.nml @@ -104,7 +104,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 1000000.0, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/pe2lyr/work/input.nml b/models/pe2lyr/work/input.nml index ab7c31f1dd..94d2ebfc97 100644 --- a/models/pe2lyr/work/input.nml +++ b/models/pe2lyr/work/input.nml @@ -77,7 +77,6 @@ perturbation_amplitude = 0.2 / &assim_tools_nml - filter_kind = 1, cutoff = 0.02, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/rose/work/input.nml b/models/rose/work/input.nml index 0b0baca301..7092c2e086 100644 --- a/models/rose/work/input.nml +++ b/models/rose/work/input.nml @@ -80,7 +80,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 0.2, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/simple_advection/work/input.nml b/models/simple_advection/work/input.nml index 1a1f25aaf7..8174c039d3 100644 --- a/models/simple_advection/work/input.nml +++ b/models/simple_advection/work/input.nml @@ -98,7 +98,6 @@ # large for the model to converge. to test that the model is # doing a successful assimilation, change cutoff to 0.02 and rerun. &assim_tools_nml - filter_kind = 1 cutoff = 100000000.0 sort_obs_inc = .false. spread_restoration = .false. diff --git a/models/sqg/work/input.nml b/models/sqg/work/input.nml index fe4a2c9c2b..bd4c13a193 100644 --- a/models/sqg/work/input.nml +++ b/models/sqg/work/input.nml @@ -86,7 +86,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 100000.0, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/template/work/oned_input.nml b/models/template/work/oned_input.nml index 42ec36bf15..40444d3c42 100644 --- a/models/template/work/oned_input.nml +++ b/models/template/work/oned_input.nml @@ -93,7 +93,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 0.02, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/template/work/threed_input.nml b/models/template/work/threed_input.nml index cd962d5fe1..e2cc53e4bd 100644 --- a/models/template/work/threed_input.nml +++ b/models/template/work/threed_input.nml @@ -93,7 +93,6 @@ / &assim_tools_nml - filter_kind = 1, cutoff = 1000000.0 sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/tiegcm/work/input.nml b/models/tiegcm/work/input.nml index bdffe30be7..6478346746 100644 --- a/models/tiegcm/work/input.nml +++ b/models/tiegcm/work/input.nml @@ -111,7 +111,6 @@ / &assim_tools_nml - filter_kind = 1 cutoff = 0.2 sort_obs_inc = .false. spread_restoration = .false. diff --git a/models/wrf/work/input.nml b/models/wrf/work/input.nml index d1165099f2..17af11a9e4 100644 --- a/models/wrf/work/input.nml +++ b/models/wrf/work/input.nml @@ -103,7 +103,6 @@ # localization radius, where the influence of an obs decreases # to ~half at 300 km, and ~0 at the edges of the area. &assim_tools_nml - filter_kind = 1, cutoff = 0.05, sort_obs_inc = .false., spread_restoration = .false., diff --git a/models/wrf_hydro/work/input.nml b/models/wrf_hydro/work/input.nml index fb02247d26..67dc994862 100644 --- a/models/wrf_hydro/work/input.nml +++ b/models/wrf_hydro/work/input.nml @@ -129,7 +129,6 @@ / -# filter_kind=9 => JPoterjoy particle filter # cutoff is in radians; for the earth, 0.05 is about 300 km. # cutoff is defined to be the half-width of the localization radius # so 0.05 radians for cutoff is about an 600 km effective @@ -141,7 +140,6 @@ # max_link_distance = 2000m = cutoff = 0.000157 radians &assim_tools_nml - filter_kind = 1 cutoff = 0.000157 sort_obs_inc = .false. spread_restoration = .false. From f19bb1c832ec50e83cbc6f04be58b7a93c3ddeab Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 18 Oct 2023 14:46:18 -0600 Subject: [PATCH 080/129] Fixing comment accidentally removed from MITgmc_ocean namelist --- models/MITgcm_ocean/work/input.nml | 1 + models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/models/MITgcm_ocean/work/input.nml b/models/MITgcm_ocean/work/input.nml index 46211431fe..c8ddd50476 100644 --- a/models/MITgcm_ocean/work/input.nml +++ b/models/MITgcm_ocean/work/input.nml @@ -78,6 +78,7 @@ # enabling sampling error correction is generally beneficial # the default file is in assimilation_code/programs/gen_sampling_err_table/work # +# With a deterministic filter (filter_kind == 1 or 8) # and a deterministic inflation (filter_nml:inf_deterministic == .true.) # sort_obs_inc is not needed and is expensive. Should be .false. # diff --git a/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml b/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml index 0eda864c17..e1a0b9a8db 100644 --- a/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml +++ b/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml @@ -67,7 +67,6 @@ &assim_tools_nml - filter_kind = 1, cutoff = 0.125, sort_obs_inc = .false., spread_restoration = .false., From 385777eb01fc4b93bc08f998776b2d854caad6bd Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Thu, 19 Oct 2023 14:44:57 -0600 Subject: [PATCH 081/129] Adding documentation for the lorenz_96_tracer_advection examples with Google Sheets --- index.rst | 8 +- .../work/readme.rst | 79 ++++++++++++++++--- 2 files changed, 72 insertions(+), 15 deletions(-) diff --git a/index.rst b/index.rst index fa63356f3b..07cf134e25 100644 --- a/index.rst +++ b/index.rst @@ -99,9 +99,12 @@ estimated with DA and large improvements can occur for bounded parameters. Varia non-Gaussian prior distributions can also see large improvements. Examples can include atmospheric quantities like moisture and cloud amount in the presence of convection, and many land surface variables. -The instructions to use these tools can be found on this page: +Instructions to use these tools can be found on this page: :ref:`QCF` +Examples for using these tools with the lorenz_96_tracer_advection model can be found here: +:ref:`quantile tracer` + Organization of the documentation --------------------------------- @@ -270,7 +273,8 @@ References guide/downloading-dart guide/compiling-dart guide/verifying-installation - guide/qcf_probit.rst + guide/qcf_probit + models/lorenz_96_tracer_advection/work/readme .. toctree:: :maxdepth: 2 diff --git a/models/lorenz_96_tracer_advection/work/readme.rst b/models/lorenz_96_tracer_advection/work/readme.rst index 8ae7d72681..6043b9490f 100644 --- a/models/lorenz_96_tracer_advection/work/readme.rst +++ b/models/lorenz_96_tracer_advection/work/readme.rst @@ -4,12 +4,14 @@ Quantile conserving and probit transform tools ============================================== -This file contains instructions for using the lorenz_96_tracer model with DART +This file contains instructions for using the lorenz_96_tracer_advection model with DART quantile conserving and probit transform filtering tools. These tools are still being refined, but are working for the examples described. The DART development team (dart@ucar.edu) would be happy to hear about your experiences and is anxious to build scientific collaborations using these new capabilities. +Make sure that you are on the quantile_methods branch of DART: +``git checkout quantile_methods`` Steps for reproducing basic tests: @@ -20,9 +22,26 @@ The default model configuration has a single tracer source at gridpoint 1 along small uniform tracer sinks that lead to areas where the true tracer concentration is usually 0. This is a particularly tough test for ensemble methods. +#. Download the QCF Table from Google Sheets as a .csv file: + + Visit this link https://docs.google.com/spreadsheets/d/1ZhKbj0EYKHCgOHvTmJI3k7HI_Ae1NyNKchtekPW0lZs/edit#gid=0 + Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. + Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the + menu bar. + Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. + For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv" + Rename this file to remove this addition to ensure that there are no spaces in the filename. + Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). + +#. Add the filename of the downloaded .csv file to /DART/models/lorenz_96_tracer_advection/work/input.nml + + Add the name of the downloaded .csv file in between the single quotes on the line ``qcf_table_filename = ''`` + in the &filter_mod section. + #. Build all executables, ``./quickbuild.sh nompi`` + #. Create a set_def.out file using create_obs_sequence: ``./create_obs_sequence < create_obs_sequence_input`` @@ -71,9 +90,21 @@ Doing a diff between these modules shows how the control is being changed for th following tests in that module. The tests below replace the default version of that module with others that change certain options. -#. In directory assimilation_code/modules/assimilation, +#. Download the QCF Table from Google Sheets as a .csv file: + + Visit this link https://docs.google.com/spreadsheets/d/1e26KuOv_uwrn8y1Ki85FzSeQAc9Pw-nCGk91MpJGVC0/edit#gid=0 + Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. + Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the + menu bar. + Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. + For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv" + Rename this file to remove this addition to ensure that there are no spaces in the filename. + Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). + +#. Add the filename of the downloaded .csv file to /DART/models/lorenz_96_tracer_advection/work/input.nml - ``cp all_eakf_algorithm_info_mod algorithm_info_mod.f90`` + Add the name of the downloaded .csv file in between the single quotes on the line ``qcf_table_filename = ''`` + in the &filter_mod section. #. Recompile all programs in this directory, @@ -84,10 +115,22 @@ replace the default version of that module with others that change certain optio Test C: Using default ensemble adjustment Kalman filter for state, but bounded normal rank histogram filter and priors for tracer concentration and source. -#. In directory assimilation_code/modules/assimilation, - - ``cp state_eakf_tracer_bnrhf_algorithm_info_mod algorithm_info_mod.f90`` - +#. Download the QCF Table from Google Sheets as a .csv file: + + Visit this link https://docs.google.com/spreadsheets/d/1BEKEnFrw5KI9jf6ewg0POyr98ul5nGjerSVxjqEPDgA/edit#gid=0 + Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. + Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the + menu bar. + Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. + For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv" + Rename this file to remove this addition to ensure that there are no spaces in the filename. + Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). + +#. Add the filename of the downloaded .csv file to /DART/models/lorenz_96_tracer_advection/work/input.nml + + Add the name of the downloaded .csv file in between the single quotes on the line ``qcf_table_filename = ''`` + in the &filter_mod section. + #. Recompile all programs in this directory, ``./quickbiuld.sh nompi`` @@ -102,10 +145,22 @@ above. There are distinct numerical challenges in implementing the quantile algo for quantities that are bounded above, so flipping the sign of the tracers is a good test. -#. In directory assimilation_code/modules/assimilation, - - ``cp neg_algorithm_info_mod algorithm_info_mod.f90`` - +#. Download the QCF Table from Google Sheets as a .csv file: + + Visit this link https://docs.google.com/spreadsheets/d/1RHlwyhCpbgcShoQnGW-xp2v-paw1ar-5-EA-uj9CkR8/edit#gid=0 + Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. + Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the + menu bar. + Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. + For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv" + Rename this file to remove this addition to ensure that there are no spaces in the filename. + Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). + +#. Add the filename of the downloaded .csv file to /DART/models/lorenz_96_tracer_advection/work/input.nml + + Add the name of the downloaded .csv file in between the single quotes on the line ``qcf_table_filename = ''`` + in the &filter_mod section. + #. Recompile all programs in this directory, ``./quickbiuld.sh nompi`` @@ -114,5 +169,3 @@ test. entry read_input_state_from_file back to .false. #. Repeat steps 3-6 from Test A. - - From 4b3dfb72f98de5e6b40a33b77b1e0782847c8d50 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Thu, 19 Oct 2023 15:13:05 -0600 Subject: [PATCH 082/129] Doc fixes for lorenz_96_tracer_advection examples --- .../work/readme.rst | 86 +++++++------------ 1 file changed, 33 insertions(+), 53 deletions(-) diff --git a/models/lorenz_96_tracer_advection/work/readme.rst b/models/lorenz_96_tracer_advection/work/readme.rst index 6043b9490f..8df03e3cac 100644 --- a/models/lorenz_96_tracer_advection/work/readme.rst +++ b/models/lorenz_96_tracer_advection/work/readme.rst @@ -1,8 +1,8 @@ .. _quantile tracer: -Quantile conserving and probit transform tools -============================================== +QCF and Probit Transform Tools - Examples with lorenz_96_tracer_advection +========================================================================= This file contains instructions for using the lorenz_96_tracer_advection model with DART quantile conserving and probit transform filtering tools. These tools are still @@ -24,20 +24,18 @@ usually 0. This is a particularly tough test for ensemble methods. #. Download the QCF Table from Google Sheets as a .csv file: - Visit this link https://docs.google.com/spreadsheets/d/1ZhKbj0EYKHCgOHvTmJI3k7HI_Ae1NyNKchtekPW0lZs/edit#gid=0 - Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. - Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the + * Visit this link: https://docs.google.com/spreadsheets/d/1ZhKbj0EYKHCgOHvTmJI3k7HI_Ae1NyNKchtekPW0lZs/edit#gid=0 + * Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. + * Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the menu bar. - Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. + * Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv" Rename this file to remove this addition to ensure that there are no spaces in the filename. - Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). - -#. Add the filename of the downloaded .csv file to /DART/models/lorenz_96_tracer_advection/work/input.nml - - Add the name of the downloaded .csv file in between the single quotes on the line ``qcf_table_filename = ''`` - in the &filter_mod section. + * Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). +#. Add the filename of the downloaded .csv file to in between the single quotes on the line ``qcf_table_filename = ''`` + in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml + #. Build all executables, ``./quickbuild.sh nompi`` @@ -92,24 +90,18 @@ replace the default version of that module with others that change certain optio #. Download the QCF Table from Google Sheets as a .csv file: - Visit this link https://docs.google.com/spreadsheets/d/1e26KuOv_uwrn8y1Ki85FzSeQAc9Pw-nCGk91MpJGVC0/edit#gid=0 - Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. - Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the + * Visit this link https://docs.google.com/spreadsheets/d/1e26KuOv_uwrn8y1Ki85FzSeQAc9Pw-nCGk91MpJGVC0/edit#gid=0 + * Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. + * Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the menu bar. - Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. + * Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv" Rename this file to remove this addition to ensure that there are no spaces in the filename. - Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). - -#. Add the filename of the downloaded .csv file to /DART/models/lorenz_96_tracer_advection/work/input.nml - - Add the name of the downloaded .csv file in between the single quotes on the line ``qcf_table_filename = ''`` - in the &filter_mod section. - -#. Recompile all programs in this directory, - - ``./quickbiuld.sh nompi`` + * Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). +#. Add the filename of the downloaded .csv file to in between the single quotes on the line ``qcf_table_filename = ''`` + in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml + #. Run the filter ``./filter`` @@ -117,24 +109,18 @@ Test C: Using default ensemble adjustment Kalman filter for state, but bounded n #. Download the QCF Table from Google Sheets as a .csv file: - Visit this link https://docs.google.com/spreadsheets/d/1BEKEnFrw5KI9jf6ewg0POyr98ul5nGjerSVxjqEPDgA/edit#gid=0 - Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. - Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the + * Visit this link https://docs.google.com/spreadsheets/d/1BEKEnFrw5KI9jf6ewg0POyr98ul5nGjerSVxjqEPDgA/edit#gid=0 + * Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. + * Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the menu bar. - Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. + * Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv" Rename this file to remove this addition to ensure that there are no spaces in the filename. - Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). - -#. Add the filename of the downloaded .csv file to /DART/models/lorenz_96_tracer_advection/work/input.nml + * Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). - Add the name of the downloaded .csv file in between the single quotes on the line ``qcf_table_filename = ''`` - in the &filter_mod section. +#. Add the filename of the downloaded .csv file to in between the single quotes on the line ``qcf_table_filename = ''`` + in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml -#. Recompile all programs in this directory, - - ``./quickbiuld.sh nompi`` - #. Run the filter ``./filter`` @@ -147,25 +133,19 @@ test. #. Download the QCF Table from Google Sheets as a .csv file: - Visit this link https://docs.google.com/spreadsheets/d/1RHlwyhCpbgcShoQnGW-xp2v-paw1ar-5-EA-uj9CkR8/edit#gid=0 - Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. - Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the + * Visit this link https://docs.google.com/spreadsheets/d/1RHlwyhCpbgcShoQnGW-xp2v-paw1ar-5-EA-uj9CkR8/edit#gid=0 + * Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. + * Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the menu bar. - Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. + * Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv" Rename this file to remove this addition to ensure that there are no spaces in the filename. - Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). + * Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). -#. Add the filename of the downloaded .csv file to /DART/models/lorenz_96_tracer_advection/work/input.nml - - Add the name of the downloaded .csv file in between the single quotes on the line ``qcf_table_filename = ''`` - in the &filter_mod section. +#. Add the filename of the downloaded .csv file to in between the single quotes on the line ``qcf_table_filename = ''`` + in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml -#. Recompile all programs in this directory, - - ``./quickbiuld.sh nompi`` - #. In the file input.nml, change the entry positive_tracer to .false. Also, change the entry read_input_state_from_file back to .false. -#. Repeat steps 3-6 from Test A. +#. Repeat steps 5-8 from Test A. From 5c03e3cdd5332510a0532b02fcbb15d041a8cc88 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Thu, 19 Oct 2023 15:53:19 -0600 Subject: [PATCH 083/129] More doc fixes --- guide/qcf_probit.rst | 4 +- .../work/readme.rst | 40 +++++++------------ 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/guide/qcf_probit.rst b/guide/qcf_probit.rst index f411f476f7..80a7c6b2fd 100644 --- a/guide/qcf_probit.rst +++ b/guide/qcf_probit.rst @@ -69,9 +69,9 @@ EAKF, ENKF, UNBOUNDED_RHF, GAMMA_FILTER, BOUNDED_NORMAL_RHF Make a copy of the table by selecting 'File > Make a copy' from the menu bar. To customize the spreadsheet, click on the cell you want to edit and change the value of that cell. -To add a new QTY to the spreadsheet, copy row 3 of the table into the next available row, change ``QTY_TEMPLATE`` to the name of the QTY to specify, and edit the cells individually to set the control options. +To add a new QTY to the spreadsheet, copy row 3 of the table into the next available row, change ``QTY_NAME`` to the name of the QTY to specify, and edit the cells individually to set the control options. To remove a QTY from the spreadsheet, select the row number corresponding to that QTY. Then right click and choose "Delete Row" -Make sure to remove the row for ``QTY_TEMPLATE`` when you have finished adding all of the specified QTYs to the table. +Make sure to remove the row for ``QTY_NAME`` when you have finished adding all of the specified QTYs to the table. Ensure that there are no empty rows in between the QTYs listed in the spreadsheet. diff --git a/models/lorenz_96_tracer_advection/work/readme.rst b/models/lorenz_96_tracer_advection/work/readme.rst index 8df03e3cac..67ca1515c5 100644 --- a/models/lorenz_96_tracer_advection/work/readme.rst +++ b/models/lorenz_96_tracer_advection/work/readme.rst @@ -1,8 +1,8 @@ .. _quantile tracer: -QCF and Probit Transform Tools - Examples with lorenz_96_tracer_advection -========================================================================= +QCF and Probit Transform Tools: Examples with the Lorenz 96 Tracer Model +======================================================================== This file contains instructions for using the lorenz_96_tracer_advection model with DART quantile conserving and probit transform filtering tools. These tools are still @@ -26,14 +26,11 @@ usually 0. This is a particularly tough test for ensemble methods. * Visit this link: https://docs.google.com/spreadsheets/d/1ZhKbj0EYKHCgOHvTmJI3k7HI_Ae1NyNKchtekPW0lZs/edit#gid=0 * Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. - * Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the - menu bar. - * Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. - For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv" - Rename this file to remove this addition to ensure that there are no spaces in the filename. + * Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the menu bar. + * Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv". Rename this file to remove this addition to ensure that there are no spaces in the filename. * Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). -#. Add the filename of the downloaded .csv file to in between the single quotes on the line ``qcf_table_filename = ''`` +#. Add the filename of the downloaded .csv file in between the single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml #. Build all executables, @@ -92,14 +89,11 @@ replace the default version of that module with others that change certain optio * Visit this link https://docs.google.com/spreadsheets/d/1e26KuOv_uwrn8y1Ki85FzSeQAc9Pw-nCGk91MpJGVC0/edit#gid=0 * Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. - * Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the - menu bar. - * Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. - For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv" - Rename this file to remove this addition to ensure that there are no spaces in the filename. + * Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the menu bar. + * Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv". Rename this file to remove this addition to ensure that there are no spaces in the filename. * Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). -#. Add the filename of the downloaded .csv file to in between the single quotes on the line ``qcf_table_filename = ''`` +#. Add the filename of the downloaded .csv file in between the single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml #. Run the filter @@ -111,14 +105,11 @@ Test C: Using default ensemble adjustment Kalman filter for state, but bounded n * Visit this link https://docs.google.com/spreadsheets/d/1BEKEnFrw5KI9jf6ewg0POyr98ul5nGjerSVxjqEPDgA/edit#gid=0 * Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. - * Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the - menu bar. - * Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. - For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv" - Rename this file to remove this addition to ensure that there are no spaces in the filename. + * Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the menu bar. + * Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv". Rename this file to remove this addition to ensure that there are no spaces in the filename. * Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). -#. Add the filename of the downloaded .csv file to in between the single quotes on the line ``qcf_table_filename = ''`` +#. Add the filename of the downloaded .csv file in between the single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml #. Run the filter @@ -135,14 +126,11 @@ test. * Visit this link https://docs.google.com/spreadsheets/d/1RHlwyhCpbgcShoQnGW-xp2v-paw1ar-5-EA-uj9CkR8/edit#gid=0 * Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. - * Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the - menu bar. - * Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. - For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv" - Rename this file to remove this addition to ensure that there are no spaces in the filename. + * Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the menu bar. + * Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv". Rename this file to remove this addition to ensure that there are no spaces in the filename. * Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). -#. Add the filename of the downloaded .csv file to in between the single quotes on the line ``qcf_table_filename = ''`` +#. Add the filename of the downloaded .csv file in between the single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml #. In the file input.nml, change the entry positive_tracer to .false. Also, change the From f38ddc73f175d0498f57e73c337b8920e2b9fa54 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 23 Oct 2023 13:47:01 -0600 Subject: [PATCH 084/129] removing spread_restoration from the QCF table and related code from assim_tools_mod --- .../assimilation/algorithm_info_mod.f90 | 21 +++----- .../modules/assimilation/assim_tools_mod.f90 | 49 +++---------------- guide/qcf_probit.rst | 9 ++-- 3 files changed, 19 insertions(+), 60 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index ba32e5b177..15e55b8761 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -67,7 +67,6 @@ module algorithm_info_mod type obs_inc_info_type integer :: filter_kind - logical :: spread_restoration logical :: bounded_below, bounded_above real(r8) :: lower_bound, upper_bound end type @@ -82,7 +81,7 @@ module algorithm_info_mod integer, parameter :: HEADER_LINES = 2 character(len=129), dimension(4) :: header1 -character(len=129), dimension(26) :: header2 ! Number of table columns plus 1 +character(len=129), dimension(25) :: header2 ! Number of table columns plus 1 character(len=129), allocatable :: specified_qtys(:) type(algorithm_info_type), allocatable :: qcf_table_data(:) @@ -181,8 +180,7 @@ subroutine read_qcf_table(qcf_table_filename) qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, dist_type_string_probit_extended_state(row), & qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - filter_kind_string(row), qcf_table_data(row)%obs_inc_info%spread_restoration, & - qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & + filter_kind_string(row), qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound ! Converting the distribution types (read in from table as a string) to its corresponding int value @@ -419,12 +417,11 @@ end subroutine probit_dist_info !------------------------------------------------------------------------ -subroutine obs_inc_info(obs_qty, filter_kind, spread_restoration, & - bounded_below, bounded_above, lower_bound, upper_bound) +subroutine obs_inc_info(obs_qty, filter_kind, bounded_below, bounded_above, & + lower_bound, upper_bound) integer, intent(in) :: obs_qty integer, intent(out) :: filter_kind -logical, intent(inout) :: spread_restoration logical, intent(out) :: bounded_below, bounded_above real(r8), intent(out) :: lower_bound, upper_bound @@ -443,7 +440,6 @@ subroutine obs_inc_info(obs_qty, filter_kind, spread_restoration, & filter_kind = BOUNDED_NORMAL_RHF bounded_below = .false.; bounded_above = .false. lower_bound = missing_r8; upper_bound = missing_r8 - spread_restoration = .false. return endif @@ -458,13 +454,10 @@ subroutine obs_inc_info(obs_qty, filter_kind, spread_restoration, & filter_kind = BOUNDED_NORMAL_RHF bounded_below = .false.; bounded_above = .false. lower_bound = missing_r8; upper_bound = missing_r8 - spread_restoration = .false. - ! Default settings for now for Icepack and tracer model tests (spread_restoration) else filter_kind = qcf_table_data(QTY_loc(1))%obs_inc_info%filter_kind - spread_restoration = qcf_table_data(QTY_loc(1))%obs_inc_info%spread_restoration bounded_below = qcf_table_data(QTY_loc(1))%obs_inc_info%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%obs_inc_info%bounded_above lower_bound = qcf_table_data(QTY_loc(1))%obs_inc_info%lower_bound @@ -573,7 +566,7 @@ subroutine log_qcf_table_data() write(log_msg, '(A4, A6, A9, A)') header1(:) call error_handler(E_MSG, 'log_qcf_table_data:', trim(log_msg), source) -write(log_msg,'(3A14, 2A12, 3(A10, 2A14, 2A12), A12, A23, A26, A13, A19, 2A14, 2A12)') header2(:) +write(log_msg,'(3A14, 2A12, 3(A10, 2A14, 2A12), A12, 2A14, 2A12)') header2(:) call error_handler(E_MSG, 'log_qcf_table_data:', trim(log_msg), source) ! Write the table data to the dart_log and terminal @@ -586,8 +579,8 @@ subroutine log_qcf_table_data() qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, trim(dist_type_string_probit_extended_state(row)), & qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - trim(filter_kind_string(row)), qcf_table_data(row)%obs_inc_info%spread_restoration, qcf_table_data(row)%obs_inc_info%bounded_below, & - qcf_table_data(row)%obs_inc_info%bounded_above, qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound + trim(filter_kind_string(row)), qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & + qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound call error_handler(E_MSG, 'log_qcf_table_data:', trim(log_msg), source) end do diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index 16f9d54994..2e800de41a 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -246,6 +246,12 @@ subroutine assim_tools_init() ! Note null_win_mod.f90 ignores distibute_mean. if (task_count() == 1) distribute_mean = .true. +if(spread_restoration) then + write(msgstring, *) 'The spread_restoration option is not supported in this version of ', & + 'DART. Contact the DAReS team if this option is needed ' + call error_handler(E_ERR,'assim_tools_init:', msgstring, source) +endif + ! allocate a list in all cases - even the ones where there is only ! a single cutoff value. note that in spite of the name these ! are specific types (e.g. RADIOSONDE_TEMPERATURE, AIRCRAFT_TEMPERATURE) @@ -965,12 +971,8 @@ subroutine obs_increment(ens_in, ens_size, obs, obs_var, obs_kind, obs_inc, & bounded_below = .false.; lower_bound = 0.0_r8 bounded_above = .false.; upper_bound = 0.0_r8 -call obs_inc_info(obs_kind, filter_kind, spread_restoration, & - bounded_below, bounded_above, lower_bound, upper_bound) - -! Could add logic to check on sort being true when not needed. -! Could also add logic to limit the use of spread_restoration to EAKF. It will fail -! in some ugly way right now. +call obs_inc_info(obs_kind, filter_kind, bounded_below, bounded_above, & + lower_bound, upper_bound) !----------------------------end algorithm_info control block----------------- @@ -1547,41 +1549,6 @@ subroutine update_from_obs_inc(obs, obs_prior_mean, obs_prior_var, obs_inc, & ! Then compute the increment as product of reg_coef and observation space increment state_inc = reg_coef * obs_inc -! -! FIXME: craig schwartz has a degenerate case involving externally computed -! forward operators in which the obs prior variance is in fact exactly 0. -! adding this test allowed him to continue to use spread restoration -! without numerical problems. we don't know if this is sufficient; -! for now we'll leave the original code but it needs to be revisited. -! -! Spread restoration algorithm option. -!if(spread_restoration .and. obs_prior_var > 0.0_r8) then -! - -! Spread restoration algorithm option. -if(spread_restoration) then - ! Don't use this to reduce spread at present (should revisit this line) - net_a = min(net_a_in, 1.0_r8) - - ! Default restoration increment is 0.0 - restoration_inc = 0.0_r8 - - ! Compute the factor by which to inflate - ! These come from correl_error.f90 in system_simulation and the files ens??_pairs and - ! ens_pairs_0.5 in work under system_simulation. Assume a linear reduction from 1 - ! as a function of the net_a. Assume that the slope of this reduction is a function of - ! the reciprocal of the ensemble_size (slope = 0.80 / ens_size). These are empirical - ! for now. See also README in spread_restoration_paper documentation. - !!!factor = 1.0_r8 / (1.0_r8 + (net_a - 1.0_r8) * (0.8_r8 / ens_size)) - 1.0_r8 - factor = 1.0_r8 / (1.0_r8 + (net_a - 1.0_r8) / (-2.4711_r8 + 1.6386_r8 * ens_size)) - 1.0_r8 - !!!factor = 1.0_r8 / (1.0_r8 + (net_a**2 - 1.0_r8) * (-0.0111_r8 + .8585_r8 / ens_size)) - 1.0_r8 - - ! Variance restoration - state_mean = sum(state) / ens_size - restoration_inc = factor * (state - state_mean) - state_inc = state_inc + restoration_inc -endif - !! NOTE: if requested to be returned, correl_out is set further up in the !! code, before the sampling error correction, if enabled, is applied. !! this means it's returning a different larger value than the correl diff --git a/guide/qcf_probit.rst b/guide/qcf_probit.rst index 80a7c6b2fd..dabe7de794 100644 --- a/guide/qcf_probit.rst +++ b/guide/qcf_probit.rst @@ -18,9 +18,9 @@ If the user does not use a QCF input table with the DART quantile conserving and Table Composition ----------------- -The table consists of two headers. The first states the version # of the table being used; the most recent version of the table needs to be used to ensure compatibilty with DART. The current version # is 1. The second header lists the full set of input options, or all 25 column names in other words. +The table consists of two headers. The first states the version # of the table being used; the most recent version of the table needs to be used to ensure compatibilty with DART. The current version # is 1. The second header lists the full set of input options, or all 24 column names in other words. -Each QTY is specified in its own column, having 25 total control options. +Each QTY is specified in its own column, having 24 total control options. These control options are divided into 3 main groups, which are the options used for the obs_error_info, probit_dist_info, and obs_inc_info. However, the user is able to specify different values for probit inflation, probit state, and probit extended state, resulting in 5 total groupings for the control options. The obs_error_info subroutine computes information needed to compute error sample for this observation. @@ -30,12 +30,12 @@ The probit_dist_info subroutine computes the details of the probit transform. From probit_dist_info, the values needed are the bounds and the distribution type. These can be different for all three cases (inflation, state, and extended_state). The obs_inc_info subrotuine sets the details of how to assimilate this observation. -From obs_inc_info, the bounds, plus the filter_kind and spread_restoration are needed. +From obs_inc_info, the values needed are the bounds and the filter_kind. Full list of options: Obs_error_info: bounded_below, bounded_above, lower_bound, upper_bound [4 columns] Probit_dist_info: dist_type, bounded_below, bounded_above, lower_bound, upper_bound (x3 for inflation, state, and observation (extended state) priors) [15 columns] -Obs_inc_info: filter_kind, spread_restoration, bounded_below, bounded_above, lower_bound, upper_bound [6 columns] +Obs_inc_info: filter_kind, bounded_below, bounded_above, lower_bound, upper_bound [5 columns] Customizing the Table --------------------- @@ -50,7 +50,6 @@ lower_bound = -888888 upper_bound = -888888 dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION filter_kind = BOUNDED_NORMAL_RHF -spread_restoration = .false. Note that bounds set to -888888 are missing_r8 values. From 24c663ca7a27de09a042ca6a0519ab69b90f8f43 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 23 Oct 2023 14:09:14 -0600 Subject: [PATCH 085/129] Moving the code for sort_obs_inc to the end of obs_increment_enkf subroutine --- .../modules/assimilation/assim_tools_mod.f90 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index 2e800de41a..0acf24c052 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -1352,12 +1352,18 @@ subroutine obs_increment_enkf(ens, ens_size, prior_var, obs, obs_var, obs_inc) temp_mean = sum(temp_obs) / ens_size temp_obs(:) = temp_obs(:) - temp_mean + obs +! Loop through pairs of priors and obs and compute new mean +do i = 1, ens_size + new_mean(i) = new_var * (prior_var_inv * ens(i) + temp_obs(i) / obs_var) + obs_inc(i) = new_mean(i) - ens(i) +end do + ! To minimize regression errors, may want to sort to minimize increments ! This makes sense for any of the non-deterministic algorithms ! By doing it here, can take care of both standard non-deterministic updates ! plus non-deterministic obs space covariance inflation. This is expensive, so ! don't use it if it's not needed. -if (sort_obs_inc) then +if (sort_obs_inc) then new_val = ens + obs_inc ! Sorting to make increments as small as possible call index_sort(ens, ens_index, ens_size) @@ -1367,12 +1373,6 @@ subroutine obs_increment_enkf(ens, ens_size, prior_var, obs, obs_var, obs_inc) end do endif -! Loop through pairs of priors and obs and compute new mean -do i = 1, ens_size - new_mean(i) = new_var * (prior_var_inv * ens(i) + temp_obs(i) / obs_var) - obs_inc(i) = new_mean(i) - ens(i) -end do - ! Can also adjust mean (and) variance of final sample; works fine !sx = sum(new_mean) !s_x2 = sum(new_mean * new_mean) From f45123c3ffbf358c6f421bcb45a6179baaaf2cab Mon Sep 17 00:00:00 2001 From: Marlena Smith <44214771+mjs2369@users.noreply.github.com> Date: Mon, 23 Oct 2023 14:49:57 -0600 Subject: [PATCH 086/129] Add call to finalize_utilities to developer_tests/qceff/test_table_read.f90 Co-authored-by: Helen Kershaw <20047007+hkershaw-brown@users.noreply.github.com> --- developer_tests/qceff/test_table_read.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/developer_tests/qceff/test_table_read.f90 b/developer_tests/qceff/test_table_read.f90 index aaaa279c2a..9e5ae23772 100644 --- a/developer_tests/qceff/test_table_read.f90 +++ b/developer_tests/qceff/test_table_read.f90 @@ -17,7 +17,7 @@ program test_table_read call get_command_argument(1,qcf_table_filename) call init_algorithm_info_mod(qcf_table_filename) - +call finalize_utilities() call end_algorithm_info_mod() From b96593b05ec31a749872ed0e2755dde07f65cb03 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 23 Oct 2023 16:08:59 -0600 Subject: [PATCH 087/129] Restoring lorenz_96_tracer_advection/readme.rst --- models/lorenz_96_tracer_advection/readme.rst | 143 +++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 models/lorenz_96_tracer_advection/readme.rst diff --git a/models/lorenz_96_tracer_advection/readme.rst b/models/lorenz_96_tracer_advection/readme.rst new file mode 100644 index 0000000000..417f82d903 --- /dev/null +++ b/models/lorenz_96_tracer_advection/readme.rst @@ -0,0 +1,143 @@ +Lorenz 96 Tracer Advection +========================== + +Overview +-------- + +The Lorenz 96 Tracer Advection model combines the Lorenz 96 model with an +upstream semi-Lagrangian method. This simulates the advection of tracer +particles from any source(s) by the Lorenz 96 variables (here serving as wind). + +The Lorenz 96 model was first described by Edward Lorenz during a seminar at +the European Centre for Medium-Range Weather Forecasts in the Autumn of 1995, +the proceedings of which were published as Lorenz (1996) [1]_ the following +year, hence the model is commonly referred to as Lorenz 96. + +Lorenz and Emmanuel (1998) [2]_ describe the model as: + + ... consisting of 40 ordinary differential equations, with the dependent + variables representing values of some atmospheric quantity at 40 sites spaced + equally about a latitude circle. The equations contain quadratic, linear, and + constant terms representing advection, dissipation, and external forcing. + Numerical integration indicates that small errors (differences between + solutions) tend to double in about 2 days. Localized errors tend to spread + eastward as they grow, encircling the globe after about 14 days. + + We have chosen a model with :math:`J` variables, denoted by: + + .. math:: + + X_1, ... , X_j; + + in most of our experiments we have let :math:`J = 40`. The governing + equations are: + + .. math:: + + dX_j/dt=(X_{j+1}-X_{j-2})X_{j-1}-X_j+F (1) + + for: + + .. math:: + + j=1,...,J. + + To make Eq. (1) meaningful for all values of *j* we define: + + .. math:: + + X_{-1}=X_{J-1}, X_0=X_J, \& X_{J+1}=X_1, + + so that the variables form a cyclic chain, and may be looked at as values of + some unspecified scalar meteorological quantity, perhaps vorticity or + temperature, at *J* equally spaced sites extending around a latitude circle. + Nothing will simulate the atmosphere's latitudinal or vertical extent. + +In this model we are using the Semi-Lagrangian Scheme to model how tracer particles +get distributed upstream across the grids by the Lorenz 96 winds + +|Plot of 1D Semi-Lagrangian Method| + +The figure above describes the implementation of the Semi-Lagrangian scheme in a +one dimensional array. The tracer particle in the figure lands on a predefined grid +point at t\ :sup:`n+1`. The trajectory of this tracer particle is then integrated +backwards by one time step to time t\ :sup:`n`, often landing between grid points. +Then, due to advection without diffusion, the concentration of tracer at time + t\ :sup:`n+1` is simply the concentration of tracer at time t\ :sup:`n`, which +can be determined by interpolating concentrations of the surrounding grids [3]_. + +Once the coupled Lorenz 96 and semi-Lagrangian is run with a source of strength +100 units/s and location at grid point one (with exponential sinks present in +all grid points), the time evolution is as depicted below: + +|Plot of Lorenz 96 Tracer Advection| + +For Lorenz 96 Tracer Advection, DART advances the model, gets the model state and +metadata describing this state, finds state variables that are close to a given +location, and does spatial interpolation for model state variables. + +Namelist +-------- + +The ``&model_nml`` namelist is read from the ``input.nml`` file. Namelists +start with an ampersand ``&`` and terminate with a slash ``/``. Character +strings that contain a ``/`` must be enclosed in quotes to prevent them from +prematurely terminating the namelist. + +.. code-block:: fortran + + &model_nml + model_size = 120, + forcing = 8.00, + delta_t = 0.05, + time_step_days = 0, + time_step_seconds = 3600 + / + +Description of each namelist entry +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++-------------------+----------+-------------------------------------+ +| Item | Type | Description | ++===================+==========+=====================================+ +| model_size | integer | Total number of items in the state | +| | | vector. | +| | | The first third of the state vector | +| | | describes winds, the second third | +| | | describes tracer concentration, and | +| | | the final third of the state vector | +| | | describes the location strength of | +| | | sources. | ++-------------------+----------+-------------------------------------+ +| forcing | real(r8) | Forcing, F, for model. | ++-------------------+----------+-------------------------------------+ +| delta_t | real(r8) | Non-dimensional timestep. This is | +| | | mapped to the dimensional timestep | +| | | specified by time_step_days and | +| | | time_step_seconds. | ++-------------------+----------+-------------------------------------+ +| time_step_days | integer | Number of days for dimensional | +| | | timestep, mapped to delta_t. | ++-------------------+----------+-------------------------------------+ +| time_step_seconds | integer | Number of seconds for dimensional | +| | | timestep, mapped to delta_t. | ++-------------------+----------+-------------------------------------+ + +References +---------- + +.. [1] Lorenz, Edward N., 1996: Predictability: A Problem Partly Solved. + *Seminar on Predictability.* **1**, ECMWF, Reading, Berkshire, UK, 1-18. + +.. [2] Lorenz, Edward N., and Kerry A. Emanuel, 1998: Optimal Sites for + Supplementary Weather Observations: Simulations with a Small Model. + *Journal of the Atmospheric Sciences*, **55**, 399-414, + `doi:10.1175/1520-0469(1998)055\<0399:OSFSWO\>2.0.CO;2 + 2.0.CO;2>`__ + +.. [3] Cushman-Roisin, Benoit, and Jean-Marie Beckers. 2011. + Introduction to Geophysical Fluid Dynamics: Volume 101: Physical + and Numerical Aspects. 2nd ed. San Diego, CA: Academic Press. + +.. |Plot of 1D Semi-Lagrangian Method| image:: images/Semi_lag.png +.. |Plot of Lorenz 96 Tracer Advection| image:: images/lorenz_96_tracer_advection.gif From 9b3b6fb0248db0a71dc48ab18cfeabef2525cac0 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 23 Oct 2023 16:14:53 -0600 Subject: [PATCH 088/129] Moving the QCF examples doc to /guide --- .../work/readme.rst => guide/qcf-examples.rst | 3 +-- index.rst | 8 +++----- 2 files changed, 4 insertions(+), 7 deletions(-) rename models/lorenz_96_tracer_advection/work/readme.rst => guide/qcf-examples.rst (99%) diff --git a/models/lorenz_96_tracer_advection/work/readme.rst b/guide/qcf-examples.rst similarity index 99% rename from models/lorenz_96_tracer_advection/work/readme.rst rename to guide/qcf-examples.rst index 67ca1515c5..8c2a5b4d85 100644 --- a/models/lorenz_96_tracer_advection/work/readme.rst +++ b/guide/qcf-examples.rst @@ -1,5 +1,4 @@ -.. _quantile tracer: - +.. _quantile tracer: QCF and Probit Transform Tools: Examples with the Lorenz 96 Tracer Model ======================================================================== diff --git a/index.rst b/index.rst index 07cf134e25..df01eac0a6 100644 --- a/index.rst +++ b/index.rst @@ -99,11 +99,9 @@ estimated with DA and large improvements can occur for bounded parameters. Varia non-Gaussian prior distributions can also see large improvements. Examples can include atmospheric quantities like moisture and cloud amount in the presence of convection, and many land surface variables. -Instructions to use these tools can be found on this page: -:ref:`QCF` +For instructions on how to use these tools, see :ref:`QCF` -Examples for using these tools with the lorenz_96_tracer_advection model can be found here: -:ref:`quantile tracer` +For step-by-step examples of the QCEFF tools, you can work through :ref:`quantile tracer` Organization of the documentation --------------------------------- @@ -274,7 +272,6 @@ References guide/compiling-dart guide/verifying-installation guide/qcf_probit - models/lorenz_96_tracer_advection/work/readme .. toctree:: :maxdepth: 2 @@ -410,6 +407,7 @@ References guide/DART_LAB/DART_LAB CLM-DART Tutorial WRF-DART Tutorial + guide/qcf-examples.rst .. toctree:: :maxdepth: 2 From a0ed835e6e861575f31163907f9c5a8753283978 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 23 Oct 2023 16:32:39 -0600 Subject: [PATCH 089/129] Removing old comment from obs_inc_info --- assimilation_code/modules/assimilation/algorithm_info_mod.f90 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 15e55b8761..c2dcb3742b 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -428,10 +428,6 @@ subroutine obs_inc_info(obs_qty, filter_kind, bounded_below, bounded_above, & integer :: QTY_loc(1) character(len=129) :: qty_name -! The information arguments are all intent (inout). This means that if they are not set -! here, they retain the default values from the assim_tools_mod namelist. Bounds don't exist -! in that namelist, so default values are set in assim_tools_mod just before the call to here. - ! Temporary approach for setting the details of how to assimilate this observation ! This example is designed to reproduce the squared forward operator results from paper From c529ecf010a12f17693092fe33ef3f1b0d18c631 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 23 Oct 2023 16:34:05 -0600 Subject: [PATCH 090/129] Removing another old comment from obs_inc_info --- assimilation_code/modules/assimilation/algorithm_info_mod.f90 | 3 --- 1 file changed, 3 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index c2dcb3742b..aa2d26136f 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -428,9 +428,6 @@ subroutine obs_inc_info(obs_qty, filter_kind, bounded_below, bounded_above, & integer :: QTY_loc(1) character(len=129) :: qty_name -! Temporary approach for setting the details of how to assimilate this observation -! This example is designed to reproduce the squared forward operator results from paper - !use default values if qcf_table_filename is not in namelist if (use_qty_defaults) then filter_kind = BOUNDED_NORMAL_RHF From 4481d2dd49266afe4215f7e928a1aab002e41eea Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 23 Oct 2023 16:37:50 -0600 Subject: [PATCH 091/129] Removing old comment from assim_tools_mod --- .../modules/assimilation/assim_tools_mod.f90 | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index 0acf24c052..f33d48c7a2 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -131,18 +131,6 @@ module assim_tools_mod !---- namelist with default values -! Filter kind selects type of observation space filter -! 1 = EAKF filter -! 2 = ENKF -! 3 = Kernel filter -! 4 = particle filter -! 5 = random draw from posterior -! 6 = deterministic draw from posterior with fixed kurtosis -! 8 = Rank Histogram Filter (see Anderson 2011) -! -! special_localization_obs_types -> Special treatment for the specified observation types -! special_localization_cutoffs -> Different cutoff value for each specified obs type -! real(r8) :: cutoff = 0.2_r8 logical :: sort_obs_inc = .true. logical :: spread_restoration = .false. From 8eaeb5bc373d57a85470a7b57b1590e227e14197 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 23 Oct 2023 16:47:54 -0600 Subject: [PATCH 092/129] Small fixes to the main DART doc page (index.rst) --- index.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/index.rst b/index.rst index df01eac0a6..4e2b9eb53d 100644 --- a/index.rst +++ b/index.rst @@ -7,8 +7,6 @@ Welcome to the Data Assimilation Research Testbed Pre-release version of DART: quantile conserving and probit transform tools - To get started, see the :ref:`tracer advection example` - The Data Assimilation Research Testbed (DART) is an open-source, freely available community facility for ensemble data assimilation (DA). [1]_ DART is @@ -51,6 +49,7 @@ DART includes: - Extensive documentation of its source code. - Interfaces to a variety of models and observation sets that can be used to introduce new users or graduate students to ensemble DA. +- Nonlinear and Non-Gaussian DA Capabilities DART is also designed to facilitate the combination of assimilation algorithms, models, and real or synthetic observations to allow increased From 8fd96328b18299964d0efb35ffb1cdf8c19fa45e Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 23 Oct 2023 16:56:59 -0600 Subject: [PATCH 093/129] Adding earlier link to the QCF docs --- index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.rst b/index.rst index 4e2b9eb53d..89971b0f0b 100644 --- a/index.rst +++ b/index.rst @@ -67,8 +67,8 @@ The default DART algorithms assume a normal distribution to compute ensemble inc for the observed quantity (this is the ensemble adjustment Kalman filter, or EAKF) and then linearly regresses the observation increments onto each state variable. -DART’s newest and innovative capability, the Quantile Conserving Filters (QCF), also known -as the Quantile Conserving Ensemble Filtering Framework (QCEFF), provide a +DART’s newest and innovative capability, the :ref:`Quantile Conserving Filters (QCF) `, +also known as the Quantile Conserving Ensemble Filtering Framework (QCEFF), provide a very general method of computing increments for the prior ensemble of an observed quantity by allowing the use of quantile conserving ensemble filters that can assume arbitrary distributions for the prior and the observation error. Quantile Conserving Filters are From 8cb0ad801dd1ecca0518352ffa7bb34eba819b3d Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Mon, 23 Oct 2023 17:38:32 -0600 Subject: [PATCH 094/129] Adding the pre-made .csv files for the lorenx 96 tracer examples to /lorenz_96_tracer_advection/work. Removing the information describing how to download the .csv files from Google Sheets from the QCF examples doc --- guide/qcf-examples.rst | 74 +++++++++---------- .../work/all_bnrhf_qcf_table.csv | 5 ++ .../work/all_eakf_qcf_table.csv | 5 ++ .../work/neg_qcf_table.csv | 5 ++ .../state_eakf_tracer_bnrhf_qcf_table.csv | 5 ++ 5 files changed, 53 insertions(+), 41 deletions(-) create mode 100644 models/lorenz_96_tracer_advection/work/all_bnrhf_qcf_table.csv create mode 100644 models/lorenz_96_tracer_advection/work/all_eakf_qcf_table.csv create mode 100644 models/lorenz_96_tracer_advection/work/neg_qcf_table.csv create mode 100644 models/lorenz_96_tracer_advection/work/state_eakf_tracer_bnrhf_qcf_table.csv diff --git a/guide/qcf-examples.rst b/guide/qcf-examples.rst index 8c2a5b4d85..d2325ca7f0 100644 --- a/guide/qcf-examples.rst +++ b/guide/qcf-examples.rst @@ -21,20 +21,18 @@ The default model configuration has a single tracer source at gridpoint 1 along small uniform tracer sinks that lead to areas where the true tracer concentration is usually 0. This is a particularly tough test for ensemble methods. -#. Download the QCF Table from Google Sheets as a .csv file: - - * Visit this link: https://docs.google.com/spreadsheets/d/1ZhKbj0EYKHCgOHvTmJI3k7HI_Ae1NyNKchtekPW0lZs/edit#gid=0 - * Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. - * Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the menu bar. - * Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv". Rename this file to remove this addition to ensure that there are no spaces in the filename. - * Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). - -#. Add the filename of the downloaded .csv file in between the single quotes on the line ``qcf_table_filename = ''`` - in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml - #. Build all executables, - ``./quickbuild.sh nompi`` + ``./quickbuild.sh nompi`` + +#. Add the filename of the already prepared .csv file (all_bnrhf_qcf_table.csv) in between + the single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of + /DART/models/lorenz_96_tracer_advection/work/input.nml + + .. code:: + + &filter_nml + qcf_table_filename = 'all_bnrhf_qcf_table.csv' #. Create a set_def.out file using create_obs_sequence: @@ -84,33 +82,29 @@ Doing a diff between these modules shows how the control is being changed for th following tests in that module. The tests below replace the default version of that module with others that change certain options. -#. Download the QCF Table from Google Sheets as a .csv file: - - * Visit this link https://docs.google.com/spreadsheets/d/1e26KuOv_uwrn8y1Ki85FzSeQAc9Pw-nCGk91MpJGVC0/edit#gid=0 - * Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. - * Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the menu bar. - * Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv". Rename this file to remove this addition to ensure that there are no spaces in the filename. - * Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). +#. Add the filename of the already prepared .csv file (all_eakf_qcf_table.csv) in between + the single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of + /DART/models/lorenz_96_tracer_advection/work/input.nml + + .. code:: + + &filter_nml + qcf_table_filename = 'all_eakf_qcf_table.csv' -#. Add the filename of the downloaded .csv file in between the single quotes on the line ``qcf_table_filename = ''`` - in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml - #. Run the filter ``./filter`` Test C: Using default ensemble adjustment Kalman filter for state, but bounded normal rank histogram filter and priors for tracer concentration and source. -#. Download the QCF Table from Google Sheets as a .csv file: - - * Visit this link https://docs.google.com/spreadsheets/d/1BEKEnFrw5KI9jf6ewg0POyr98ul5nGjerSVxjqEPDgA/edit#gid=0 - * Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. - * Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the menu bar. - * Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv". Rename this file to remove this addition to ensure that there are no spaces in the filename. - * Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). +#. Add the filename of the already prepared .csv file (state_eakf_tracer_bnrhf_qcf_table.csv) in + between the single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of + /DART/models/lorenz_96_tracer_advection/work/input.nml + + .. code:: + + &filter_nml + qcf_table_filename = 'state_eakf_tracer_bnrhf_qcf_table.csv' -#. Add the filename of the downloaded .csv file in between the single quotes on the line ``qcf_table_filename = ''`` - in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml - #. Run the filter ``./filter`` @@ -121,16 +115,14 @@ above. There are distinct numerical challenges in implementing the quantile algo for quantities that are bounded above, so flipping the sign of the tracers is a good test. -#. Download the QCF Table from Google Sheets as a .csv file: - - * Visit this link https://docs.google.com/spreadsheets/d/1RHlwyhCpbgcShoQnGW-xp2v-paw1ar-5-EA-uj9CkR8/edit#gid=0 - * Make a copy of the spreadsheet by selecting "File > Make a copy" from the menu bar. - * Download the spreadsheet as a .csv file by selecting "File > Download > csv" from the menu bar. - * Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv". Rename this file to remove this addition to ensure that there are no spaces in the filename. - * Copy or move this file to your working directory (/DART/models/lorenz_96_tracer_advection/work). +#. Add the filename of the already prepared .csv file (neg_qcf_table.csv) in between the + single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of + /DART/models/lorenz_96_tracer_advection/work/input.nml + + .. code:: -#. Add the filename of the downloaded .csv file in between the single quotes on the line ``qcf_table_filename = ''`` - in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml + &filter_nml + qcf_table_filename = 'neg_qcf_table.csv' #. In the file input.nml, change the entry positive_tracer to .false. Also, change the entry read_input_state_from_file back to .false. diff --git a/models/lorenz_96_tracer_advection/work/all_bnrhf_qcf_table.csv b/models/lorenz_96_tracer_advection/work/all_bnrhf_qcf_table.csv new file mode 100644 index 0000000000..890ecb1983 --- /dev/null +++ b/models/lorenz_96_tracer_advection/work/all_bnrhf_qcf_table.csv @@ -0,0 +1,5 @@ +QCF table version: 1,obs_error_info,,,,probit_inflation,,,,,probit_state,,,,,probit_extended_state,,,,,obs_inc_info,,,, +QTY_TEMPLATE:,bounded_below,bounded_above,lower_bound,upper_bound,dist_type,bounded_below,bounded_above,lower_bound,upper_bound,dist_type,bounded_below,bounded_above,lower_bound,upper_bound,dist_type,bounded_below,bounded_above,lower_bound,upper_bound,filter_kind,bounded_below,bounded_above,lower_bound,upper_bound +QTY_STATE_VARIABLE,.false.,.false.,-888888,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.false.,.false.,-888888,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.false.,.false.,-888888,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.false.,.false.,-888888,-888888,BOUNDED_NORMAL_RHF,.false.,.false.,-888888,-888888 +QTY_TRACER_CONCENTRATION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RHF,.true.,.false.,0,-888888 +QTY_TRACER_SOURCE,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RHF,.true.,.false.,0,-888888 \ No newline at end of file diff --git a/models/lorenz_96_tracer_advection/work/all_eakf_qcf_table.csv b/models/lorenz_96_tracer_advection/work/all_eakf_qcf_table.csv new file mode 100644 index 0000000000..5b6286816c --- /dev/null +++ b/models/lorenz_96_tracer_advection/work/all_eakf_qcf_table.csv @@ -0,0 +1,5 @@ +QCF table version: 1,obs_error_info,,,,probit_inflation,,,,,probit_state,,,,,probit_extended_state,,,,,obs_inc_info,,,, +QTY_TEMPLATE:,bounded_below,bounded_above,lower_bound,upper_bound,dist_type,bounded_below,bounded_above,lower_bound,upper_bound,dist_type,bounded_below,bounded_above,lower_bound,upper_bound,dist_type,bounded_below,bounded_above,lower_bound,upper_bound,filter_kind,bounded_below,bounded_above,lower_bound,upper_bound +QTY_STATE_VARIABLE,.false.,.false.,-888888,-888888,NORMAL_DISTRIBUTION,.false.,.false.,-888888,-888888,NORMAL_DISTRIBUTION,.false.,.false.,-888888,-888888,NORMAL_DISTRIBUTION,.false.,.false.,-888888,-888888,EAKF,.false.,.false.,-888888,-888888 +QTY_TRACER_CONCENTRATION,.true.,.false.,0,-888888,NORMAL_DISTRIBUTION,.true.,.false.,0,-888888,NORMAL_DISTRIBUTION,.true.,.false.,0,-888888,NORMAL_DISTRIBUTION,.true.,.false.,0,-888888,EAKF,.true.,.false.,0,-888888 +QTY_TRACER_SOURCE,.true.,.false.,0,-888888,NORMAL_DISTRIBUTION,.true.,.false.,0,-888888,NORMAL_DISTRIBUTION,.true.,.false.,0,-888888,NORMAL_DISTRIBUTION,.true.,.false.,0,-888888,EAKF,.true.,.false.,0,-888888 \ No newline at end of file diff --git a/models/lorenz_96_tracer_advection/work/neg_qcf_table.csv b/models/lorenz_96_tracer_advection/work/neg_qcf_table.csv new file mode 100644 index 0000000000..01d64ad744 --- /dev/null +++ b/models/lorenz_96_tracer_advection/work/neg_qcf_table.csv @@ -0,0 +1,5 @@ +QCF table version: 1,obs_error_info,,,,probit_inflation,,,,,probit_state,,,,,probit_extended_state,,,,,obs_inc_info,,,, +QTY_TEMPLATE:,bounded_below,bounded_above,lower_bound,upper_bound,dist_type,bounded_below,bounded_above,lower_bound,upper_bound,dist_type,bounded_below,bounded_above,lower_bound,upper_bound,dist_type,bounded_below,bounded_above,lower_bound,upper_bound,filter_kind,bounded_below,bounded_above,lower_bound,upper_bound +QTY_STATE_VARIABLE,.false.,.false.,-888888,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.false.,.false.,-888888,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.false.,.false.,-888888,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.false.,.false.,-888888,-888888,BOUNDED_NORMAL_RHF,.false.,.false.,-888888,-888888 +QTY_TRACER_CONCENTRATION,.false.,.true.,-888888,0,BOUNDED_NORMAL_RH_DISTRIBUTION,.false.,.true.,-888888,0,BOUNDED_NORMAL_RH_DISTRIBUTION,.false.,.true.,-888888,0,BOUNDED_NORMAL_RH_DISTRIBUTION,.false.,.true.,-888888,0,BOUNDED_NORMAL_RHF,.false.,.true.,-888888,0 +QTY_TRACER_SOURCE,.false.,.true.,-888888,0,BOUNDED_NORMAL_RH_DISTRIBUTION,.false.,.true.,-888888,0,BOUNDED_NORMAL_RH_DISTRIBUTION,.false.,.true.,-888888,0,BOUNDED_NORMAL_RH_DISTRIBUTION,.false.,.true.,-888888,0,BOUNDED_NORMAL_RHF,.false.,.true.,-888888,0 \ No newline at end of file diff --git a/models/lorenz_96_tracer_advection/work/state_eakf_tracer_bnrhf_qcf_table.csv b/models/lorenz_96_tracer_advection/work/state_eakf_tracer_bnrhf_qcf_table.csv new file mode 100644 index 0000000000..3ae9561edd --- /dev/null +++ b/models/lorenz_96_tracer_advection/work/state_eakf_tracer_bnrhf_qcf_table.csv @@ -0,0 +1,5 @@ +QCF table version: 1,obs_error_info,,,,probit_inflation,,,,,probit_state,,,,,probit_extended_state,,,,,obs_inc_info,,,, +QTY_NAME:,bounded_below,bounded_above,lower_bound,upper_bound,dist_type,bounded_below,bounded_above,lower_bound,upper_bound,dist_type,bounded_below,bounded_above,lower_bound,upper_bound,dist_type,bounded_below,bounded_above,lower_bound,upper_bound,filter_kind,bounded_below,bounded_above,lower_bound,upper_bound +QTY_STATE_VARIABLE,.false.,.false.,-888888,-888888,NORMAL_DISTRIBUTION,.false.,.false.,-888888,-888888,NORMAL_DISTRIBUTION,.false.,.false.,-888888,-888888,NORMAL_DISTRIBUTION,.false.,.false.,-888888,-888888,EAKF,.false.,.false.,-888888,-888888 +QTY_TRACER_CONCENTRATION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RHF,.true.,.false.,0,-888888 +QTY_TRACER_SOURCE,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RHF,.true.,.false.,0,-888888 \ No newline at end of file From 8dd039aff36c594762abb0d17a47ce25f7c09b4a Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 24 Oct 2023 10:23:47 -0600 Subject: [PATCH 095/129] Making the table version number be a parameter, not a magic number --- assimilation_code/modules/assimilation/algorithm_info_mod.f90 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index aa2d26136f..d59184997f 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -467,7 +467,9 @@ subroutine assert_qcf_table_version() ! Subroutine to ensure the correct version of the QCF table is being used -if (trim(header1(4)) /= '1') then +character(1), parameter :: QCF_VERSION = '1' + +if (trim(header1(4)) /= QCF_VERSION) then write(errstring,*) 'Using outdated/incorrect version of the QCF table' call error_handler(E_ERR, 'assert_qcf_table_version:', errstring, source) endif From bdfdbb91d3053add0bc999175cf7d29e6477ebbe Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 24 Oct 2023 10:28:12 -0600 Subject: [PATCH 096/129] Removing unnecessary setting of the bounds before the call to obs_inc_info --- assimilation_code/modules/assimilation/assim_tools_mod.f90 | 4 ---- 1 file changed, 4 deletions(-) diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index f33d48c7a2..d4c712eaa5 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -955,10 +955,6 @@ subroutine obs_increment(ens_in, ens_size, obs, obs_var, obs_kind, obs_inc, & ! Note that all but the first argument to obs_inc_info are intent(inout) so that if they ! are not set in that routine they will remain with the namelist selected values. -! Set default values for bounds information -bounded_below = .false.; lower_bound = 0.0_r8 -bounded_above = .false.; upper_bound = 0.0_r8 - call obs_inc_info(obs_kind, filter_kind, bounded_below, bounded_above, & lower_bound, upper_bound) From 360ab2c32157bd6f2725a28a0a914ec523b6e886 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 24 Oct 2023 10:54:31 -0600 Subject: [PATCH 097/129] Fixing extended link in the docs --- guide/qcf-examples.rst | 22 +++++++++++----------- guide/qcf_probit.rst | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/guide/qcf-examples.rst b/guide/qcf-examples.rst index d2325ca7f0..4c93008d7f 100644 --- a/guide/qcf-examples.rst +++ b/guide/qcf-examples.rst @@ -12,6 +12,9 @@ anxious to build scientific collaborations using these new capabilities. Make sure that you are on the quantile_methods branch of DART: ``git checkout quantile_methods`` +Build all executables: + ``./quickbuild.sh nompi`` + Steps for reproducing basic tests: Test A: Assimilating observations of state (wind) and tracer concentration using @@ -21,11 +24,7 @@ The default model configuration has a single tracer source at gridpoint 1 along small uniform tracer sinks that lead to areas where the true tracer concentration is usually 0. This is a particularly tough test for ensemble methods. -#. Build all executables, - - ``./quickbuild.sh nompi`` - -#. Add the filename of the already prepared .csv file (all_bnrhf_qcf_table.csv) in between +#. Add the filename of the already prepared QCF table (all_bnrhf_qcf_table.csv) in between the single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml @@ -82,7 +81,7 @@ Doing a diff between these modules shows how the control is being changed for th following tests in that module. The tests below replace the default version of that module with others that change certain options. -#. Add the filename of the already prepared .csv file (all_eakf_qcf_table.csv) in between +#. Add the filename of the already prepared QCF table (all_eakf_qcf_table.csv) in between the single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml @@ -96,7 +95,7 @@ replace the default version of that module with others that change certain optio Test C: Using default ensemble adjustment Kalman filter for state, but bounded normal rank histogram filter and priors for tracer concentration and source. -#. Add the filename of the already prepared .csv file (state_eakf_tracer_bnrhf_qcf_table.csv) in +#. Add the filename of the already prepared QCF table (state_eakf_tracer_bnrhf_qcf_table.csv) in between the single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml @@ -115,15 +114,16 @@ above. There are distinct numerical challenges in implementing the quantile algo for quantities that are bounded above, so flipping the sign of the tracers is a good test. -#. Add the filename of the already prepared .csv file (neg_qcf_table.csv) in between the +#. Add the filename of the already prepared QCF table (neg_qcf_table.csv) in between the single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml - .. code:: + .. code-block:: text &filter_nml - qcf_table_filename = 'neg_qcf_table.csv' - + qcf_table_filename = 'neg_qcf_table.csv' + / + #. In the file input.nml, change the entry positive_tracer to .false. Also, change the entry read_input_state_from_file back to .false. diff --git a/guide/qcf_probit.rst b/guide/qcf_probit.rst index dabe7de794..179d6ab1ab 100644 --- a/guide/qcf_probit.rst +++ b/guide/qcf_probit.rst @@ -39,7 +39,7 @@ Obs_inc_info: filter_kind, bounded_below, bounded_above, lower_bound, upper_boun Customizing the Table --------------------- -The table can be customized by editing a Google Sheet spreadsheet (which is then downloaded in .csv format). Folow this link https://docs.google.com/spreadsheets/d/1SI4wHBXatLAAMfiMx3mUUC7x0fqz4lniKuM4_i5j6bM/edit#gid=0 to access the template spreadsheet. +The table can be customized by editing a Google Sheet spreadsheet (which is then downloaded in .csv format). Folow this `link `_ to access the template spreadsheet. The user will add and fill in one row for each bounded QTY they want to specify. If a QTY is not listed in the table, the default values will be used for all 25 options. Therefore, the user will only need to add rows for QTYs that use non-default values for any of the input options. From dfb467f618fedfec9ca11643430b0f1225e41b36 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 24 Oct 2023 11:24:12 -0600 Subject: [PATCH 098/129] Fixing the formatiing of code blocks in the docs --- guide/qcf-examples.rst | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/guide/qcf-examples.rst b/guide/qcf-examples.rst index 4c93008d7f..640dc13b75 100644 --- a/guide/qcf-examples.rst +++ b/guide/qcf-examples.rst @@ -9,13 +9,9 @@ being refined, but are working for the examples described. The DART development team (dart@ucar.edu) would be happy to hear about your experiences and is anxious to build scientific collaborations using these new capabilities. -Make sure that you are on the quantile_methods branch of DART: -``git checkout quantile_methods`` +Make sure that you are on the quantile_methods branch of DART: ``git checkout quantile_methods`` -Build all executables: - ``./quickbuild.sh nompi`` - -Steps for reproducing basic tests: +Build all executables: ``./quickbuild.sh nompi`` Test A: Assimilating observations of state (wind) and tracer concentration using a rank histogram observation space filter and rank histogram probit transforms for @@ -28,10 +24,11 @@ usually 0. This is a particularly tough test for ensemble methods. the single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml - .. code:: + .. code-block:: text &filter_nml - qcf_table_filename = 'all_bnrhf_qcf_table.csv' + qcf_table_filename = 'neg_qcf_table.csv' + / #. Create a set_def.out file using create_obs_sequence: @@ -85,10 +82,11 @@ replace the default version of that module with others that change certain optio the single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml - .. code:: + .. code-block:: text &filter_nml - qcf_table_filename = 'all_eakf_qcf_table.csv' + qcf_table_filename = 'neg_qcf_table.csv' + / #. Run the filter ``./filter`` @@ -99,10 +97,11 @@ Test C: Using default ensemble adjustment Kalman filter for state, but bounded n between the single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of /DART/models/lorenz_96_tracer_advection/work/input.nml - .. code:: + .. code-block:: text &filter_nml - qcf_table_filename = 'state_eakf_tracer_bnrhf_qcf_table.csv' + qcf_table_filename = 'neg_qcf_table.csv' + / #. Run the filter ``./filter`` From a597dd8e62318aaea9f703ebf50af8d3a010b94a Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 24 Oct 2023 11:42:30 -0600 Subject: [PATCH 099/129] MISSING_R8 is now all in capitals --- .../modules/assimilation/algorithm_info_mod.f90 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index d59184997f..145b3d211f 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -4,7 +4,7 @@ module algorithm_info_mod -use types_mod, only : r8, i8, missing_r8 +use types_mod, only : r8, i8, MISSING_R8 use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance use obs_kind_mod, only : get_quantity_for_type_of_obs, get_name_for_quantity, get_index_for_quantity @@ -299,7 +299,7 @@ subroutine obs_error_info(obs_def, error_variance, & !use default values if qcf_table_filename is not in namelist if (use_qty_defaults) then bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 + lower_bound = MISSING_R8; upper_bound = MISSING_R8 return endif @@ -312,7 +312,7 @@ subroutine obs_error_info(obs_def, error_variance, & if (QTY_loc(1) == 0) then !use default values if QTY is not in table bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 + lower_bound = MISSING_R8; upper_bound = MISSING_R8 else bounded_below = qcf_table_data(QTY_loc(1))%obs_error_info%bounded_below @@ -367,7 +367,7 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & if (use_qty_defaults) then dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 + lower_bound = MISSING_R8; upper_bound = MISSING_R8 return endif @@ -381,7 +381,7 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & !use default values if QTY is not in table dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 + lower_bound = MISSING_R8; upper_bound = MISSING_R8 elseif(is_inflation) then ! Case for inflation transformation @@ -432,7 +432,7 @@ subroutine obs_inc_info(obs_qty, filter_kind, bounded_below, bounded_above, & if (use_qty_defaults) then filter_kind = BOUNDED_NORMAL_RHF bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 + lower_bound = MISSING_R8; upper_bound = MISSING_R8 return endif @@ -446,7 +446,7 @@ subroutine obs_inc_info(obs_qty, filter_kind, bounded_below, bounded_above, & !use default values if QTY is not in table filter_kind = BOUNDED_NORMAL_RHF bounded_below = .false.; bounded_above = .false. - lower_bound = missing_r8; upper_bound = missing_r8 + lower_bound = MISSING_R8; upper_bound = MISSING_R8 else From d9cbc8d469acdf779a1493cafe13c728cdc7e95d Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 24 Oct 2023 11:49:27 -0600 Subject: [PATCH 100/129] Fixing misleading comment placement --- assimilation_code/modules/assimilation/assim_tools_mod.f90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index d4c712eaa5..8193b61e8d 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -907,12 +907,13 @@ subroutine obs_increment(ens_in, ens_size, obs, obs_var, obs_kind, obs_inc, & real(r8) :: rel_weights(ens_size) -! Declarations for bounded rank histogram filter -real(r8) :: likelihood(ens_size), like_sum integer :: filter_kind logical :: bounded_below, bounded_above real(r8) :: lower_bound, upper_bound +! Declarations for bounded rank histogram filter +real(r8) :: likelihood(ens_size), like_sum + ! Copy the input ensemble to something that can be modified ens = ens_in From defd770ea0acf57a67474d42ced9ae969b520bef Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 24 Oct 2023 15:50:28 -0600 Subject: [PATCH 101/129] Using the public parameters from algorithm_info_mod.f90 for comparisons with filter_kind value --- .../assimilation/algorithm_info_mod.f90 | 5 ++++- .../modules/assimilation/assim_tools_mod.f90 | 18 ++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 145b3d211f..8719085429 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -33,13 +33,16 @@ module algorithm_info_mod ! That will change if backwards compatibility is removed in the future. integer, parameter :: EAKF = 1 integer, parameter :: ENKF = 2 +integer, parameter :: KERNEL = 3 +integer, parameter :: OBS_PARTICLE = 4 integer, parameter :: UNBOUNDED_RHF = 8 integer, parameter :: GAMMA_FILTER = 11 integer, parameter :: BOUNDED_NORMAL_RHF = 101 public :: obs_error_info, probit_dist_info, obs_inc_info, & init_algorithm_info_mod, end_algorithm_info_mod, & - EAKF, ENKF, BOUNDED_NORMAL_RHF, UNBOUNDED_RHF, GAMMA_FILTER + EAKF, ENKF, BOUNDED_NORMAL_RHF, UNBOUNDED_RHF, & + GAMMA_FILTER, KERNEL, OBS_PARTICLE !Creates the type definitions for the QCF table type obs_error_info_type diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index 8193b61e8d..9d231062fb 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -76,7 +76,9 @@ module assim_tools_mod use normal_distribution_mod, only : normal_cdf, inv_weighted_normal_cdf -use algorithm_info_mod, only : probit_dist_info, obs_inc_info +use algorithm_info_mod, only : probit_dist_info, obs_inc_info, EAKF, ENKF, & + BOUNDED_NORMAL_RHF, UNBOUNDED_RHF, GAMMA_FILTER, & + KERNEL, OBS_PARTICLE use gamma_distribution_mod, only : gamma_cdf, inv_gamma_cdf, gamma_mn_var_to_shape_scale, & gamma_gamma_prod @@ -992,21 +994,21 @@ subroutine obs_increment(ens_in, ens_size, obs, obs_var, obs_kind, obs_inc, & ! note that at this point we've taken care of the cases where either the ! obs_var or the prior_var is 0, so the individual routines no longer need ! to have code to test for those cases. - if(filter_kind == 1) then + if(filter_kind == EAKF) then call obs_increment_eakf(ens, ens_size, prior_mean, prior_var, & obs, obs_var, obs_inc, net_a) - else if(filter_kind == 2) then + else if(filter_kind == ENKF) then call obs_increment_enkf(ens, ens_size, prior_var, obs, obs_var, obs_inc) - else if(filter_kind == 3) then + else if(filter_kind == KERNEL) then call obs_increment_kernel(ens, ens_size, obs, obs_var, obs_inc) - else if(filter_kind == 4) then + else if(filter_kind == OBS_PARTICLE) then call obs_increment_particle(ens, ens_size, obs, obs_var, obs_inc) - else if(filter_kind == 8) then + else if(filter_kind == UNBOUNDED_RHF) then call obs_increment_rank_histogram(ens, ens_size, prior_var, obs, obs_var, obs_inc) - else if(filter_kind == 11) then + else if(filter_kind == GAMMA_FILTER) then call obs_increment_gamma(ens, ens_size, prior_mean, prior_var, obs, obs_var, obs_inc) !-------------------------------------------------------------------------- - else if(filter_kind == 101) then + else if(filter_kind == BOUNDED_NORMAL_RHF) then ! Use bounded normal likelihood; Could use an arbitrary likelihood do i = 1, ens_size From c1f79217844c14d42727b1408f80530b56021b27 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Tue, 24 Oct 2023 16:06:35 -0600 Subject: [PATCH 102/129] Fixing and removing outdated comments --- .../modules/assimilation/algorithm_info_mod.f90 | 12 +++++------- .../modules/assimilation/assim_tools_mod.f90 | 15 +-------------- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 8719085429..de7aa32088 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -349,15 +349,13 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & ! Have input information about the kind of the state or observation being transformed ! along with additional logical info that indicates whether this is an observation ! or state variable and about whether the transformation is being done for inflation -! or for regress. -! Need to select the appropriate transform. At present, the options are NORMAL_DISTRIBUTION, -! BOUNDED_NORMAL_RH_DISTRIBUTION, GAMMA_DISTRIBUTION, BETA_DISTRIBUTION, LOG_NORMAL_DISTRIBUTION, +! or for regress. + +! Selects the appropriate transform, which is specified in the QCF input table per QTY. +! At present, the options are NORMAL_DISTRIBUTION, BOUNDED_NORMAL_RH_DISTRIBUTION, +! GAMMA_DISTRIBUTION, BETA_DISTRIBUTION, LOG_NORMAL_DISTRIBUTION, ! UNIFORM_DISTRIBUTION, and PARTICLE_FILTER_DISTRIBUTION. ! If the BNRH is selected then information about the bounds must also be set. -! The two dimensional logical array 'bounded' is set to false for no bounds and true -! for bounded. the first element of the array is for the lower bound, the second for the upper. -! If bounded is chosen, the corresponding bound value(s) must be set in the two dimensional -! real array 'bounds'. ! For example, if my_state_kind corresponds to a sea ice fraction then an appropriate choice ! would be: ! bounded_below = .true.; bounded_above = .true. diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index 9d231062fb..d631b1266d 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -946,23 +946,10 @@ subroutine obs_increment(ens_in, ens_size, obs, obs_var, obs_kind, obs_inc, & prior_var = sum((ens - prior_mean)**2) / (ens_size - 1) endif -!--------------------------begin algorithm_info control block----------------- -! More flexible abilities to control the observation space increments are -! available with this code block. It gets information about the increment method -! for the current observation. - -! This is not an extensible mechanism for doing this as the number of -! obs increments distributions and associated information goes up -! Implications for sorting increments and for spread restoration need to be examined -! further. -! Note that all but the first argument to obs_inc_info are intent(inout) so that if they -! are not set in that routine they will remain with the namelist selected values. - +! Gets information about the increment method (filter_kind, bounds) for the current observation. call obs_inc_info(obs_kind, filter_kind, bounded_below, bounded_above, & lower_bound, upper_bound) -!----------------------------end algorithm_info control block----------------- - ! The first three options in the next if block of code may be inappropriate for ! some more general filters; need to revisit ! If obs_var == 0, delta function. The mean becomes obs value with no spread. From dc015b06e9abaee815e1b7a0a255576cea08951c Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 25 Oct 2023 15:36:33 -0600 Subject: [PATCH 103/129] Removing one last reference to spread_rest from the QCF table docs --- guide/qcf_probit.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/qcf_probit.rst b/guide/qcf_probit.rst index 179d6ab1ab..9958475cf6 100644 --- a/guide/qcf_probit.rst +++ b/guide/qcf_probit.rst @@ -53,7 +53,7 @@ filter_kind = BOUNDED_NORMAL_RHF Note that bounds set to -888888 are missing_r8 values. -The following input options are read in as logicals, and will need to be written in the format of either 'F' or '.false.' These include bounded_below, bounded_above, and spread_restoration. +bounded_below and bounded_above are read in as logicals, and will need to be written in the format of either 'F' or '.false.' The actual numerical values of the bounds are read in as real_r8 types. These can be specified as reals or integers in the table. From 9669bfb830345ebbf3742d84c0cfb33363192de1 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Thu, 26 Oct 2023 13:42:36 -0400 Subject: [PATCH 104/129] fix: finalize utilities called last & need to be in use statement --- developer_tests/qceff/test_table_read.f90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/developer_tests/qceff/test_table_read.f90 b/developer_tests/qceff/test_table_read.f90 index 9e5ae23772..e5fb8f57e0 100644 --- a/developer_tests/qceff/test_table_read.f90 +++ b/developer_tests/qceff/test_table_read.f90 @@ -6,7 +6,7 @@ program test_table_read use algorithm_info_mod, only : init_algorithm_info_mod, end_algorithm_info_mod -use utilities_mod, only : initialize_utilities +use utilities_mod, only : initialize_utilities, finalize_utilities implicit none @@ -17,8 +17,8 @@ program test_table_read call get_command_argument(1,qcf_table_filename) call init_algorithm_info_mod(qcf_table_filename) -call finalize_utilities() call end_algorithm_info_mod() +call finalize_utilities() end program test_table_read From 8764a1158991e3c91229e64300da1b2b7ebc238d Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Thu, 26 Oct 2023 14:33:16 -0400 Subject: [PATCH 105/129] updated developer tests for qceff to match latest qcf_table removed columns: rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration --- developer_tests/qceff/work/qcf_table.txt | 4 ++-- developer_tests/qceff/work/qcf_table_bad_qty.txt | 4 ++-- developer_tests/qceff/work/qcf_table_broke.txt | 4 ++-- developer_tests/qceff/work/qcf_table_duplicates.txt | 10 +++++----- developer_tests/qceff/work/qcf_table_extra_columns.txt | 4 ++-- .../qceff/work/qcf_table_incorrect_distribution.txt | 4 ++-- .../qceff/work/qcf_table_incorrect_filter_kind.txt | 4 ++-- .../qceff/work/qcf_table_lower_bound_only.txt | 10 +++++----- .../qceff/work/qcf_table_lower_gt_upper.txt | 10 +++++----- .../qceff/work/qcf_table_no_bounds_with_values.txt | 10 +++++----- 10 files changed, 32 insertions(+), 32 deletions(-) diff --git a/developer_tests/qceff/work/qcf_table.txt b/developer_tests/qceff/work/qcf_table.txt index 7d4f146540..0449b56d87 100644 --- a/developer_tests/qceff/work/qcf_table.txt +++ b/developer_tests/qceff/work/qcf_table.txt @@ -1,3 +1,3 @@ QCF table version: 1 -QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound -QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind bounded_below bounded_above lower_bound upper_bound +QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/qcf_table_bad_qty.txt b/developer_tests/qceff/work/qcf_table_bad_qty.txt index 428e5fd6c5..3933fc478b 100644 --- a/developer_tests/qceff/work/qcf_table_bad_qty.txt +++ b/developer_tests/qceff/work/qcf_table_bad_qty.txt @@ -1,3 +1,3 @@ QCF table version: 1 -QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound -QTY_HAIRCUT .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind bounded_below bounded_above lower_bound upper_bound +QTY_HAIRCUT .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/qcf_table_broke.txt b/developer_tests/qceff/work/qcf_table_broke.txt index cb78e95e49..6585f67485 100644 --- a/developer_tests/qceff/work/qcf_table_broke.txt +++ b/developer_tests/qceff/work/qcf_table_broke.txt @@ -1,3 +1,3 @@ QCF table version: 1 -QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound -QTY_STATE_VARIABLE .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind bounded_below bounded_above lower_bound upper_bound +QTY_STATE_VARIABLE .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/qcf_table_duplicates.txt b/developer_tests/qceff/work/qcf_table_duplicates.txt index 7ffddff61f..7c4dfd9bd9 100644 --- a/developer_tests/qceff/work/qcf_table_duplicates.txt +++ b/developer_tests/qceff/work/qcf_table_duplicates.txt @@ -1,6 +1,6 @@ QCF table version: 1 -QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound -QTY_VEGETATED_AREA_FRACTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 -QTY_AQUIFER_WATER .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 -QTY_SEAICE_SALINITY008 .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 -QTY_VEGETATED_AREA_FRACTION .true. .false. 0 1000 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind bounded_below bounded_above lower_bound upper_bound +QTY_VEGETATED_AREA_FRACTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 +QTY_AQUIFER_WATER .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 +QTY_SEAICE_SALINITY008 .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 +QTY_VEGETATED_AREA_FRACTION .true. .false. 0 1000 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/qcf_table_extra_columns.txt b/developer_tests/qceff/work/qcf_table_extra_columns.txt index d298573349..3f1236b2b6 100644 --- a/developer_tests/qceff/work/qcf_table_extra_columns.txt +++ b/developer_tests/qceff/work/qcf_table_extra_columns.txt @@ -1,3 +1,3 @@ QCF table version: 1 -QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound frog -QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 toad newt +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind bounded_below bounded_above lower_bound upper_bound frog +QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 toad newt diff --git a/developer_tests/qceff/work/qcf_table_incorrect_distribution.txt b/developer_tests/qceff/work/qcf_table_incorrect_distribution.txt index 37decd57bf..93d10d7869 100644 --- a/developer_tests/qceff/work/qcf_table_incorrect_distribution.txt +++ b/developer_tests/qceff/work/qcf_table_incorrect_distribution.txt @@ -1,3 +1,3 @@ QCF table version: 1 -QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound -QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 POLAR_BEAR_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind bounded_below bounded_above lower_bound upper_bound +QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 POLAR_BEAR_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/qcf_table_incorrect_filter_kind.txt b/developer_tests/qceff/work/qcf_table_incorrect_filter_kind.txt index c1125c3360..38d567f833 100644 --- a/developer_tests/qceff/work/qcf_table_incorrect_filter_kind.txt +++ b/developer_tests/qceff/work/qcf_table_incorrect_filter_kind.txt @@ -1,3 +1,3 @@ QCF table version: 1 -QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound -QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 PENGUIN_FILTER .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind bounded_below bounded_above lower_bound upper_bound +QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 PENGUIN_FILTER .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/qcf_table_lower_bound_only.txt b/developer_tests/qceff/work/qcf_table_lower_bound_only.txt index 6f0fca4ee4..bd84571319 100644 --- a/developer_tests/qceff/work/qcf_table_lower_bound_only.txt +++ b/developer_tests/qceff/work/qcf_table_lower_bound_only.txt @@ -1,6 +1,6 @@ QCF table version: 1 -QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound -QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 -QTY_AQUIFER_WATER .true. .false. 0.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 -QTY_SEAICE_SALINITY008 .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 -QTY_VEGETATED_AREA_FRACTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind bounded_below bounded_above lower_bound upper_bound +QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 +QTY_AQUIFER_WATER .true. .false. 0.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. -888888.0 -888888.0 +QTY_SEAICE_SALINITY008 .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 +QTY_VEGETATED_AREA_FRACTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/qcf_table_lower_gt_upper.txt b/developer_tests/qceff/work/qcf_table_lower_gt_upper.txt index 6370c2cdd7..4afb33e579 100644 --- a/developer_tests/qceff/work/qcf_table_lower_gt_upper.txt +++ b/developer_tests/qceff/work/qcf_table_lower_gt_upper.txt @@ -1,6 +1,6 @@ QCF table version: 1 -QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound -QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 -QTY_AQUIFER_WATER .true. .true. 10.0 0.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 -QTY_SEAICE_SALINITY008 .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 -QTY_VEGETATED_AREA_FRACTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind bounded_below bounded_above lower_bound upper_bound +QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 +QTY_AQUIFER_WATER .true. .true. 10.0 0.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 +QTY_SEAICE_SALINITY008 .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 +QTY_VEGETATED_AREA_FRACTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/qcf_table_no_bounds_with_values.txt b/developer_tests/qceff/work/qcf_table_no_bounds_with_values.txt index 32c8d4f8e9..c987d2f9e9 100644 --- a/developer_tests/qceff/work/qcf_table_no_bounds_with_values.txt +++ b/developer_tests/qceff/work/qcf_table_no_bounds_with_values.txt @@ -1,6 +1,6 @@ QCF table version: 1 -QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind rectangular_quadrature gaussian_likelihood_tails sort_obs_inc spread_restoration bounded_below bounded_above lower_bound upper_bound -QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 -QTY_AQUIFER_WATER .false. .false. 10.0 0.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 -QTY_SEAICE_SALINITY008 .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 -QTY_VEGETATED_AREA_FRACTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. .false. .false. .false. -888888.0 -888888.0 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind spread_restoration bounded_below bounded_above lower_bound upper_bound +QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 +QTY_AQUIFER_WATER .false. .false. 10.0 0.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 +QTY_SEAICE_SALINITY008 .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 +QTY_VEGETATED_AREA_FRACTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 From 728b0be0145fffe1014ca110246a9ae731895f47 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Thu, 26 Oct 2023 14:51:43 -0400 Subject: [PATCH 106/129] remove unused variable NORMAL_DISTRIBUTION --- assimilation_code/modules/assimilation/filter_mod.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assimilation_code/modules/assimilation/filter_mod.f90 b/assimilation_code/modules/assimilation/filter_mod.f90 index 1a4dbfe585..8ecbc51ea4 100644 --- a/assimilation_code/modules/assimilation/filter_mod.f90 +++ b/assimilation_code/modules/assimilation/filter_mod.f90 @@ -92,7 +92,7 @@ module filter_mod use algorithm_info_mod, only : probit_dist_info, init_algorithm_info_mod, end_algorithm_info_mod -use distribution_params_mod, only : distribution_params_type, NORMAL_DISTRIBUTION +use distribution_params_mod, only : distribution_params_type !------------------------------------------------------------------------------ From d0f2e303a06b46fb61263a2fa95fbce4697d159e Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Thu, 26 Oct 2023 15:00:21 -0400 Subject: [PATCH 107/129] swap magic number 8 for filter_kind paramter --- assimilation_code/modules/assimilation/assim_tools_mod.f90 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index d631b1266d..ca2f51360e 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -149,7 +149,7 @@ module assim_tools_mod logical :: output_localization_diagnostics = .false. character(len = 129) :: localization_diagnostics_file = "localization_diagnostics" -! Following only relevant for filter_kind = 8 +! Following only relevant for filter_kind = UNBOUNDED_RHF logical :: rectangular_quadrature = .true. logical :: gaussian_likelihood_tails = .false. From 461aa6ba2d720b505842c0e97acc14754159e13f Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Thu, 26 Oct 2023 15:00:49 -0400 Subject: [PATCH 108/129] fix qcf_table_lower_bound_only.txt to match latest Currently the when lower_bound=.false. the lower bound is set the value lower_bound rather MISSING_R8 --- developer_tests/qceff/work/qcf_table_lower_bound_only.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/developer_tests/qceff/work/qcf_table_lower_bound_only.txt b/developer_tests/qceff/work/qcf_table_lower_bound_only.txt index bd84571319..3916443577 100644 --- a/developer_tests/qceff/work/qcf_table_lower_bound_only.txt +++ b/developer_tests/qceff/work/qcf_table_lower_bound_only.txt @@ -1,6 +1,6 @@ QCF table version: 1 QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind bounded_below bounded_above lower_bound upper_bound QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 -QTY_AQUIFER_WATER .true. .false. 0.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. .false. -888888.0 -888888.0 +QTY_AQUIFER_WATER .true. .false. 0.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 QTY_SEAICE_SALINITY008 .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 QTY_VEGETATED_AREA_FRACTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 From 70e296f97c28660d0371e691abe1d22313e6eb7b Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Thu, 26 Oct 2023 15:57:50 -0400 Subject: [PATCH 109/129] store specified qtys as integers because qtys in dart are integer parameters replace kind with qty --- .../assimilation/algorithm_info_mod.f90 | 52 +++++++------------ 1 file changed, 19 insertions(+), 33 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index de7aa32088..14cfefde9a 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -4,7 +4,7 @@ module algorithm_info_mod -use types_mod, only : r8, i8, MISSING_R8 +use types_mod, only : r8, i8, MISSING_R8, obstypelength use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance use obs_kind_mod, only : get_quantity_for_type_of_obs, get_name_for_quantity, get_index_for_quantity @@ -86,7 +86,7 @@ module algorithm_info_mod character(len=129), dimension(4) :: header1 character(len=129), dimension(25) :: header2 ! Number of table columns plus 1 -character(len=129), allocatable :: specified_qtys(:) +integer, allocatable :: specified_qtys(:) type(algorithm_info_type), allocatable :: qcf_table_data(:) character(len=129), allocatable :: dist_type_string_probit_inflation(:) @@ -164,6 +164,7 @@ subroutine read_qcf_table(qcf_table_filename) integer :: fileid integer :: row +character(len=obstypelength) :: qty_string if (.not. module_initialized) call init_algorithm_info_mod(qcf_table_filename) @@ -175,7 +176,7 @@ subroutine read_qcf_table(qcf_table_filename) ! read in table values directly to qcf_table_data type do row = 1, size(qcf_table_data) - read(fileid, *) specified_qtys(row), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & + read(fileid, *) qty_string, qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, dist_type_string_probit_inflation(row), & qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, dist_type_string_probit_state(row), & @@ -186,6 +187,13 @@ subroutine read_qcf_table(qcf_table_filename) filter_kind_string(row), qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound + specified_qtys(row) = get_index_for_quantity(qty_string) + + if(specified_qtys(row) == -1) then + write(errstring,*) trim(qty_string), ' is not a valid DART QTY' + call error_handler(E_ERR, 'read_qcf_table:', errstring, source) + endif + ! Converting the distribution types (read in from table as a string) to its corresponding int value if (trim(dist_type_string_probit_inflation(row)) == 'NORMAL_DISTRIBUTION') then qcf_table_data(row)%probit_inflation%dist_type = NORMAL_DISTRIBUTION @@ -284,7 +292,6 @@ subroutine obs_error_info(obs_def, error_variance, & type(location_type) :: temp_loc integer :: QTY_loc(1) -character(len=129) :: qty_name ! Get the kind of the observation obs_type = get_obs_def_type_of_obs(obs_def) @@ -306,11 +313,8 @@ subroutine obs_error_info(obs_def, error_variance, & return endif -!get actual name of QTY from integer index -qty_name = get_name_for_quantity(obs_qty) - !find location of QTY in qcf_table_data structure -QTY_loc = findloc(specified_qtys, qty_name) +QTY_loc = findloc(specified_qtys, obs_qty) if (QTY_loc(1) == 0) then !use default values if QTY is not in table @@ -330,13 +334,13 @@ end subroutine obs_error_info !------------------------------------------------------------------------- -subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & +subroutine probit_dist_info(qty, is_state, is_inflation, dist_type, & bounded_below, bounded_above, lower_bound, upper_bound) ! Computes the details of the probit transform for initial experiments ! with Molly -integer, intent(in) :: kind +integer, intent(in) :: qty logical, intent(in) :: is_state ! True for state variable, false for obs logical, intent(in) :: is_inflation ! True for inflation transform integer, intent(out) :: dist_type @@ -344,7 +348,6 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & real(r8), intent(out) :: lower_bound, upper_bound integer :: QTY_loc(1) -character(len=129) :: qty_name ! Have input information about the kind of the state or observation being transformed ! along with additional logical info that indicates whether this is an observation @@ -372,11 +375,7 @@ subroutine probit_dist_info(kind, is_state, is_inflation, dist_type, & return endif -!get actual name of QTY from integer index -qty_name = get_name_for_quantity(kind) - -!find location of QTY in qcf_table_data structure -QTY_loc = findloc(specified_qtys, qty_name) +QTY_loc = findloc(specified_qtys, qty) if (QTY_loc(1) == 0) then !use default values if QTY is not in table @@ -427,7 +426,6 @@ subroutine obs_inc_info(obs_qty, filter_kind, bounded_below, bounded_above, & real(r8), intent(out) :: lower_bound, upper_bound integer :: QTY_loc(1) -character(len=129) :: qty_name !use default values if qcf_table_filename is not in namelist if (use_qty_defaults) then @@ -437,11 +435,8 @@ subroutine obs_inc_info(obs_qty, filter_kind, bounded_below, bounded_above, & return endif -!get actual name of QTY from integer index -qty_name = get_name_for_quantity(obs_qty) - !find location of QTY in qcf_table_data structure -QTY_loc = findloc(specified_qtys, qty_name) +QTY_loc = findloc(specified_qtys, obs_qty) if (QTY_loc(1) == 0) then !use default values if QTY is not in table @@ -484,7 +479,6 @@ subroutine verify_qcf_table_data() ! Subroutine to ensure that the data in the QCF table is valid -integer :: varid integer :: row if (use_qty_defaults) return @@ -525,19 +519,11 @@ subroutine verify_qcf_table_data() endif end do -!Ensures that all QTYs listed in the table exist in DART -do row = 1, size(qcf_table_data) - varid = get_index_for_quantity(trim(specified_qtys(row))) - if(varid == -1) then - write(errstring,*) trim(specified_qtys(row)), ' is not a valid DART QTY' - call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) - endif -end do !Ensures that there are no duplicate QTYs in the table do row = 1, size(qcf_table_data) - if(count(specified_qtys==trim(specified_qtys(row))) > 1) then - write(errstring,*) trim(specified_qtys(row)), ' has multiple entries in the table' + if(count(specified_qtys==specified_qtys(row)) > 1) then + write(errstring,*) trim(get_name_for_quantity(specified_qtys(row))), ' has multiple entries in the table' call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) endif end do @@ -567,7 +553,7 @@ subroutine log_qcf_table_data() ! Write the table data to the dart_log and terminal do row = 1, size(qcf_table_data) - write(log_msg, *) trim(specified_qtys(row)), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & + write(log_msg, *) trim(get_name_for_quantity(specified_qtys(row))), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, trim(dist_type_string_probit_inflation(row)), & qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, trim(dist_type_string_probit_state(row)), & From 7935f552201cbbbe866999046c8a4bfa871fcee9 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Thu, 26 Oct 2023 16:43:42 -0400 Subject: [PATCH 110/129] Comment tidy: kind, type, qty cleanup and remove out-of-date comment whitespace tidy for readability --- .../assimilation/algorithm_info_mod.f90 | 64 +++++++++---------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 14cfefde9a..6f50705161 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -4,15 +4,19 @@ module algorithm_info_mod -use types_mod, only : r8, i8, MISSING_R8, obstypelength +! Provides routines that give information about details of algorithms for +! observation error sampling, observation increments, and the transformations +! for regression and inflation in probit space. -use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance -use obs_kind_mod, only : get_quantity_for_type_of_obs, get_name_for_quantity, get_index_for_quantity +use types_mod, only : r8, i8, MISSING_R8, obstypelength -use utilities_mod, only : error_handler, E_ERR, E_MSG, open_file, close_file, to_upper +use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance +use obs_kind_mod, only : get_quantity_for_type_of_obs, get_name_for_quantity, get_index_for_quantity + +use utilities_mod, only : error_handler, E_ERR, E_MSG, open_file, close_file, to_upper use assim_model_mod, only : get_state_meta_data -use location_mod, only : location_type +use location_mod, only : location_type use distribution_params_mod, only : NORMAL_DISTRIBUTION, BOUNDED_NORMAL_RH_DISTRIBUTION, & GAMMA_DISTRIBUTION, BETA_DISTRIBUTION, LOG_NORMAL_DISTRIBUTION, UNIFORM_DISTRIBUTION, & @@ -27,10 +31,7 @@ module algorithm_info_mod logical :: module_initialized = .false. logical :: use_qty_defaults = .true. -! Defining parameter strings for different observation space filters -! For now, retaining backwards compatibility in assim_tools_mod requires using -! these specific integer values and there is no point in using these in assim_tools. -! That will change if backwards compatibility is removed in the future. +! Defining parameters for different observation space filters integer, parameter :: EAKF = 1 integer, parameter :: ENKF = 2 integer, parameter :: KERNEL = 3 @@ -44,7 +45,7 @@ module algorithm_info_mod EAKF, ENKF, BOUNDED_NORMAL_RHF, UNBOUNDED_RHF, & GAMMA_FILTER, KERNEL, OBS_PARTICLE -!Creates the type definitions for the QCF table +! type definitions for the QCF table type obs_error_info_type logical :: bounded_below, bounded_above real(r8) :: lower_bound, upper_bound @@ -94,10 +95,6 @@ module algorithm_info_mod character(len=129), allocatable :: dist_type_string_probit_extended_state(:) character(len=129), allocatable :: filter_kind_string(:) -! Provides routines that give information about details of algorithms for -! observation error sampling, observation increments, and the transformations -! for regression and inflation in probit space. - contains !------------------------------------------------------------------------- @@ -127,7 +124,7 @@ subroutine init_algorithm_info_mod(qcf_table_filename) use_qty_defaults = .false. fileid = open_file(trim(qcf_table_filename), 'formatted', 'read') -! Do loop to get number of rows (or QTY's) in the table +! Do loop to get number of rows (or QTYs) in the table nlines = 0 do read(fileid,*,iostat=io) @@ -293,7 +290,7 @@ subroutine obs_error_info(obs_def, error_variance, & integer :: QTY_loc(1) -! Get the kind of the observation +! Get the type of the observation obs_type = get_obs_def_type_of_obs(obs_def) ! If it is negative, it is an identity obs if(obs_type < 0) then @@ -324,8 +321,8 @@ subroutine obs_error_info(obs_def, error_variance, & else bounded_below = qcf_table_data(QTY_loc(1))%obs_error_info%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%obs_error_info%bounded_above - lower_bound = qcf_table_data(QTY_loc(1))%obs_error_info%lower_bound - upper_bound = qcf_table_data(QTY_loc(1))%obs_error_info%upper_bound + lower_bound = qcf_table_data(QTY_loc(1))%obs_error_info%lower_bound + upper_bound = qcf_table_data(QTY_loc(1))%obs_error_info%upper_bound endif @@ -337,9 +334,6 @@ end subroutine obs_error_info subroutine probit_dist_info(qty, is_state, is_inflation, dist_type, & bounded_below, bounded_above, lower_bound, upper_bound) -! Computes the details of the probit transform for initial experiments -! with Molly - integer, intent(in) :: qty logical, intent(in) :: is_state ! True for state variable, false for obs logical, intent(in) :: is_inflation ! True for inflation transform @@ -349,7 +343,7 @@ subroutine probit_dist_info(qty, is_state, is_inflation, dist_type, & integer :: QTY_loc(1) -! Have input information about the kind of the state or observation being transformed +! Have input information about the qty of the state or observation being transformed ! along with additional logical info that indicates whether this is an observation ! or state variable and about whether the transformation is being done for inflation ! or for regress. @@ -359,7 +353,7 @@ subroutine probit_dist_info(qty, is_state, is_inflation, dist_type, & ! GAMMA_DISTRIBUTION, BETA_DISTRIBUTION, LOG_NORMAL_DISTRIBUTION, ! UNIFORM_DISTRIBUTION, and PARTICLE_FILTER_DISTRIBUTION. ! If the BNRH is selected then information about the bounds must also be set. -! For example, if my_state_kind corresponds to a sea ice fraction then an appropriate choice +! For example, if qty corresponds to a sea ice fraction then an appropriate choice ! would be: ! bounded_below = .true.; bounded_above = .true. ! lower_bound = 0.0_r8; upper_bounds = 1.0_r8 @@ -386,29 +380,29 @@ subroutine probit_dist_info(qty, is_state, is_inflation, dist_type, & elseif(is_inflation) then ! Case for inflation transformation - dist_type = qcf_table_data(QTY_loc(1))%probit_inflation%dist_type + dist_type = qcf_table_data(QTY_loc(1))%probit_inflation%dist_type bounded_below = qcf_table_data(QTY_loc(1))%probit_inflation%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%probit_inflation%bounded_above - lower_bound = qcf_table_data(QTY_loc(1))%probit_inflation%lower_bound - upper_bound = qcf_table_data(QTY_loc(1))%probit_inflation%upper_bound + lower_bound = qcf_table_data(QTY_loc(1))%probit_inflation%lower_bound + upper_bound = qcf_table_data(QTY_loc(1))%probit_inflation%upper_bound elseif(is_state) then ! Case for state variable priors - dist_type = qcf_table_data(QTY_loc(1))%probit_state%dist_type + dist_type = qcf_table_data(QTY_loc(1))%probit_state%dist_type bounded_below = qcf_table_data(QTY_loc(1))%probit_state%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%probit_state%bounded_above - lower_bound = qcf_table_data(QTY_loc(1))%probit_state%lower_bound - upper_bound = qcf_table_data(QTY_loc(1))%probit_state%upper_bound + lower_bound = qcf_table_data(QTY_loc(1))%probit_state%lower_bound + upper_bound = qcf_table_data(QTY_loc(1))%probit_state%upper_bound else ! This case is for observation (extended state) priors - dist_type = qcf_table_data(QTY_loc(1))%probit_extended_state%dist_type + dist_type = qcf_table_data(QTY_loc(1))%probit_extended_state%dist_type bounded_below = qcf_table_data(QTY_loc(1))%probit_extended_state%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%probit_extended_state%bounded_above - lower_bound = qcf_table_data(QTY_loc(1))%probit_extended_state%lower_bound - upper_bound = qcf_table_data(QTY_loc(1))%probit_extended_state%upper_bound + lower_bound = qcf_table_data(QTY_loc(1))%probit_extended_state%lower_bound + upper_bound = qcf_table_data(QTY_loc(1))%probit_extended_state%upper_bound endif @@ -446,11 +440,11 @@ subroutine obs_inc_info(obs_qty, filter_kind, bounded_below, bounded_above, & else - filter_kind = qcf_table_data(QTY_loc(1))%obs_inc_info%filter_kind + filter_kind = qcf_table_data(QTY_loc(1))%obs_inc_info%filter_kind bounded_below = qcf_table_data(QTY_loc(1))%obs_inc_info%bounded_below bounded_above = qcf_table_data(QTY_loc(1))%obs_inc_info%bounded_above - lower_bound = qcf_table_data(QTY_loc(1))%obs_inc_info%lower_bound - upper_bound = qcf_table_data(QTY_loc(1))%obs_inc_info%upper_bound + lower_bound = qcf_table_data(QTY_loc(1))%obs_inc_info%lower_bound + upper_bound = qcf_table_data(QTY_loc(1))%obs_inc_info%upper_bound endif From d6ff8f7fd4d9e90c77b8a12541afcc32906b90be Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Fri, 27 Oct 2023 14:28:41 -0400 Subject: [PATCH 111/129] doc: describe the example qcf table files for the lorenz_96_tracer examples --- guide/qcf-examples.rst | 161 ++++++++++++++++++++++++++++------------- 1 file changed, 109 insertions(+), 52 deletions(-) diff --git a/guide/qcf-examples.rst b/guide/qcf-examples.rst index 640dc13b75..338402e0ea 100644 --- a/guide/qcf-examples.rst +++ b/guide/qcf-examples.rst @@ -1,44 +1,88 @@ .. _quantile tracer: -QCF and Probit Transform Tools: Examples with the Lorenz 96 Tracer Model -======================================================================== +Quantile Conserving and Probit Transform Tools: +=============================================== +Examples with the Lorenz 96 Tracer Model +------------------------------------------ -This file contains instructions for using the lorenz_96_tracer_advection model with DART -quantile conserving and probit transform filtering tools. These tools are still -being refined, but are working for the examples described. The DART development -team (dart@ucar.edu) would be happy to hear about your experiences and is + +The QCEFF tools are in the alpha release stage. +The DART development team (dart@ucar.edu) would be happy to hear about your experiences and is anxious to build scientific collaborations using these new capabilities. -Make sure that you are on the quantile_methods branch of DART: ``git checkout quantile_methods`` +To get started, make sure that you are on the quantile_methods branch of DART: + +.. code-block:: text + + git checkout quantile_methods + +Build the DART executables for the Lorenz 96 tracer advection model: + +.. code-block:: text + + cd DART/models/lorenz_96_tracer_advection/work + ./quickbuild.sh nompi + + +The new quantile options are set using a :ref:`qcf table ` given as a namelist +option to &filter_nml. The examples below show how to change the quantile options +using various qcf tables. You can find the .csv files for these four example in the directory +``DART/models/lorenz_96_tracer_advection/work`` + -Build all executables: ``./quickbuild.sh nompi`` +.. list-table:: + :header-rows: 1 + :widths: 15 60 25 -Test A: Assimilating observations of state (wind) and tracer concentration using + * - example + - description + - .cvs filename + * - Example A + - boundend normal rank histogram with no bounds set (default value) + - all_bnrhf_qcf_table.csv (or no qcf_table_filename set) + * - Example B + - Ensemble Adjustment Kalman filters + - all_eakf_qcf_table.csv + * - Example C + - EAKF for state and bounded normal rank histogram filter and priors for tracer concentration and source + - state_eakf_tracer_bnrhf_qcf_table.csv + * - Example D + - Negative tracers bounded above + - neg_qcf_table.csv + + +You can view .csv files with a text editor, or spreadsheet tool such as Google Sheets, +or Microsoft Excel. + +Example A +---------- + +Assimilating observations of state (wind) and tracer concentration using a rank histogram observation space filter and rank histogram probit transforms for -state variable updates. Example includes adaptive inflation. +state variable updates. This example includes adaptive inflation. + The default model configuration has a single tracer source at gridpoint 1 along with small uniform tracer sinks that lead to areas where the true tracer concentration is usually 0. This is a particularly tough test for ensemble methods. -#. Add the filename of the already prepared QCF table (all_bnrhf_qcf_table.csv) in between - the single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of - /DART/models/lorenz_96_tracer_advection/work/input.nml +#. Edit input.nml to set the qcf_table_filename to 'all_bnrhf_qcf_table.csv' .. code-block:: text &filter_nml - qcf_table_filename = 'neg_qcf_table.csv' - / + qcf_table_filename = 'all_bnrhf_qcf_table.csv' + -#. Create a set_def.out file using create_obs_sequence: +#. Create a set_def.out file using create_obs_sequence, ``./create_obs_sequence < create_obs_sequence_input`` -#. Create an obs_sequence.in file using ``./create_fixed_network_seq`` +#. Create an obs_sequence.in file using create_fixed_network_seq + + ``./create_fixed_network_seq`` .. code:: text - ./create_fixed_network_seq Select the default input filename , Create a regularly repeating sequence by entering "1", Enter "1000" for the number of observation times, @@ -48,19 +92,26 @@ usually 0. This is a particularly tough test for ensemble methods. #. Spin-up a model initial condition by running perfect_model_obs - ``./perfect_model_obs`` + ``./perfect_model_obs`` #. Generate a spun-up true time series, + ``cp perfect_output.nc perfect_input.nc`` + + + Edit input.nml to set read_input_state_from_file to .true. + .. code:: text + + &filter_nml + read_input_state_from_file = .false., - cp perfect_output.nc perfect_input.nc - Use a text editor to change read_input_state_from_file to .true. in the file input.nml - Run "./perfect_model_obs" again + + Run ``./perfect_model_obs`` again. #. Run a filter assimilation, - ``./filter`` + ``./filter`` #. Examine the output with your favorite tools. Looking at the analysis ensemble for the tracer_concentration variables with indices near the source (location 1) @@ -68,62 +119,68 @@ usually 0. This is a particularly tough test for ensemble methods. source estimation capabilities of the model and filters are not being tested here. -Test B: Using default ensemble adjustment Kalman filters. +Example B +--------- + +Using Ensemble Adjustment Kalman filters. -The new quantile options are controlled by Fortran code in the module -algorithm_info_mod.f90 in the assimilation_code/modules/assimilation directory. -More information about the control can be found in that module. The tests below -replace the default version of that module with others that change certain options. -Doing a diff between these modules shows how the control is being changed for the -following tests in that module. The tests below -replace the default version of that module with others that change certain options. -#. Add the filename of the already prepared QCF table (all_eakf_qcf_table.csv) in between - the single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of - /DART/models/lorenz_96_tracer_advection/work/input.nml +#. Edit input.nml to set the qcf_table_filename to 'all_eakf_qcf_table.csv' .. code-block:: text &filter_nml - qcf_table_filename = 'neg_qcf_table.csv' - / + qcf_table_filename = 'all_eakf_qcf_table.csv' + #. Run the filter - ``./filter`` -Test C: Using default ensemble adjustment Kalman filter for state, but bounded normal rank histogram filter and priors for tracer concentration and source. + ``./filter`` + +Example C +--------- + +Using Ensemble Adjustment Kalman filter for state, but bounded normal rank histogram filter and priors for tracer concentration and source. + -#. Add the filename of the already prepared QCF table (state_eakf_tracer_bnrhf_qcf_table.csv) in - between the single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of - /DART/models/lorenz_96_tracer_advection/work/input.nml +#. Edit input.nml to set the qcf_table_filename to state_eakf_tracer_bnrhf_qcf_table.csv .. code-block:: text &filter_nml - qcf_table_filename = 'neg_qcf_table.csv' - / + qcf_table_filename = 'state_eakf_tracer_bnrhf_qcf_table.csv' + #. Run the filter - ``./filter`` -Test D: Testing bounded above option + ``./filter`` + +Example D +---------- -Normally tracers are bounded below, but there are other quantities that may be bounded +Testing the bounded above option. Normally tracers are bounded below, but there are other quantities that may be bounded above. There are distinct numerical challenges in implementing the quantile algorithms for quantities that are bounded above, so flipping the sign of the tracers is a good test. -#. Add the filename of the already prepared QCF table (neg_qcf_table.csv) in between the - single quotes on the line ``qcf_table_filename = ''`` in the &filter_mod section of - /DART/models/lorenz_96_tracer_advection/work/input.nml +#. Edit input.nml to set the qcf_table_filename to neg_qcf_table.csv .. code-block:: text &filter_nml qcf_table_filename = 'neg_qcf_table.csv' - / + + +#. Edit input.nml, to change the entry positive_tracer to .false. and read_input_state_from_file back to .false. + + + .. code-block:: text + + &model_nml + positive_tracer = .false., + + &filter_nml + read_input_state_from_file = .false., -#. In the file input.nml, change the entry positive_tracer to .false. Also, change the - entry read_input_state_from_file back to .false. #. Repeat steps 5-8 from Test A. From 24c4880e8a3873e36e161dededd486b1b5555827 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Fri, 27 Oct 2023 16:56:28 -0400 Subject: [PATCH 112/129] doc: how-to for qcf table moved QCEFF out of getting started. replaced Quantile Conserving and Probit Transform Filtering Tools with Quantile Conserving Ensemble Filtering Framework because the docs refer to QCEFF --- guide/qcf-examples.rst | 8 +- guide/qcf_probit.rst | 179 +++++++++++++++++++++++++++-------------- index.rst | 7 +- 3 files changed, 124 insertions(+), 70 deletions(-) diff --git a/guide/qcf-examples.rst b/guide/qcf-examples.rst index 338402e0ea..2fab60111c 100644 --- a/guide/qcf-examples.rst +++ b/guide/qcf-examples.rst @@ -1,12 +1,10 @@ .. _quantile tracer: -Quantile Conserving and Probit Transform Tools: -=============================================== -Examples with the Lorenz 96 Tracer Model ------------------------------------------- +QCEFF: Examples with the Lorenz 96 Tracer Model +----------------------------------------------- -The QCEFF tools are in the alpha release stage. +The Quantile-Conserving Ensemble Filter Framewor (QCEFF) tools are in the alpha release stage. The DART development team (dart@ucar.edu) would be happy to hear about your experiences and is anxious to build scientific collaborations using these new capabilities. diff --git a/guide/qcf_probit.rst b/guide/qcf_probit.rst index 9958475cf6..19db31afa0 100644 --- a/guide/qcf_probit.rst +++ b/guide/qcf_probit.rst @@ -1,97 +1,152 @@ .. _QCF: -######################################################## -Quantile Conserving and Probit Transform Filtering Tools -######################################################## +Quantile-Conserving Ensemble Filter Framework +============================================== -This file contains instructions for using the DART Quantile Conserving Filters (QCF), also known as the Quantile Conserving Ensemble Filtering Framework (QCEFF), and probit transform filtering tools. +The Quantile-Conserving Ensemble Filter Framework (QCEFF) tools are in the alpha release stage. +The DART development team (dart@ucar.edu) would be happy to hear about your experiences +and is anxious to build scientific collaborations using these new capabilities. -The DART development team (dart@ucar.edu) would be happy to hear about your experiences and is anxious to build scientific collaborations using these new capabilities. +The QCEFF options are set using a :ref:`qcf table ` given as a namelist option to &filter_nml. -The user can include an input table allows the user to specify the control options for these tools. The observation, state, and inflation variables are all included in this single table. + .. code-block:: text -The new quantile options are read in from the table at runtime and then set in the module algorithm_info_mod.f90 in the DART/assimilation_code/modules/assimilation directory. This module provides routines that give information about details of algorithms for observation error sampling, observation increments, and the transformations for regression and inflation in probit space. + &filter_nml + qcf_table_filename = 'qcf_table.csv' -For individual QTYs in DART, the user can specify the options such as the bounds, distribution type, filter kind, etc. for the obs_error_info, probit_dist_info, and obs_inc_info subroutines in algorithm_info_mod.f90 -If the user does not use a QCF input table with the DART quantile conserving and probit transform filtering tools, then the default values for these options will be used for all QTYs. +.. _QCEFF options: -Table Composition ------------------ -The table consists of two headers. The first states the version # of the table being used; the most recent version of the table needs to be used to ensure compatibilty with DART. The current version # is 1. The second header lists the full set of input options, or all 24 column names in other words. +QCEFF options +-------------- -Each QTY is specified in its own column, having 24 total control options. -These control options are divided into 3 main groups, which are the options used for the obs_error_info, probit_dist_info, and obs_inc_info. However, the user is able to specify different values for probit inflation, probit state, and probit extended state, resulting in 5 total groupings for the control options. +QCEFF options are per quantity. For a given quantity, you specify the following +options as columns of the qcf_table: -The obs_error_info subroutine computes information needed to compute error sample for this observation. -For obs_error_info the input options are the two bounds (lower and upper). +* Observation error information -The probit_dist_info subroutine computes the details of the probit transform. -From probit_dist_info, the values needed are the bounds and the distribution type. These can be different for all three cases (inflation, state, and extended_state). + Used to compute sample for this observation when using perfect_model_obs + to generate noisy observations. + + * bounded_below (default .false.) + * bounded_above (default .false.) + * lower_bound + * upper_bound -The obs_inc_info subrotuine sets the details of how to assimilate this observation. -From obs_inc_info, the values needed are the bounds and the filter_kind. -Full list of options: -Obs_error_info: bounded_below, bounded_above, lower_bound, upper_bound [4 columns] -Probit_dist_info: dist_type, bounded_below, bounded_above, lower_bound, upper_bound (x3 for inflation, state, and observation (extended state) priors) [15 columns] -Obs_inc_info: filter_kind, bounded_below, bounded_above, lower_bound, upper_bound [5 columns] +* Probit distribution information -Customizing the Table ---------------------- -The table can be customized by editing a Google Sheet spreadsheet (which is then downloaded in .csv format). Folow this `link `_ to access the template spreadsheet. + Used in the computation of the probit transform. + The values needed are the bounds and the distribution type. + These can be different for all three cases (inflation, state, and extended_state priors) + + * distribution (one of :ref:`Distributions`) + * bounded_below (default .false.) + * bounded_above (default .false.) + * lower_bound + * upper_bound -The user will add and fill in one row for each bounded QTY they want to specify. If a QTY is not listed in the table, the default values will be used for all 25 options. Therefore, the user will only need to add rows for QTYs that use non-default values for any of the input options. -The default values for each of the options are listed below: -bounded_below = .false. -bounded_above = .false. -lower_bound = -888888 -upper_bound = -888888 -dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION -filter_kind = BOUNDED_NORMAL_RHF +* Observation increment information -Note that bounds set to -888888 are missing_r8 values. + * filter_kind (one of :ref:`Filter kinds`) + * bounded_below (default .false.) + * bounded_above (default .false.) + * lower_bound + * upper_bound -bounded_below and bounded_above are read in as logicals, and will need to be written in the format of either 'F' or '.false.' -The actual numerical values of the bounds are read in as real_r8 types. These can be specified as reals or integers in the table. -dist_type and filter_kind are read in as strings. The possible values for these variables are listed below: +.. _qcf table: -dist_type: -NORMAL_DISTRIBUTION, BOUNDED_NORMAL_RH_DISTRIBUTION, GAMMA_DISTRIBUTION, BETA_DISTRIBUTION, LOG_NORMAL_DISTRIBUTION, UNIFORM_DISTRIBUTION, PARTICLE_FILTER_DISTRIBUTION +Creating a qcf table +-------------------- -filter_kind: -EAKF, ENKF, UNBOUNDED_RHF, GAMMA_FILTER, BOUNDED_NORMAL_RHF +The table has two headers, row 1 and 2. +The first row is the version number. The second row describes the :ref:`QCEFF options` corresponding to each column of the table. +These two headers must be present in your qcf table. +The :ref:`qcf trunc table` below shows the table headers, +and an example quantity QTY_TRACER_CONCENTRATION for the first 5 columns of the table. +There is a complete table with all 25 columns in `Google Sheets `_. You can copy and edit this table as needed. -Make a copy of the table by selecting 'File > Make a copy' from the menu bar. +To add a quantity, add a row to the table. +For any quantity not listed in the table, the :ref:`Default values` values will be used for all 25 options. +You only have to add rows for quantitiies that use non-default values for any of the input options. +Ensure that there are no empty rows in between the quantities listed in the spreadsheet. +Save your spreadsheet as a .csv file. -To customize the spreadsheet, click on the cell you want to edit and change the value of that cell. -To add a new QTY to the spreadsheet, copy row 3 of the table into the next available row, change ``QTY_NAME`` to the name of the QTY to specify, and edit the cells individually to set the control options. -To remove a QTY from the spreadsheet, select the row number corresponding to that QTY. Then right click and choose "Delete Row" -Make sure to remove the row for ``QTY_NAME`` when you have finished adding all of the specified QTYs to the table. +To run filter or perfect_model_obs, put the .csv file in the directory where you are running. +Edit input.nml to set the filter_nml option qcf_table_filename, for example: -Ensure that there are no empty rows in between the QTYs listed in the spreadsheet. -Download the spreadsheet as a .csv file by selecting 'File > Download > csv' from the menu bar. + .. code-block:: text -Google Sheets will append the name of the file with " - Sheet1.csv" when it is downloaded. For example, a spreadsheet named "qcf_table" wil be downloaded as "qcf_table - Sheet1.csv" -Rename this file to remove this addition to ensure that there are no spaces in the filename. + &filter_nml + qcf_table_filename = 'qcf_table.csv' -Copy or move this file to your working directory (/DART/models/model_name/work). -Using the table in DART +.. _qcf trunc table: + +.. list-table:: truncated table + :header-rows: 2 + + * - QCF table version: 1 + - + - + - + - + * - QTY + - bounded_below + - bounded_above + - lower_bound + - upper_bound + * - QTY_TRACER_CONCENTRATION + - .true. + - .false. + - 0 + - -888888 + + +.. _Filter kinds: + +Available filter kinds ----------------------- -Navigate to your working directory (/DART/models/model_name/work). -Switch to the quantile_methods branch of DART: -``git checkout quantile_methods`` + * EAKF + * ENKF + * UNBOUNDED_RH + * GAMMA_FILTER + * BOUNDED_NORMAL_RHF (default) + +.. _Distributions: + +Available distributions +------------------------ + + * NORMAL_DISTRIBUTION + * BOUNDED_NORMAL_RH_DISTRIBUTION + * GAMMA_DISTRIBUTION + * BETA_DISTRIBUTION + * LOG_NORMAL_DISTRIBUTION + * UNIFORM_DISTRIBUTION + * PARTICLE_FILTER_DISTRIBUTION + + + +.. _Default values: + +Default values +--------------- + +If a quantity is not in the qcf table, the following default values +are used: -Edit your namelist file (input.nml): -Add the name of the QCF table file in between the quotes of ``qcf_table_filename = ''`` in the &filter_nml section. -Remember that the default values will be used for all QTYs if no filename is listed here. + * filter_kind (default BOUNDED_NORMAL_RHF) + * dist_type (default BOUNDED_NORMAL_RH_DISTRIBUTION) + * bounded_below (default .false.) + * bounded_above (default .false.) + * lower_bound (default -888888) + * upper_bound (default -888888) -Build and run filter normally. +Note -888888 is a missing value in DART. -The data that is read from in the QCF table is written to the output file dart_log.out diff --git a/index.rst b/index.rst index 89971b0f0b..eb2d593c76 100644 --- a/index.rst +++ b/index.rst @@ -98,9 +98,10 @@ estimated with DA and large improvements can occur for bounded parameters. Varia non-Gaussian prior distributions can also see large improvements. Examples can include atmospheric quantities like moisture and cloud amount in the presence of convection, and many land surface variables. -For instructions on how to use these tools, see :ref:`QCF` +For instructions on how to use these tools, see :ref:`QCF`. -For step-by-step examples of the QCEFF tools, you can work through :ref:`quantile tracer` +For step-by-step examples of the QCEFF tools, you can work through +:ref:`examples with the Lorenz 96 tracer model ` Organization of the documentation --------------------------------- @@ -270,7 +271,6 @@ References guide/downloading-dart guide/compiling-dart guide/verifying-installation - guide/qcf_probit .. toctree:: :maxdepth: 2 @@ -290,6 +290,7 @@ References guide/high-level-da-workflows guide/dart-design-philosophy guide/important-capabilities-dart + guide/qcf_probit .. toctree:: :maxdepth: 2 From c9b579ebb18441ca56a05446882c61a6a4c836c9 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Mon, 30 Oct 2023 13:26:13 -0400 Subject: [PATCH 113/129] doc-fix: example A QTY_TRACER_CONCENTRATION lower bound = 0 --- guide/qcf-examples.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/guide/qcf-examples.rst b/guide/qcf-examples.rst index 2fab60111c..fed6716b40 100644 --- a/guide/qcf-examples.rst +++ b/guide/qcf-examples.rst @@ -1,10 +1,10 @@ .. _quantile tracer: QCEFF: Examples with the Lorenz 96 Tracer Model ------------------------------------------------ +=============================================== -The Quantile-Conserving Ensemble Filter Framewor (QCEFF) tools are in the alpha release stage. +The Quantile-Conserving Ensemble Filter Framework (QCEFF) tools are in the alpha release stage. The DART development team (dart@ucar.edu) would be happy to hear about your experiences and is anxious to build scientific collaborations using these new capabilities. @@ -36,8 +36,8 @@ using various qcf tables. You can find the .csv files for these four example in - description - .cvs filename * - Example A - - boundend normal rank histogram with no bounds set (default value) - - all_bnrhf_qcf_table.csv (or no qcf_table_filename set) + - boundend normal rank histogram with QTY_TRACER_CONCENTRATION lower bound = 0 + - all_bnrhf_qcf_table.csv * - Example B - Ensemble Adjustment Kalman filters - all_eakf_qcf_table.csv From 61c202b624c336eaa16b316e30460ea4f01b2a09 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Mon, 30 Oct 2023 13:42:49 -0400 Subject: [PATCH 114/129] probit_transform defaults fix_bound_violations = .false., use_logit_instead_of_probit = .false., do_inverse_check = .false., removed duplicate &probit_transform_nml from lorenz_96_tracer_advection input.nml --- .../modules/assimilation/probit_transform_mod.f90 | 2 +- models/9var/work/input.nml | 3 --- models/FESOM/work/input.nml | 3 --- models/LMDZ/work/input.nml | 3 --- models/MITgcm_annulus/work/input.nml | 3 --- models/MOM6/work/input.nml | 3 --- models/NAAPS/work/input.nml | 3 --- models/NCOMMAS/work/input.nml | 3 --- models/POP/work/input.nml | 3 --- models/ROMS/work/input.nml | 5 +---- models/am2/work/input.nml | 3 --- models/bgrid_solo/work/input.nml | 3 --- models/cam-fv/work/input.nml | 3 --- models/cam-fv/work/new_qcf_input.nml | 3 --- models/cam-se/work/input.nml | 3 --- models/cice/work/input.nml | 3 --- models/clm/work/input.nml | 3 --- models/cm1/work/input.nml | 3 --- .../coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml | 3 --- models/dynamo/work/input.nml | 3 --- models/forced_barot/work/input.nml | 3 --- models/forced_lorenz_96/work/input.nml | 3 --- models/gitm/work/input.nml | 3 --- models/ikeda/work/input.nml | 3 --- models/lorenz_04/work/input.nml | 3 --- models/lorenz_63/work/input.nml | 3 --- models/lorenz_84/work/input.nml | 3 --- models/lorenz_96/work/input.nml | 3 --- models/lorenz_96_2scale/work/input.nml | 3 --- models/lorenz_96_tracer_advection/work/input.nml | 9 --------- models/mpas_atm/work/input.nml | 3 --- models/mpas_ocn/work/input.nml | 3 --- models/noah/work/input.nml | 5 +---- models/null_model/work/input.nml | 3 --- models/pe2lyr/work/input.nml | 3 --- models/rose/work/input.nml | 3 --- models/simple_advection/work/input.nml | 3 --- models/sqg/work/input.nml | 3 --- models/template/work/oned_input.nml | 3 --- models/template/work/threed_input.nml | 3 --- models/tiegcm/work/input.nml | 3 --- models/wrf/work/input.nml | 3 --- models/wrf_hydro/work/input.nml | 3 --- 43 files changed, 3 insertions(+), 135 deletions(-) diff --git a/assimilation_code/modules/assimilation/probit_transform_mod.f90 b/assimilation_code/modules/assimilation/probit_transform_mod.f90 index e388f2d06c..f0ea534a27 100644 --- a/assimilation_code/modules/assimilation/probit_transform_mod.f90 +++ b/assimilation_code/modules/assimilation/probit_transform_mod.f90 @@ -47,7 +47,7 @@ module probit_transform_mod ! Logical to fix bounds violations for bounded_normal_rh logical :: fix_bound_violations = .false. ! Should we use a logit transform instead of the default probit transform -logical :: use_logit_instead_of_probit = .true. +logical :: use_logit_instead_of_probit = .false. ! Set to true to do a check of the probit to/from transforms for inverse accuracy logical :: do_inverse_check = .false. diff --git a/models/9var/work/input.nml b/models/9var/work/input.nml index fccc09cf31..f95a275a0b 100644 --- a/models/9var/work/input.nml +++ b/models/9var/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/FESOM/work/input.nml b/models/FESOM/work/input.nml index 80d0e09c4f..02d9fead5a 100644 --- a/models/FESOM/work/input.nml +++ b/models/FESOM/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false. - use_logit_instead_of_probit = .false. - do_inverse_check = .true. / &perfect_model_obs_nml diff --git a/models/LMDZ/work/input.nml b/models/LMDZ/work/input.nml index 440eb8a9ee..b3f9fa6ae5 100644 --- a/models/LMDZ/work/input.nml +++ b/models/LMDZ/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &filter_nml diff --git a/models/MITgcm_annulus/work/input.nml b/models/MITgcm_annulus/work/input.nml index 065a524d74..dc810e8946 100644 --- a/models/MITgcm_annulus/work/input.nml +++ b/models/MITgcm_annulus/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/MOM6/work/input.nml b/models/MOM6/work/input.nml index 867191e4bf..153fce5e13 100644 --- a/models/MOM6/work/input.nml +++ b/models/MOM6/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/NAAPS/work/input.nml b/models/NAAPS/work/input.nml index 00425d2245..403c98d92d 100644 --- a/models/NAAPS/work/input.nml +++ b/models/NAAPS/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false. - use_logit_instead_of_probit = .false. - do_inverse_check = .true. / &assim_tools_nml diff --git a/models/NCOMMAS/work/input.nml b/models/NCOMMAS/work/input.nml index 52c176a737..2f6f64165c 100644 --- a/models/NCOMMAS/work/input.nml +++ b/models/NCOMMAS/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/POP/work/input.nml b/models/POP/work/input.nml index a1eb9e0dab..f8614c4c7b 100644 --- a/models/POP/work/input.nml +++ b/models/POP/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false. - use_logit_instead_of_probit = .false. - do_inverse_check = .true. / &perfect_model_obs_nml diff --git a/models/ROMS/work/input.nml b/models/ROMS/work/input.nml index 9120b6e916..6ac2180fa3 100644 --- a/models/ROMS/work/input.nml +++ b/models/ROMS/work/input.nml @@ -1,8 +1,5 @@ &probit_transform_nml - fix_bound_violations = .false. - use_logit_instead_of_probit = .false. - do_inverse_check = .true. - / + / &perfect_model_obs_nml read_input_state_from_file = .true. diff --git a/models/am2/work/input.nml b/models/am2/work/input.nml index 58d0b3dee2..9ec433d290 100644 --- a/models/am2/work/input.nml +++ b/models/am2/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/bgrid_solo/work/input.nml b/models/bgrid_solo/work/input.nml index f85cd5b2a6..c26214686a 100644 --- a/models/bgrid_solo/work/input.nml +++ b/models/bgrid_solo/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/cam-fv/work/input.nml b/models/cam-fv/work/input.nml index 8a8ae3d10a..1c64d9e210 100644 --- a/models/cam-fv/work/input.nml +++ b/models/cam-fv/work/input.nml @@ -34,9 +34,6 @@ ! if needed. &probit_transform_nml - fix_bound_violations = .false. - use_logit_instead_of_probit = .false. - do_inverse_check = .true. / &filter_nml diff --git a/models/cam-fv/work/new_qcf_input.nml b/models/cam-fv/work/new_qcf_input.nml index 92d4f8b95e..1e920aaa08 100644 --- a/models/cam-fv/work/new_qcf_input.nml +++ b/models/cam-fv/work/new_qcf_input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .true., - use_logit_instead_of_probit = .false. - do_inverse_check = .false. / &filter_nml diff --git a/models/cam-se/work/input.nml b/models/cam-se/work/input.nml index 6b9a561b68..37b63e1d0e 100644 --- a/models/cam-se/work/input.nml +++ b/models/cam-se/work/input.nml @@ -29,9 +29,6 @@ ! if needed. &probit_transform_nml - fix_bound_violations = .false. - use_logit_instead_of_probit = .false. - do_inverse_check = .true. / &filter_nml diff --git a/models/cice/work/input.nml b/models/cice/work/input.nml index c78fd038a4..9f0c5edecb 100644 --- a/models/cice/work/input.nml +++ b/models/cice/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false. - use_logit_instead_of_probit = .false. - do_inverse_check = .true. / &perfect_model_obs_nml diff --git a/models/clm/work/input.nml b/models/clm/work/input.nml index cb46cab1ff..737fbc097c 100644 --- a/models/clm/work/input.nml +++ b/models/clm/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false. - use_logit_instead_of_probit = .false. - do_inverse_check = .true. / &perfect_model_obs_nml diff --git a/models/cm1/work/input.nml b/models/cm1/work/input.nml index b0a6d5cef0..29623c9228 100644 --- a/models/cm1/work/input.nml +++ b/models/cm1/work/input.nml @@ -3,9 +3,6 @@ ! use 'distributed_state = .true.' &probit_transform_nml - fix_bound_violations = .false. - use_logit_instead_of_probit = .false. - do_inverse_check = .true. / &filter_nml diff --git a/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml b/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml index e1a0b9a8db..5d596ec966 100644 --- a/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml +++ b/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false. - use_logit_instead_of_probit = .false. - do_inverse_check = .true. / &perfect_model_obs_nml diff --git a/models/dynamo/work/input.nml b/models/dynamo/work/input.nml index 3add1a1c6e..6e40149985 100644 --- a/models/dynamo/work/input.nml +++ b/models/dynamo/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/forced_barot/work/input.nml b/models/forced_barot/work/input.nml index aed880c7b4..f616546f69 100644 --- a/models/forced_barot/work/input.nml +++ b/models/forced_barot/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/forced_lorenz_96/work/input.nml b/models/forced_lorenz_96/work/input.nml index 537d7aec4e..b605a63a32 100644 --- a/models/forced_lorenz_96/work/input.nml +++ b/models/forced_lorenz_96/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/gitm/work/input.nml b/models/gitm/work/input.nml index 70156882d0..ae584c7aeb 100644 --- a/models/gitm/work/input.nml +++ b/models/gitm/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false. - use_logit_instead_of_probit = .false. - do_inverse_check = .true. / &filter_nml diff --git a/models/ikeda/work/input.nml b/models/ikeda/work/input.nml index 51d0d15c50..4faa524ff8 100644 --- a/models/ikeda/work/input.nml +++ b/models/ikeda/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/lorenz_04/work/input.nml b/models/lorenz_04/work/input.nml index 7d2f85fc02..4a0a976b02 100644 --- a/models/lorenz_04/work/input.nml +++ b/models/lorenz_04/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/lorenz_63/work/input.nml b/models/lorenz_63/work/input.nml index da3f873619..b53bc108d7 100644 --- a/models/lorenz_63/work/input.nml +++ b/models/lorenz_63/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false. - do_inverse_check = .true. / &perfect_model_obs_nml diff --git a/models/lorenz_84/work/input.nml b/models/lorenz_84/work/input.nml index 40276b9994..1a91ec6518 100644 --- a/models/lorenz_84/work/input.nml +++ b/models/lorenz_84/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/lorenz_96/work/input.nml b/models/lorenz_96/work/input.nml index 49b3244f1d..cce2f9d3a8 100644 --- a/models/lorenz_96/work/input.nml +++ b/models/lorenz_96/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false. - do_inverse_check = .true. / &perfect_model_obs_nml diff --git a/models/lorenz_96_2scale/work/input.nml b/models/lorenz_96_2scale/work/input.nml index bf1468237c..398fd66e27 100644 --- a/models/lorenz_96_2scale/work/input.nml +++ b/models/lorenz_96_2scale/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/lorenz_96_tracer_advection/work/input.nml b/models/lorenz_96_tracer_advection/work/input.nml index bb5353fc67..057c08937a 100644 --- a/models/lorenz_96_tracer_advection/work/input.nml +++ b/models/lorenz_96_tracer_advection/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml @@ -90,12 +87,6 @@ silence = .false., / -&probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false. - do_inverse_check = .true. - / - &ensemble_manager_nml / diff --git a/models/mpas_atm/work/input.nml b/models/mpas_atm/work/input.nml index bfbe13f568..5e7521dd33 100644 --- a/models/mpas_atm/work/input.nml +++ b/models/mpas_atm/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false. - use_logit_instead_of_probit = .false. - do_inverse_check = .true. / &perfect_model_obs_nml diff --git a/models/mpas_ocn/work/input.nml b/models/mpas_ocn/work/input.nml index f11d657cda..930abf70bb 100644 --- a/models/mpas_ocn/work/input.nml +++ b/models/mpas_ocn/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/noah/work/input.nml b/models/noah/work/input.nml index c5e48d8429..7ffbe98215 100644 --- a/models/noah/work/input.nml +++ b/models/noah/work/input.nml @@ -1,10 +1,7 @@ # This namelist is for both NOAH and NOAH-MP &probit_transform_nml - fix_bound_violations = .false. - use_logit_instead_of_probit = .false. - do_inverse_check = .true. - / + / &model_nml lsm_model_choice = 'noahMP_36' diff --git a/models/null_model/work/input.nml b/models/null_model/work/input.nml index f5282c3b22..412e8731a0 100644 --- a/models/null_model/work/input.nml +++ b/models/null_model/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/pe2lyr/work/input.nml b/models/pe2lyr/work/input.nml index 94d2ebfc97..02838242e4 100644 --- a/models/pe2lyr/work/input.nml +++ b/models/pe2lyr/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/rose/work/input.nml b/models/rose/work/input.nml index 7092c2e086..639a37c02c 100644 --- a/models/rose/work/input.nml +++ b/models/rose/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/simple_advection/work/input.nml b/models/simple_advection/work/input.nml index 8174c039d3..e60d00921b 100644 --- a/models/simple_advection/work/input.nml +++ b/models/simple_advection/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false. - use_logit_instead_of_probit = .false. - do_inverse_check = .true. / &perfect_model_obs_nml diff --git a/models/sqg/work/input.nml b/models/sqg/work/input.nml index bd4c13a193..d36cfd71d5 100644 --- a/models/sqg/work/input.nml +++ b/models/sqg/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/template/work/oned_input.nml b/models/template/work/oned_input.nml index 40444d3c42..5ecb7e4863 100644 --- a/models/template/work/oned_input.nml +++ b/models/template/work/oned_input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/template/work/threed_input.nml b/models/template/work/threed_input.nml index e2cc53e4bd..d30866baa8 100644 --- a/models/template/work/threed_input.nml +++ b/models/template/work/threed_input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/tiegcm/work/input.nml b/models/tiegcm/work/input.nml index 6478346746..b4c3343723 100644 --- a/models/tiegcm/work/input.nml +++ b/models/tiegcm/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &quality_control_nml diff --git a/models/wrf/work/input.nml b/models/wrf/work/input.nml index 17af11a9e4..9304c3dc9c 100644 --- a/models/wrf/work/input.nml +++ b/models/wrf/work/input.nml @@ -1,7 +1,4 @@ &probit_transform_nml - fix_bound_violations = .false., - use_logit_instead_of_probit = .false., - do_inverse_check = .true., / &perfect_model_obs_nml diff --git a/models/wrf_hydro/work/input.nml b/models/wrf_hydro/work/input.nml index 67dc994862..ac2037247b 100644 --- a/models/wrf_hydro/work/input.nml +++ b/models/wrf_hydro/work/input.nml @@ -8,9 +8,6 @@ # domain_shapefiles = 'restart.hydro.nc', 'parameters.nc' &probit_transform_nml - fix_bound_violations = .false. - use_logit_instead_of_probit = .false. - do_inverse_check = .true. / &model_nml From 71cdaf09a5fa9c412915bcb60fc4428898c1c175 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Mon, 30 Oct 2023 13:52:52 -0400 Subject: [PATCH 115/129] two qtys are bounded --- guide/qcf-examples.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/qcf-examples.rst b/guide/qcf-examples.rst index fed6716b40..79b092e0ac 100644 --- a/guide/qcf-examples.rst +++ b/guide/qcf-examples.rst @@ -36,7 +36,7 @@ using various qcf tables. You can find the .csv files for these four example in - description - .cvs filename * - Example A - - boundend normal rank histogram with QTY_TRACER_CONCENTRATION lower bound = 0 + - boundend normal rank histogram - all_bnrhf_qcf_table.csv * - Example B - Ensemble Adjustment Kalman filters From dac1f96eaf2f4692d9c892ccfd6799ddd407c146 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Mon, 30 Oct 2023 14:30:22 -0400 Subject: [PATCH 116/129] Jeff edits for index.html defaults: filter_kind EAKF, dist_type NORMAL_DISTRIBUTION code changed to match Jeffs edits. --- .../assimilation/algorithm_info_mod.f90 | 8 +-- guide/qcf_probit.rst | 10 +-- index.rst | 64 ++++++++++--------- 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 6f50705161..1c65d535e8 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -363,7 +363,7 @@ subroutine probit_dist_info(qty, is_state, is_inflation, dist_type, & !use default values if qcf_table_filename is not in namelist if (use_qty_defaults) then - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION + dist_type = NORMAL_DISTRIBUTION bounded_below = .false.; bounded_above = .false. lower_bound = MISSING_R8; upper_bound = MISSING_R8 return @@ -373,7 +373,7 @@ subroutine probit_dist_info(qty, is_state, is_inflation, dist_type, & if (QTY_loc(1) == 0) then !use default values if QTY is not in table - dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION + dist_type = NORMAL_DISTRIBUTION bounded_below = .false.; bounded_above = .false. lower_bound = MISSING_R8; upper_bound = MISSING_R8 @@ -423,7 +423,7 @@ subroutine obs_inc_info(obs_qty, filter_kind, bounded_below, bounded_above, & !use default values if qcf_table_filename is not in namelist if (use_qty_defaults) then - filter_kind = BOUNDED_NORMAL_RHF + filter_kind = EAKF bounded_below = .false.; bounded_above = .false. lower_bound = MISSING_R8; upper_bound = MISSING_R8 return @@ -434,7 +434,7 @@ subroutine obs_inc_info(obs_qty, filter_kind, bounded_below, bounded_above, & if (QTY_loc(1) == 0) then !use default values if QTY is not in table - filter_kind = BOUNDED_NORMAL_RHF + filter_kind = EAKF bounded_below = .false.; bounded_above = .false. lower_bound = MISSING_R8; upper_bound = MISSING_R8 diff --git a/guide/qcf_probit.rst b/guide/qcf_probit.rst index 19db31afa0..e19d9775e6 100644 --- a/guide/qcf_probit.rst +++ b/guide/qcf_probit.rst @@ -112,18 +112,18 @@ Edit input.nml to set the filter_nml option qcf_table_filename, for example: Available filter kinds ----------------------- - * EAKF + * EAKF (default) * ENKF * UNBOUNDED_RH * GAMMA_FILTER - * BOUNDED_NORMAL_RHF (default) + * BOUNDED_NORMAL_RHF .. _Distributions: Available distributions ------------------------ - * NORMAL_DISTRIBUTION + * NORMAL_DISTRIBUTION (default) * BOUNDED_NORMAL_RH_DISTRIBUTION * GAMMA_DISTRIBUTION * BETA_DISTRIBUTION @@ -141,8 +141,8 @@ Default values If a quantity is not in the qcf table, the following default values are used: - * filter_kind (default BOUNDED_NORMAL_RHF) - * dist_type (default BOUNDED_NORMAL_RH_DISTRIBUTION) + * filter_kind (default EAKF) + * dist_type (default NORMAL_DISTRIBUTION) * bounded_below (default .false.) * bounded_above (default .false.) * lower_bound (default -888888) diff --git a/index.rst b/index.rst index eb2d593c76..1a5f9bf24b 100644 --- a/index.rst +++ b/index.rst @@ -63,38 +63,40 @@ research labs. Nonlinear and Non-Gaussian Data Assimilation Capabilities in DART ----------------------------------------------------------------- -The default DART algorithms assume a normal distribution to compute ensemble increments + +The default DART algorithms assume a normal distribution to compute ensemble increments for the observed quantity (this is the ensemble adjustment Kalman filter, or EAKF) and -then linearly regresses the observation increments onto each state variable. - -DART’s newest and innovative capability, the :ref:`Quantile Conserving Filters (QCF) `, -also known as the Quantile Conserving Ensemble Filtering Framework (QCEFF), provide a -very general method of computing increments for the prior ensemble of an observed quantity -by allowing the use of quantile conserving ensemble filters that can assume arbitrary -distributions for the prior and the observation error. Quantile Conserving Filters are -especially useful for bounded quantities like tracer concentrations, depths of things like -snow or ice, and estimating model parameters that have a restricted range. - -While Quantile Conserving Filters lead to significant improvements in analysis estimates for -observed variables, those improvements can be lost when using standard linear regression of -observation increments to update other state variables. Therefore, DART also includes new -functionality to use probit-transformed quantile regression methods that allow much more general -regression for computing state increments. Doing the regression of observation quantile increments -in a probit-transformed, bivariate, quantile space guarantees that the posterior ensembles -for state variables also have all the advantages of the observation space quantile conserving -posteriors. For example, if state variables are bounded, then posterior ensembles will respect -the bounds. The posterior ensembles also respect other aspects of the continuous prior distributions. - -Inflation and localization, methods that improve the quality of ensemble DA, can also negate the -advantages of the quantile conserving method. For this reason, both localization and inflation can be done -in the probit-transformed quantile space as well. - -Combining these new methods can significantly improve data assimilation for non-Gaussian quantities -in Earth system models by extending the capabilities of ensemble DA to general non-Gaussian and -nonlinear distributions. Transformative improvements in DA can result for many applications. The -largest improvements are found for bounded variables like tracer concentrations, snow and ice depth, -soil moisture, and similar quantities in other parts of the Earth system. Model parameters can also be -estimated with DA and large improvements can occur for bounded parameters. Variables that have distinctly +then linearly regress the observation increments onto each state variable. + + +DART now implements a Quantile-Conserving Ensemble Filtering Framework :ref:`(QCEFF) `. +The QCEFF provides a very general method of computing increments for the prior ensemble of +an observed quantity by allowing the use of arbitrary distributions for the prior and the +observation error. This is especially useful for bounded quantities like tracer concentrations, +depths of things like snow or ice, and estimating model parameters that have a restricted range. +See this Monthly Weather Review article for details, +`QCEFF part1 `_. + +While the QCEFF for computing observation increments can lead to significant improvements in +analysis estimates for observed variables, those improvements can be lost when using standard +linear regression of observation increments to update other state variables. The QCEFF also +implements a capability to do regression in a probit probability integral transformed space. +Doing the regression of observation quantile increments in the transformed space guarantees +that the posterior ensembles for state variables also the advantages of the observation space +quantile conserving posteriors. For example, if state variables are bounded, then posterior +ensembles will respect the bounds. The posterior ensembles also respect other aspects of the +continuous prior distributions. See this Monthly Weather Review article for details, +`QCEFF part 2 `_. + +Inflation and localization, methods that improve the quality of ensemble DA, can also negate +the advantages of the QCEFF methods. For this reason, both localization and inflation can be +done in the probit-transformed quantile space as well. Combining these new methods can +significantly improve data assimilation for non-Gaussian quantities in Earth system models by +extending the capabilities of ensemble DA to general non-Gaussian and nonlinear distributions. +Transformative improvements in DA can result for many applications. The largest improvements are +found for bounded variables like tracer concentrations, snow and ice depth, soil moisture, and +similar quantities in other parts of the Earth system. Model parameters can also be estimated +with DA and large improvements can occur for bounded parameters. Variables that have distinctly non-Gaussian prior distributions can also see large improvements. Examples can include atmospheric quantities like moisture and cloud amount in the presence of convection, and many land surface variables. From 5583e397f562be4bf65057a819e39e7948242713 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Mon, 30 Oct 2023 14:32:17 -0400 Subject: [PATCH 117/129] remove out-of-date cam-fv input.nml for testing quantile_methods --- models/cam-fv/work/new_qcf_input.nml | 433 --------------------------- 1 file changed, 433 deletions(-) delete mode 100644 models/cam-fv/work/new_qcf_input.nml diff --git a/models/cam-fv/work/new_qcf_input.nml b/models/cam-fv/work/new_qcf_input.nml deleted file mode 100644 index 1e920aaa08..0000000000 --- a/models/cam-fv/work/new_qcf_input.nml +++ /dev/null @@ -1,433 +0,0 @@ -&probit_transform_nml - / - -&filter_nml - use_algorithm_info_mod = .true. - input_state_file_list = 'cam_init_files' - input_state_files = '' - single_file_in = .false. - perturb_from_single_instance = .false. - init_time_days = -1 - init_time_seconds = -1 - - stages_to_write = 'forecast','output' - - output_state_files = '' - output_state_file_list = 'cam_init_files' - output_mean = .true. - output_sd = .true. - output_members = .true. - num_output_state_members = 80 - single_file_out = .false. - write_all_stages_at_end = .false. - output_interval = 1 - - ens_size = 80 - num_groups = 1 - distributed_state = .true. - - inf_flavor = 5, 0 - inf_initial_from_restart = .true., .false. - inf_initial = 1.0, 1.0 - inf_lower_bound = 0.0, 0.0 - inf_upper_bound = 100.0, 100.0 - inf_sd_initial_from_restart = .true., .false. - inf_sd_initial = 0.6, 0.6 - inf_sd_lower_bound = 0.6, 0.6 - inf_sd_max_change = 1.05, 1.05 - inf_damping = 0.9, 0.9 - inf_deterministic = .true., .true. - - obs_sequence_in_name = 'obs_seq.out' - obs_sequence_out_name = 'obs_seq.final' - num_output_obs_members = 80 - compute_posterior = .true. - - trace_execution = .true. - output_timestamps = .true. - output_forward_op_errors = .false. - silence = .false. - / - - - first_obs_days = -1 - first_obs_seconds = -1 - last_obs_days = -1 - last_obs_seconds = -1 - obs_window_days = -1 - obs_window_seconds = -1 - adv_ens_command = 'no_CESM_advance_script' - tasks_per_model_advance = -1 Used only for models run inside filter. - write_obs_every_cycle = .false. intended for debugging when cycling inside filter. - -&perfect_model_obs_nml - read_input_state_from_file = .true. - input_state_files = "caminput.nc" - init_time_days = -1 - init_time_seconds = -1 - - write_output_state_to_file = .true. - output_state_files = "perfect_restart.nc" - - obs_seq_in_file_name = "obs_seq.in" - obs_seq_out_file_name = "obs_seq.out" - first_obs_days = -1 - first_obs_seconds = -1 - last_obs_days = -1 - last_obs_seconds = -1 - - trace_execution = .true. - output_timestamps = .true. - print_every_nth_obs = 0 - output_forward_op_errors = .false. - / - - - -&model_nml - cam_template_filename = 'caminput.nc' - cam_phis_filename = 'cam_phis.nc' - custom_routine_to_generate_ensemble = .true. - fields_to_perturb = 'QTY_TEMPERATURE', 'QTY_U_WIND_COMPONENT', 'QTY_V_WIND_COMPONENT', 'QTY_SURFACE_PRESSURE' - perturbation_amplitude = 1.0, 1.0, 1.0, 100.0 - state_variables = 'T', 'QTY_TEMPERATURE', 'NA', 'NA', 'UPDATE' - 'US', 'QTY_U_WIND_COMPONENT', 'NA', 'NA', 'UPDATE' - 'VS', 'QTY_V_WIND_COMPONENT', 'NA', 'NA', 'UPDATE' - 'Q', 'QTY_SPECIFIC_HUMIDITY', 'NA', 'NA', 'UPDATE' - 'CLDLIQ','QTY_CLOUD_LIQUID_WATER', 'NA', 'NA', 'UPDATE' - 'CLDICE','QTY_CLOUD_ICE', 'NA', 'NA', 'UPDATE' - 'PS', 'QTY_SURFACE_PRESSURE', 'NA', 'NA', 'UPDATE' - use_log_vertical_scale = .true. - use_variable_mean_mass = .false. - no_normalization_of_scale_heights = .true. - vertical_localization_coord = 'SCALEHEIGHT' - no_obs_assim_above_level = 5 - model_damping_ends_at_level = -1 - using_chemistry = .false. - assimilation_period_days = 0 - assimilation_period_seconds = 21600 - suppress_grid_info_in_output = .false. - debug_level = 0 - / - -&location_nml - horiz_dist_only = .false. - vert_normalization_pressure = 20000.0 - vert_normalization_height = 10000.0 - vert_normalization_level = 20.0 - vert_normalization_scale_height = 1.5 - approximate_distance = .true. - nlon = 283 - nlat = 144 - output_box_info = .false. - print_box_level = 0 - special_vert_normalization_obs_types = 'null' - special_vert_normalization_pressures = -888888.0 - special_vert_normalization_heights = -888888.0 - special_vert_normalization_levels = -888888.0 - special_vert_normalization_scale_heights = -888888.0 - / - - -&fill_inflation_restart_nml - write_prior_inf = .true. - prior_inf_mean = 1.01 - prior_inf_sd = 0.6 - - write_post_inf = .false. - post_inf_mean = 1.00 - post_inf_sd = 0.6 - - input_state_files = 'caminput.nc' - single_file = .false. - - verbose = .false. - / - - -&preprocess_nml - overwrite_output = .true. - input_obs_qty_mod_file = '../../../assimilation_code/modules/observations/DEFAULT_obs_kind_mod.F90' - output_obs_qty_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' - obs_type_files = '../../../observations/forward_operators/obs_def_gps_mod.f90', - '../../../observations/forward_operators/obs_def_upper_atm_mod.f90', - '../../../observations/forward_operators/obs_def_reanalysis_bufr_mod.f90', - '../../../observations/forward_operators/obs_def_altimeter_mod.f90', - '../../../observations/forward_operators/obs_def_AIRS_mod.f90' - quantity_files = '../../../assimilation_code/modules/observations/atmosphere_quantities_mod.f90', - '../../../assimilation_code/modules/observations/space_quantities_mod.f90', - '../../../assimilation_code/modules/observations/chemistry_quantities_mod.f90' - '../../../assimilation_code/modules/observations/default_quantities_mod.f90' - - -&obs_kind_nml - assimilate_these_obs_types = 'RADIOSONDE_U_WIND_COMPONENT', - 'RADIOSONDE_V_WIND_COMPONENT', - 'RADIOSONDE_TEMPERATURE', - 'AIRCRAFT_U_WIND_COMPONENT', - 'AIRCRAFT_V_WIND_COMPONENT', - 'AIRCRAFT_TEMPERATURE', - 'ACARS_U_WIND_COMPONENT', - 'ACARS_V_WIND_COMPONENT', - 'ACARS_TEMPERATURE', - 'SAT_U_WIND_COMPONENT', - 'SAT_V_WIND_COMPONENT', - 'GPSRO_REFRACTIVITY', - 'AIRS_TEMPERATURE' - 'AIRS_SPECIFIC_HUMIDITY' - 'RADIOSONDE_SPECIFIC_HUMIDITY' - evaluate_these_obs_types = - 'RADIOSONDE_SURFACE_ALTIMETER', - 'MARINE_SFC_ALTIMETER', - 'LAND_SFC_ALTIMETER' - use_precomputed_FOs_these_obs_types = 'null' - / - - -&state_vector_io_nml - buffer_state_io = .false. - single_precision_output = .false. - / - - - -&ensemble_manager_nml - layout = 2 - tasks_per_node = 36 - communication_configuration = 1 - debug = .false. - / - - -&assim_tools_nml - use_algorithm_info_mod = .true. - filter_kind = 1 - cutoff = 0.15 - sort_obs_inc = .false. - spread_restoration = .false. - sampling_error_correction = .true. - adaptive_localization_threshold = -1 - adaptive_cutoff_floor = 0.0 - output_localization_diagnostics = .false. - localization_diagnostics_file = 'localization_diagnostics' - rectangular_quadrature = .true. - gaussian_likelihood_tails = .false. - close_obs_caching = .true. - adjust_obs_impact = .false. - obs_impact_filename = "" - allow_any_impact_values = .false. - convert_all_obs_verticals_first = .true. - convert_all_state_verticals_first = .true. - special_localization_obs_types = 'null' - special_localization_cutoffs = -888888.0 - print_every_nth_obs = 10000 - distribute_mean = .false. - / - - -&cov_cutoff_nml - select_localization = 1 - / - - -®_factor_nml - select_regression = 1 - input_reg_file = 'time_mean_reg' - save_reg_diagnostics = .false. - reg_diagnostics_file = 'reg_diagnostics' - / - - -&obs_sequence_nml - write_binary_obs_sequence = .true. - read_binary_file_format = 'native' - / - - -&quality_control_nml - input_qc_threshold = 3.0 - outlier_threshold = 3.0 - enable_special_outlier_code = .false. - / - - -&xyz_location_nml - / - - -&utilities_nml - TERMLEVEL = 2 - module_details = .false. - logfilename = 'dart_log.out' - nmlfilename = 'dart_log.nml' - print_debug = .false. - write_nml = 'file' - / - - -&mpi_utilities_nml - reverse_task_layout = .false. - all_tasks_print = .false. - verbose = .false. - async2_verbose = .false. - async4_verbose = .false. - shell_name = '' - separate_node_sync = .false. - create_local_comm = .true. - make_copy_before_sendrecv = .false. - / - - -&obs_def_gps_nml - max_gpsro_obs = 15000000 - / - - - - - -&obs_sequence_tool_nml - num_input_files = 2 - filename_seq = 'obs_seq.one', 'obs_seq.two' - filename_out = 'obs_seq.processed' - first_obs_days = -1 - first_obs_seconds = -1 - last_obs_days = -1 - last_obs_seconds = -1 - min_lat = -90.0 - max_lat = 90.0 - min_lon = 0.0 - max_lon = 360.0 - gregorian_cal = .true. - print_only = .false. - / - - -&obs_common_subset_nml - num_to_compare_at_once = 2 - filename_seq = '' - filename_seq_list = '' - filename_out_suffix = '.common' - print_only = .false. - print_every = 10000 - calendar = 'Gregorian' - dart_qc_threshold = 3 - eval_and_assim_can_match = .false. - / - - -&obs_impact_tool_nml - input_filename = 'cross_correlations.txt' - output_filename = 'control_impact_runtime.txt' - debug = .false. - / - - -&smoother_nml - num_lags = 0 - start_from_restart = .false. - output_restart = .false. - restart_in_file_name = 'smoother_ics' - restart_out_file_name = 'smoother_restart' - / - - - - -&obs_diag_nml - obs_sequence_name = 'obs_seq.final' - obs_sequence_list = '' - first_bin_center = BOGUS_YEAR, 1, 1, 0, 0, 0 - last_bin_center = BOGUS_YEAR, 1, 2, 0, 0, 0 - bin_separation = 0, 0, 0, 6, 0, 0 - bin_width = 0, 0, 0, 6, 0, 0 - time_to_skip = 0, 0, 1, 0, 0, 0 - max_num_bins = 1000 - trusted_obs = 'null' - plevel_edges = 1036.5, 962.5, 887.5, 775, 600, 450, 350, 275, 225, 175, 125, 75, 35, 15, 2 - hlevel_edges = 200, 630, 930, 1880,3670,5680,7440,9130,10530,12290, 14650,18220,23560,29490,43000 - Nregions = 3 - reg_names = 'Northern Hemisphere', 'Tropics', 'Southern Hemisphere' - lonlim1 = 0.0, 0.0, 0.0 - lonlim2 = 360.0, 360.0, 360.0 - latlim1 = 20.0, -20.0, -90.0 - latlim2 = 90.0, 20.0, -20.0 - print_mismatched_locs = .false. - create_rank_histogram = .true. - outliers_in_histogram = .true. - use_zero_error_obs = .false. - verbose = .false. - / - - -&schedule_nml - calendar = 'Gregorian' - first_bin_start = 1601, 1, 1, 0, 0, 0 - first_bin_end = 2999, 1, 1, 0, 0, 0 - last_bin_end = 2999, 1, 1, 0, 0, 0 - bin_interval_days = 1000000 - bin_interval_seconds = 0 - max_num_bins = 1000 - print_table = .true. - / - - -&obs_seq_to_netcdf_nml - obs_sequence_name = 'obs_seq.final' - obs_sequence_list = '' - append_to_netcdf = .false. - lonlim1 = 0.0 - lonlim2 = 360.0 - latlim1 = -90.0 - latlim2 = 90.0 - verbose = .false. - / - - -&model_mod_check_nml - input_state_files = 'caminput.nc' - output_state_files = 'mmc_output.nc' - test1thru = 0 - run_tests = 1,2,3,4,5,7 - x_ind = 175001 - - quantity_of_interest = 'QTY_U_WIND_COMPONENT' - loc_of_interest = 254.727854, 39.9768545, 50000.0 - - interp_test_lonrange = 0.0, 360.0 - interp_test_dlon = 1.0 - interp_test_latrange = -90.0, 90.0 - interp_test_dlat = 1.0 - interp_test_vertrange = 10000.0, 90000.0 - interp_test_dvert = 10000.0 - interp_test_vertcoord = 'VERTISPRESSURE' - verbose = .false. - / - - - -&closest_member_tool_nml - input_restart_file_list = 'cam_in.txt' - output_file_name = 'closest_restart' - ens_size = 80 - single_restart_file_in = .false. - difference_method = 4 - use_only_qtys = '' - / - - -&perturb_single_instance_nml - ens_size = 80 - input_files = 'caminput.nc' - output_files = 'cam_pert1.nc','cam_pert2.nc','cam_pert3.nc' - output_file_list = '' - perturbation_amplitude = 0.2 - / - - -&quad_interpolate_nml - debug = 0 - / - From 8b77d1958eefbb6926c3b1e1b641a7f4dda42cb8 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Mon, 30 Oct 2023 14:58:16 -0400 Subject: [PATCH 118/129] docs: sort_obs_inc only applied for ENKF, and default is true --- .../modules/assimilation/assim_tools_mod.nml | 6 ++---- .../modules/assimilation/assim_tools_mod.rst | 9 +++++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.nml b/assimilation_code/modules/assimilation/assim_tools_mod.nml index d33aeead61..6169da563d 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.nml +++ b/assimilation_code/modules/assimilation/assim_tools_mod.nml @@ -8,9 +8,7 @@ # enabling sampling error correction is generally beneficial # the default file is in assimilation_code/programs/gen_sampling_err_table/work -# With a deterministic filter (filter_kind == 1 or 8) -# and a deterministic inflation (filter_nml:inf_deterministic == .true.) -# sort_obs_inc is not needed and is expensive. Should be .false. +# sort_obs_inc applies to ENKF only. # specify special localization items in the same order # in both lists, the same number of items @@ -20,7 +18,7 @@ filter_kind = 1 cutoff = 0.2 distribute_mean = .false. - sort_obs_inc = .false. + sort_obs_inc = .true. spread_restoration = .false. sampling_error_correction = .false. adaptive_localization_threshold = -1 diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.rst b/assimilation_code/modules/assimilation/assim_tools_mod.rst index 88d0923164..d031d8533c 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.rst +++ b/assimilation_code/modules/assimilation/assim_tools_mod.rst @@ -172,7 +172,7 @@ namelist. filter_kind = 1 cutoff = 0.2 distribute_mean = .false. - sort_obs_inc = .false. + sort_obs_inc = .true. spread_restoration = .false. sampling_error_correction = .false. adaptive_localization_threshold = -1 @@ -245,10 +245,11 @@ Description of each namelist entry *type:* logical If true, the final increments from obs_increment are sorted so that the mean increment value is as small as possible. - This minimizes regression errors when non-deterministic filters or error correction algorithms are applied. HOWEVER, - when using deterministic filters (filter_kind == 1 or 8) with no inflation or a combination of a determinstic filter + Applies to ENKF only. + ``sort_ob_inc`` minimizes regression errors when non-deterministic filters or error correction algorithms are applied. HOWEVER, + when using deterministic filters with no inflation or a combination of a determinstic filter and deterministic inflation (filter_nml:inf_deterministic = .TRUE.) sorting the increments is both unnecessary and - expensive. A warning is printed to stdout and the log and the sorting is skipped. + expensive. ``spread_restoration`` *type:* logical From 7ad9f3c04a40940ddaf04c2fad4cf60313569855 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Mon, 30 Oct 2023 15:06:43 -0400 Subject: [PATCH 119/129] doc: spread_restoration not available in this version --- assimilation_code/modules/assimilation/assim_tools_mod.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.rst b/assimilation_code/modules/assimilation/assim_tools_mod.rst index d031d8533c..8ff5026cb3 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.rst +++ b/assimilation_code/modules/assimilation/assim_tools_mod.rst @@ -257,6 +257,11 @@ Description of each namelist entry True turns on algorithm to restore amount of spread that would be expected to be lost if underlying obs/state variable correlation were really 0. +.. Warning:: + + ``spread_restoration`` is not supported in this version, please reach out to the DAReS team dart@ucar.edu + if you need to use spread_restoration. + ``sampling_error_correction`` *type:* logical From c95611e9d4463bc9e21bf13a983bcb975fcb4ba4 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Mon, 30 Oct 2023 15:08:41 -0400 Subject: [PATCH 120/129] doc: grammar --- index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.rst b/index.rst index 1a5f9bf24b..2d20f5b96a 100644 --- a/index.rst +++ b/index.rst @@ -82,7 +82,7 @@ analysis estimates for observed variables, those improvements can be lost when u linear regression of observation increments to update other state variables. The QCEFF also implements a capability to do regression in a probit probability integral transformed space. Doing the regression of observation quantile increments in the transformed space guarantees -that the posterior ensembles for state variables also the advantages of the observation space +that the posterior ensembles for state variables also retain the advantages of the observation space quantile conserving posteriors. For example, if state variables are bounded, then posterior ensembles will respect the bounds. The posterior ensembles also respect other aspects of the continuous prior distributions. See this Monthly Weather Review article for details, From d67be0a02a0db533963b8d95df88d34aaba4d6cc Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Mon, 30 Oct 2023 15:25:37 -0400 Subject: [PATCH 121/129] doc: remove filter_kind from assim_tools_mod namelist info update error message (filter_kind not a namelist option) --- .../modules/assimilation/assim_tools_mod.f90 | 2 +- .../modules/assimilation/assim_tools_mod.rst | 54 +------------------ 2 files changed, 3 insertions(+), 53 deletions(-) diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.f90 b/assimilation_code/modules/assimilation/assim_tools_mod.f90 index ca2f51360e..69da9d12dc 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.f90 +++ b/assimilation_code/modules/assimilation/assim_tools_mod.f90 @@ -1029,7 +1029,7 @@ subroutine obs_increment(ens_in, ens_size, obs, obs_var, obs_kind, obs_inc, & !-------------------------------------------------------------------------- else call error_handler(E_ERR,'obs_increment', & - 'Illegal value of filter_kind in assim_tools namelist [1-8 OK]', source) + 'Illegal value of filter_kind', source) endif endif diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.rst b/assimilation_code/modules/assimilation/assim_tools_mod.rst index 8ff5026cb3..9bbe135059 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.rst +++ b/assimilation_code/modules/assimilation/assim_tools_mod.rst @@ -10,25 +10,6 @@ for both mean and spread. In addition, algorithms to do a variety of flavors of particle filter, and kernel filters are included. The parallel implementation that allows each observation to update all state variables that are close to it at the same time is described in Anderson and Collins, 2007. -Filter types ------------- - -Available observation space filter types include: - -- 1 = EAKF (Ensemble Adjustment Kalman Filter, see Anderson 2001) -- 2 = ENKF (Ensemble Kalman Filter) -- 3 = Kernel filter -- 4 = Observation Space Particle filter -- 5 = Random draw from posterior (contact dart@ucar.edu before using) -- 6 = Deterministic draw from posterior with fixed kurtosis (ditto) -- 7 = Boxcar kernel filter -- 8 = Rank Histogram filter (see Anderson 2010) -- 9 = Particle filter (see Poterjoy 2016) - -We recommend using type=1, the EAKF. Note that although the algorithm is expressed in a slightly different form, the -EAKF is identical to the EnSRF (Ensemble Square Root Filter) described by Whitaker and Hamill in 2002. Highly -non-gaussian distributions may get better results from type=8, Rank Histogram filter. - Localization ------------ @@ -169,7 +150,6 @@ namelist. :: &assim_tools_nml - filter_kind = 1 cutoff = 0.2 distribute_mean = .false. sort_obs_inc = .true. @@ -195,36 +175,6 @@ namelist. Description of each namelist entry ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -``filter_kind`` - *type:* integer - - Selects the variant of filter to be used. - - - 1 = EAKF (Ensemble Adjustment Kalman Filter, see Anderson 2001) - - 2 = ENKF (Ensemble Kalman Filter) - - 3 = Kernel filter - - 4 = Observation Space Particle filter - - 5 = Random draw from posterior (contact dart@ucar.edu before using) - - 6 = Deterministic draw from posterior with fixed kurtosis (ditto) - - 7 = Boxcar kernel filter - - 8 = Rank Histogram filter (see Anderson 2010) - - 9 = Particle filter (see Poterjoy 2016) - - The EAKF is the most commonly used filter. Note that although the algorithm is expressed in a slightly different - form, the EAKF is identical to the EnSRF (Ensemble Square Root Filter) described by Whitaker and Hamill in 2002. - - The Rank Histgram filter can be more successful for highly nongaussian distributions. - - Jon Poterjoy's Particle filter is included with this code release. To use, it, overwrite ``assim_tools_mod.f90`` with - ``assim_tools_mod.pf.f90`` and rebuild filter. - - :: - - - $ mv assimilation_code/modules/assimilation/assim_tools_mod.pf.f90 assimilation_code/modules/assimilation/assim_tools_mod.f90 - - There are additional namelist items in this version specific to the particle filter. Read the code for more details. - ``cutoff`` *type:* real(r8) @@ -313,12 +263,12 @@ Description of each namelist entry ``rectangular_quadrature`` *type:* logical - Only relevant for filter type 8 and recommended to leave ``.true.``. + Only relevant for filter type UNBOUNDED_RHF and recommended to leave ``.true.``. ``gaussian_likelihood_tails`` *type:* logical - Only relevant for filter type 8 and recommended to leave ``.false.``. + Only relevant for filter type UNBOUNDED_RHF and recommended to leave ``.false.``. ``close_obs_caching`` *type:* logical From 254f59a71f92bb180610965767564959d824e415 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Mon, 30 Oct 2023 16:09:55 -0400 Subject: [PATCH 122/129] rename all things qcf to qceff The offical name: Quantile-Conserving Ensemble Filter Framework --- .../assimilation/algorithm_info_mod.f90 | 256 +++++++++--------- .../modules/assimilation/filter_mod.f90 | 8 +- .../modules/assimilation/filter_mod.nml | 2 +- developer_tests/qceff/test_table_read.f90 | 8 +- .../{qcf-examples.rst => qceff-examples.rst} | 30 +- guide/{qcf_probit.rst => qceff_probit.rst} | 22 +- index.rst | 10 +- models/9var/work/input.nml | 2 +- models/FESOM/work/input.nml | 2 +- models/LMDZ/work/input.nml | 2 +- models/MITgcm_annulus/work/input.nml | 2 +- models/MOM6/work/input.nml | 2 +- models/NAAPS/work/input.nml | 2 +- models/NCOMMAS/work/input.nml | 2 +- models/POP/work/input.nml | 2 +- models/ROMS/work/input.nml | 2 +- models/am2/work/input.nml | 2 +- models/bgrid_solo/work/input.nml | 2 +- models/cam-fv/work/input.nml | 2 +- models/cam-se/work/input.nml | 2 +- models/cice/work/input.nml | 2 +- models/clm/work/input.nml | 2 +- models/cm1/work/input.nml | 2 +- .../templates/EXPERIMENT_EXAMPLE/input.nml | 2 +- models/dynamo/work/input.nml | 2 +- models/forced_barot/work/input.nml | 2 +- models/forced_lorenz_96/work/input.nml | 2 +- models/gitm/work/input.nml | 2 +- models/ikeda/work/input.nml | 2 +- models/lorenz_04/work/input.nml | 2 +- models/lorenz_63/work/input.nml | 2 +- models/lorenz_84/work/input.nml | 2 +- models/lorenz_96/work/input.nml | 2 +- models/lorenz_96_2scale/work/input.nml | 2 +- ...cf_table.csv => all_bnrhf_qceff_table.csv} | 0 ...qcf_table.csv => all_eakf_qceff_table.csv} | 0 .../lorenz_96_tracer_advection/work/input.nml | 2 +- ...{neg_qcf_table.csv => neg_qceff_table.csv} | 0 ...> state_eakf_tracer_bnrhf_qceff_table.csv} | 0 models/mpas_atm/work/input.nml | 2 +- models/mpas_ocn/work/input.nml | 2 +- models/noah/work/input.nml | 2 +- models/null_model/work/input.nml | 2 +- models/pe2lyr/work/input.nml | 2 +- models/rose/work/input.nml | 2 +- models/simple_advection/work/input.nml | 2 +- models/sqg/work/input.nml | 2 +- models/template/work/oned_input.nml | 2 +- models/template/work/threed_input.nml | 2 +- models/tiegcm/work/input.nml | 2 +- models/wrf/work/input.nml | 2 +- models/wrf_hydro/work/input.nml | 2 +- 52 files changed, 209 insertions(+), 209 deletions(-) rename guide/{qcf-examples.rst => qceff-examples.rst} (80%) rename guide/{qcf_probit.rst => qceff_probit.rst} (87%) rename models/lorenz_96_tracer_advection/work/{all_bnrhf_qcf_table.csv => all_bnrhf_qceff_table.csv} (100%) rename models/lorenz_96_tracer_advection/work/{all_eakf_qcf_table.csv => all_eakf_qceff_table.csv} (100%) rename models/lorenz_96_tracer_advection/work/{neg_qcf_table.csv => neg_qceff_table.csv} (100%) rename models/lorenz_96_tracer_advection/work/{state_eakf_tracer_bnrhf_qcf_table.csv => state_eakf_tracer_bnrhf_qceff_table.csv} (100%) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 1c65d535e8..5fda240286 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -88,7 +88,7 @@ module algorithm_info_mod character(len=129), dimension(25) :: header2 ! Number of table columns plus 1 integer, allocatable :: specified_qtys(:) -type(algorithm_info_type), allocatable :: qcf_table_data(:) +type(algorithm_info_type), allocatable :: qceff_table_data(:) character(len=129), allocatable :: dist_type_string_probit_inflation(:) character(len=129), allocatable :: dist_type_string_probit_state(:) @@ -100,11 +100,11 @@ module algorithm_info_mod !------------------------------------------------------------------------- -subroutine init_algorithm_info_mod(qcf_table_filename) +subroutine init_algorithm_info_mod(qceff_table_filename) ! Gets number of lines/QTYs in the QCF table, allocates space for the table data -character(len=129), intent(in) :: qcf_table_filename +character(len=129), intent(in) :: qceff_table_filename integer :: fileid integer :: io @@ -115,14 +115,14 @@ subroutine init_algorithm_info_mod(qcf_table_filename) if (module_initialized) return module_initialized = .true. -if (qcf_table_filename == '') then +if (qceff_table_filename == '') then write(errstring,*) 'No QCF table file listed in namelist, using default values for all QTYs' call error_handler(E_MSG, 'init_algorithm_info_mod:', errstring, source) return endif use_qty_defaults = .false. -fileid = open_file(trim(qcf_table_filename), 'formatted', 'read') +fileid = open_file(trim(qceff_table_filename), 'formatted', 'read') ! Do loop to get number of rows (or QTYs) in the table nlines = 0 @@ -137,139 +137,139 @@ subroutine init_algorithm_info_mod(qcf_table_filename) numrows = nlines - HEADER_LINES allocate(specified_qtys(numrows)) -allocate(qcf_table_data(numrows)) +allocate(qceff_table_data(numrows)) allocate(dist_type_string_probit_inflation(numrows)) allocate(dist_type_string_probit_state(numrows)) allocate(dist_type_string_probit_extended_state(numrows)) allocate(filter_kind_string(numrows)) -call read_qcf_table(qcf_table_filename) -call assert_qcf_table_version() -call verify_qcf_table_data() -call log_qcf_table_data() +call read_qceff_table(qceff_table_filename) +call assert_qceff_table_version() +call verify_qceff_table_data() +call log_qceff_table_data() end subroutine init_algorithm_info_mod !------------------------------------------------------------------------ -subroutine read_qcf_table(qcf_table_filename) +subroutine read_qceff_table(qceff_table_filename) ! Reads in the QCEFF input options from tabular data file -character(len=129), intent(in) :: qcf_table_filename +character(len=129), intent(in) :: qceff_table_filename integer :: fileid integer :: row character(len=obstypelength) :: qty_string -if (.not. module_initialized) call init_algorithm_info_mod(qcf_table_filename) +if (.not. module_initialized) call init_algorithm_info_mod(qceff_table_filename) -fileid = open_file(trim(qcf_table_filename), 'formatted', 'read') +fileid = open_file(trim(qceff_table_filename), 'formatted', 'read') ! skip the headers read(fileid, *) header1 read(fileid, *) header2 -! read in table values directly to qcf_table_data type -do row = 1, size(qcf_table_data) - read(fileid, *) qty_string, qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & - qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, dist_type_string_probit_inflation(row), & - qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & - qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, dist_type_string_probit_state(row), & - qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & - qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, dist_type_string_probit_extended_state(row), & - qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & - qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - filter_kind_string(row), qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & - qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound +! read in table values directly to qceff_table_data type +do row = 1, size(qceff_table_data) + read(fileid, *) qty_string, qceff_table_data(row)%obs_error_info%bounded_below, qceff_table_data(row)%obs_error_info%bounded_above, & + qceff_table_data(row)%obs_error_info%lower_bound, qceff_table_data(row)%obs_error_info%upper_bound, dist_type_string_probit_inflation(row), & + qceff_table_data(row)%probit_inflation%bounded_below, qceff_table_data(row)%probit_inflation%bounded_above, & + qceff_table_data(row)%probit_inflation%lower_bound, qceff_table_data(row)%probit_inflation%upper_bound, dist_type_string_probit_state(row), & + qceff_table_data(row)%probit_state%bounded_below, qceff_table_data(row)%probit_state%bounded_above, & + qceff_table_data(row)%probit_state%lower_bound, qceff_table_data(row)%probit_state%upper_bound, dist_type_string_probit_extended_state(row), & + qceff_table_data(row)%probit_extended_state%bounded_below, qceff_table_data(row)%probit_extended_state%bounded_above, & + qceff_table_data(row)%probit_extended_state%lower_bound, qceff_table_data(row)%probit_extended_state%upper_bound, & + filter_kind_string(row), qceff_table_data(row)%obs_inc_info%bounded_below, qceff_table_data(row)%obs_inc_info%bounded_above, & + qceff_table_data(row)%obs_inc_info%lower_bound, qceff_table_data(row)%obs_inc_info%upper_bound specified_qtys(row) = get_index_for_quantity(qty_string) if(specified_qtys(row) == -1) then write(errstring,*) trim(qty_string), ' is not a valid DART QTY' - call error_handler(E_ERR, 'read_qcf_table:', errstring, source) + call error_handler(E_ERR, 'read_qceff_table:', errstring, source) endif ! Converting the distribution types (read in from table as a string) to its corresponding int value if (trim(dist_type_string_probit_inflation(row)) == 'NORMAL_DISTRIBUTION') then - qcf_table_data(row)%probit_inflation%dist_type = NORMAL_DISTRIBUTION + qceff_table_data(row)%probit_inflation%dist_type = NORMAL_DISTRIBUTION elseif (trim(dist_type_string_probit_inflation(row)) == 'BOUNDED_NORMAL_RH_DISTRIBUTION') then - qcf_table_data(row)%probit_inflation%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION + qceff_table_data(row)%probit_inflation%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION elseif (trim(dist_type_string_probit_inflation(row)) == 'GAMMA_DISTRIBUTION') then - qcf_table_data(row)%probit_inflation%dist_type = GAMMA_DISTRIBUTION + qceff_table_data(row)%probit_inflation%dist_type = GAMMA_DISTRIBUTION elseif (trim(dist_type_string_probit_inflation(row)) == 'BETA_DISTRIBUTION') then - qcf_table_data(row)%probit_inflation%dist_type = BETA_DISTRIBUTION + qceff_table_data(row)%probit_inflation%dist_type = BETA_DISTRIBUTION elseif (trim(dist_type_string_probit_inflation(row)) == 'LOG_NORMAL_DISTRIBUTION') then - qcf_table_data(row)%probit_inflation%dist_type = LOG_NORMAL_DISTRIBUTION + qceff_table_data(row)%probit_inflation%dist_type = LOG_NORMAL_DISTRIBUTION elseif (trim(dist_type_string_probit_inflation(row)) == 'UNIFORM_DISTRIBUTION') then - qcf_table_data(row)%probit_inflation%dist_type = UNIFORM_DISTRIBUTION + qceff_table_data(row)%probit_inflation%dist_type = UNIFORM_DISTRIBUTION elseif (trim(dist_type_string_probit_inflation(row)) == 'PARTICLE_FILTER_DISTRIBUTION') then - qcf_table_data(row)%probit_inflation%dist_type = PARTICLE_FILTER_DISTRIBUTION + qceff_table_data(row)%probit_inflation%dist_type = PARTICLE_FILTER_DISTRIBUTION else write(errstring, *) 'Invalid distribution type for probit inflation: ', trim(dist_type_string_probit_inflation(row)) - call error_handler(E_ERR, 'read_qcf_table:', errstring, source) + call error_handler(E_ERR, 'read_qceff_table:', errstring, source) endif if (trim(dist_type_string_probit_state(row)) == 'NORMAL_DISTRIBUTION') then - qcf_table_data(row)%probit_state%dist_type = NORMAL_DISTRIBUTION + qceff_table_data(row)%probit_state%dist_type = NORMAL_DISTRIBUTION elseif (trim(dist_type_string_probit_state(row)) == 'BOUNDED_NORMAL_RH_DISTRIBUTION') then - qcf_table_data(row)%probit_state%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION + qceff_table_data(row)%probit_state%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION elseif (trim(dist_type_string_probit_state(row)) == 'GAMMA_DISTRIBUTION') then - qcf_table_data(row)%probit_state%dist_type = GAMMA_DISTRIBUTION + qceff_table_data(row)%probit_state%dist_type = GAMMA_DISTRIBUTION elseif (trim(dist_type_string_probit_state(row)) == 'BETA_DISTRIBUTION') then - qcf_table_data(row)%probit_state%dist_type = BETA_DISTRIBUTION + qceff_table_data(row)%probit_state%dist_type = BETA_DISTRIBUTION elseif (trim(dist_type_string_probit_state(row)) == 'LOG_NORMAL_DISTRIBUTION') then - qcf_table_data(row)%probit_state%dist_type = LOG_NORMAL_DISTRIBUTION + qceff_table_data(row)%probit_state%dist_type = LOG_NORMAL_DISTRIBUTION elseif (trim(dist_type_string_probit_state(row)) == 'UNIFORM_DISTRIBUTION') then - qcf_table_data(row)%probit_state%dist_type = UNIFORM_DISTRIBUTION + qceff_table_data(row)%probit_state%dist_type = UNIFORM_DISTRIBUTION elseif (trim(dist_type_string_probit_state(row)) == 'PARTICLE_FILTER_DISTRIBUTION') then - qcf_table_data(row)%probit_state%dist_type = PARTICLE_FILTER_DISTRIBUTION + qceff_table_data(row)%probit_state%dist_type = PARTICLE_FILTER_DISTRIBUTION else write(errstring, *) 'Invalid distribution type for probit state: ', trim(dist_type_string_probit_state(row)) - call error_handler(E_ERR, 'read_qcf_table:', errstring, source) + call error_handler(E_ERR, 'read_qceff_table:', errstring, source) endif if (trim(dist_type_string_probit_extended_state(row)) == 'NORMAL_DISTRIBUTION') then - qcf_table_data(row)%probit_extended_state%dist_type = NORMAL_DISTRIBUTION + qceff_table_data(row)%probit_extended_state%dist_type = NORMAL_DISTRIBUTION elseif (trim(dist_type_string_probit_extended_state(row)) == 'BOUNDED_NORMAL_RH_DISTRIBUTION') then - qcf_table_data(row)%probit_extended_state%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION + qceff_table_data(row)%probit_extended_state%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION elseif (trim(dist_type_string_probit_extended_state(row)) == 'GAMMA_DISTRIBUTION') then - qcf_table_data(row)%probit_extended_state%dist_type = GAMMA_DISTRIBUTION + qceff_table_data(row)%probit_extended_state%dist_type = GAMMA_DISTRIBUTION elseif (trim(dist_type_string_probit_extended_state(row)) == 'BETA_DISTRIBUTION') then - qcf_table_data(row)%probit_extended_state%dist_type = BETA_DISTRIBUTION + qceff_table_data(row)%probit_extended_state%dist_type = BETA_DISTRIBUTION elseif (trim(dist_type_string_probit_extended_state(row)) == 'LOG_NORMAL_DISTRIBUTION') then - qcf_table_data(row)%probit_extended_state%dist_type = LOG_NORMAL_DISTRIBUTION + qceff_table_data(row)%probit_extended_state%dist_type = LOG_NORMAL_DISTRIBUTION elseif (trim(dist_type_string_probit_extended_state(row)) == 'UNIFORM_DISTRIBUTION') then - qcf_table_data(row)%probit_extended_state%dist_type = UNIFORM_DISTRIBUTION + qceff_table_data(row)%probit_extended_state%dist_type = UNIFORM_DISTRIBUTION elseif (trim(dist_type_string_probit_extended_state(row)) == 'PARTICLE_FILTER_DISTRIBUTION') then - qcf_table_data(row)%probit_extended_state%dist_type = PARTICLE_FILTER_DISTRIBUTION + qceff_table_data(row)%probit_extended_state%dist_type = PARTICLE_FILTER_DISTRIBUTION else write(errstring, *) 'Invalid distribution type for probit extended state: ', trim(dist_type_string_probit_extended_state(row)) - call error_handler(E_ERR, 'read_qcf_table:', errstring, source) + call error_handler(E_ERR, 'read_qceff_table:', errstring, source) endif ! Converting the filter kind (read in from table as a string) to its corresponding int value if (trim(filter_kind_string(row)) == 'EAKF') then - qcf_table_data(row)%obs_inc_info%filter_kind = EAKF + qceff_table_data(row)%obs_inc_info%filter_kind = EAKF elseif (trim(filter_kind_string(row)) == 'ENKF') then - qcf_table_data(row)%obs_inc_info%filter_kind = ENKF + qceff_table_data(row)%obs_inc_info%filter_kind = ENKF elseif (trim(filter_kind_string(row)) == 'UNBOUNDED_RHF') then - qcf_table_data(row)%obs_inc_info%filter_kind = UNBOUNDED_RHF + qceff_table_data(row)%obs_inc_info%filter_kind = UNBOUNDED_RHF elseif (trim(filter_kind_string(row)) == 'GAMMA_FILTER') then - qcf_table_data(row)%obs_inc_info%filter_kind = GAMMA_FILTER + qceff_table_data(row)%obs_inc_info%filter_kind = GAMMA_FILTER elseif (trim(filter_kind_string(row)) == 'BOUNDED_NORMAL_RHF') then - qcf_table_data(row)%obs_inc_info%filter_kind = BOUNDED_NORMAL_RHF + qceff_table_data(row)%obs_inc_info%filter_kind = BOUNDED_NORMAL_RHF else write(errstring, *) 'Invalid filter kind: ', trim(filter_kind_string(row)) - call error_handler(E_ERR, 'read_qcf_table:', errstring, source) + call error_handler(E_ERR, 'read_qceff_table:', errstring, source) endif end do call close_file(fileid) -end subroutine read_qcf_table +end subroutine read_qceff_table !------------------------------------------------------------------------ @@ -303,14 +303,14 @@ subroutine obs_error_info(obs_def, error_variance, & ! Get the default error variance error_variance = get_obs_def_error_variance(obs_def) -!use default values if qcf_table_filename is not in namelist +!use default values if qceff_table_filename is not in namelist if (use_qty_defaults) then bounded_below = .false.; bounded_above = .false. lower_bound = MISSING_R8; upper_bound = MISSING_R8 return endif -!find location of QTY in qcf_table_data structure +!find location of QTY in qceff_table_data structure QTY_loc = findloc(specified_qtys, obs_qty) if (QTY_loc(1) == 0) then @@ -319,10 +319,10 @@ subroutine obs_error_info(obs_def, error_variance, & lower_bound = MISSING_R8; upper_bound = MISSING_R8 else - bounded_below = qcf_table_data(QTY_loc(1))%obs_error_info%bounded_below - bounded_above = qcf_table_data(QTY_loc(1))%obs_error_info%bounded_above - lower_bound = qcf_table_data(QTY_loc(1))%obs_error_info%lower_bound - upper_bound = qcf_table_data(QTY_loc(1))%obs_error_info%upper_bound + bounded_below = qceff_table_data(QTY_loc(1))%obs_error_info%bounded_below + bounded_above = qceff_table_data(QTY_loc(1))%obs_error_info%bounded_above + lower_bound = qceff_table_data(QTY_loc(1))%obs_error_info%lower_bound + upper_bound = qceff_table_data(QTY_loc(1))%obs_error_info%upper_bound endif @@ -361,7 +361,7 @@ subroutine probit_dist_info(qty, is_state, is_inflation, dist_type, & ! In the long run, may not have to have separate controls for each of the input possibilities ! However, for now these are things that need to be explored for science understanding -!use default values if qcf_table_filename is not in namelist +!use default values if qceff_table_filename is not in namelist if (use_qty_defaults) then dist_type = NORMAL_DISTRIBUTION bounded_below = .false.; bounded_above = .false. @@ -380,29 +380,29 @@ subroutine probit_dist_info(qty, is_state, is_inflation, dist_type, & elseif(is_inflation) then ! Case for inflation transformation - dist_type = qcf_table_data(QTY_loc(1))%probit_inflation%dist_type - bounded_below = qcf_table_data(QTY_loc(1))%probit_inflation%bounded_below - bounded_above = qcf_table_data(QTY_loc(1))%probit_inflation%bounded_above - lower_bound = qcf_table_data(QTY_loc(1))%probit_inflation%lower_bound - upper_bound = qcf_table_data(QTY_loc(1))%probit_inflation%upper_bound + dist_type = qceff_table_data(QTY_loc(1))%probit_inflation%dist_type + bounded_below = qceff_table_data(QTY_loc(1))%probit_inflation%bounded_below + bounded_above = qceff_table_data(QTY_loc(1))%probit_inflation%bounded_above + lower_bound = qceff_table_data(QTY_loc(1))%probit_inflation%lower_bound + upper_bound = qceff_table_data(QTY_loc(1))%probit_inflation%upper_bound elseif(is_state) then ! Case for state variable priors - dist_type = qcf_table_data(QTY_loc(1))%probit_state%dist_type - bounded_below = qcf_table_data(QTY_loc(1))%probit_state%bounded_below - bounded_above = qcf_table_data(QTY_loc(1))%probit_state%bounded_above - lower_bound = qcf_table_data(QTY_loc(1))%probit_state%lower_bound - upper_bound = qcf_table_data(QTY_loc(1))%probit_state%upper_bound + dist_type = qceff_table_data(QTY_loc(1))%probit_state%dist_type + bounded_below = qceff_table_data(QTY_loc(1))%probit_state%bounded_below + bounded_above = qceff_table_data(QTY_loc(1))%probit_state%bounded_above + lower_bound = qceff_table_data(QTY_loc(1))%probit_state%lower_bound + upper_bound = qceff_table_data(QTY_loc(1))%probit_state%upper_bound else ! This case is for observation (extended state) priors - dist_type = qcf_table_data(QTY_loc(1))%probit_extended_state%dist_type - bounded_below = qcf_table_data(QTY_loc(1))%probit_extended_state%bounded_below - bounded_above = qcf_table_data(QTY_loc(1))%probit_extended_state%bounded_above - lower_bound = qcf_table_data(QTY_loc(1))%probit_extended_state%lower_bound - upper_bound = qcf_table_data(QTY_loc(1))%probit_extended_state%upper_bound + dist_type = qceff_table_data(QTY_loc(1))%probit_extended_state%dist_type + bounded_below = qceff_table_data(QTY_loc(1))%probit_extended_state%bounded_below + bounded_above = qceff_table_data(QTY_loc(1))%probit_extended_state%bounded_above + lower_bound = qceff_table_data(QTY_loc(1))%probit_extended_state%lower_bound + upper_bound = qceff_table_data(QTY_loc(1))%probit_extended_state%upper_bound endif @@ -421,7 +421,7 @@ subroutine obs_inc_info(obs_qty, filter_kind, bounded_below, bounded_above, & integer :: QTY_loc(1) -!use default values if qcf_table_filename is not in namelist +!use default values if qceff_table_filename is not in namelist if (use_qty_defaults) then filter_kind = EAKF bounded_below = .false.; bounded_above = .false. @@ -429,7 +429,7 @@ subroutine obs_inc_info(obs_qty, filter_kind, bounded_below, bounded_above, & return endif -!find location of QTY in qcf_table_data structure +!find location of QTY in qceff_table_data structure QTY_loc = findloc(specified_qtys, obs_qty) if (QTY_loc(1) == 0) then @@ -440,11 +440,11 @@ subroutine obs_inc_info(obs_qty, filter_kind, bounded_below, bounded_above, & else - filter_kind = qcf_table_data(QTY_loc(1))%obs_inc_info%filter_kind - bounded_below = qcf_table_data(QTY_loc(1))%obs_inc_info%bounded_below - bounded_above = qcf_table_data(QTY_loc(1))%obs_inc_info%bounded_above - lower_bound = qcf_table_data(QTY_loc(1))%obs_inc_info%lower_bound - upper_bound = qcf_table_data(QTY_loc(1))%obs_inc_info%upper_bound + filter_kind = qceff_table_data(QTY_loc(1))%obs_inc_info%filter_kind + bounded_below = qceff_table_data(QTY_loc(1))%obs_inc_info%bounded_below + bounded_above = qceff_table_data(QTY_loc(1))%obs_inc_info%bounded_above + lower_bound = qceff_table_data(QTY_loc(1))%obs_inc_info%lower_bound + upper_bound = qceff_table_data(QTY_loc(1))%obs_inc_info%upper_bound endif @@ -453,7 +453,7 @@ end subroutine obs_inc_info !------------------------------------------------------------------------ -subroutine assert_qcf_table_version() +subroutine assert_qceff_table_version() ! Subroutine to ensure the correct version of the QCF table is being used @@ -461,15 +461,15 @@ subroutine assert_qcf_table_version() if (trim(header1(4)) /= QCF_VERSION) then write(errstring,*) 'Using outdated/incorrect version of the QCF table' - call error_handler(E_ERR, 'assert_qcf_table_version:', errstring, source) + call error_handler(E_ERR, 'assert_qceff_table_version:', errstring, source) endif -end subroutine assert_qcf_table_version +end subroutine assert_qceff_table_version !------------------------------------------------------------------------ -subroutine verify_qcf_table_data() +subroutine verify_qceff_table_data() ! Subroutine to ensure that the data in the QCF table is valid @@ -479,55 +479,55 @@ subroutine verify_qcf_table_data() !Checks that all bounds are valid; currently checks that the lower bound in less than the upper !Here we could add more specific checks if we have known limits on the bounds -do row = 1, size(qcf_table_data) +do row = 1, size(qceff_table_data) - if (qcf_table_data(row)%obs_error_info%bounded_below .and. qcf_table_data(row)%obs_error_info%bounded_above) then - if(qcf_table_data(row)%obs_error_info%lower_bound > qcf_table_data(row)%obs_error_info%upper_bound) then + if (qceff_table_data(row)%obs_error_info%bounded_below .and. qceff_table_data(row)%obs_error_info%bounded_above) then + if(qceff_table_data(row)%obs_error_info%lower_bound > qceff_table_data(row)%obs_error_info%upper_bound) then write(errstring,*) 'Invalid bounds in obs_error_info' - call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) + call error_handler(E_ERR, 'verify_qceff_table_data:', errstring, source) endif endif - if (qcf_table_data(row)%probit_inflation%bounded_below .and. qcf_table_data(row)%probit_inflation%bounded_above) then - if(qcf_table_data(row)%probit_inflation%lower_bound > qcf_table_data(row)%probit_inflation%upper_bound) then + if (qceff_table_data(row)%probit_inflation%bounded_below .and. qceff_table_data(row)%probit_inflation%bounded_above) then + if(qceff_table_data(row)%probit_inflation%lower_bound > qceff_table_data(row)%probit_inflation%upper_bound) then write(errstring,*) 'Invalid bounds in probit_inflation' - call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) + call error_handler(E_ERR, 'verify_qceff_table_data:', errstring, source) endif endif - if(qcf_table_data(row)%probit_state%bounded_below .and. qcf_table_data(row)%probit_state%bounded_above) then - if(qcf_table_data(row)%probit_state%lower_bound > qcf_table_data(row)%probit_state%upper_bound) then + if(qceff_table_data(row)%probit_state%bounded_below .and. qceff_table_data(row)%probit_state%bounded_above) then + if(qceff_table_data(row)%probit_state%lower_bound > qceff_table_data(row)%probit_state%upper_bound) then write(errstring,*) 'Invalid bounds in probit_state' - call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) + call error_handler(E_ERR, 'verify_qceff_table_data:', errstring, source) endif endif - if(qcf_table_data(row)%probit_extended_state%bounded_below .and. qcf_table_data(row)%probit_extended_state%bounded_above) then - if(qcf_table_data(row)%probit_extended_state%lower_bound > qcf_table_data(row)%probit_extended_state%upper_bound) then + if(qceff_table_data(row)%probit_extended_state%bounded_below .and. qceff_table_data(row)%probit_extended_state%bounded_above) then + if(qceff_table_data(row)%probit_extended_state%lower_bound > qceff_table_data(row)%probit_extended_state%upper_bound) then write(errstring,*) 'Invalid bounds in probit_extended_state' - call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) + call error_handler(E_ERR, 'verify_qceff_table_data:', errstring, source) endif endif - if(qcf_table_data(row)%obs_inc_info%bounded_below .and. qcf_table_data(row)%obs_inc_info%bounded_above) then - if(qcf_table_data(row)%obs_inc_info%lower_bound > qcf_table_data(row)%obs_inc_info%upper_bound) then + if(qceff_table_data(row)%obs_inc_info%bounded_below .and. qceff_table_data(row)%obs_inc_info%bounded_above) then + if(qceff_table_data(row)%obs_inc_info%lower_bound > qceff_table_data(row)%obs_inc_info%upper_bound) then write(errstring,*) 'Invalid bounds in obs_inc_info' - call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) + call error_handler(E_ERR, 'verify_qceff_table_data:', errstring, source) endif endif end do !Ensures that there are no duplicate QTYs in the table -do row = 1, size(qcf_table_data) +do row = 1, size(qceff_table_data) if(count(specified_qtys==specified_qtys(row)) > 1) then write(errstring,*) trim(get_name_for_quantity(specified_qtys(row))), ' has multiple entries in the table' - call error_handler(E_ERR, 'verify_qcf_table_data:', errstring, source) + call error_handler(E_ERR, 'verify_qceff_table_data:', errstring, source) endif end do -end subroutine verify_qcf_table_data +end subroutine verify_qceff_table_data !------------------------------------------------------------------------ -subroutine log_qcf_table_data() +subroutine log_qceff_table_data() ! Subroutine to write the data in QCF table to dart_log character(len=2000) :: log_msg @@ -536,33 +536,33 @@ subroutine log_qcf_table_data() if (use_qty_defaults) return call error_handler(E_MSG, '', '', source) !Writing blank line to log -call error_handler(E_MSG, 'log_qcf_table_data:', 'Logging the data in the QCF Table', source) +call error_handler(E_MSG, 'log_qceff_table_data:', 'Logging the data in the QCF Table', source) ! Write the table headers to the dart_log and terminal write(log_msg, '(A4, A6, A9, A)') header1(:) -call error_handler(E_MSG, 'log_qcf_table_data:', trim(log_msg), source) +call error_handler(E_MSG, 'log_qceff_table_data:', trim(log_msg), source) write(log_msg,'(3A14, 2A12, 3(A10, 2A14, 2A12), A12, 2A14, 2A12)') header2(:) -call error_handler(E_MSG, 'log_qcf_table_data:', trim(log_msg), source) +call error_handler(E_MSG, 'log_qceff_table_data:', trim(log_msg), source) ! Write the table data to the dart_log and terminal -do row = 1, size(qcf_table_data) - write(log_msg, *) trim(get_name_for_quantity(specified_qtys(row))), qcf_table_data(row)%obs_error_info%bounded_below, qcf_table_data(row)%obs_error_info%bounded_above, & - qcf_table_data(row)%obs_error_info%lower_bound, qcf_table_data(row)%obs_error_info%upper_bound, trim(dist_type_string_probit_inflation(row)), & - qcf_table_data(row)%probit_inflation%bounded_below, qcf_table_data(row)%probit_inflation%bounded_above, & - qcf_table_data(row)%probit_inflation%lower_bound, qcf_table_data(row)%probit_inflation%upper_bound, trim(dist_type_string_probit_state(row)), & - qcf_table_data(row)%probit_state%bounded_below, qcf_table_data(row)%probit_state%bounded_above, & - qcf_table_data(row)%probit_state%lower_bound, qcf_table_data(row)%probit_state%upper_bound, trim(dist_type_string_probit_extended_state(row)), & - qcf_table_data(row)%probit_extended_state%bounded_below, qcf_table_data(row)%probit_extended_state%bounded_above, & - qcf_table_data(row)%probit_extended_state%lower_bound, qcf_table_data(row)%probit_extended_state%upper_bound, & - trim(filter_kind_string(row)), qcf_table_data(row)%obs_inc_info%bounded_below, qcf_table_data(row)%obs_inc_info%bounded_above, & - qcf_table_data(row)%obs_inc_info%lower_bound, qcf_table_data(row)%obs_inc_info%upper_bound -call error_handler(E_MSG, 'log_qcf_table_data:', trim(log_msg), source) +do row = 1, size(qceff_table_data) + write(log_msg, *) trim(get_name_for_quantity(specified_qtys(row))), qceff_table_data(row)%obs_error_info%bounded_below, qceff_table_data(row)%obs_error_info%bounded_above, & + qceff_table_data(row)%obs_error_info%lower_bound, qceff_table_data(row)%obs_error_info%upper_bound, trim(dist_type_string_probit_inflation(row)), & + qceff_table_data(row)%probit_inflation%bounded_below, qceff_table_data(row)%probit_inflation%bounded_above, & + qceff_table_data(row)%probit_inflation%lower_bound, qceff_table_data(row)%probit_inflation%upper_bound, trim(dist_type_string_probit_state(row)), & + qceff_table_data(row)%probit_state%bounded_below, qceff_table_data(row)%probit_state%bounded_above, & + qceff_table_data(row)%probit_state%lower_bound, qceff_table_data(row)%probit_state%upper_bound, trim(dist_type_string_probit_extended_state(row)), & + qceff_table_data(row)%probit_extended_state%bounded_below, qceff_table_data(row)%probit_extended_state%bounded_above, & + qceff_table_data(row)%probit_extended_state%lower_bound, qceff_table_data(row)%probit_extended_state%upper_bound, & + trim(filter_kind_string(row)), qceff_table_data(row)%obs_inc_info%bounded_below, qceff_table_data(row)%obs_inc_info%bounded_above, & + qceff_table_data(row)%obs_inc_info%lower_bound, qceff_table_data(row)%obs_inc_info%upper_bound +call error_handler(E_MSG, 'log_qceff_table_data:', trim(log_msg), source) end do call error_handler(E_MSG, '', '', source) !Writing blank line to log -end subroutine log_qcf_table_data +end subroutine log_qceff_table_data !------------------------------------------------------------------------ @@ -575,7 +575,7 @@ subroutine end_algorithm_info_mod() if (use_qty_defaults) return deallocate(specified_qtys) -deallocate(qcf_table_data) +deallocate(qceff_table_data) end subroutine end_algorithm_info_mod diff --git a/assimilation_code/modules/assimilation/filter_mod.f90 b/assimilation_code/modules/assimilation/filter_mod.f90 index 8ecbc51ea4..acd4cd5d62 100644 --- a/assimilation_code/modules/assimilation/filter_mod.f90 +++ b/assimilation_code/modules/assimilation/filter_mod.f90 @@ -166,7 +166,7 @@ module filter_mod !---------------------------------------------------------------- ! Namelist input with default values ! -character(len = 129) :: qcf_table_filename = '' +character(len = 129) :: qceff_table_filename = '' integer :: async = 0, ens_size = 20 integer :: tasks_per_model_advance = 1 ! if init_time_days and seconds are negative initial time is 0, 0 @@ -261,7 +261,7 @@ module filter_mod namelist /filter_nml/ async, & - qcf_table_filename, & + qceff_table_filename, & adv_ens_command, & ens_size, & tasks_per_model_advance, & @@ -1150,7 +1150,7 @@ subroutine filter_main() call end_assim_model() call trace_message('After end_model call') -! deallocate qcf_table_data structures +! deallocate qceff_table_data structures call end_algorithm_info_mod() call trace_message('Before ensemble and obs memory cleanup') @@ -1277,7 +1277,7 @@ subroutine filter_initialize_modules_used() call initialize_qc() ! Initialize algorothm_info_mod and read in QCF table data -call init_algorithm_info_mod(qcf_table_filename) +call init_algorithm_info_mod(qceff_table_filename) call trace_message('After filter_initialize_module_used call') diff --git a/assimilation_code/modules/assimilation/filter_mod.nml b/assimilation_code/modules/assimilation/filter_mod.nml index 79611257bf..ca9c75f1ce 100644 --- a/assimilation_code/modules/assimilation/filter_mod.nml +++ b/assimilation_code/modules/assimilation/filter_mod.nml @@ -1,5 +1,5 @@ &filter_nml - qcf_table_filename = '' + qceff_table_filename = '' use_algorithm_info_mod = .true., single_file_in = .false., input_state_files = '' diff --git a/developer_tests/qceff/test_table_read.f90 b/developer_tests/qceff/test_table_read.f90 index e5fb8f57e0..9e373dbeae 100644 --- a/developer_tests/qceff/test_table_read.f90 +++ b/developer_tests/qceff/test_table_read.f90 @@ -2,7 +2,7 @@ ! by UCAR, "as is", without charge, subject to all terms of use at ! http://www.image.ucar.edu/DAReS/DART/DART_download -! qcf_table_filename expected as command line arguement +! qceff_table_filename expected as command line arguement program test_table_read use algorithm_info_mod, only : init_algorithm_info_mod, end_algorithm_info_mod @@ -10,13 +10,13 @@ program test_table_read implicit none -character(len=129) :: qcf_table_filename +character(len=129) :: qceff_table_filename call initialize_utilities('test_table_read') -call get_command_argument(1,qcf_table_filename) +call get_command_argument(1,qceff_table_filename) -call init_algorithm_info_mod(qcf_table_filename) +call init_algorithm_info_mod(qceff_table_filename) call end_algorithm_info_mod() call finalize_utilities() diff --git a/guide/qcf-examples.rst b/guide/qceff-examples.rst similarity index 80% rename from guide/qcf-examples.rst rename to guide/qceff-examples.rst index 79b092e0ac..ee680d1757 100644 --- a/guide/qcf-examples.rst +++ b/guide/qceff-examples.rst @@ -22,9 +22,9 @@ Build the DART executables for the Lorenz 96 tracer advection model: ./quickbuild.sh nompi -The new quantile options are set using a :ref:`qcf table ` given as a namelist -option to &filter_nml. The examples below show how to change the quantile options -using various qcf tables. You can find the .csv files for these four example in the directory +The new quantile options are set using a :ref:`qceff table ` given as a namelist +option ``qceff_table_filename`` to &filter_nml. The examples below show how to change the quantile options +using various qceff tables. You can find the .csv files for these four example in the directory ``DART/models/lorenz_96_tracer_advection/work`` @@ -37,16 +37,16 @@ using various qcf tables. You can find the .csv files for these four example in - .cvs filename * - Example A - boundend normal rank histogram - - all_bnrhf_qcf_table.csv + - all_bnrhf_qceff_table.csv * - Example B - Ensemble Adjustment Kalman filters - - all_eakf_qcf_table.csv + - all_eakf_qceff_table.csv * - Example C - EAKF for state and bounded normal rank histogram filter and priors for tracer concentration and source - - state_eakf_tracer_bnrhf_qcf_table.csv + - state_eakf_tracer_bnrhf_qceff_table.csv * - Example D - Negative tracers bounded above - - neg_qcf_table.csv + - neg_qceff_table.csv You can view .csv files with a text editor, or spreadsheet tool such as Google Sheets, @@ -63,12 +63,12 @@ The default model configuration has a single tracer source at gridpoint 1 along small uniform tracer sinks that lead to areas where the true tracer concentration is usually 0. This is a particularly tough test for ensemble methods. -#. Edit input.nml to set the qcf_table_filename to 'all_bnrhf_qcf_table.csv' +#. Edit input.nml to set the qceff_table_filename to 'all_bnrhf_qceff_table.csv' .. code-block:: text &filter_nml - qcf_table_filename = 'all_bnrhf_qcf_table.csv' + qceff_table_filename = 'all_bnrhf_qceff_table.csv' #. Create a set_def.out file using create_obs_sequence, @@ -123,12 +123,12 @@ Example B Using Ensemble Adjustment Kalman filters. -#. Edit input.nml to set the qcf_table_filename to 'all_eakf_qcf_table.csv' +#. Edit input.nml to set the qceff_table_filename to 'all_eakf_qceff_table.csv' .. code-block:: text &filter_nml - qcf_table_filename = 'all_eakf_qcf_table.csv' + qceff_table_filename = 'all_eakf_qceff_table.csv' #. Run the filter @@ -141,12 +141,12 @@ Example C Using Ensemble Adjustment Kalman filter for state, but bounded normal rank histogram filter and priors for tracer concentration and source. -#. Edit input.nml to set the qcf_table_filename to state_eakf_tracer_bnrhf_qcf_table.csv +#. Edit input.nml to set the qceff_table_filename to state_eakf_tracer_bnrhf_qceff_table.csv .. code-block:: text &filter_nml - qcf_table_filename = 'state_eakf_tracer_bnrhf_qcf_table.csv' + qceff_table_filename = 'state_eakf_tracer_bnrhf_qceff_table.csv' #. Run the filter @@ -161,12 +161,12 @@ above. There are distinct numerical challenges in implementing the quantile algo for quantities that are bounded above, so flipping the sign of the tracers is a good test. -#. Edit input.nml to set the qcf_table_filename to neg_qcf_table.csv +#. Edit input.nml to set the qceff_table_filename to neg_qceff_table.csv .. code-block:: text &filter_nml - qcf_table_filename = 'neg_qcf_table.csv' + qceff_table_filename = 'neg_qceff_table.csv' #. Edit input.nml, to change the entry positive_tracer to .false. and read_input_state_from_file back to .false. diff --git a/guide/qcf_probit.rst b/guide/qceff_probit.rst similarity index 87% rename from guide/qcf_probit.rst rename to guide/qceff_probit.rst index e19d9775e6..bc60b58784 100644 --- a/guide/qcf_probit.rst +++ b/guide/qceff_probit.rst @@ -1,4 +1,4 @@ -.. _QCF: +.. _QCEFF: Quantile-Conserving Ensemble Filter Framework ============================================== @@ -7,12 +7,12 @@ The Quantile-Conserving Ensemble Filter Framework (QCEFF) tools are in the alpha The DART development team (dart@ucar.edu) would be happy to hear about your experiences and is anxious to build scientific collaborations using these new capabilities. -The QCEFF options are set using a :ref:`qcf table ` given as a namelist option to &filter_nml. +The QCEFF options are set using a :ref:`qceff table ` given as a namelist option to &filter_nml. .. code-block:: text &filter_nml - qcf_table_filename = 'qcf_table.csv' + qceff_table_filename = 'qceff_table.csv' .. _QCEFF options: @@ -21,7 +21,7 @@ QCEFF options -------------- QCEFF options are per quantity. For a given quantity, you specify the following -options as columns of the qcf_table: +options as columns of the qceff_table: * Observation error information @@ -57,14 +57,14 @@ options as columns of the qcf_table: -.. _qcf table: +.. _qceff table: -Creating a qcf table --------------------- +Creating a qceff table +----------------------- The table has two headers, row 1 and 2. The first row is the version number. The second row describes the :ref:`QCEFF options` corresponding to each column of the table. -These two headers must be present in your qcf table. +These two headers must be present in your qceff table. The :ref:`qcf trunc table` below shows the table headers, and an example quantity QTY_TRACER_CONCENTRATION for the first 5 columns of the table. There is a complete table with all 25 columns in `Google Sheets `_. You can copy and edit this table as needed. @@ -76,13 +76,13 @@ Ensure that there are no empty rows in between the quantities listed in the spre Save your spreadsheet as a .csv file. To run filter or perfect_model_obs, put the .csv file in the directory where you are running. -Edit input.nml to set the filter_nml option qcf_table_filename, for example: +Edit input.nml to set the filter_nml option qceff_table_filename, for example: .. code-block:: text &filter_nml - qcf_table_filename = 'qcf_table.csv' + qceff_table_filename = 'qceff_table.csv' .. _qcf trunc table: @@ -138,7 +138,7 @@ Available distributions Default values --------------- -If a quantity is not in the qcf table, the following default values +If a quantity is not in the qceff table, the following default values are used: * filter_kind (default EAKF) diff --git a/index.rst b/index.rst index 2d20f5b96a..16ff70bd10 100644 --- a/index.rst +++ b/index.rst @@ -5,7 +5,7 @@ Welcome to the Data Assimilation Research Testbed .. warning:: - Pre-release version of DART: quantile conserving and probit transform tools + Pre-release version of DART: Quantile-Conserving Ensemble Filter Framework The Data Assimilation Research Testbed (DART) is an open-source, freely @@ -69,7 +69,7 @@ for the observed quantity (this is the ensemble adjustment Kalman filter, or EAK then linearly regress the observation increments onto each state variable. -DART now implements a Quantile-Conserving Ensemble Filtering Framework :ref:`(QCEFF) `. +DART now implements a Quantile-Conserving Ensemble Filtering Framework :ref:`(QCEFF) `. The QCEFF provides a very general method of computing increments for the prior ensemble of an observed quantity by allowing the use of arbitrary distributions for the prior and the observation error. This is especially useful for bounded quantities like tracer concentrations, @@ -100,7 +100,7 @@ with DA and large improvements can occur for bounded parameters. Variables that non-Gaussian prior distributions can also see large improvements. Examples can include atmospheric quantities like moisture and cloud amount in the presence of convection, and many land surface variables. -For instructions on how to use these tools, see :ref:`QCF`. +For instructions on how to use these tools, see :ref:`QCEFF`. For step-by-step examples of the QCEFF tools, you can work through :ref:`examples with the Lorenz 96 tracer model ` @@ -292,7 +292,7 @@ References guide/high-level-da-workflows guide/dart-design-philosophy guide/important-capabilities-dart - guide/qcf_probit + guide/qceff_probit .. toctree:: :maxdepth: 2 @@ -409,7 +409,7 @@ References guide/DART_LAB/DART_LAB CLM-DART Tutorial WRF-DART Tutorial - guide/qcf-examples.rst + guide/qceff-examples.rst .. toctree:: :maxdepth: 2 diff --git a/models/9var/work/input.nml b/models/9var/work/input.nml index f95a275a0b..b8f852e952 100644 --- a/models/9var/work/input.nml +++ b/models/9var/work/input.nml @@ -35,7 +35,7 @@ # output_state_files = 'filter_output.nc' &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/FESOM/work/input.nml b/models/FESOM/work/input.nml index 02d9fead5a..abbfa7201e 100644 --- a/models/FESOM/work/input.nml +++ b/models/FESOM/work/input.nml @@ -34,7 +34,7 @@ # state by specifying the 'input' stage. &filter_nml - qcf_table_filename = '' + qceff_table_filename = '' async = 5 adv_ens_command = "advance_model_script.die" ens_size = 3 diff --git a/models/LMDZ/work/input.nml b/models/LMDZ/work/input.nml index b3f9fa6ae5..761050c7e7 100644 --- a/models/LMDZ/work/input.nml +++ b/models/LMDZ/work/input.nml @@ -2,7 +2,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', async = 2, adv_ens_command = "./advance_model.csh", ens_size = 40, diff --git a/models/MITgcm_annulus/work/input.nml b/models/MITgcm_annulus/work/input.nml index dc810e8946..8b5ec8c3b1 100644 --- a/models/MITgcm_annulus/work/input.nml +++ b/models/MITgcm_annulus/work/input.nml @@ -25,7 +25,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', async = 0, adv_ens_command = "../shell_scripts/advance_model.csh", ens_size = 20, diff --git a/models/MOM6/work/input.nml b/models/MOM6/work/input.nml index 153fce5e13..ef48bc6915 100644 --- a/models/MOM6/work/input.nml +++ b/models/MOM6/work/input.nml @@ -31,7 +31,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', single_file_in = .false., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/NAAPS/work/input.nml b/models/NAAPS/work/input.nml index 403c98d92d..6ed9d62147 100644 --- a/models/NAAPS/work/input.nml +++ b/models/NAAPS/work/input.nml @@ -125,7 +125,7 @@ &filter_nml - qcf_table_filename = '' + qceff_table_filename = '' async = 0 adv_ens_command = "./advance_model.csh" ens_size = 20 diff --git a/models/NCOMMAS/work/input.nml b/models/NCOMMAS/work/input.nml index 2f6f64165c..057ed5e13a 100644 --- a/models/NCOMMAS/work/input.nml +++ b/models/NCOMMAS/work/input.nml @@ -27,7 +27,7 @@ &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', async = 4, adv_ens_command = "../shell_scripts/advance_model.csh", ens_size = 20, diff --git a/models/POP/work/input.nml b/models/POP/work/input.nml index f8614c4c7b..deb22c6825 100644 --- a/models/POP/work/input.nml +++ b/models/POP/work/input.nml @@ -31,7 +31,7 @@ / &filter_nml - qcf_table_filename = '' + qceff_table_filename = '' async = 0 adv_ens_command = 'no_CESM_advance_script' ens_size = 3 diff --git a/models/ROMS/work/input.nml b/models/ROMS/work/input.nml index 6ac2180fa3..f7cbd3e27f 100644 --- a/models/ROMS/work/input.nml +++ b/models/ROMS/work/input.nml @@ -32,7 +32,7 @@ &filter_nml - qcf_table_filename = '' + qceff_table_filename = '' async = 0 adv_ens_command = "DART_trying_to_advance_ROMS_not_supported" ens_size = 3 diff --git a/models/am2/work/input.nml b/models/am2/work/input.nml index 9ec433d290..5cc4a2c9ad 100644 --- a/models/am2/work/input.nml +++ b/models/am2/work/input.nml @@ -25,7 +25,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', async = 2, adv_ens_command = "./advance_model.csh", ens_size = 10, diff --git a/models/bgrid_solo/work/input.nml b/models/bgrid_solo/work/input.nml index c26214686a..b33e5f8191 100644 --- a/models/bgrid_solo/work/input.nml +++ b/models/bgrid_solo/work/input.nml @@ -31,7 +31,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', single_file_in = .true., input_state_files = 'filter_input.nc' input_state_file_list = '' diff --git a/models/cam-fv/work/input.nml b/models/cam-fv/work/input.nml index 1c64d9e210..ac9bb46de7 100644 --- a/models/cam-fv/work/input.nml +++ b/models/cam-fv/work/input.nml @@ -37,7 +37,7 @@ / &filter_nml - qcf_table_filename = '' + qceff_table_filename = '' input_state_file_list = 'cam_init_files' input_state_files = '' single_file_in = .false. diff --git a/models/cam-se/work/input.nml b/models/cam-se/work/input.nml index 37b63e1d0e..f08b4e818a 100644 --- a/models/cam-se/work/input.nml +++ b/models/cam-se/work/input.nml @@ -32,7 +32,7 @@ / &filter_nml - qcf_table_filename = '' + qceff_table_filename = '' input_state_files = '' input_state_file_list = 'cam_init_files' single_file_in = .false. diff --git a/models/cice/work/input.nml b/models/cice/work/input.nml index 9f0c5edecb..f096104f4c 100644 --- a/models/cice/work/input.nml +++ b/models/cice/work/input.nml @@ -25,7 +25,7 @@ / &filter_nml - qcf_table_filename = '' + qceff_table_filename = '' async = 0 adv_ens_command = "no_advance_script" ens_size = 6 diff --git a/models/clm/work/input.nml b/models/clm/work/input.nml index 737fbc097c..9bfea0e628 100644 --- a/models/clm/work/input.nml +++ b/models/clm/work/input.nml @@ -28,7 +28,7 @@ &filter_nml - qcf_table_filename = '' + qceff_table_filename = '' allow_missing_clm = .true. perturb_from_single_instance = .FALSE. perturbation_amplitude = 0.2 diff --git a/models/cm1/work/input.nml b/models/cm1/work/input.nml index 29623c9228..c07a9f9807 100644 --- a/models/cm1/work/input.nml +++ b/models/cm1/work/input.nml @@ -6,7 +6,7 @@ / &filter_nml - qcf_table_filename = '' + qceff_table_filename = '' async = 2 adv_ens_command = 'advance_model.csh' input_state_file_list = 'input_filelist.txt' diff --git a/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml b/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml index 5d596ec966..6c6bcbf3f3 100644 --- a/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml +++ b/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml @@ -20,7 +20,7 @@ / &filter_nml - qcf_table_filename = '' + qceff_table_filename = '' async = 4, adv_ens_command = "./advance_wrapper.sh", ens_size = 16, diff --git a/models/dynamo/work/input.nml b/models/dynamo/work/input.nml index 6e40149985..a1ff28fe86 100644 --- a/models/dynamo/work/input.nml +++ b/models/dynamo/work/input.nml @@ -25,7 +25,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', async = 2, adv_ens_command = "./advance_model.ksh", ens_size = 20, diff --git a/models/forced_barot/work/input.nml b/models/forced_barot/work/input.nml index f616546f69..3d07cb5502 100644 --- a/models/forced_barot/work/input.nml +++ b/models/forced_barot/work/input.nml @@ -25,7 +25,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', async = 0, adv_ens_command = "./advance_model.csh", ens_size = 20, diff --git a/models/forced_lorenz_96/work/input.nml b/models/forced_lorenz_96/work/input.nml index b605a63a32..a6a8839ec3 100644 --- a/models/forced_lorenz_96/work/input.nml +++ b/models/forced_lorenz_96/work/input.nml @@ -33,7 +33,7 @@ # stages_to_write = 'preassim', 'postassim', 'output' &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/gitm/work/input.nml b/models/gitm/work/input.nml index ae584c7aeb..d9fad6240d 100644 --- a/models/gitm/work/input.nml +++ b/models/gitm/work/input.nml @@ -2,7 +2,7 @@ / &filter_nml - qcf_table_filename = '' + qceff_table_filename = '' input_state_files = '' input_state_file_list = 'gitm_input_files.txt' single_file_in = .false. diff --git a/models/ikeda/work/input.nml b/models/ikeda/work/input.nml index 4faa524ff8..a7a73a92e6 100644 --- a/models/ikeda/work/input.nml +++ b/models/ikeda/work/input.nml @@ -31,7 +31,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', single_file_in = .true., input_state_files = 'filter_input.nc' input_state_file_list = '' diff --git a/models/lorenz_04/work/input.nml b/models/lorenz_04/work/input.nml index 4a0a976b02..9da7ef60dc 100644 --- a/models/lorenz_04/work/input.nml +++ b/models/lorenz_04/work/input.nml @@ -35,7 +35,7 @@ # output_state_files = 'filter_output.nc' &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/lorenz_63/work/input.nml b/models/lorenz_63/work/input.nml index b53bc108d7..5626cba931 100644 --- a/models/lorenz_63/work/input.nml +++ b/models/lorenz_63/work/input.nml @@ -31,7 +31,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/lorenz_84/work/input.nml b/models/lorenz_84/work/input.nml index 1a91ec6518..1bc0810060 100644 --- a/models/lorenz_84/work/input.nml +++ b/models/lorenz_84/work/input.nml @@ -35,7 +35,7 @@ # output_state_files = 'filter_output.nc' &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/lorenz_96/work/input.nml b/models/lorenz_96/work/input.nml index cce2f9d3a8..84520de49d 100644 --- a/models/lorenz_96/work/input.nml +++ b/models/lorenz_96/work/input.nml @@ -31,7 +31,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/lorenz_96_2scale/work/input.nml b/models/lorenz_96_2scale/work/input.nml index 398fd66e27..17dc80b6e8 100644 --- a/models/lorenz_96_2scale/work/input.nml +++ b/models/lorenz_96_2scale/work/input.nml @@ -35,7 +35,7 @@ # output_state_files = 'filter_output.nc' &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/lorenz_96_tracer_advection/work/all_bnrhf_qcf_table.csv b/models/lorenz_96_tracer_advection/work/all_bnrhf_qceff_table.csv similarity index 100% rename from models/lorenz_96_tracer_advection/work/all_bnrhf_qcf_table.csv rename to models/lorenz_96_tracer_advection/work/all_bnrhf_qceff_table.csv diff --git a/models/lorenz_96_tracer_advection/work/all_eakf_qcf_table.csv b/models/lorenz_96_tracer_advection/work/all_eakf_qceff_table.csv similarity index 100% rename from models/lorenz_96_tracer_advection/work/all_eakf_qcf_table.csv rename to models/lorenz_96_tracer_advection/work/all_eakf_qceff_table.csv diff --git a/models/lorenz_96_tracer_advection/work/input.nml b/models/lorenz_96_tracer_advection/work/input.nml index 057c08937a..dd84a5aaeb 100644 --- a/models/lorenz_96_tracer_advection/work/input.nml +++ b/models/lorenz_96_tracer_advection/work/input.nml @@ -32,7 +32,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', single_file_in = .true., input_state_files = 'perfect_input.nc' input_state_file_list = '' diff --git a/models/lorenz_96_tracer_advection/work/neg_qcf_table.csv b/models/lorenz_96_tracer_advection/work/neg_qceff_table.csv similarity index 100% rename from models/lorenz_96_tracer_advection/work/neg_qcf_table.csv rename to models/lorenz_96_tracer_advection/work/neg_qceff_table.csv diff --git a/models/lorenz_96_tracer_advection/work/state_eakf_tracer_bnrhf_qcf_table.csv b/models/lorenz_96_tracer_advection/work/state_eakf_tracer_bnrhf_qceff_table.csv similarity index 100% rename from models/lorenz_96_tracer_advection/work/state_eakf_tracer_bnrhf_qcf_table.csv rename to models/lorenz_96_tracer_advection/work/state_eakf_tracer_bnrhf_qceff_table.csv diff --git a/models/mpas_atm/work/input.nml b/models/mpas_atm/work/input.nml index 5e7521dd33..450f292bde 100644 --- a/models/mpas_atm/work/input.nml +++ b/models/mpas_atm/work/input.nml @@ -31,7 +31,7 @@ / &filter_nml - qcf_table_filename = '' + qceff_table_filename = '' async = 0 adv_ens_command = './advance_model.csh' ens_size = 3 diff --git a/models/mpas_ocn/work/input.nml b/models/mpas_ocn/work/input.nml index 930abf70bb..ca00423fca 100644 --- a/models/mpas_ocn/work/input.nml +++ b/models/mpas_ocn/work/input.nml @@ -25,7 +25,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', async = 2, adv_ens_command = "../shell_scripts/advance_model.csh", ens_size = 3, diff --git a/models/noah/work/input.nml b/models/noah/work/input.nml index 7ffbe98215..f2b3182374 100644 --- a/models/noah/work/input.nml +++ b/models/noah/work/input.nml @@ -52,7 +52,7 @@ &filter_nml - qcf_table_filename = '' + qceff_table_filename = '' input_state_file_list = 'input_file_list.txt' perturb_from_single_instance = .false. init_time_days = -1 diff --git a/models/null_model/work/input.nml b/models/null_model/work/input.nml index 412e8731a0..ab69b54b66 100644 --- a/models/null_model/work/input.nml +++ b/models/null_model/work/input.nml @@ -31,7 +31,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', single_file_in = .true., input_state_files = 'filter_input.nc' input_state_file_list = '' diff --git a/models/pe2lyr/work/input.nml b/models/pe2lyr/work/input.nml index 02838242e4..7c61841eea 100644 --- a/models/pe2lyr/work/input.nml +++ b/models/pe2lyr/work/input.nml @@ -25,7 +25,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', async = 0, adv_ens_command = "./advance_model.csh", ens_size = 20, diff --git a/models/rose/work/input.nml b/models/rose/work/input.nml index 639a37c02c..a44ff8bff2 100644 --- a/models/rose/work/input.nml +++ b/models/rose/work/input.nml @@ -25,7 +25,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', async = 2, adv_ens_command = "../shell_scripts/advance_model.csh", ens_size = 20, diff --git a/models/simple_advection/work/input.nml b/models/simple_advection/work/input.nml index e60d00921b..19e26e6cec 100644 --- a/models/simple_advection/work/input.nml +++ b/models/simple_advection/work/input.nml @@ -35,7 +35,7 @@ # output_state_files = 'filter_output.nc' &filter_nml - qcf_table_filename = '' + qceff_table_filename = '' single_file_in = .true. input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/sqg/work/input.nml b/models/sqg/work/input.nml index d36cfd71d5..4a60a9acd1 100644 --- a/models/sqg/work/input.nml +++ b/models/sqg/work/input.nml @@ -33,7 +33,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', async = 0, adv_ens_command = "model called as a subroutine", ens_size = 25, diff --git a/models/template/work/oned_input.nml b/models/template/work/oned_input.nml index 5ecb7e4863..21c8efc29e 100644 --- a/models/template/work/oned_input.nml +++ b/models/template/work/oned_input.nml @@ -31,7 +31,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/template/work/threed_input.nml b/models/template/work/threed_input.nml index d30866baa8..b1e7d9e179 100644 --- a/models/template/work/threed_input.nml +++ b/models/template/work/threed_input.nml @@ -31,7 +31,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/tiegcm/work/input.nml b/models/tiegcm/work/input.nml index b4c3343723..fb0fdea050 100644 --- a/models/tiegcm/work/input.nml +++ b/models/tiegcm/work/input.nml @@ -41,7 +41,7 @@ # output_state_file_list = 'out_restart_p_files.txt', 'out_secondary_files.txt', 'out_f10.7.txt' &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', single_file_in = .false., input_state_files = '' input_state_file_list = 'restart_p_files.txt', 'secondary_files.txt' diff --git a/models/wrf/work/input.nml b/models/wrf/work/input.nml index 9304c3dc9c..41ce4227a7 100644 --- a/models/wrf/work/input.nml +++ b/models/wrf/work/input.nml @@ -31,7 +31,7 @@ / &filter_nml - qcf_table_filename = '', + qceff_table_filename = '', async = 0, adv_ens_command = "../shell_scripts/advance_model.csh", ens_size = 3, diff --git a/models/wrf_hydro/work/input.nml b/models/wrf_hydro/work/input.nml index ac2037247b..07ddafbf98 100644 --- a/models/wrf_hydro/work/input.nml +++ b/models/wrf_hydro/work/input.nml @@ -74,7 +74,7 @@ # output_state_file_list = 'hydro_file_list.txt' &filter_nml - qcf_table_filename = '' + qceff_table_filename = '' input_state_file_list = 'hydro_file_list.txt' single_file_in = .false. init_time_days = -1, From 072328ab36230dfd9d566ae13cf489b5fda52cff Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Mon, 30 Oct 2023 16:23:24 -0400 Subject: [PATCH 123/129] developer test for lower case in qceff table currently failing --- developer_tests/qceff/work/all_bnrhf_qceff_table.csv | 5 +++++ developer_tests/qceff/work/runall.sh | 3 +++ 2 files changed, 8 insertions(+) create mode 100644 developer_tests/qceff/work/all_bnrhf_qceff_table.csv diff --git a/developer_tests/qceff/work/all_bnrhf_qceff_table.csv b/developer_tests/qceff/work/all_bnrhf_qceff_table.csv new file mode 100644 index 0000000000..3e50dfea1c --- /dev/null +++ b/developer_tests/qceff/work/all_bnrhf_qceff_table.csv @@ -0,0 +1,5 @@ +QCF table version: 1,obs_error_info,,,,probit_inflation,,,,,probit_state,,,,,probit_extended_state,,,,,obs_inc_info,,,, +QTY_TEMPLATE:,bounded_below,bounded_above,lower_bound,upper_bound,dist_type,bounded_below,bounded_above,lower_bound,upper_bound,dist_type,bounded_below,bounded_above,lower_bound,upper_bound,dist_type,bounded_below,bounded_above,lower_bound,upper_bound,filter_kind,bounded_below,bounded_above,lower_bound,upper_bound +QTY_state_VARIABLE,.false.,.false.,-888888,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.false.,.false.,-888888,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.false.,.false.,-888888,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.false.,.false.,-888888,-888888,BOUNDED_NORMAL_RHF,.false.,.false.,-888888,-888888 +QTY_TRACER_CONCENTRATION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RHF,.true.,.false.,0,-888888 +QTY_TRACER_SOURCE,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RH_DISTRIBUTION,.true.,.false.,0,-888888,BOUNDED_NORMAL_RHF,.true.,.false.,0,-888888 diff --git a/developer_tests/qceff/work/runall.sh b/developer_tests/qceff/work/runall.sh index 62d42c3fc9..4e6b6df74f 100755 --- a/developer_tests/qceff/work/runall.sh +++ b/developer_tests/qceff/work/runall.sh @@ -49,3 +49,6 @@ fi ./test_table_read qcf_table_incorrect_filter_kind.txt ; should_fail "incorrect filter_kind" ./test_table_read qcf_table_incorrect_distribution.txt ; should_fail "incorrect distribution" + +./test_table_read all_bnrhf_qceff_table.csv ; should_pass "lower case QTY" + From 27048654503203963df223273744ca19b2e5e722 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Mon, 30 Oct 2023 16:46:17 -0400 Subject: [PATCH 124/129] developer test for lower case dist_type currently failing, need to_upper on all string inputs in algorithm_info_mod --- developer_tests/qceff/work/qcf_table_lower_case_dist.txt | 3 +++ developer_tests/qceff/work/runall.sh | 2 ++ 2 files changed, 5 insertions(+) create mode 100644 developer_tests/qceff/work/qcf_table_lower_case_dist.txt diff --git a/developer_tests/qceff/work/qcf_table_lower_case_dist.txt b/developer_tests/qceff/work/qcf_table_lower_case_dist.txt new file mode 100644 index 0000000000..b6750b66ec --- /dev/null +++ b/developer_tests/qceff/work/qcf_table_lower_case_dist.txt @@ -0,0 +1,3 @@ +QCF table version: 1 +QTY_TEMPLATE: bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound dist_type bounded_below bounded_above lower_bound upper_bound filter_kind bounded_below bounded_above lower_bound upper_bound +QTY_STATE_VARIABLE .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_normal_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RH_DISTRIBUTION .false. .false. -888888.0 -888888.0 BOUNDED_NORMAL_RHF .false. .false. -888888.0 -888888.0 diff --git a/developer_tests/qceff/work/runall.sh b/developer_tests/qceff/work/runall.sh index 4e6b6df74f..c354f9b4d8 100755 --- a/developer_tests/qceff/work/runall.sh +++ b/developer_tests/qceff/work/runall.sh @@ -52,3 +52,5 @@ fi ./test_table_read all_bnrhf_qceff_table.csv ; should_pass "lower case QTY" +./test_table_read qcf_table_lower_case_dist.txt; should_pass "lower case dist_type" + From 43f43a0c011bf748d89036aa7088aebbb7e18536 Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Tue, 31 Oct 2023 10:45:22 -0400 Subject: [PATCH 125/129] fix: upper case for string inputs changed if statements to case, so to_upper called once before the case statement --- .../assimilation/algorithm_info_mod.f90 | 155 ++++++++++-------- 1 file changed, 85 insertions(+), 70 deletions(-) diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 5fda240286..95d33095e0 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -183,7 +183,8 @@ subroutine read_qceff_table(qceff_table_filename) qceff_table_data(row)%probit_extended_state%lower_bound, qceff_table_data(row)%probit_extended_state%upper_bound, & filter_kind_string(row), qceff_table_data(row)%obs_inc_info%bounded_below, qceff_table_data(row)%obs_inc_info%bounded_above, & qceff_table_data(row)%obs_inc_info%lower_bound, qceff_table_data(row)%obs_inc_info%upper_bound - + + call to_upper(qty_string) specified_qtys(row) = get_index_for_quantity(qty_string) if(specified_qtys(row) == -1) then @@ -192,78 +193,92 @@ subroutine read_qceff_table(qceff_table_filename) endif ! Converting the distribution types (read in from table as a string) to its corresponding int value - if (trim(dist_type_string_probit_inflation(row)) == 'NORMAL_DISTRIBUTION') then - qceff_table_data(row)%probit_inflation%dist_type = NORMAL_DISTRIBUTION - elseif (trim(dist_type_string_probit_inflation(row)) == 'BOUNDED_NORMAL_RH_DISTRIBUTION') then - qceff_table_data(row)%probit_inflation%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - elseif (trim(dist_type_string_probit_inflation(row)) == 'GAMMA_DISTRIBUTION') then - qceff_table_data(row)%probit_inflation%dist_type = GAMMA_DISTRIBUTION - elseif (trim(dist_type_string_probit_inflation(row)) == 'BETA_DISTRIBUTION') then - qceff_table_data(row)%probit_inflation%dist_type = BETA_DISTRIBUTION - elseif (trim(dist_type_string_probit_inflation(row)) == 'LOG_NORMAL_DISTRIBUTION') then - qceff_table_data(row)%probit_inflation%dist_type = LOG_NORMAL_DISTRIBUTION - elseif (trim(dist_type_string_probit_inflation(row)) == 'UNIFORM_DISTRIBUTION') then - qceff_table_data(row)%probit_inflation%dist_type = UNIFORM_DISTRIBUTION - elseif (trim(dist_type_string_probit_inflation(row)) == 'PARTICLE_FILTER_DISTRIBUTION') then - qceff_table_data(row)%probit_inflation%dist_type = PARTICLE_FILTER_DISTRIBUTION - else - write(errstring, *) 'Invalid distribution type for probit inflation: ', trim(dist_type_string_probit_inflation(row)) - call error_handler(E_ERR, 'read_qceff_table:', errstring, source) - endif + call to_upper(dist_type_string_probit_inflation(row)) + + select case (trim(dist_type_string_probit_inflation(row))) + case ('NORMAL_DISTRIBUTION') + qceff_table_data(row)%probit_inflation%dist_type = NORMAL_DISTRIBUTION + case ('BOUNDED_NORMAL_RH_DISTRIBUTION') + qceff_table_data(row)%probit_inflation%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION + case ('GAMMA_DISTRIBUTION') + qceff_table_data(row)%probit_inflation%dist_type = GAMMA_DISTRIBUTION + case ('BETA_DISTRIBUTION') + qceff_table_data(row)%probit_inflation%dist_type = BETA_DISTRIBUTION + case ('LOG_NORMAL_DISTRIBUTION') + qceff_table_data(row)%probit_inflation%dist_type = LOG_NORMAL_DISTRIBUTION + case ('UNIFORM_DISTRIBUTION') + qceff_table_data(row)%probit_inflation%dist_type = UNIFORM_DISTRIBUTION + case ('PARTICLE_FILTER_DISTRIBUTION') + qceff_table_data(row)%probit_inflation%dist_type = PARTICLE_FILTER_DISTRIBUTION + case default + write(errstring, *) 'Invalid distribution type for probit inflation: ', trim(dist_type_string_probit_inflation(row)) + call error_handler(E_ERR, 'read_qceff_table:', errstring, source) + end select + + + call to_upper(dist_type_string_probit_state(row)) + + select case (trim(dist_type_string_probit_state(row))) + case ('NORMAL_DISTRIBUTION') + qceff_table_data(row)%probit_state%dist_type = NORMAL_DISTRIBUTION + case ('BOUNDED_NORMAL_RH_DISTRIBUTION') + qceff_table_data(row)%probit_state%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION + case ('GAMMA_DISTRIBUTION') + qceff_table_data(row)%probit_state%dist_type = GAMMA_DISTRIBUTION + case ('BETA_DISTRIBUTION') + qceff_table_data(row)%probit_state%dist_type = BETA_DISTRIBUTION + case ('LOG_NORMAL_DISTRIBUTION') + qceff_table_data(row)%probit_state%dist_type = LOG_NORMAL_DISTRIBUTION + case ('UNIFORM_DISTRIBUTION') + qceff_table_data(row)%probit_state%dist_type = UNIFORM_DISTRIBUTION + case ('PARTICLE_FILTER_DISTRIBUTION') + qceff_table_data(row)%probit_state%dist_type = PARTICLE_FILTER_DISTRIBUTION + case default + write(errstring, *) 'Invalid distribution type for probit state: ', trim(dist_type_string_probit_state(row)) + call error_handler(E_ERR, 'read_qceff_table:', errstring, source) + end select + + call to_upper(dist_type_string_probit_extended_state(row)) + + select case (trim(dist_type_string_probit_extended_state(row))) + case ('NORMAL_DISTRIBUTION') + qceff_table_data(row)%probit_extended_state%dist_type = NORMAL_DISTRIBUTION + case ('BOUNDED_NORMAL_RH_DISTRIBUTION') + qceff_table_data(row)%probit_extended_state%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION + case ('GAMMA_DISTRIBUTION') + qceff_table_data(row)%probit_extended_state%dist_type = GAMMA_DISTRIBUTION + case ('BETA_DISTRIBUTION') + qceff_table_data(row)%probit_extended_state%dist_type = BETA_DISTRIBUTION + case ('LOG_NORMAL_DISTRIBUTION') + qceff_table_data(row)%probit_extended_state%dist_type = LOG_NORMAL_DISTRIBUTION + case ('UNIFORM_DISTRIBUTION') + qceff_table_data(row)%probit_extended_state%dist_type = UNIFORM_DISTRIBUTION + case ('PARTICLE_FILTER_DISTRIBUTION') + qceff_table_data(row)%probit_extended_state%dist_type = PARTICLE_FILTER_DISTRIBUTION + case default + write(errstring, *) 'Invalid distribution type for probit extended state: ', trim(dist_type_string_probit_extended_state(row)) + call error_handler(E_ERR, 'read_qceff_table:', errstring, source) + end select - if (trim(dist_type_string_probit_state(row)) == 'NORMAL_DISTRIBUTION') then - qceff_table_data(row)%probit_state%dist_type = NORMAL_DISTRIBUTION - elseif (trim(dist_type_string_probit_state(row)) == 'BOUNDED_NORMAL_RH_DISTRIBUTION') then - qceff_table_data(row)%probit_state%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - elseif (trim(dist_type_string_probit_state(row)) == 'GAMMA_DISTRIBUTION') then - qceff_table_data(row)%probit_state%dist_type = GAMMA_DISTRIBUTION - elseif (trim(dist_type_string_probit_state(row)) == 'BETA_DISTRIBUTION') then - qceff_table_data(row)%probit_state%dist_type = BETA_DISTRIBUTION - elseif (trim(dist_type_string_probit_state(row)) == 'LOG_NORMAL_DISTRIBUTION') then - qceff_table_data(row)%probit_state%dist_type = LOG_NORMAL_DISTRIBUTION - elseif (trim(dist_type_string_probit_state(row)) == 'UNIFORM_DISTRIBUTION') then - qceff_table_data(row)%probit_state%dist_type = UNIFORM_DISTRIBUTION - elseif (trim(dist_type_string_probit_state(row)) == 'PARTICLE_FILTER_DISTRIBUTION') then - qceff_table_data(row)%probit_state%dist_type = PARTICLE_FILTER_DISTRIBUTION - else - write(errstring, *) 'Invalid distribution type for probit state: ', trim(dist_type_string_probit_state(row)) - call error_handler(E_ERR, 'read_qceff_table:', errstring, source) - endif - - if (trim(dist_type_string_probit_extended_state(row)) == 'NORMAL_DISTRIBUTION') then - qceff_table_data(row)%probit_extended_state%dist_type = NORMAL_DISTRIBUTION - elseif (trim(dist_type_string_probit_extended_state(row)) == 'BOUNDED_NORMAL_RH_DISTRIBUTION') then - qceff_table_data(row)%probit_extended_state%dist_type = BOUNDED_NORMAL_RH_DISTRIBUTION - elseif (trim(dist_type_string_probit_extended_state(row)) == 'GAMMA_DISTRIBUTION') then - qceff_table_data(row)%probit_extended_state%dist_type = GAMMA_DISTRIBUTION - elseif (trim(dist_type_string_probit_extended_state(row)) == 'BETA_DISTRIBUTION') then - qceff_table_data(row)%probit_extended_state%dist_type = BETA_DISTRIBUTION - elseif (trim(dist_type_string_probit_extended_state(row)) == 'LOG_NORMAL_DISTRIBUTION') then - qceff_table_data(row)%probit_extended_state%dist_type = LOG_NORMAL_DISTRIBUTION - elseif (trim(dist_type_string_probit_extended_state(row)) == 'UNIFORM_DISTRIBUTION') then - qceff_table_data(row)%probit_extended_state%dist_type = UNIFORM_DISTRIBUTION - elseif (trim(dist_type_string_probit_extended_state(row)) == 'PARTICLE_FILTER_DISTRIBUTION') then - qceff_table_data(row)%probit_extended_state%dist_type = PARTICLE_FILTER_DISTRIBUTION - else - write(errstring, *) 'Invalid distribution type for probit extended state: ', trim(dist_type_string_probit_extended_state(row)) - call error_handler(E_ERR, 'read_qceff_table:', errstring, source) - endif ! Converting the filter kind (read in from table as a string) to its corresponding int value - if (trim(filter_kind_string(row)) == 'EAKF') then - qceff_table_data(row)%obs_inc_info%filter_kind = EAKF - elseif (trim(filter_kind_string(row)) == 'ENKF') then - qceff_table_data(row)%obs_inc_info%filter_kind = ENKF - elseif (trim(filter_kind_string(row)) == 'UNBOUNDED_RHF') then - qceff_table_data(row)%obs_inc_info%filter_kind = UNBOUNDED_RHF - elseif (trim(filter_kind_string(row)) == 'GAMMA_FILTER') then - qceff_table_data(row)%obs_inc_info%filter_kind = GAMMA_FILTER - elseif (trim(filter_kind_string(row)) == 'BOUNDED_NORMAL_RHF') then - qceff_table_data(row)%obs_inc_info%filter_kind = BOUNDED_NORMAL_RHF - else - write(errstring, *) 'Invalid filter kind: ', trim(filter_kind_string(row)) - call error_handler(E_ERR, 'read_qceff_table:', errstring, source) - endif + call to_upper(filter_kind_string(row)) + + select case (trim(filter_kind_string(row))) + case ('EAKF') + qceff_table_data(row)%obs_inc_info%filter_kind = EAKF + case ('ENKF') + qceff_table_data(row)%obs_inc_info%filter_kind = ENKF + case ('UNBOUNDED_RHF') + qceff_table_data(row)%obs_inc_info%filter_kind = UNBOUNDED_RHF + case ('GAMMA_FILTER') + qceff_table_data(row)%obs_inc_info%filter_kind = GAMMA_FILTER + case ('BOUNDED_NORMAL_RHF') + qceff_table_data(row)%obs_inc_info%filter_kind = BOUNDED_NORMAL_RHF + case default + write(errstring, *) 'Invalid filter kind: ', trim(filter_kind_string(row)) + call error_handler(E_ERR, 'read_qceff_table:', errstring, source) + end select end do From 88512618049f69b0cf7849e04ae144734641b77b Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Tue, 31 Oct 2023 14:07:47 -0400 Subject: [PATCH 126/129] doc-fix: change code block for read_input_state_from_file to match the text --- guide/qceff-examples.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/qceff-examples.rst b/guide/qceff-examples.rst index ee680d1757..de5574aea5 100644 --- a/guide/qceff-examples.rst +++ b/guide/qceff-examples.rst @@ -102,7 +102,7 @@ usually 0. This is a particularly tough test for ensemble methods. .. code:: text &filter_nml - read_input_state_from_file = .false., + read_input_state_from_file = .true., Run ``./perfect_model_obs`` again. From ae9b6d9ba43f7e954a69fb16bdfc9087de1b72ca Mon Sep 17 00:00:00 2001 From: Helen Kershaw Date: Tue, 31 Oct 2023 14:48:42 -0400 Subject: [PATCH 127/129] fix: qceff_table_filename now a namelist option in algorithm_info_mod This is so perfect_model_obs and filter_mod can use the algorithm_info_mod remove obsolete use_algorithm_info_mod namelist option from perfect_model_obs perfect model obs initialize and end algorithm_info_mod qceff_table_filename removed from filter_nml algorithm_info_mod example.nml update example.nmls to match latest options (removed filter_kind) adding algorithm_info_nml to model input.nmls The developer_tests/qceff will not work with this (passing in a filename) --- .../assimilation/algorithm_info_mod.f90 | 31 ++++++++++++++++--- .../assimilation/algorithm_info_mod.nml | 3 ++ .../modules/assimilation/assim_tools_mod.nml | 2 -- .../modules/assimilation/filter_mod.f90 | 4 +-- .../modules/assimilation/filter_mod.nml | 2 -- .../perfect_model_obs/perfect_model_obs.f90 | 19 +++++------- .../perfect_model_obs/perfect_model_obs.nml | 1 - guide/qceff-examples.rst | 14 ++++----- guide/qceff_probit.rst | 8 ++--- models/9var/work/input.nml | 5 ++- models/FESOM/work/input.nml | 5 ++- models/LMDZ/work/input.nml | 5 ++- models/MITgcm_annulus/work/input.nml | 5 ++- models/MOM6/work/input.nml | 5 ++- models/NAAPS/work/input.nml | 5 ++- models/NCOMMAS/work/input.nml | 5 ++- models/POP/work/input.nml | 5 ++- models/ROMS/work/input.nml | 7 +++-- models/am2/work/input.nml | 5 ++- models/bgrid_solo/work/input.nml | 5 ++- models/cam-fv/work/input.nml | 5 ++- models/cam-se/work/input.nml | 5 ++- models/cice/work/input.nml | 5 ++- models/clm/work/input.nml | 5 ++- models/cm1/work/input.nml | 5 ++- .../templates/EXPERIMENT_EXAMPLE/input.nml | 5 ++- models/dynamo/work/input.nml | 5 ++- models/forced_barot/work/input.nml | 5 ++- models/forced_lorenz_96/work/input.nml | 5 ++- models/gitm/work/input.nml | 5 ++- models/ikeda/work/input.nml | 5 ++- models/lorenz_04/work/input.nml | 5 ++- models/lorenz_63/work/input.nml | 5 ++- models/lorenz_84/work/input.nml | 5 ++- models/lorenz_96/work/input.nml | 5 ++- models/lorenz_96_2scale/work/input.nml | 5 ++- .../lorenz_96_tracer_advection/work/input.nml | 6 ++-- models/mpas_atm/work/input.nml | 5 ++- models/mpas_ocn/work/input.nml | 5 ++- models/noah/work/input.nml | 7 +++-- models/null_model/work/input.nml | 5 ++- models/pe2lyr/work/input.nml | 5 ++- models/rose/work/input.nml | 5 ++- models/simple_advection/work/input.nml | 5 ++- models/sqg/work/input.nml | 5 ++- models/template/work/oned_input.nml | 5 ++- models/template/work/threed_input.nml | 5 ++- models/tiegcm/work/input.nml | 5 ++- models/wrf/work/input.nml | 5 ++- models/wrf_hydro/work/input.nml | 5 ++- 50 files changed, 214 insertions(+), 80 deletions(-) create mode 100644 assimilation_code/modules/assimilation/algorithm_info_mod.nml diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 index 95d33095e0..aed33c0fc8 100644 --- a/assimilation_code/modules/assimilation/algorithm_info_mod.f90 +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.f90 @@ -13,7 +13,9 @@ module algorithm_info_mod use obs_def_mod, only : obs_def_type, get_obs_def_type_of_obs, get_obs_def_error_variance use obs_kind_mod, only : get_quantity_for_type_of_obs, get_name_for_quantity, get_index_for_quantity -use utilities_mod, only : error_handler, E_ERR, E_MSG, open_file, close_file, to_upper +use utilities_mod, only : error_handler, E_ERR, E_MSG, open_file, close_file, to_upper, & + do_nml_file, do_nml_term, nmlfileunit, check_namelist_read, & + find_namelist_in_file use assim_model_mod, only : get_state_meta_data use location_mod, only : location_type @@ -95,19 +97,23 @@ module algorithm_info_mod character(len=129), allocatable :: dist_type_string_probit_extended_state(:) character(len=129), allocatable :: filter_kind_string(:) +! namelist +character(len=129) :: qceff_table_filename = '' + +namelist /algorithm_info_nml/ qceff_table_filename + contains !------------------------------------------------------------------------- -subroutine init_algorithm_info_mod(qceff_table_filename) +subroutine init_algorithm_info_mod() ! Gets number of lines/QTYs in the QCF table, allocates space for the table data -character(len=129), intent(in) :: qceff_table_filename integer :: fileid -integer :: io +integer :: io, iunit integer :: numrows integer :: nlines @@ -115,6 +121,15 @@ subroutine init_algorithm_info_mod(qceff_table_filename) if (module_initialized) return module_initialized = .true. +! Read the namelist entry +call find_namelist_in_file("input.nml", "algorithm_info_nml", iunit) +read(iunit, nml = algorithm_info_nml, iostat = io) +call check_namelist_read(iunit, io, "algorithm_info_nml") + +if (do_nml_file()) write(nmlfileunit, nml=algorithm_info_nml) +if (do_nml_term()) write( * , nml=algorithm_info_nml) + + if (qceff_table_filename == '') then write(errstring,*) 'No QCF table file listed in namelist, using default values for all QTYs' call error_handler(E_MSG, 'init_algorithm_info_mod:', errstring, source) @@ -163,7 +178,7 @@ subroutine read_qceff_table(qceff_table_filename) integer :: row character(len=obstypelength) :: qty_string -if (.not. module_initialized) call init_algorithm_info_mod(qceff_table_filename) +if (.not. module_initialized) call init_algorithm_info_mod() fileid = open_file(trim(qceff_table_filename), 'formatted', 'read') @@ -305,6 +320,8 @@ subroutine obs_error_info(obs_def, error_variance, & integer :: QTY_loc(1) +if (.not. module_initialized) call init_algorithm_info_mod() + ! Get the type of the observation obs_type = get_obs_def_type_of_obs(obs_def) ! If it is negative, it is an identity obs @@ -376,6 +393,8 @@ subroutine probit_dist_info(qty, is_state, is_inflation, dist_type, & ! In the long run, may not have to have separate controls for each of the input possibilities ! However, for now these are things that need to be explored for science understanding +if (.not. module_initialized) call init_algorithm_info_mod() + !use default values if qceff_table_filename is not in namelist if (use_qty_defaults) then dist_type = NORMAL_DISTRIBUTION @@ -436,6 +455,8 @@ subroutine obs_inc_info(obs_qty, filter_kind, bounded_below, bounded_above, & integer :: QTY_loc(1) +if (.not. module_initialized) call init_algorithm_info_mod() + !use default values if qceff_table_filename is not in namelist if (use_qty_defaults) then filter_kind = EAKF diff --git a/assimilation_code/modules/assimilation/algorithm_info_mod.nml b/assimilation_code/modules/assimilation/algorithm_info_mod.nml new file mode 100644 index 0000000000..730cc67423 --- /dev/null +++ b/assimilation_code/modules/assimilation/algorithm_info_mod.nml @@ -0,0 +1,3 @@ +&algorithm_info_mod + qceff_table_filename = '' +/ diff --git a/assimilation_code/modules/assimilation/assim_tools_mod.nml b/assimilation_code/modules/assimilation/assim_tools_mod.nml index 6169da563d..b0a0b76d71 100644 --- a/assimilation_code/modules/assimilation/assim_tools_mod.nml +++ b/assimilation_code/modules/assimilation/assim_tools_mod.nml @@ -14,8 +14,6 @@ # in both lists, the same number of items &assim_tools_nml - use_algorithm_info_mod = .true., - filter_kind = 1 cutoff = 0.2 distribute_mean = .false. sort_obs_inc = .true. diff --git a/assimilation_code/modules/assimilation/filter_mod.f90 b/assimilation_code/modules/assimilation/filter_mod.f90 index acd4cd5d62..d945abde24 100644 --- a/assimilation_code/modules/assimilation/filter_mod.f90 +++ b/assimilation_code/modules/assimilation/filter_mod.f90 @@ -166,7 +166,6 @@ module filter_mod !---------------------------------------------------------------- ! Namelist input with default values ! -character(len = 129) :: qceff_table_filename = '' integer :: async = 0, ens_size = 20 integer :: tasks_per_model_advance = 1 ! if init_time_days and seconds are negative initial time is 0, 0 @@ -261,7 +260,6 @@ module filter_mod namelist /filter_nml/ async, & - qceff_table_filename, & adv_ens_command, & ens_size, & tasks_per_model_advance, & @@ -1277,7 +1275,7 @@ subroutine filter_initialize_modules_used() call initialize_qc() ! Initialize algorothm_info_mod and read in QCF table data -call init_algorithm_info_mod(qceff_table_filename) +call init_algorithm_info_mod() call trace_message('After filter_initialize_module_used call') diff --git a/assimilation_code/modules/assimilation/filter_mod.nml b/assimilation_code/modules/assimilation/filter_mod.nml index ca9c75f1ce..0e3913be42 100644 --- a/assimilation_code/modules/assimilation/filter_mod.nml +++ b/assimilation_code/modules/assimilation/filter_mod.nml @@ -1,6 +1,4 @@ &filter_nml - qceff_table_filename = '' - use_algorithm_info_mod = .true., single_file_in = .false., input_state_files = '' input_state_file_list = '' diff --git a/assimilation_code/programs/perfect_model_obs/perfect_model_obs.f90 b/assimilation_code/programs/perfect_model_obs/perfect_model_obs.f90 index 97593321c8..6417785e2c 100644 --- a/assimilation_code/programs/perfect_model_obs/perfect_model_obs.f90 +++ b/assimilation_code/programs/perfect_model_obs/perfect_model_obs.f90 @@ -63,7 +63,7 @@ program perfect_model_obs use mpi_utilities_mod, only : my_task_id -use algorithm_info_mod, only : obs_error_info +use algorithm_info_mod, only : init_algorithm_info_mod, obs_error_info, end_algorithm_info_mod implicit none @@ -77,7 +77,6 @@ program perfect_model_obs !----------------------------------------------------------------------------- ! Namelist with default values ! -logical :: use_algorithm_info_mod = .true. logical :: read_input_state_from_file = .false. logical :: write_output_state_to_file = .false. integer :: async = 0 @@ -112,7 +111,7 @@ program perfect_model_obs obs_seq_out_file_name = 'obs_seq.out', & adv_ens_command = './advance_model.csh' -namelist /perfect_model_obs_nml/ use_algorithm_info_mod, read_input_state_from_file,& +namelist /perfect_model_obs_nml/ read_input_state_from_file,& write_output_state_to_file, & init_time_days, init_time_seconds, async, & first_obs_days, first_obs_seconds, & @@ -552,15 +551,8 @@ subroutine perfect_main() if( qc_ens_handle%vars(i, 1) == 0 ) then ! Get the information for generating error sample for this observation - if(use_algorithm_info_mod) then - call obs_error_info(obs_def, error_variance, & - bounded_below, bounded_above, lower_bound, upper_bound) - else - ! Default is unbounded with standard error_variance - error_variance = get_obs_def_error_variance(obs_def) - bounded_below = .false. ; bounded_above = .false. - lower_bound = 0.0_r8; upper_bound = 0.0_r8 - endif + call obs_error_info(obs_def, error_variance, & + bounded_below, bounded_above, lower_bound, upper_bound) ! Capability to do a bounded normal error if(bounded_below .and. bounded_above) then @@ -666,6 +658,8 @@ subroutine perfect_main() call destroy_obs_sequence(seq) call trace_message('After ensemble and obs memory cleanup') +call end_algorithm_info_mod() + call trace_message('Perfect_model done') call timestamp_message('Perfect_model done') @@ -693,6 +687,7 @@ subroutine perfect_initialize_modules_used() call state_vector_io_init() call initialize_qc() +call init_algorithm_info_mod() end subroutine perfect_initialize_modules_used diff --git a/assimilation_code/programs/perfect_model_obs/perfect_model_obs.nml b/assimilation_code/programs/perfect_model_obs/perfect_model_obs.nml index 68f0b8ddad..37a91b74cb 100644 --- a/assimilation_code/programs/perfect_model_obs/perfect_model_obs.nml +++ b/assimilation_code/programs/perfect_model_obs/perfect_model_obs.nml @@ -1,5 +1,4 @@ &perfect_model_obs_nml - use_algorithm_info_mod = .true., read_input_state_from_file = .false., single_file_in = .false., input_state_files = "", diff --git a/guide/qceff-examples.rst b/guide/qceff-examples.rst index de5574aea5..b90c3b58b0 100644 --- a/guide/qceff-examples.rst +++ b/guide/qceff-examples.rst @@ -23,7 +23,7 @@ Build the DART executables for the Lorenz 96 tracer advection model: The new quantile options are set using a :ref:`qceff table ` given as a namelist -option ``qceff_table_filename`` to &filter_nml. The examples below show how to change the quantile options +option ``qceff_table_filename`` to &algorithm_info_nml. The examples below show how to change the quantile options using various qceff tables. You can find the .csv files for these four example in the directory ``DART/models/lorenz_96_tracer_advection/work`` @@ -67,7 +67,7 @@ usually 0. This is a particularly tough test for ensemble methods. .. code-block:: text - &filter_nml + &algorithm_info_nml qceff_table_filename = 'all_bnrhf_qceff_table.csv' @@ -101,7 +101,7 @@ usually 0. This is a particularly tough test for ensemble methods. .. code:: text - &filter_nml + &perfect_model_obs_nml read_input_state_from_file = .true., @@ -127,7 +127,7 @@ Using Ensemble Adjustment Kalman filters. .. code-block:: text - &filter_nml + &algorithm_info_nml qceff_table_filename = 'all_eakf_qceff_table.csv' @@ -145,7 +145,7 @@ Using Ensemble Adjustment Kalman filter for state, but bounded normal rank histo .. code-block:: text - &filter_nml + &algorithm_info_nml qceff_table_filename = 'state_eakf_tracer_bnrhf_qceff_table.csv' @@ -165,7 +165,7 @@ test. .. code-block:: text - &filter_nml + &algorithm_info_nml qceff_table_filename = 'neg_qceff_table.csv' @@ -177,7 +177,7 @@ test. &model_nml positive_tracer = .false., - &filter_nml + &perfect_model_obs_nml read_input_state_from_file = .false., diff --git a/guide/qceff_probit.rst b/guide/qceff_probit.rst index bc60b58784..34e7478702 100644 --- a/guide/qceff_probit.rst +++ b/guide/qceff_probit.rst @@ -7,11 +7,11 @@ The Quantile-Conserving Ensemble Filter Framework (QCEFF) tools are in the alpha The DART development team (dart@ucar.edu) would be happy to hear about your experiences and is anxious to build scientific collaborations using these new capabilities. -The QCEFF options are set using a :ref:`qceff table ` given as a namelist option to &filter_nml. +The QCEFF options are set using a :ref:`qceff table ` given as a namelist option to &algorithm_info_nml. .. code-block:: text - &filter_nml + &algorithm_info_nml qceff_table_filename = 'qceff_table.csv' @@ -76,12 +76,12 @@ Ensure that there are no empty rows in between the quantities listed in the spre Save your spreadsheet as a .csv file. To run filter or perfect_model_obs, put the .csv file in the directory where you are running. -Edit input.nml to set the filter_nml option qceff_table_filename, for example: +Edit input.nml to set the algorithm_info_nml option qceff_table_filename, for example: .. code-block:: text - &filter_nml + &algorithm_info_nml qceff_table_filename = 'qceff_table.csv' diff --git a/models/9var/work/input.nml b/models/9var/work/input.nml index b8f852e952..4ace01b342 100644 --- a/models/9var/work/input.nml +++ b/models/9var/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -35,7 +39,6 @@ # output_state_files = 'filter_output.nc' &filter_nml - qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/FESOM/work/input.nml b/models/FESOM/work/input.nml index abbfa7201e..f8b1d7304b 100644 --- a/models/FESOM/work/input.nml +++ b/models/FESOM/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true. input_state_files = "ENS01.2009.oce.nc" @@ -34,7 +38,6 @@ # state by specifying the 'input' stage. &filter_nml - qceff_table_filename = '' async = 5 adv_ens_command = "advance_model_script.die" ens_size = 3 diff --git a/models/LMDZ/work/input.nml b/models/LMDZ/work/input.nml index 761050c7e7..a3d72caa37 100644 --- a/models/LMDZ/work/input.nml +++ b/models/LMDZ/work/input.nml @@ -1,8 +1,11 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &filter_nml - qceff_table_filename = '', async = 2, adv_ens_command = "./advance_model.csh", ens_size = 40, diff --git a/models/MITgcm_annulus/work/input.nml b/models/MITgcm_annulus/work/input.nml index 8b5ec8c3b1..e91333406d 100644 --- a/models/MITgcm_annulus/work/input.nml +++ b/models/MITgcm_annulus/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml start_from_restart = .false., output_restart = .true., @@ -25,7 +29,6 @@ / &filter_nml - qceff_table_filename = '', async = 0, adv_ens_command = "../shell_scripts/advance_model.csh", ens_size = 20, diff --git a/models/MOM6/work/input.nml b/models/MOM6/work/input.nml index ef48bc6915..e442ab8c2a 100644 --- a/models/MOM6/work/input.nml +++ b/models/MOM6/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -31,7 +35,6 @@ / &filter_nml - qceff_table_filename = '', single_file_in = .false., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/NAAPS/work/input.nml b/models/NAAPS/work/input.nml index 6ed9d62147..92c3ecf452 100644 --- a/models/NAAPS/work/input.nml +++ b/models/NAAPS/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &assim_tools_nml cutoff = 0.03 sort_obs_inc = .false. @@ -125,7 +129,6 @@ &filter_nml - qceff_table_filename = '' async = 0 adv_ens_command = "./advance_model.csh" ens_size = 20 diff --git a/models/NCOMMAS/work/input.nml b/models/NCOMMAS/work/input.nml index 057ed5e13a..f8c477f70b 100644 --- a/models/NCOMMAS/work/input.nml +++ b/models/NCOMMAS/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml start_from_restart = .true., output_restart = .true., @@ -27,7 +31,6 @@ &filter_nml - qceff_table_filename = '', async = 4, adv_ens_command = "../shell_scripts/advance_model.csh", ens_size = 20, diff --git a/models/POP/work/input.nml b/models/POP/work/input.nml index deb22c6825..6fb54e6f2c 100644 --- a/models/POP/work/input.nml +++ b/models/POP/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true. single_file_in = .false. @@ -31,7 +35,6 @@ / &filter_nml - qceff_table_filename = '' async = 0 adv_ens_command = 'no_CESM_advance_script' ens_size = 3 diff --git a/models/ROMS/work/input.nml b/models/ROMS/work/input.nml index f7cbd3e27f..ad4ccd3aca 100644 --- a/models/ROMS/work/input.nml +++ b/models/ROMS/work/input.nml @@ -1,5 +1,9 @@ &probit_transform_nml - / + / + +&algorithm_info_nml + qceff_table_filename = '' + / &perfect_model_obs_nml read_input_state_from_file = .true. @@ -32,7 +36,6 @@ &filter_nml - qceff_table_filename = '' async = 0 adv_ens_command = "DART_trying_to_advance_ROMS_not_supported" ens_size = 3 diff --git a/models/am2/work/input.nml b/models/am2/work/input.nml index 5cc4a2c9ad..3643d228bc 100644 --- a/models/am2/work/input.nml +++ b/models/am2/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml start_from_restart = .true., output_restart = .true., @@ -25,7 +29,6 @@ / &filter_nml - qceff_table_filename = '', async = 2, adv_ens_command = "./advance_model.csh", ens_size = 10, diff --git a/models/bgrid_solo/work/input.nml b/models/bgrid_solo/work/input.nml index b33e5f8191..eebd179d2c 100644 --- a/models/bgrid_solo/work/input.nml +++ b/models/bgrid_solo/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -31,7 +35,6 @@ / &filter_nml - qceff_table_filename = '', single_file_in = .true., input_state_files = 'filter_input.nc' input_state_file_list = '' diff --git a/models/cam-fv/work/input.nml b/models/cam-fv/work/input.nml index ac9bb46de7..8fd9fa689b 100644 --- a/models/cam-fv/work/input.nml +++ b/models/cam-fv/work/input.nml @@ -36,8 +36,11 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &filter_nml - qceff_table_filename = '' input_state_file_list = 'cam_init_files' input_state_files = '' single_file_in = .false. diff --git a/models/cam-se/work/input.nml b/models/cam-se/work/input.nml index f08b4e818a..621ecffcb9 100644 --- a/models/cam-se/work/input.nml +++ b/models/cam-se/work/input.nml @@ -31,8 +31,11 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &filter_nml - qceff_table_filename = '' input_state_files = '' input_state_file_list = 'cam_init_files' single_file_in = .false. diff --git a/models/cice/work/input.nml b/models/cice/work/input.nml index f096104f4c..6b061b9954 100644 --- a/models/cice/work/input.nml +++ b/models/cice/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true. write_output_state_to_file = .true. @@ -25,7 +29,6 @@ / &filter_nml - qceff_table_filename = '' async = 0 adv_ens_command = "no_advance_script" ens_size = 6 diff --git a/models/clm/work/input.nml b/models/clm/work/input.nml index 9bfea0e628..8fc480e653 100644 --- a/models/clm/work/input.nml +++ b/models/clm/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true. write_output_state_to_file = .false. @@ -28,7 +32,6 @@ &filter_nml - qceff_table_filename = '' allow_missing_clm = .true. perturb_from_single_instance = .FALSE. perturbation_amplitude = 0.2 diff --git a/models/cm1/work/input.nml b/models/cm1/work/input.nml index c07a9f9807..465a6d1d82 100644 --- a/models/cm1/work/input.nml +++ b/models/cm1/work/input.nml @@ -5,8 +5,11 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &filter_nml - qceff_table_filename = '' async = 2 adv_ens_command = 'advance_model.csh' input_state_file_list = 'input_filelist.txt' diff --git a/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml b/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml index 6c6bcbf3f3..2bc0b72bcf 100644 --- a/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml +++ b/models/coamps_nest/templates/EXPERIMENT_EXAMPLE/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml start_from_restart = .true., output_restart = .true., @@ -20,7 +24,6 @@ / &filter_nml - qceff_table_filename = '' async = 4, adv_ens_command = "./advance_wrapper.sh", ens_size = 16, diff --git a/models/dynamo/work/input.nml b/models/dynamo/work/input.nml index a1ff28fe86..290276fdaf 100644 --- a/models/dynamo/work/input.nml +++ b/models/dynamo/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml start_from_restart = .false., output_restart = .true., @@ -25,7 +29,6 @@ / &filter_nml - qceff_table_filename = '', async = 2, adv_ens_command = "./advance_model.ksh", ens_size = 20, diff --git a/models/forced_barot/work/input.nml b/models/forced_barot/work/input.nml index 3d07cb5502..9f17e2bb1f 100644 --- a/models/forced_barot/work/input.nml +++ b/models/forced_barot/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml start_from_restart = .true., output_restart = .true., @@ -25,7 +29,6 @@ / &filter_nml - qceff_table_filename = '', async = 0, adv_ens_command = "./advance_model.csh", ens_size = 20, diff --git a/models/forced_lorenz_96/work/input.nml b/models/forced_lorenz_96/work/input.nml index a6a8839ec3..57fa73ea4a 100644 --- a/models/forced_lorenz_96/work/input.nml +++ b/models/forced_lorenz_96/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -33,7 +37,6 @@ # stages_to_write = 'preassim', 'postassim', 'output' &filter_nml - qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/gitm/work/input.nml b/models/gitm/work/input.nml index d9fad6240d..5e5d47f4ef 100644 --- a/models/gitm/work/input.nml +++ b/models/gitm/work/input.nml @@ -1,8 +1,11 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &filter_nml - qceff_table_filename = '' input_state_files = '' input_state_file_list = 'gitm_input_files.txt' single_file_in = .false. diff --git a/models/ikeda/work/input.nml b/models/ikeda/work/input.nml index a7a73a92e6..2f65e7217f 100644 --- a/models/ikeda/work/input.nml +++ b/models/ikeda/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .false., single_file_in = .true. @@ -31,7 +35,6 @@ / &filter_nml - qceff_table_filename = '', single_file_in = .true., input_state_files = 'filter_input.nc' input_state_file_list = '' diff --git a/models/lorenz_04/work/input.nml b/models/lorenz_04/work/input.nml index 9da7ef60dc..2385b45b64 100644 --- a/models/lorenz_04/work/input.nml +++ b/models/lorenz_04/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -35,7 +39,6 @@ # output_state_files = 'filter_output.nc' &filter_nml - qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/lorenz_63/work/input.nml b/models/lorenz_63/work/input.nml index 5626cba931..2a020e875b 100644 --- a/models/lorenz_63/work/input.nml +++ b/models/lorenz_63/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -31,7 +35,6 @@ / &filter_nml - qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/lorenz_84/work/input.nml b/models/lorenz_84/work/input.nml index 1bc0810060..2c8baa0680 100644 --- a/models/lorenz_84/work/input.nml +++ b/models/lorenz_84/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -35,7 +39,6 @@ # output_state_files = 'filter_output.nc' &filter_nml - qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/lorenz_96/work/input.nml b/models/lorenz_96/work/input.nml index 84520de49d..c1ba2dca4e 100644 --- a/models/lorenz_96/work/input.nml +++ b/models/lorenz_96/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -31,7 +35,6 @@ / &filter_nml - qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/lorenz_96_2scale/work/input.nml b/models/lorenz_96_2scale/work/input.nml index 17dc80b6e8..024038aeca 100644 --- a/models/lorenz_96_2scale/work/input.nml +++ b/models/lorenz_96_2scale/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -35,7 +39,6 @@ # output_state_files = 'filter_output.nc' &filter_nml - qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/lorenz_96_tracer_advection/work/input.nml b/models/lorenz_96_tracer_advection/work/input.nml index dd84a5aaeb..955e328a72 100644 --- a/models/lorenz_96_tracer_advection/work/input.nml +++ b/models/lorenz_96_tracer_advection/work/input.nml @@ -1,8 +1,11 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml - use_algorithm_info_mod = .true., read_input_state_from_file = .false., single_file_in = .true. input_state_files = "perfect_input.nc" @@ -32,7 +35,6 @@ / &filter_nml - qceff_table_filename = '', single_file_in = .true., input_state_files = 'perfect_input.nc' input_state_file_list = '' diff --git a/models/mpas_atm/work/input.nml b/models/mpas_atm/work/input.nml index 450f292bde..10a2171162 100644 --- a/models/mpas_atm/work/input.nml +++ b/models/mpas_atm/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true. single_file_in = .false. @@ -31,7 +35,6 @@ / &filter_nml - qceff_table_filename = '' async = 0 adv_ens_command = './advance_model.csh' ens_size = 3 diff --git a/models/mpas_ocn/work/input.nml b/models/mpas_ocn/work/input.nml index ca00423fca..1aa03fe07f 100644 --- a/models/mpas_ocn/work/input.nml +++ b/models/mpas_ocn/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml start_from_restart = .true., output_restart = .true., @@ -25,7 +29,6 @@ / &filter_nml - qceff_table_filename = '', async = 2, adv_ens_command = "../shell_scripts/advance_model.csh", ens_size = 3, diff --git a/models/noah/work/input.nml b/models/noah/work/input.nml index f2b3182374..0f52583682 100644 --- a/models/noah/work/input.nml +++ b/models/noah/work/input.nml @@ -1,7 +1,11 @@ # This namelist is for both NOAH and NOAH-MP &probit_transform_nml - / + / + +&algorithm_info_nml + qceff_table_filename = '' + / &model_nml lsm_model_choice = 'noahMP_36' @@ -52,7 +56,6 @@ &filter_nml - qceff_table_filename = '' input_state_file_list = 'input_file_list.txt' perturb_from_single_instance = .false. init_time_days = -1 diff --git a/models/null_model/work/input.nml b/models/null_model/work/input.nml index ab69b54b66..cbb0e06326 100644 --- a/models/null_model/work/input.nml +++ b/models/null_model/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -31,7 +35,6 @@ / &filter_nml - qceff_table_filename = '', single_file_in = .true., input_state_files = 'filter_input.nc' input_state_file_list = '' diff --git a/models/pe2lyr/work/input.nml b/models/pe2lyr/work/input.nml index 7c61841eea..e25edd4337 100644 --- a/models/pe2lyr/work/input.nml +++ b/models/pe2lyr/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml start_from_restart = .true., output_restart = .true., @@ -25,7 +29,6 @@ / &filter_nml - qceff_table_filename = '', async = 0, adv_ens_command = "./advance_model.csh", ens_size = 20, diff --git a/models/rose/work/input.nml b/models/rose/work/input.nml index a44ff8bff2..8f52f2fb5e 100644 --- a/models/rose/work/input.nml +++ b/models/rose/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml start_from_restart = .false., output_restart = .true., @@ -25,7 +29,6 @@ / &filter_nml - qceff_table_filename = '', async = 2, adv_ens_command = "../shell_scripts/advance_model.csh", ens_size = 20, diff --git a/models/simple_advection/work/input.nml b/models/simple_advection/work/input.nml index 19e26e6cec..cd436c8f4a 100644 --- a/models/simple_advection/work/input.nml +++ b/models/simple_advection/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true. single_file_in = .true. @@ -35,7 +39,6 @@ # output_state_files = 'filter_output.nc' &filter_nml - qceff_table_filename = '' single_file_in = .true. input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/sqg/work/input.nml b/models/sqg/work/input.nml index 4a60a9acd1..5981b6ca67 100644 --- a/models/sqg/work/input.nml +++ b/models/sqg/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml start_from_restart = .true., output_restart = .true., @@ -33,7 +37,6 @@ / &filter_nml - qceff_table_filename = '', async = 0, adv_ens_command = "model called as a subroutine", ens_size = 25, diff --git a/models/template/work/oned_input.nml b/models/template/work/oned_input.nml index 21c8efc29e..65ee6dcb9d 100644 --- a/models/template/work/oned_input.nml +++ b/models/template/work/oned_input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -31,7 +35,6 @@ / &filter_nml - qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/template/work/threed_input.nml b/models/template/work/threed_input.nml index b1e7d9e179..8b50853c78 100644 --- a/models/template/work/threed_input.nml +++ b/models/template/work/threed_input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true., single_file_in = .true. @@ -31,7 +35,6 @@ / &filter_nml - qceff_table_filename = '', single_file_in = .true., input_state_files = '' input_state_file_list = 'filter_input_list.txt' diff --git a/models/tiegcm/work/input.nml b/models/tiegcm/work/input.nml index fb0fdea050..7420562fa9 100644 --- a/models/tiegcm/work/input.nml +++ b/models/tiegcm/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &quality_control_nml / @@ -41,7 +45,6 @@ # output_state_file_list = 'out_restart_p_files.txt', 'out_secondary_files.txt', 'out_f10.7.txt' &filter_nml - qceff_table_filename = '', single_file_in = .false., input_state_files = '' input_state_file_list = 'restart_p_files.txt', 'secondary_files.txt' diff --git a/models/wrf/work/input.nml b/models/wrf/work/input.nml index 41ce4227a7..aec2653ea6 100644 --- a/models/wrf/work/input.nml +++ b/models/wrf/work/input.nml @@ -1,6 +1,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &perfect_model_obs_nml read_input_state_from_file = .true. single_file_in = .false. @@ -31,7 +35,6 @@ / &filter_nml - qceff_table_filename = '', async = 0, adv_ens_command = "../shell_scripts/advance_model.csh", ens_size = 3, diff --git a/models/wrf_hydro/work/input.nml b/models/wrf_hydro/work/input.nml index 07ddafbf98..7ab439a0ca 100644 --- a/models/wrf_hydro/work/input.nml +++ b/models/wrf_hydro/work/input.nml @@ -10,6 +10,10 @@ &probit_transform_nml / +&algorithm_info_nml + qceff_table_filename = '' + / + &model_nml assimilation_period_days = 0 assimilation_period_seconds = 3600 @@ -74,7 +78,6 @@ # output_state_file_list = 'hydro_file_list.txt' &filter_nml - qceff_table_filename = '' input_state_file_list = 'hydro_file_list.txt' single_file_in = .false. init_time_days = -1, From dd0a96ba3ebaa98f8455e9bb54029f6d9a7c1d35 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Wed, 1 Nov 2023 13:09:36 -0600 Subject: [PATCH 128/129] Fixing typo in the qceff-examples doc --- guide/qceff-examples.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/qceff-examples.rst b/guide/qceff-examples.rst index b90c3b58b0..123a9a3d9c 100644 --- a/guide/qceff-examples.rst +++ b/guide/qceff-examples.rst @@ -181,4 +181,4 @@ test. read_input_state_from_file = .false., -#. Repeat steps 5-8 from Test A. +#. Repeat steps 3-6 from Test A. From 876963ee7d95b99a125a90f724623c43319c11b5 Mon Sep 17 00:00:00 2001 From: Marlee Smith Date: Thu, 2 Nov 2023 12:51:17 -0600 Subject: [PATCH 129/129] Updating the CHANGELOG and version # in conf.py --- CHANGELOG.rst | 14 ++++++++++++++ conf.py | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 20689760e4..ff4686efe6 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -22,6 +22,20 @@ individual files. The changes are now listed with the most recent at the top. +**November 2 2023 :: QCEFF Input Table. Tag v11.1.0-alpha** + +- The QCEFF input table allows for the specification of QCEFF/probit + input options, per QTY, at runtime. +- This replaces the functionality of using an algorithm_info_mod specific + to the model, which meant editing algorithm_info_mod.f90 to specify + which distribution should be used for which quantity. +- The algorithm_info_mod files for the lorenz_96_tracer_advection model + examples have been replaced with set QCF tables (all_bnrhf_qcf_table.csv, + all_eakf_qcf_table.csv, state_eakf_tracer_bnrhf_qcf_table.csv, + neg_qcf_table.csv) and can be found in lorenz_96_tracer_advection/work. +- Removed the ‘global’ version of filter_kind from assim_tools_mod.f90 + and the &assim_tools_nml + **October 5 2023 :: WRF-DART tutorial diagnostic section. Tag v10.8.5** - Improvements: diff --git a/conf.py b/conf.py index 87e25bad53..eea345845e 100644 --- a/conf.py +++ b/conf.py @@ -21,7 +21,7 @@ author = 'Data Assimilation Research Section' # The full version, including alpha/beta/rc tags -release = '10.8.5' +release = '11.1.0-alpha' root_doc = 'index' # -- General configuration ---------------------------------------------------