From c4ac7af4b4d692701be6b729e240245af286f4cd Mon Sep 17 00:00:00 2001 From: tsga Date: Sat, 31 Jan 2026 12:12:34 +0000 Subject: [PATCH 01/15] add snow ensemble configs --- build.sh | 25 +-- .../snow/snow_background_ensemble.yaml.j2 | 30 +++ .../snow/snow_ensemble_increments_fms.yaml.j2 | 24 +++ ..._ensemble_increments_fms_norestart.yaml.j2 | 4 + .../snow/snow_posterior_output_fms.yaml.j2 | 25 +++ parm/snow/jcb-base.yaml.j2 | 15 +- parm/snow/jcb-prototype_lgetkf.yaml.j2 | 21 ++ .../jcb-prototype_lgetkf_observer.yaml.j2 | 28 +++ parm/snow/jcb-prototype_lgetkf_solver.yaml.j2 | 31 +++ parm/snow/snow_ensda_config.yaml.j2 | 204 ++++++++++++++++++ 10 files changed, 388 insertions(+), 19 deletions(-) create mode 100644 parm/jcb-gdas/model/snow/snow_background_ensemble.yaml.j2 create mode 100644 parm/jcb-gdas/model/snow/snow_ensemble_increments_fms.yaml.j2 create mode 100644 parm/jcb-gdas/model/snow/snow_ensemble_increments_fms_norestart.yaml.j2 create mode 100644 parm/jcb-gdas/model/snow/snow_posterior_output_fms.yaml.j2 create mode 100644 parm/snow/jcb-prototype_lgetkf.yaml.j2 create mode 100644 parm/snow/jcb-prototype_lgetkf_observer.yaml.j2 create mode 100644 parm/snow/jcb-prototype_lgetkf_solver.yaml.j2 create mode 100644 parm/snow/snow_ensda_config.yaml.j2 diff --git a/build.sh b/build.sh index 252a98557..9b173062e 100755 --- a/build.sh +++ b/build.sh @@ -112,18 +112,19 @@ mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR} # Set WORKFLOW_TESTS as CMake option CMAKE_OPTS+=" -DWORKFLOW_TESTS=${WORKFLOW_TESTS:-${WORKFLOW_BUILD}}" -if [[ $BUILD_SOCA == 'ON' ]]; then - if [[ $WORKFLOW_BUILD == 'ON' ]]; then - # Link MOM6 and Icepack in SOCA to submodules in the UFS repo - rm -rf $dir_root/sorc/soca/external/mom6/MOM6 - rm -rf $dir_root/sorc/soca/external/icepack/Icepack - ln -sf $HOMEgfs/sorc/ufs_model.fd/MOM6-interface/MOM6/ $dir_root/sorc/soca/external/mom6/MOM6 - ln -sf $HOMEgfs/sorc/ufs_model.fd/CICE-interface/CICE/icepack/ $dir_root/sorc/soca/external/icepack/Icepack - else - # Delete forked SOCA NOAA-EMC dev/emc repo and clone the original JCSDA develop repo - rm -rf "$dir_root/sorc/soca/" - git clone https://github.com/jcsda/soca "$dir_root/sorc/soca" --recurse-submodules - fi +if [[ $WORKFLOW_BUILD == 'ON' ]]; then + # Link MOM6 and Icepack in SOCA to submodules in the UFS repo + rm -rf $dir_root/sorc/soca/external/mom6/MOM6 + rm -rf $dir_root/sorc/soca/external/icepack/Icepack + ln -sf $HOMEgfs/sorc/ufs_model.fd/MOM6-interface/MOM6/ $dir_root/sorc/soca/external/mom6/MOM6 + ln -sf $HOMEgfs/sorc/ufs_model.fd/CICE-interface/CICE/icepack/ $dir_root/sorc/soca/external/icepack/Icepack +else + # Delete forked SOCA NOAA-EMC dev/emc repo and clone the original JCSDA develop repo + rm -rf "$dir_root/sorc/soca/" + git clone https://github.com/jcsda/soca "$dir_root/sorc/soca" --recurse-submodules + cd "$dir_root/sorc/soca" + git checkout 733ac0177ad0b45e04586f2ead5aa67137da332c + cd ${BUILD_DIR} fi if [[ $BUILD_IODA_CONVERTERS == 'YES' ]]; then diff --git a/parm/jcb-gdas/model/snow/snow_background_ensemble.yaml.j2 b/parm/jcb-gdas/model/snow/snow_background_ensemble.yaml.j2 new file mode 100644 index 000000000..73b1afdab --- /dev/null +++ b/parm/jcb-gdas/model/snow/snow_background_ensemble.yaml.j2 @@ -0,0 +1,30 @@ +datetime: '{{ snow_background_time_iso }}' +members from template: + template: + datetime: '{{ snow_background_time_iso }}' + filetype: fms restart + skip coupler file: true +# provider: ufs + state variables: + - totalSnowDepth + - vtype + - slmsk + - sheleg + - filtered_orography + - fraction_of_ice + - fraction_of_land + - stc + field io names: + totalSnowDepth: snodl + filtered_orography: orog_filt + fraction_of_ice: fice + fraction_of_land: land_frac + datapath: {{ snow_background_ensemble_path }} + filename is datetime templated: true + filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' + filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' + filename_orog: '{{ snow_orog_prefix }}_oro_data.nc' + max allowable geometry difference: 1e-4 + pattern: "{{ snow_ensemble_pattern | default("%mem%", true) }}" + nmembers: {{ snow_number_ensemble_members }} + zero padding: 3 diff --git a/parm/jcb-gdas/model/snow/snow_ensemble_increments_fms.yaml.j2 b/parm/jcb-gdas/model/snow/snow_ensemble_increments_fms.yaml.j2 new file mode 100644 index 000000000..25fd93136 --- /dev/null +++ b/parm/jcb-gdas/model/snow/snow_ensemble_increments_fms.yaml.j2 @@ -0,0 +1,24 @@ +output: + state component: + datapath: ./anl/mem%{member}% + prefix: snowinc + filetype: fms restart + filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' + filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' + state variables: + - totalSnowDepth + - vtype + - slmsk + field io names: + totalSnowDepth: snodl +geometry: + fms initialization: + namelist filename: "{{ snow_fv3jedi_files_path }}/fmsmpp.nml" + field table filename: "{{ snow_fv3jedi_files_path }}/field_table" + akbk: "{{ snow_fv3jedi_files_path }}/akbk.nc4" + layout: + - {{ snow_layout_x }} + - {{ snow_layout_y }} + npx: {{ snow_npx_ges }} + npy: {{ snow_npy_ges }} + npz: {{ snow_npz_ges }} diff --git a/parm/jcb-gdas/model/snow/snow_ensemble_increments_fms_norestart.yaml.j2 b/parm/jcb-gdas/model/snow/snow_ensemble_increments_fms_norestart.yaml.j2 new file mode 100644 index 000000000..f065f10fd --- /dev/null +++ b/parm/jcb-gdas/model/snow/snow_ensemble_increments_fms_norestart.yaml.j2 @@ -0,0 +1,4 @@ +filetype: fms restart +is restart: false +datapath: ./anl/mem%{member}% +filename_nonrestart: cubed_sphere_grid_sfcinc.jedi.nc diff --git a/parm/jcb-gdas/model/snow/snow_posterior_output_fms.yaml.j2 b/parm/jcb-gdas/model/snow/snow_posterior_output_fms.yaml.j2 new file mode 100644 index 000000000..e2dff3304 --- /dev/null +++ b/parm/jcb-gdas/model/snow/snow_posterior_output_fms.yaml.j2 @@ -0,0 +1,25 @@ +output: + state component: + datapath: ./anl + prefix: snow_posterior_ensmean + filetype: fms restart + filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' + filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' + state variables: + - totalSnowDepth + - vtype + - slmsk + field io names: + totalSnowDepth: snodl +geometry: + fms initialization: + namelist filename: "{{ snow_fv3jedi_files_path }}/fmsmpp.nml" + field table filename: "{{ snow_fv3jedi_files_path }}/field_table" + akbk: "{{ snow_fv3jedi_files_path }}/akbk.nc4" + layout: + - {{ snow_layout_x }} + - {{ snow_layout_y }} + npx: {{ snow_npx_ges }} + npy: {{ snow_npy_ges }} + npz: {{ snow_npz_ges }} + diff --git a/parm/snow/jcb-base.yaml.j2 b/parm/snow/jcb-base.yaml.j2 index 1067a721e..f4519d0d0 100644 --- a/parm/snow/jcb-base.yaml.j2 +++ b/parm/snow/jcb-base.yaml.j2 @@ -9,10 +9,12 @@ app_path_observation_chronicle: "{{PARMgfs}}/gdas/jcb-gdas/observation_chronicle # Places where we deviate from the generic file name of a yaml # ------------------------------------------------------------ -final_increment_file: snow_final_increment_fms model_file: model_pseudo initial_condition_file: background # Initial conditions for 4D apps is background - +#jedi_increment_output: gaussian +final_increment_file: snow_final_increment_fms +output_ensemble_increments_file: snow_ensemble_increments_fms +posterior_output_file: snow_posterior_output_fms # Assimilation window # ------------------- @@ -30,7 +32,6 @@ snow_background_time_julian: "{{ bkg_time_julian }}" snow_increment_time_iso: "{{ bkg_time_iso }}" snow_increment_time_fv3: "{{ bkg_time_fv3 }}" - # Analysis standard things # ------------------------ analysis_variables: [totalSnowDepth] @@ -60,12 +61,11 @@ snow_orog_prefix: "{{ CASE }}.mx{{ OCNRES }}" # Background snow_background_path: {{snow_bkg_path}} -background_ensemble_path: ./ens/mem%mem% +background_ensemble_path: ./ens/mem%mem% #TODO: this may not be ncessary +snow_background_ensemble_path: ./bkg/mem%mem% # Background error snow_bump_data_directory: "{{ DATA }}/berror" -number_ensemble_members: {{ NMEM_ENS | default(1, true) }} - snow_background_error_file: "{{BERROR_YAML}}" # Forecasting @@ -105,7 +105,8 @@ snow_obsbiascovout_prefix: "{{APREFIX}}" snow_obsbiascovout_suffix: ".satbias_cov.nc" # Ensemble mean things -snow_number_ensemble_members: {{NMEM_ENS}} +snow_number_ensemble_members: {{NMEM_ENS}} #do we need the below? +number_ensemble_members: {{ NMEM_ENS | default(1, true) }} # Local Ensemble DA (LETKF) # ------------------------- diff --git a/parm/snow/jcb-prototype_lgetkf.yaml.j2 b/parm/snow/jcb-prototype_lgetkf.yaml.j2 new file mode 100644 index 000000000..2a41c0118 --- /dev/null +++ b/parm/snow/jcb-prototype_lgetkf.yaml.j2 @@ -0,0 +1,21 @@ +# Use observations for lgetkf +# --------------------------- +app_path_observations: {{PARMgfs}}/gdas/jcb-gdas/observations/snow +app_path_observation_chronicle: {{PARMgfs}}/gdas/jcb-gdas/observation_chronicle/snow/{{cycle}} +# Algorithm +# --------- +algorithm: local_ensemble_da + +# Model things +# ------------ +snow_background_ensemble_path: ./bkg/mem%mem% + +# Observation things +# ------------------ +{% include OBS_LIST_YAML %} + +# Testing things +# -------------- +{% if DO_TEST_MODE %} +{% include LETKF_JEDI_TEST_YAML %} +{% endif %} diff --git a/parm/snow/jcb-prototype_lgetkf_observer.yaml.j2 b/parm/snow/jcb-prototype_lgetkf_observer.yaml.j2 new file mode 100644 index 000000000..f188fecf1 --- /dev/null +++ b/parm/snow/jcb-prototype_lgetkf_observer.yaml.j2 @@ -0,0 +1,28 @@ +# Use observations for lgetkf +# --------------------------- +app_path_observations: {{PARMgfs}}/gdas/jcb-gdas/observations/atmosphere-lgetkf +app_path_observation_chronicle: {{PARMgfs}}/gdas/jcb-gdas/observation_chronicle/atmosphere + +# Algorithm +# --------- +algorithm: local_ensemble_da_observer + +# Model things +# ------------ +atmosphere_background_ensemble_path: ./bkg/mem%mem% + +# Naming conventions for observation files +atmosphere_obsdataout_prefix: diag_lobs_ + +# Distribution type +distribution_type: RoundRobin + +# Observation things +# ------------------ +{% include OBS_LIST_YAML %} + +# Testing things +# -------------- +{% if DO_TEST_MODE %} +{% include OBS_JEDI_TEST_YAML %} +{% endif %} diff --git a/parm/snow/jcb-prototype_lgetkf_solver.yaml.j2 b/parm/snow/jcb-prototype_lgetkf_solver.yaml.j2 new file mode 100644 index 000000000..abd0022dd --- /dev/null +++ b/parm/snow/jcb-prototype_lgetkf_solver.yaml.j2 @@ -0,0 +1,31 @@ +# Use observations for lgetkf +# --------------------------- +app_path_observations: {{PARMgfs}}/gdas/jcb-gdas/observations/atmosphere-lgetkf +app_path_observation_chronicle: {{PARMgfs}}/gdas/jcb-gdas/observation_chronicle/atmosphere + +# Algorithm +# --------- +algorithm: local_ensemble_da_solver + +# Model things +# ------------ +atmosphere_background_ensemble_path: ./bkg/mem%mem% + +# Naming conventions for observation files +atmosphere_obsdatain_path: "{{DATA}}/diags" +atmosphere_obsdatain_prefix: diag_lobs_ +atmosphere_obsdatain_suffix: "_{{ current_cycle | to_YMDH }}.nc" +atmosphere_obsdataout_prefix: diag_solv_ + +# Distribution type +distribution_type: Halo + +# Observation things +# ------------------ +{% include OBS_LIST_YAML %} + +# Testing things +# -------------- +{% if DO_TEST_MODE %} +{% include SOL_JEDI_TEST_YAML %} +{% endif %} diff --git a/parm/snow/snow_ensda_config.yaml.j2 b/parm/snow/snow_ensda_config.yaml.j2 new file mode 100644 index 000000000..86014387f --- /dev/null +++ b/parm/snow/snow_ensda_config.yaml.j2 @@ -0,0 +1,204 @@ +jedi_config: + snowensanlobs: + rundir: '{{ DATA }}' + exe_src: '{{ EXECgfs }}/gdas.x' + mpi_cmd: '{{ APRUN_SNOWENSANLOBS }}' + jedi_args: ['fv3jedi', 'localensembleda'] + jcb_base_yaml: '{{ PARMgfs }}/gdas/snow/jcb-base.yaml.j2' + jcb_algo_yaml: '{{ PARMgfs }}/gdas/snow/jcb-prototype_lgetkf_observer.yaml.j2' + obs_list_yaml: '{{ OBS_LIST_YAML }}' + snowensanlsol: + rundir: '{{ DATA }}' + exe_src: '{{ EXECgfs }}/gdas.x' + mpi_cmd: '{{ APRUN_SNOWENSANLSOL }}' + jedi_args: ['fv3jedi', 'localensembleda'] + jcb_base_yaml: '{{ PARMgfs }}/gdas/snow/jcb-base.yaml.j2' + jcb_algo_yaml: '{{ PARMgfs }}/gdas/snow/jcb-prototype_lgetkf_solver.yaml.j2' + obs_list_yaml: '{{ OBS_LIST_YAML }}' + snowensanlletkf: + rundir: '{{ DATA }}' + exe_src: '{{ EXECgfs }}/gdas.x' + mpi_cmd: '{{ APRUN_SNOWENSANLLETKF }}' + jedi_args: ['fv3jedi', 'localensembleda'] + jcb_base_yaml: '{{ PARMgfs }}/gdas/snow/jcb-base.yaml.j2' +#TODO: 'TESTING' clause here not ported jcb_algo_yaml: '{{ PARMgfs }}/gdas/snow/jcb-prototype_lgetkf.yaml.j2' + jcb_algo: 'local_ensemble_da' + obs_list_yaml: '{{ OBS_LIST_YAML }}' + scf_to_ioda: + rundir: '{{ DATA }}' + exe_src: '{{ EXECgfs }}/gdas_fv3jedi_scf_to_ioda.x' + mpi_cmd: '{{ APRUN_SNOWANL }}' + jcb_algo: 'snow_ims_scf_preprocess' + jcb_base_yaml: '{{ PARMgfs }}/gdas/snow/jcb-base.yaml.j2' +# snowensanlfv3inc: +# rundir: '{{ DATA }}' +# exe_src: '{{ EXECgfs }}/gdas_fv3jedi_fv3inc.x' +# mpi_cmd: '{{ APRUN_SNOWENSANLFV3INC }}' +# jcb_algo: 'fv3jedi_fv3inc_lgetkf' +# jcb_base_yaml: '{{ PARMgfs }}/gdas/snow/jcb-base.yaml.j2' +# snowanladdinc: +# rundir: '{{ DATA }}' +# exe_src: '{{ EXECgdas }}/fv3jedi_addincrement.x' +# mpi_cmd: '{{ APRUN_SNOW_ADDINC }}' +# jcb_base_yaml: '{{ PARMgdas }}/snow/jcb-base.yaml.j2' +# jcb_algo: snow_addincrement + +data_in: + mkdir: + - '{{ DATA }}/bkg' + - '{{ DATA }}/anl' + - '{{ DATA }}/bkg/ensmean' + - '{{ DATA }}/anl/ensmean' +{% for mem in range(1, NMEM_ENS + 1) %} + - '{{ DATA }}/bkg/mem{{ '%03d' % mem }}' + - '{{ DATA }}/anl/mem{{ '%03d' % mem }}' +{% endfor %} + - '{{ DATA }}/orog/ens' + - '{{ DATA }}/fv3jedi' + - '{{ DATA }}/berror' + + copy_req: +{% for mem in range(1, NMEM_ENS + 1) %} + {% set gmem = mem+mem_offset %} + {% if gmem > NMEM_ENS_MAX %} + {% set gmem = gmem-NMEM_ENS_MAX %} + {% endif %} + # define variables + # copy coupler file + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ current_cycle | to_fv3time }}.coupler.res', '{{ DATA }}/bkg/mem{{ '%03d' % mem }}/'] + # we need to copy them to two places, one serves as the basis for the analysis + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ current_cycle | to_fv3time }}.sfc_data.tile1.nc', '{{ DATA }}/bkg/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ current_cycle | to_fv3time }}.sfc_data.tile2.nc', '{{ DATA }}/bkg/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ current_cycle | to_fv3time }}.sfc_data.tile3.nc', '{{ DATA }}/bkg/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ current_cycle | to_fv3time }}.sfc_data.tile4.nc', '{{ DATA }}/bkg/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ current_cycle | to_fv3time }}.sfc_data.tile5.nc', '{{ DATA }}/bkg/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ current_cycle | to_fv3time }}.sfc_data.tile6.nc', '{{ DATA }}/bkg/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ current_cycle | to_fv3time }}.sfc_data.tile1.nc', '{{ DATA }}/anl/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ current_cycle | to_fv3time }}.sfc_data.tile2.nc', '{{ DATA }}/anl/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ current_cycle | to_fv3time }}.sfc_data.tile3.nc', '{{ DATA }}/anl/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ current_cycle | to_fv3time }}.sfc_data.tile4.nc', '{{ DATA }}/anl/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ current_cycle | to_fv3time }}.sfc_data.tile5.nc', '{{ DATA }}/anl/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ current_cycle | to_fv3time }}.sfc_data.tile6.nc', '{{ DATA }}/anl/mem{{ '%03d' % mem }}/'] + {% if DOIAU %} + # if using IAU, also need backgrounds copied at the beginning of the window + # we need to copy them to two places, one serves as the basis for the analysis + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ WINDOW_BEGIN | to_fv3time }}.sfc_data.tile1.nc', '{{ DATA }}/bkg/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ WINDOW_BEGIN | to_fv3time }}.sfc_data.tile2.nc', '{{ DATA }}/bkg/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ WINDOW_BEGIN | to_fv3time }}.sfc_data.tile3.nc', '{{ DATA }}/bkg/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ WINDOW_BEGIN | to_fv3time }}.sfc_data.tile4.nc', '{{ DATA }}/bkg/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ WINDOW_BEGIN | to_fv3time }}.sfc_data.tile5.nc', '{{ DATA }}/bkg/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ WINDOW_BEGIN | to_fv3time }}.sfc_data.tile6.nc', '{{ DATA }}/bkg/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ WINDOW_BEGIN | to_fv3time }}.sfc_data.tile1.nc', '{{ DATA }}/anl/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ WINDOW_BEGIN | to_fv3time }}.sfc_data.tile2.nc', '{{ DATA }}/anl/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ WINDOW_BEGIN | to_fv3time }}.sfc_data.tile3.nc', '{{ DATA }}/anl/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ WINDOW_BEGIN | to_fv3time }}.sfc_data.tile4.nc', '{{ DATA }}/anl/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ WINDOW_BEGIN | to_fv3time }}.sfc_data.tile5.nc', '{{ DATA }}/anl/mem{{ '%03d' % mem }}/'] + - ['{{ COMIN_ATMOS_RESTART_PREV_ENS }}/mem{{ '%03d' % gmem }}/{{ WINDOW_BEGIN | to_fv3time }}.sfc_data.tile6.nc', '{{ DATA }}/anl/mem{{ '%03d' % mem }}/'] + {% endif %} +{% endfor %} + +{% filter indent(width=4) %} +{% include 'snow_stage_jedi_fix.yaml.j2' %} +{% include 'snow_stage_berror.yaml.j2' %} +{% include 'snow_stage_bufr2ioda_mapping.yaml.j2' %} +{% endfilter %} + + - ['{{ FIXorog }}/{{ CASE_ENS }}/{{ CASE_ENS }}_mosaic.nc', '{{ DATA }}/orog/ens/'] + - ['{{ FIXorog }}/{{ CASE_ENS }}/{{ CASE_ENS }}_grid.tile1.nc', '{{ DATA }}/orog/ens/'] + - ['{{ FIXorog }}/{{ CASE_ENS }}/{{ CASE_ENS }}_grid.tile2.nc', '{{ DATA }}/orog/ens/'] + - ['{{ FIXorog }}/{{ CASE_ENS }}/{{ CASE_ENS }}_grid.tile3.nc', '{{ DATA }}/orog/ens/'] + - ['{{ FIXorog }}/{{ CASE_ENS }}/{{ CASE_ENS }}_grid.tile4.nc', '{{ DATA }}/orog/ens/'] + - ['{{ FIXorog }}/{{ CASE_ENS }}/{{ CASE_ENS }}_grid.tile5.nc', '{{ DATA }}/orog/ens/'] + - ['{{ FIXorog }}/{{ CASE_ENS }}/{{ CASE_ENS }}_grid.tile6.nc', '{{ DATA }}/orog/ens/'] + - ['{{ FIXorog }}/{{ CASE_ENS }}/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile1.nc', '{{ DATA }}/orog/ens/' ] + - ['{{ FIXorog }}/{{ CASE_ENS }}/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile2.nc', '{{ DATA }}/orog/ens/' ] + - ['{{ FIXorog }}/{{ CASE_ENS }}/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile3.nc', '{{ DATA }}/orog/ens/' ] + - ['{{ FIXorog }}/{{ CASE_ENS }}/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile4.nc', '{{ DATA }}/orog/ens/' ] + - ['{{ FIXorog }}/{{ CASE_ENS }}/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile5.nc', '{{ DATA }}/orog/ens/' ] + - ['{{ FIXorog }}/{{ CASE_ENS }}/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile6.nc', '{{ DATA }}/orog/ens/' ] + + link_req: +{% for imem in range(1, NMEM_ENS+1) %} + {% set memchar = 'mem%03d' | format(imem) %} + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}_mosaic.nc', '{{ DATA }}/bkg/{{ memchar }}/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}_grid.tile1.nc', '{{ DATA }}/bkg/{{ memchar }}/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}_grid.tile2.nc', '{{ DATA }}/bkg/{{ memchar }}/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}_grid.tile3.nc', '{{ DATA }}/bkg/{{ memchar }}/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}_grid.tile4.nc', '{{ DATA }}/bkg/{{ memchar }}/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}_grid.tile5.nc', '{{ DATA }}/bkg/{{ memchar }}/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}_grid.tile6.nc', '{{ DATA }}/bkg/{{ memchar }}/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile1.nc', '{{ DATA }}/bkg/{{ memchar }}/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile2.nc', '{{ DATA }}/bkg/{{ memchar }}/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile3.nc', '{{ DATA }}/bkg/{{ memchar }}/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile4.nc', '{{ DATA }}/bkg/{{ memchar }}/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile5.nc', '{{ DATA }}/bkg/{{ memchar }}/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile6.nc', '{{ DATA }}/bkg/{{ memchar }}/'] +{% endfor %} + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}_mosaic.nc', '{{ DATA }}/bkg/ensmean/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}_grid.tile1.nc', '{{ DATA }}/bkg/ensmean/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}_grid.tile2.nc', '{{ DATA }}/bkg/ensmean/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}_grid.tile3.nc', '{{ DATA }}/bkg/ensmean/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}_grid.tile4.nc', '{{ DATA }}/bkg/ensmean/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}_grid.tile5.nc', '{{ DATA }}/bkg/ensmean/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}_grid.tile6.nc', '{{ DATA }}/bkg/ensmean/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile1.nc', '{{ DATA }}/bkg/ensmean/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile2.nc', '{{ DATA }}/bkg/ensmean/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile3.nc', '{{ DATA }}/bkg/ensmean/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile4.nc', '{{ DATA }}/bkg/ensmean/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile5.nc', '{{ DATA }}/bkg/ensmean/'] + - ['{{ DATA }}/orog/ens/{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data.tile6.nc', '{{ DATA }}/bkg/ensmean/'] + + copy_opt: +{% filter indent(width=4) %} +{% if DO_IMS_SCF %} +{% include 'snow_stage_ims_scf2ioda.yaml.j2' %} +{% endif %} +{% endfilter %} + +data_out: + copy_req: + # Configuration files + - ['{{ DATA }}/snowanlvar.yaml', '{{ COMOUT_CONF }}/{{ APREFIX_ENS }}snowanlvar.yaml'] + - ['{{ DATA }}/esnowanlensmean.yaml', '{{ COMOUT_CONF }}/{{ APREFIX_ENS }}esnowanlensmean.yaml'] +{% if DO_IMS_SCF %} + - ['{{ DATA }}/scf_to_ioda.yaml', '{{ COMOUT_CONF }}/{{ APREFIX_ENS }}scf_to_ioda.yaml'] +{% endif %} + +{% if DOIAU %} + {% set bkgtimes = [ current_cycle, WINDOW_BEGIN ] %} +{% else %} + {% set bkgtimes = [ current_cycle ] %} +{% endif %} +{% for bkgtime in bkgtimes %} + {% for imem in range(1, NMEM_ENS+1) %} + {% set memchar = 'mem%03d' | format(imem) %} + # Analysis + - ['{{ DATA }}/anl/{{ memchar }}/{{ bkgtime | to_fv3time }}.sfc_data.tile1.nc', + '{{ COMOUT_SNOW_ANALYSIS }}/{{ memchar }}/{{ bkgtime | to_fv3time }}.snow_analysis.sfc_data.tile1.nc'] + - ['{{ DATA }}/anl/{{ memchar }}/{{ bkgtime | to_fv3time }}.sfc_data.tile2.nc', + '{{ COMOUT_SNOW_ANALYSIS }}/{{ memchar }}/{{ bkgtime | to_fv3time }}.snow_analysis.sfc_data.tile2.nc'] + - ['{{ DATA }}/anl/{{ memchar }}/{{ bkgtime | to_fv3time }}.sfc_data.tile3.nc', + '{{ COMOUT_SNOW_ANALYSIS }}/{{ memchar }}/{{ bkgtime | to_fv3time }}.snow_analysis.sfc_data.tile3.nc'] + - ['{{ DATA }}/anl/{{ memchar }}/{{ bkgtime | to_fv3time }}.sfc_data.tile4.nc', + '{{ COMOUT_SNOW_ANALYSIS }}/{{ memchar }}/{{ bkgtime | to_fv3time }}.snow_analysis.sfc_data.tile4.nc'] + - ['{{ DATA }}/anl/{{ memchar }}/{{ bkgtime | to_fv3time }}.sfc_data.tile5.nc', + '{{ COMOUT_SNOW_ANALYSIS }}/{{ memchar }}/{{ bkgtime | to_fv3time }}.snow_analysis.sfc_data.tile5.nc'] + - ['{{ DATA }}/anl/{{ memchar }}/{{ bkgtime | to_fv3time }}.sfc_data.tile6.nc', + '{{ COMOUT_SNOW_ANALYSIS }}/{{ memchar }}/{{ bkgtime | to_fv3time }}.snow_analysis.sfc_data.tile6.nc'] + + # Increments + - ['{{ DATA }}/anl/{{ memchar }}/snowinc.{{ bkgtime | to_fv3time }}.sfc_data.tile1.nc', + '{{ COMOUT_SNOW_ANALYSIS }}/{{ memchar }}/{{ bkgtime | to_fv3time }}.snow_increment.sfc_data.tile1.nc'] + - ['{{ DATA }}/anl/{{ memchar }}/snowinc.{{ bkgtime | to_fv3time }}.sfc_data.tile2.nc', + '{{ COMOUT_SNOW_ANALYSIS }}/{{ memchar }}/{{ bkgtime | to_fv3time }}.snow_increment.sfc_data.tile2.nc'] + - ['{{ DATA }}/anl/{{ memchar }}/snowinc.{{ bkgtime | to_fv3time }}.sfc_data.tile3.nc', + '{{ COMOUT_SNOW_ANALYSIS }}/{{ memchar }}/{{ bkgtime | to_fv3time }}.snow_increment.sfc_data.tile3.nc'] + - ['{{ DATA }}/anl/{{ memchar }}/snowinc.{{ bkgtime | to_fv3time }}.sfc_data.tile4.nc', + '{{ COMOUT_SNOW_ANALYSIS }}/{{ memchar }}/{{ bkgtime | to_fv3time }}.snow_increment.sfc_data.tile4.nc'] + - ['{{ DATA }}/anl/{{ memchar }}/snowinc.{{ bkgtime | to_fv3time }}.sfc_data.tile5.nc', + '{{ COMOUT_SNOW_ANALYSIS }}/{{ memchar }}/{{ bkgtime | to_fv3time }}.snow_increment.sfc_data.tile5.nc'] + - ['{{ DATA }}/anl/{{ memchar }}/snowinc.{{ bkgtime | to_fv3time }}.sfc_data.tile6.nc', + '{{ COMOUT_SNOW_ANALYSIS }}/{{ memchar }}/{{ bkgtime | to_fv3time }}.snow_increment.sfc_data.tile6.nc'] + + {% endfor %} +{% endfor %} From 98042761591bc8d46cf884240b05f1a26d9071e9 Mon Sep 17 00:00:00 2001 From: tsga Date: Sat, 31 Jan 2026 13:02:04 +0000 Subject: [PATCH 02/15] fix bkg and ens inc --- .../snow/snow_background_ensemble.yaml.j2 | 2 +- .../snow/snow_ensemble_increments_fms.yaml.j2 | 35 ++++++------------- .../jcb-prototype_lgetkf_observer.yaml.j2 | 4 +-- parm/snow/jcb-prototype_lgetkf_solver.yaml.j2 | 12 +++---- 4 files changed, 20 insertions(+), 33 deletions(-) diff --git a/parm/jcb-gdas/model/snow/snow_background_ensemble.yaml.j2 b/parm/jcb-gdas/model/snow/snow_background_ensemble.yaml.j2 index 73b1afdab..f0ad26f11 100644 --- a/parm/jcb-gdas/model/snow/snow_background_ensemble.yaml.j2 +++ b/parm/jcb-gdas/model/snow/snow_background_ensemble.yaml.j2 @@ -1,4 +1,4 @@ -datetime: '{{ snow_background_time_iso }}' +#datetime: '{{ snow_background_time_iso }}' members from template: template: datetime: '{{ snow_background_time_iso }}' diff --git a/parm/jcb-gdas/model/snow/snow_ensemble_increments_fms.yaml.j2 b/parm/jcb-gdas/model/snow/snow_ensemble_increments_fms.yaml.j2 index 25fd93136..f0e28b9b7 100644 --- a/parm/jcb-gdas/model/snow/snow_ensemble_increments_fms.yaml.j2 +++ b/parm/jcb-gdas/model/snow/snow_ensemble_increments_fms.yaml.j2 @@ -1,24 +1,11 @@ -output: - state component: - datapath: ./anl/mem%{member}% - prefix: snowinc - filetype: fms restart - filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' - filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' - state variables: - - totalSnowDepth - - vtype - - slmsk - field io names: - totalSnowDepth: snodl -geometry: - fms initialization: - namelist filename: "{{ snow_fv3jedi_files_path }}/fmsmpp.nml" - field table filename: "{{ snow_fv3jedi_files_path }}/field_table" - akbk: "{{ snow_fv3jedi_files_path }}/akbk.nc4" - layout: - - {{ snow_layout_x }} - - {{ snow_layout_y }} - npx: {{ snow_npx_ges }} - npy: {{ snow_npy_ges }} - npz: {{ snow_npz_ges }} +datapath: ./anl/mem%{member}% +prefix: snowinc +filetype: fms restart +filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' +filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' +state variables: +- totalSnowDepth +- vtype +- slmsk +field io names: + totalSnowDepth: snodl diff --git a/parm/snow/jcb-prototype_lgetkf_observer.yaml.j2 b/parm/snow/jcb-prototype_lgetkf_observer.yaml.j2 index f188fecf1..5883a56f2 100644 --- a/parm/snow/jcb-prototype_lgetkf_observer.yaml.j2 +++ b/parm/snow/jcb-prototype_lgetkf_observer.yaml.j2 @@ -1,7 +1,7 @@ # Use observations for lgetkf # --------------------------- -app_path_observations: {{PARMgfs}}/gdas/jcb-gdas/observations/atmosphere-lgetkf -app_path_observation_chronicle: {{PARMgfs}}/gdas/jcb-gdas/observation_chronicle/atmosphere +app_path_observations: {{PARMgfs}}/gdas/jcb-gdas/observations/snow +app_path_observation_chronicle: {{PARMgfs}}/gdas/jcb-gdas/observation_chronicle/snow/{{cycle}} # Algorithm # --------- diff --git a/parm/snow/jcb-prototype_lgetkf_solver.yaml.j2 b/parm/snow/jcb-prototype_lgetkf_solver.yaml.j2 index abd0022dd..d4cc92ae0 100644 --- a/parm/snow/jcb-prototype_lgetkf_solver.yaml.j2 +++ b/parm/snow/jcb-prototype_lgetkf_solver.yaml.j2 @@ -1,7 +1,7 @@ # Use observations for lgetkf # --------------------------- -app_path_observations: {{PARMgfs}}/gdas/jcb-gdas/observations/atmosphere-lgetkf -app_path_observation_chronicle: {{PARMgfs}}/gdas/jcb-gdas/observation_chronicle/atmosphere +app_path_observations: {{PARMgfs}}/gdas/jcb-gdas/observations/snow +app_path_observation_chronicle: {{PARMgfs}}/gdas/jcb-gdas/observation_chronicle/snow/{{cycle}} # Algorithm # --------- @@ -12,10 +12,10 @@ algorithm: local_ensemble_da_solver atmosphere_background_ensemble_path: ./bkg/mem%mem% # Naming conventions for observation files -atmosphere_obsdatain_path: "{{DATA}}/diags" -atmosphere_obsdatain_prefix: diag_lobs_ -atmosphere_obsdatain_suffix: "_{{ current_cycle | to_YMDH }}.nc" -atmosphere_obsdataout_prefix: diag_solv_ +snow_obsdatain_path: "{{DATA}}/diags" +snow_obsdatain_prefix: diag_lobs_ +snow_obsdatain_suffix: "_{{ current_cycle | to_YMDH }}.nc" +snow_obsdataout_prefix: diag_solv_ # Distribution type distribution_type: Halo From 822059c93a878edc5017ffa3551236ce44f931b9 Mon Sep 17 00:00:00 2001 From: tsga Date: Sat, 31 Jan 2026 14:09:50 +0000 Subject: [PATCH 03/15] add snow obs localization for letkf --- .../snow_ensemblemean_increment_fms.yaml.j2 | 11 ++++++ parm/snow/jcb-base.yaml.j2 | 12 ++++--- parm/snow/jcb-prototype_lgetkf.yaml.j2 | 4 +++ .../snow_ens_obs_dist_localizations.yaml.j2 | 21 +++++++++++ parm/snow/snow_ensda_config.yaml.j2 | 36 ++++++++++--------- 5 files changed, 63 insertions(+), 21 deletions(-) create mode 100644 parm/jcb-gdas/model/snow/snow_ensemblemean_increment_fms.yaml.j2 create mode 100644 parm/snow/snow_ens_obs_dist_localizations.yaml.j2 diff --git a/parm/jcb-gdas/model/snow/snow_ensemblemean_increment_fms.yaml.j2 b/parm/jcb-gdas/model/snow/snow_ensemblemean_increment_fms.yaml.j2 new file mode 100644 index 000000000..3b17737c6 --- /dev/null +++ b/parm/jcb-gdas/model/snow/snow_ensemblemean_increment_fms.yaml.j2 @@ -0,0 +1,11 @@ +datapath: ./anl/mem%{member}% +prefix: snowinc_ensmean +filetype: fms restart +filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' +filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' +state variables: +- totalSnowDepth +- vtype +- slmsk +field io names: + totalSnowDepth: snodl diff --git a/parm/snow/jcb-base.yaml.j2 b/parm/snow/jcb-base.yaml.j2 index f4519d0d0..b05fc15de 100644 --- a/parm/snow/jcb-base.yaml.j2 +++ b/parm/snow/jcb-base.yaml.j2 @@ -112,7 +112,7 @@ number_ensemble_members: {{ NMEM_ENS | default(1, true) }} # ------------------------- local_ensemble_da_solver: Deterministic GETKF -increment_variables: [ua,va,DZ,delp,t,ps,sphum,ice_wat,liq_wat,o3mr] +increment_variables: [totalSnowDepth,vtype,slmsk] #[ua,va,DZ,delp,t,ps,sphum,ice_wat,liq_wat,o3mr] # Veritcal localization for GETKF vl_fraction_of_retained_variance: 0.750 @@ -124,11 +124,15 @@ inflation_mult: 1.0 # Driver driver_update_obs_config_with_geometry_info: true -driver_save_posterior_mean: false -driver_save_posterior_ensemble: false +driver_save_posterior_mean: true +driver_save_posterior_ensemble: true driver_save_prior_mean: false -driver_save_posterior_mean_increment: false +driver_save_posterior_mean_increment: true driver_save_posterior_ensemble_increments: true +driver_save_prior_variance: true +driver_save_posterior_variance: true +driver_do_posterior_observer: true +driver_use_control_member: false # Diagnostics ensemble_increment_prefix: "./anl/mem%{member}%/snowinc." diff --git a/parm/snow/jcb-prototype_lgetkf.yaml.j2 b/parm/snow/jcb-prototype_lgetkf.yaml.j2 index 2a41c0118..f84e9feb1 100644 --- a/parm/snow/jcb-prototype_lgetkf.yaml.j2 +++ b/parm/snow/jcb-prototype_lgetkf.yaml.j2 @@ -14,6 +14,10 @@ snow_background_ensemble_path: ./bkg/mem%mem% # ------------------ {% include OBS_LIST_YAML %} +# Observation distribution and localization +{% set distribution_type = "Halo" %} +{% include 'snow_ens_obs_dist_localizations.yaml.j2' %} + # Testing things # -------------- {% if DO_TEST_MODE %} diff --git a/parm/snow/snow_ens_obs_dist_localizations.yaml.j2 b/parm/snow/snow_ens_obs_dist_localizations.yaml.j2 new file mode 100644 index 000000000..8d8f7c092 --- /dev/null +++ b/parm/snow/snow_ens_obs_dist_localizations.yaml.j2 @@ -0,0 +1,21 @@ +obs_distribution_localizations: + obs_distribution: + name: {{ distribution_type }} + halo size: 250e3 + obs_localizations: + - localization method: Horizontal Box car + lengthscale: 250e3 + max nobs: 50 + +override_obs_distribution_localizations: + override: false + ims_snow: + obs_distribution: + name: {{ distribution_type }} + halo size: 250e3 + obs_localizations: + - localization method: Horizontal SOAR + lengthscale: 250e3 + soar horizontal decay: 0.000021 +#assuming one obs every 40 Km + max nobs: 6 diff --git a/parm/snow/snow_ensda_config.yaml.j2 b/parm/snow/snow_ensda_config.yaml.j2 index 86014387f..8d6fda6e3 100644 --- a/parm/snow/snow_ensda_config.yaml.j2 +++ b/parm/snow/snow_ensda_config.yaml.j2 @@ -1,27 +1,12 @@ jedi_config: - snowensanlobs: - rundir: '{{ DATA }}' - exe_src: '{{ EXECgfs }}/gdas.x' - mpi_cmd: '{{ APRUN_SNOWENSANLOBS }}' - jedi_args: ['fv3jedi', 'localensembleda'] - jcb_base_yaml: '{{ PARMgfs }}/gdas/snow/jcb-base.yaml.j2' - jcb_algo_yaml: '{{ PARMgfs }}/gdas/snow/jcb-prototype_lgetkf_observer.yaml.j2' - obs_list_yaml: '{{ OBS_LIST_YAML }}' - snowensanlsol: - rundir: '{{ DATA }}' - exe_src: '{{ EXECgfs }}/gdas.x' - mpi_cmd: '{{ APRUN_SNOWENSANLSOL }}' - jedi_args: ['fv3jedi', 'localensembleda'] - jcb_base_yaml: '{{ PARMgfs }}/gdas/snow/jcb-base.yaml.j2' - jcb_algo_yaml: '{{ PARMgfs }}/gdas/snow/jcb-prototype_lgetkf_solver.yaml.j2' - obs_list_yaml: '{{ OBS_LIST_YAML }}' snowensanlletkf: rundir: '{{ DATA }}' exe_src: '{{ EXECgfs }}/gdas.x' mpi_cmd: '{{ APRUN_SNOWENSANLLETKF }}' jedi_args: ['fv3jedi', 'localensembleda'] jcb_base_yaml: '{{ PARMgfs }}/gdas/snow/jcb-base.yaml.j2' -#TODO: 'TESTING' clause here not ported jcb_algo_yaml: '{{ PARMgfs }}/gdas/snow/jcb-prototype_lgetkf.yaml.j2' +#TODO: handle 'TESTING' clause in prototype and then don't need it? + jcb_algo_yaml: '{{ PARMgfs }}/gdas/snow/jcb-prototype_lgetkf.yaml.j2' jcb_algo: 'local_ensemble_da' obs_list_yaml: '{{ OBS_LIST_YAML }}' scf_to_ioda: @@ -30,6 +15,23 @@ jedi_config: mpi_cmd: '{{ APRUN_SNOWANL }}' jcb_algo: 'snow_ims_scf_preprocess' jcb_base_yaml: '{{ PARMgfs }}/gdas/snow/jcb-base.yaml.j2' +# snowensanlobs: +# rundir: '{{ DATA }}' +# exe_src: '{{ EXECgfs }}/gdas.x' +# mpi_cmd: '{{ APRUN_SNOWENSANLOBS }}' +# jedi_args: ['fv3jedi', 'localensembleda'] +# jcb_base_yaml: '{{ PARMgfs }}/gdas/snow/jcb-base.yaml.j2' +# jcb_algo_yaml: '{{ PARMgfs }}/gdas/snow/jcb-prototype_lgetkf_observer.yaml.j2' +# obs_list_yaml: '{{ OBS_LIST_YAML }}' +# snowensanlsol: +# rundir: '{{ DATA }}' +# exe_src: '{{ EXECgfs }}/gdas.x' +# mpi_cmd: '{{ APRUN_SNOWENSANLSOL }}' +# jedi_args: ['fv3jedi', 'localensembleda'] +# jcb_base_yaml: '{{ PARMgfs }}/gdas/snow/jcb-base.yaml.j2' +# jcb_algo_yaml: '{{ PARMgfs }}/gdas/snow/jcb-prototype_lgetkf_solver.yaml.j2' +# obs_list_yaml: '{{ OBS_LIST_YAML }}' + # snowensanlfv3inc: # rundir: '{{ DATA }}' # exe_src: '{{ EXECgfs }}/gdas_fv3jedi_fv3inc.x' From d3e587a97b12ef49542ba33d9c791799a34fccca Mon Sep 17 00:00:00 2001 From: tsga Date: Sat, 31 Jan 2026 19:53:47 +0000 Subject: [PATCH 04/15] add all letkf output templates --- ...rest_snow_ensemble_increments_fms.yaml.j2} | 0 .../snow/snow_output_increment_fms.yaml.j2 | 11 ++++++ .../snow/snow_output_mean_prior_fms.yaml | 11 ++++++ ...snow_output_variance_posterior_fms.yaml.j2 | 11 ++++++ .../snow_output_variance_prior_fms.yaml.j2 | 11 ++++++ .../snow/snow_posterior_output_fms.yaml.j2 | 36 ++++++------------- parm/snow/jcb-base.yaml.j2 | 20 ++++++----- 7 files changed, 66 insertions(+), 34 deletions(-) rename parm/jcb-gdas/model/snow/{snow_ensemble_increments_fms_norestart.yaml.j2 => norest_snow_ensemble_increments_fms.yaml.j2} (100%) create mode 100644 parm/jcb-gdas/model/snow/snow_output_increment_fms.yaml.j2 create mode 100644 parm/jcb-gdas/model/snow/snow_output_mean_prior_fms.yaml create mode 100644 parm/jcb-gdas/model/snow/snow_output_variance_posterior_fms.yaml.j2 create mode 100644 parm/jcb-gdas/model/snow/snow_output_variance_prior_fms.yaml.j2 diff --git a/parm/jcb-gdas/model/snow/snow_ensemble_increments_fms_norestart.yaml.j2 b/parm/jcb-gdas/model/snow/norest_snow_ensemble_increments_fms.yaml.j2 similarity index 100% rename from parm/jcb-gdas/model/snow/snow_ensemble_increments_fms_norestart.yaml.j2 rename to parm/jcb-gdas/model/snow/norest_snow_ensemble_increments_fms.yaml.j2 diff --git a/parm/jcb-gdas/model/snow/snow_output_increment_fms.yaml.j2 b/parm/jcb-gdas/model/snow/snow_output_increment_fms.yaml.j2 new file mode 100644 index 000000000..3b17737c6 --- /dev/null +++ b/parm/jcb-gdas/model/snow/snow_output_increment_fms.yaml.j2 @@ -0,0 +1,11 @@ +datapath: ./anl/mem%{member}% +prefix: snowinc_ensmean +filetype: fms restart +filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' +filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' +state variables: +- totalSnowDepth +- vtype +- slmsk +field io names: + totalSnowDepth: snodl diff --git a/parm/jcb-gdas/model/snow/snow_output_mean_prior_fms.yaml b/parm/jcb-gdas/model/snow/snow_output_mean_prior_fms.yaml new file mode 100644 index 000000000..d8d819758 --- /dev/null +++ b/parm/jcb-gdas/model/snow/snow_output_mean_prior_fms.yaml @@ -0,0 +1,11 @@ +datapath: ./anl/mem%{member}% +prefix: snow_ensmean_prior +filetype: fms restart +filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' +filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' +state variables: +- totalSnowDepth +- vtype +- slmsk +field io names: + totalSnowDepth: snodl diff --git a/parm/jcb-gdas/model/snow/snow_output_variance_posterior_fms.yaml.j2 b/parm/jcb-gdas/model/snow/snow_output_variance_posterior_fms.yaml.j2 new file mode 100644 index 000000000..fcf72e3d4 --- /dev/null +++ b/parm/jcb-gdas/model/snow/snow_output_variance_posterior_fms.yaml.j2 @@ -0,0 +1,11 @@ +datapath: ./anl/mem%{member}% +prefix: snow_ensvariance_posterior +filetype: fms restart +filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' +filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' +state variables: +- totalSnowDepth +- vtype +- slmsk +field io names: + totalSnowDepth: snodl diff --git a/parm/jcb-gdas/model/snow/snow_output_variance_prior_fms.yaml.j2 b/parm/jcb-gdas/model/snow/snow_output_variance_prior_fms.yaml.j2 new file mode 100644 index 000000000..1e9a45223 --- /dev/null +++ b/parm/jcb-gdas/model/snow/snow_output_variance_prior_fms.yaml.j2 @@ -0,0 +1,11 @@ +datapath: ./anl/mem%{member}% +prefix: snow_ensvariance_prior +filetype: fms restart +filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' +filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' +state variables: +- totalSnowDepth +- vtype +- slmsk +field io names: + totalSnowDepth: snodl diff --git a/parm/jcb-gdas/model/snow/snow_posterior_output_fms.yaml.j2 b/parm/jcb-gdas/model/snow/snow_posterior_output_fms.yaml.j2 index e2dff3304..01ef42626 100644 --- a/parm/jcb-gdas/model/snow/snow_posterior_output_fms.yaml.j2 +++ b/parm/jcb-gdas/model/snow/snow_posterior_output_fms.yaml.j2 @@ -1,25 +1,11 @@ -output: - state component: - datapath: ./anl - prefix: snow_posterior_ensmean - filetype: fms restart - filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' - filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' - state variables: - - totalSnowDepth - - vtype - - slmsk - field io names: - totalSnowDepth: snodl -geometry: - fms initialization: - namelist filename: "{{ snow_fv3jedi_files_path }}/fmsmpp.nml" - field table filename: "{{ snow_fv3jedi_files_path }}/field_table" - akbk: "{{ snow_fv3jedi_files_path }}/akbk.nc4" - layout: - - {{ snow_layout_x }} - - {{ snow_layout_y }} - npx: {{ snow_npx_ges }} - npy: {{ snow_npy_ges }} - npz: {{ snow_npz_ges }} - +datapath: ./anl/mem%{member}% +prefix: snow_ens_anl +filetype: fms restart +filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' +filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' +state variables: +- totalSnowDepth +- vtype +- slmsk +field io names: + totalSnowDepth: snodl diff --git a/parm/snow/jcb-base.yaml.j2 b/parm/snow/jcb-base.yaml.j2 index b05fc15de..6be45e8c4 100644 --- a/parm/snow/jcb-base.yaml.j2 +++ b/parm/snow/jcb-base.yaml.j2 @@ -11,10 +11,11 @@ app_path_observation_chronicle: "{{PARMgfs}}/gdas/jcb-gdas/observation_chronicle # ------------------------------------------------------------ model_file: model_pseudo initial_condition_file: background # Initial conditions for 4D apps is background -#jedi_increment_output: gaussian final_increment_file: snow_final_increment_fms -output_ensemble_increments_file: snow_ensemble_increments_fms posterior_output_file: snow_posterior_output_fms +#output_ensemble_increments_file: snow_ensemble_increments_fms +#output_increment_file: snow_ensemblemean_increment_fms.yaml.j2 snow_output_increment_fms.yaml.j2 +#jedi_increment_output: gaussian # Assimilation window # ------------------- @@ -61,7 +62,7 @@ snow_orog_prefix: "{{ CASE }}.mx{{ OCNRES }}" # Background snow_background_path: {{snow_bkg_path}} -background_ensemble_path: ./ens/mem%mem% #TODO: this may not be ncessary +#background_ensemble_path: ./ens/mem%mem% #TODO: this may not be ncessary snow_background_ensemble_path: ./bkg/mem%mem% # Background error @@ -105,8 +106,8 @@ snow_obsbiascovout_prefix: "{{APREFIX}}" snow_obsbiascovout_suffix: ".satbias_cov.nc" # Ensemble mean things -snow_number_ensemble_members: {{NMEM_ENS}} #do we need the below? -number_ensemble_members: {{ NMEM_ENS | default(1, true) }} +snow_number_ensemble_members: {{NMEM_ENS | default(1, true) }} #do we need the one below? +#number_ensemble_members: {{ NMEM_ENS | default(1, true) }} # Local Ensemble DA (LETKF) # ------------------------- @@ -126,14 +127,15 @@ inflation_mult: 1.0 driver_update_obs_config_with_geometry_info: true driver_save_posterior_mean: true driver_save_posterior_ensemble: true -driver_save_prior_mean: false driver_save_posterior_mean_increment: true driver_save_posterior_ensemble_increments: true driver_save_prior_variance: true driver_save_posterior_variance: true -driver_do_posterior_observer: true -driver_use_control_member: false +#default driver_save_prior_mean: false +#driver_do_test_prints: false (default true) +#default driver_do_posterior_observer: true +#default driver_use_control_member: false # Diagnostics -ensemble_increment_prefix: "./anl/mem%{member}%/snowinc." +#ensemble_increment_prefix: "./anl/mem%{member}%/snowinc." #posterior_output_gaussian: "./mem%{member}%/snowanl." From 8bb80ed1a34b08f87cfcb7f49cf212f27b307580 Mon Sep 17 00:00:00 2001 From: tsga Date: Mon, 2 Feb 2026 12:27:17 +0000 Subject: [PATCH 05/15] temporary to fix to localization --- .../observations/snow/ghcn_snow.yaml.j2 | 11 ++++++++- parm/snow/ens_apply_incr_nml.j2 | 2 +- parm/snow/jcb-base.yaml.j2 | 6 +++-- parm/snow/jcb-prototype_lgetkf.yaml.j2 | 6 ++++- .../snow_ens_obs_dist_localizations.yaml.j2 | 24 +++++++++---------- parm/snow/snow_ensda_config.yaml.j2 | 11 +++++---- 6 files changed, 39 insertions(+), 21 deletions(-) diff --git a/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 b/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 index 4ad6a7444..23828b6e8 100644 --- a/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 +++ b/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 @@ -4,6 +4,9 @@ # ----------------------- obs space: name: {{observation_from_jcb}} + distribution: + name: Halo + halo size: 250e3 obsdatain: engine: type: H5File @@ -20,7 +23,13 @@ # -------------------- obs operator: name: Identity - # + + # localization + # ------------ + obs localizations: + - localization method: Horizontal Box car + lengthscale: 250e3 + max nobs: 50 # Observation Filters (QC) # ------------------------ diff --git a/parm/snow/ens_apply_incr_nml.j2 b/parm/snow/ens_apply_incr_nml.j2 index 36d768247..e46f9df46 100644 --- a/parm/snow/ens_apply_incr_nml.j2 +++ b/parm/snow/ens_apply_incr_nml.j2 @@ -3,7 +3,7 @@ hour_str = "{{ current_cycle | strftime('%H') }}", res = {{ CASE_ENS[1:] }}, frac_grid = .true., - rst_path = "{{ DATA }}/anl/mem{{ MYMEM }}", + rst_path = "{{ DATA }}/anl", inc_path = "{{ DATA }}/anl", orog_path = "{{ HOMEgfs }}/fix/orog/{{ CASE_ENS }}", otype = "{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data", diff --git a/parm/snow/jcb-base.yaml.j2 b/parm/snow/jcb-base.yaml.j2 index 6be45e8c4..3b32d2dcb 100644 --- a/parm/snow/jcb-base.yaml.j2 +++ b/parm/snow/jcb-base.yaml.j2 @@ -13,8 +13,10 @@ model_file: model_pseudo initial_condition_file: background # Initial conditions for 4D apps is background final_increment_file: snow_final_increment_fms posterior_output_file: snow_posterior_output_fms -#output_ensemble_increments_file: snow_ensemble_increments_fms -#output_increment_file: snow_ensemblemean_increment_fms.yaml.j2 snow_output_increment_fms.yaml.j2 +output_ensemble_increments_file: snow_ensemble_increments_fms +output_increment_file: snow_output_increment_fms #snow_ensemblemean_increment_fms.yaml.j2 +output_variance_prior_file: snow_output_variance_prior_fms +output_variance_posterior_file: snow_output_variance_posterior_fms #jedi_increment_output: gaussian # Assimilation window diff --git a/parm/snow/jcb-prototype_lgetkf.yaml.j2 b/parm/snow/jcb-prototype_lgetkf.yaml.j2 index f84e9feb1..d70e66105 100644 --- a/parm/snow/jcb-prototype_lgetkf.yaml.j2 +++ b/parm/snow/jcb-prototype_lgetkf.yaml.j2 @@ -15,8 +15,12 @@ snow_background_ensemble_path: ./bkg/mem%mem% {% include OBS_LIST_YAML %} # Observation distribution and localization +# TODO: set these through templates {% set distribution_type = "Halo" %} -{% include 'snow_ens_obs_dist_localizations.yaml.j2' %} +{% set localization_method = "Horizontal Box car" %} +{% set halo_size = 250e3 %} +{% set loc_length_scale = 250e3 %} +{% set max_nobs = 50 %} # Testing things # -------------- diff --git a/parm/snow/snow_ens_obs_dist_localizations.yaml.j2 b/parm/snow/snow_ens_obs_dist_localizations.yaml.j2 index 8d8f7c092..2f8805f97 100644 --- a/parm/snow/snow_ens_obs_dist_localizations.yaml.j2 +++ b/parm/snow/snow_ens_obs_dist_localizations.yaml.j2 @@ -7,15 +7,15 @@ obs_distribution_localizations: lengthscale: 250e3 max nobs: 50 -override_obs_distribution_localizations: - override: false - ims_snow: - obs_distribution: - name: {{ distribution_type }} - halo size: 250e3 - obs_localizations: - - localization method: Horizontal SOAR - lengthscale: 250e3 - soar horizontal decay: 0.000021 -#assuming one obs every 40 Km - max nobs: 6 +#override_obs_distribution_localizations: +# override: false +# ims_snow: +# obs_distribution: +# name: {{ distribution_type }} +# halo size: 250e3 +# obs_localizations: +# - localization method: Horizontal SOAR +# lengthscale: 250e3 +# soar horizontal decay: 0.000021 +##assuming one obs every 40 Km +# max nobs: 6 diff --git a/parm/snow/snow_ensda_config.yaml.j2 b/parm/snow/snow_ensda_config.yaml.j2 index 8d6fda6e3..1ebfa6c75 100644 --- a/parm/snow/snow_ensda_config.yaml.j2 +++ b/parm/snow/snow_ensda_config.yaml.j2 @@ -7,7 +7,7 @@ jedi_config: jcb_base_yaml: '{{ PARMgfs }}/gdas/snow/jcb-base.yaml.j2' #TODO: handle 'TESTING' clause in prototype and then don't need it? jcb_algo_yaml: '{{ PARMgfs }}/gdas/snow/jcb-prototype_lgetkf.yaml.j2' - jcb_algo: 'local_ensemble_da' +# jcb_algo: 'local_ensemble_da' obs_list_yaml: '{{ OBS_LIST_YAML }}' scf_to_ioda: rundir: '{{ DATA }}' @@ -51,7 +51,7 @@ data_in: - '{{ DATA }}/anl' - '{{ DATA }}/bkg/ensmean' - '{{ DATA }}/anl/ensmean' -{% for mem in range(1, NMEM_ENS + 1) %} +{% for mem in range(0, NMEM_ENS + 1) %} - '{{ DATA }}/bkg/mem{{ '%03d' % mem }}' - '{{ DATA }}/anl/mem{{ '%03d' % mem }}' {% endfor %} @@ -160,8 +160,11 @@ data_in: data_out: copy_req: # Configuration files - - ['{{ DATA }}/snowanlvar.yaml', '{{ COMOUT_CONF }}/{{ APREFIX_ENS }}snowanlvar.yaml'] - - ['{{ DATA }}/esnowanlensmean.yaml', '{{ COMOUT_CONF }}/{{ APREFIX_ENS }}esnowanlensmean.yaml'] +# - ['{{ DATA }}/snowanlvar.yaml', '{{ COMOUT_CONF }}/{{ APREFIX_ENS }}snowanlvar.yaml'] +# - ['{{ DATA }}/esnowanlensmean.yaml', '{{ COMOUT_CONF }}/{{ APREFIX_ENS }}esnowanlensmean.yaml'] + - ['{{ DATA }}/snowensanlletkf.yaml', '{{ COMOUT_CONF }}/{{ APREFIX_ENS }}snowensanlletkf.yaml'] + - ['{{ DATA }}/apply_incr_nml', '{{ COMOUT_CONF }}/{{ APREFIX_ENS }}apply_incr_nml'] + {% if DO_IMS_SCF %} - ['{{ DATA }}/scf_to_ioda.yaml', '{{ COMOUT_CONF }}/{{ APREFIX_ENS }}scf_to_ioda.yaml'] {% endif %} From 8308dd188a3fa2123f98e78f5dd72f75750ae379 Mon Sep 17 00:00:00 2001 From: tsga Date: Wed, 4 Feb 2026 17:04:26 +0000 Subject: [PATCH 06/15] differentiate letkf from current ens in parm/snow --- parm/snow/ens_apply_incr_nml.j2 | 2 +- parm/snow/letkf_apply_incr_nml.j2 | 16 ++++++++++++++++ ...onfig.yaml.j2 => snow_letkf_config.yaml.j2} | 18 +----------------- 3 files changed, 18 insertions(+), 18 deletions(-) create mode 100644 parm/snow/letkf_apply_incr_nml.j2 rename parm/snow/{snow_ensda_config.yaml.j2 => snow_letkf_config.yaml.j2} (94%) diff --git a/parm/snow/ens_apply_incr_nml.j2 b/parm/snow/ens_apply_incr_nml.j2 index e46f9df46..80ffcba26 100644 --- a/parm/snow/ens_apply_incr_nml.j2 +++ b/parm/snow/ens_apply_incr_nml.j2 @@ -3,7 +3,7 @@ hour_str = "{{ current_cycle | strftime('%H') }}", res = {{ CASE_ENS[1:] }}, frac_grid = .true., - rst_path = "{{ DATA }}/anl", + rst_path = "{{ DATA }}/anl/mem{{ MYMEM }}", inc_path = "{{ DATA }}/anl", orog_path = "{{ HOMEgfs }}/fix/orog/{{ CASE_ENS }}", otype = "{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data", diff --git a/parm/snow/letkf_apply_incr_nml.j2 b/parm/snow/letkf_apply_incr_nml.j2 new file mode 100644 index 000000000..e46f9df46 --- /dev/null +++ b/parm/snow/letkf_apply_incr_nml.j2 @@ -0,0 +1,16 @@ +&noahmp_snow + date_str = "{{ current_cycle | to_YMD }}", + hour_str = "{{ current_cycle | strftime('%H') }}", + res = {{ CASE_ENS[1:] }}, + frac_grid = .true., + rst_path = "{{ DATA }}/anl", + inc_path = "{{ DATA }}/anl", + orog_path = "{{ HOMEgfs }}/fix/orog/{{ CASE_ENS }}", + otype = "{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data", + ntiles={{ ntiles }}, + ens_size={{ ens_size }}, + noincr_threshold={{ noincr_threshold }}, + print_summary=.true., + print_debug={{ print_debug }} , + truncate={{ truncate_incr }} +/ diff --git a/parm/snow/snow_ensda_config.yaml.j2 b/parm/snow/snow_letkf_config.yaml.j2 similarity index 94% rename from parm/snow/snow_ensda_config.yaml.j2 rename to parm/snow/snow_letkf_config.yaml.j2 index 1ebfa6c75..e9c8875b1 100644 --- a/parm/snow/snow_ensda_config.yaml.j2 +++ b/parm/snow/snow_letkf_config.yaml.j2 @@ -5,9 +5,7 @@ jedi_config: mpi_cmd: '{{ APRUN_SNOWENSANLLETKF }}' jedi_args: ['fv3jedi', 'localensembleda'] jcb_base_yaml: '{{ PARMgfs }}/gdas/snow/jcb-base.yaml.j2' -#TODO: handle 'TESTING' clause in prototype and then don't need it? jcb_algo_yaml: '{{ PARMgfs }}/gdas/snow/jcb-prototype_lgetkf.yaml.j2' -# jcb_algo: 'local_ensemble_da' obs_list_yaml: '{{ OBS_LIST_YAML }}' scf_to_ioda: rundir: '{{ DATA }}' @@ -15,6 +13,7 @@ jedi_config: mpi_cmd: '{{ APRUN_SNOWANL }}' jcb_algo: 'snow_ims_scf_preprocess' jcb_base_yaml: '{{ PARMgfs }}/gdas/snow/jcb-base.yaml.j2' +#TODO: add observer mode # snowensanlobs: # rundir: '{{ DATA }}' # exe_src: '{{ EXECgfs }}/gdas.x' @@ -32,19 +31,6 @@ jedi_config: # jcb_algo_yaml: '{{ PARMgfs }}/gdas/snow/jcb-prototype_lgetkf_solver.yaml.j2' # obs_list_yaml: '{{ OBS_LIST_YAML }}' -# snowensanlfv3inc: -# rundir: '{{ DATA }}' -# exe_src: '{{ EXECgfs }}/gdas_fv3jedi_fv3inc.x' -# mpi_cmd: '{{ APRUN_SNOWENSANLFV3INC }}' -# jcb_algo: 'fv3jedi_fv3inc_lgetkf' -# jcb_base_yaml: '{{ PARMgfs }}/gdas/snow/jcb-base.yaml.j2' -# snowanladdinc: -# rundir: '{{ DATA }}' -# exe_src: '{{ EXECgdas }}/fv3jedi_addincrement.x' -# mpi_cmd: '{{ APRUN_SNOW_ADDINC }}' -# jcb_base_yaml: '{{ PARMgdas }}/snow/jcb-base.yaml.j2' -# jcb_algo: snow_addincrement - data_in: mkdir: - '{{ DATA }}/bkg' @@ -160,8 +146,6 @@ data_in: data_out: copy_req: # Configuration files -# - ['{{ DATA }}/snowanlvar.yaml', '{{ COMOUT_CONF }}/{{ APREFIX_ENS }}snowanlvar.yaml'] -# - ['{{ DATA }}/esnowanlensmean.yaml', '{{ COMOUT_CONF }}/{{ APREFIX_ENS }}esnowanlensmean.yaml'] - ['{{ DATA }}/snowensanlletkf.yaml', '{{ COMOUT_CONF }}/{{ APREFIX_ENS }}snowensanlletkf.yaml'] - ['{{ DATA }}/apply_incr_nml', '{{ COMOUT_CONF }}/{{ APREFIX_ENS }}apply_incr_nml'] From 7309654a369ddd4be094391afa9cdeb1a3f0aba9 Mon Sep 17 00:00:00 2001 From: tsga Date: Wed, 4 Feb 2026 21:23:04 +0000 Subject: [PATCH 07/15] refine snow ensemble output files --- .../model/snow/snow_ensemble_increments_fms.yaml.j2 | 11 +---------- ...aml.j2 => snow_ensemble_output_fms_common.yaml.j2} | 1 - .../model/snow/snow_output_increment_fms.yaml.j2 | 11 +---------- .../model/snow/snow_output_mean_prior_fms.yaml | 11 ----------- .../model/snow/snow_output_mean_prior_fms.yaml.j2 | 2 ++ .../snow/snow_output_variance_posterior_fms.yaml.j2 | 11 +---------- .../model/snow/snow_output_variance_prior_fms.yaml.j2 | 11 +---------- .../model/snow/snow_posterior_output_fms.yaml.j2 | 11 +---------- parm/snow/jcb-base.yaml.j2 | 3 ++- 9 files changed, 9 insertions(+), 63 deletions(-) rename parm/jcb-gdas/model/snow/{snow_ensemblemean_increment_fms.yaml.j2 => snow_ensemble_output_fms_common.yaml.j2} (91%) delete mode 100644 parm/jcb-gdas/model/snow/snow_output_mean_prior_fms.yaml create mode 100644 parm/jcb-gdas/model/snow/snow_output_mean_prior_fms.yaml.j2 diff --git a/parm/jcb-gdas/model/snow/snow_ensemble_increments_fms.yaml.j2 b/parm/jcb-gdas/model/snow/snow_ensemble_increments_fms.yaml.j2 index f0e28b9b7..401278fc1 100644 --- a/parm/jcb-gdas/model/snow/snow_ensemble_increments_fms.yaml.j2 +++ b/parm/jcb-gdas/model/snow/snow_ensemble_increments_fms.yaml.j2 @@ -1,11 +1,2 @@ -datapath: ./anl/mem%{member}% prefix: snowinc -filetype: fms restart -filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' -filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' -state variables: -- totalSnowDepth -- vtype -- slmsk -field io names: - totalSnowDepth: snodl +{% include 'snow_ensemble_output_fms_common.yaml.j2' %} diff --git a/parm/jcb-gdas/model/snow/snow_ensemblemean_increment_fms.yaml.j2 b/parm/jcb-gdas/model/snow/snow_ensemble_output_fms_common.yaml.j2 similarity index 91% rename from parm/jcb-gdas/model/snow/snow_ensemblemean_increment_fms.yaml.j2 rename to parm/jcb-gdas/model/snow/snow_ensemble_output_fms_common.yaml.j2 index 3b17737c6..ea7e19fe2 100644 --- a/parm/jcb-gdas/model/snow/snow_ensemblemean_increment_fms.yaml.j2 +++ b/parm/jcb-gdas/model/snow/snow_ensemble_output_fms_common.yaml.j2 @@ -1,5 +1,4 @@ datapath: ./anl/mem%{member}% -prefix: snowinc_ensmean filetype: fms restart filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' diff --git a/parm/jcb-gdas/model/snow/snow_output_increment_fms.yaml.j2 b/parm/jcb-gdas/model/snow/snow_output_increment_fms.yaml.j2 index 3b17737c6..462363d2c 100644 --- a/parm/jcb-gdas/model/snow/snow_output_increment_fms.yaml.j2 +++ b/parm/jcb-gdas/model/snow/snow_output_increment_fms.yaml.j2 @@ -1,11 +1,2 @@ -datapath: ./anl/mem%{member}% prefix: snowinc_ensmean -filetype: fms restart -filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' -filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' -state variables: -- totalSnowDepth -- vtype -- slmsk -field io names: - totalSnowDepth: snodl +{% include 'snow_ensemble_output_fms_common.yaml.j2' %} diff --git a/parm/jcb-gdas/model/snow/snow_output_mean_prior_fms.yaml b/parm/jcb-gdas/model/snow/snow_output_mean_prior_fms.yaml deleted file mode 100644 index d8d819758..000000000 --- a/parm/jcb-gdas/model/snow/snow_output_mean_prior_fms.yaml +++ /dev/null @@ -1,11 +0,0 @@ -datapath: ./anl/mem%{member}% -prefix: snow_ensmean_prior -filetype: fms restart -filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' -filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' -state variables: -- totalSnowDepth -- vtype -- slmsk -field io names: - totalSnowDepth: snodl diff --git a/parm/jcb-gdas/model/snow/snow_output_mean_prior_fms.yaml.j2 b/parm/jcb-gdas/model/snow/snow_output_mean_prior_fms.yaml.j2 new file mode 100644 index 000000000..b0524dc68 --- /dev/null +++ b/parm/jcb-gdas/model/snow/snow_output_mean_prior_fms.yaml.j2 @@ -0,0 +1,2 @@ +prefix: snow_ensmean_prior +{% include 'snow_ensemble_output_fms_common.yaml.j2' %} diff --git a/parm/jcb-gdas/model/snow/snow_output_variance_posterior_fms.yaml.j2 b/parm/jcb-gdas/model/snow/snow_output_variance_posterior_fms.yaml.j2 index fcf72e3d4..905601106 100644 --- a/parm/jcb-gdas/model/snow/snow_output_variance_posterior_fms.yaml.j2 +++ b/parm/jcb-gdas/model/snow/snow_output_variance_posterior_fms.yaml.j2 @@ -1,11 +1,2 @@ -datapath: ./anl/mem%{member}% prefix: snow_ensvariance_posterior -filetype: fms restart -filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' -filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' -state variables: -- totalSnowDepth -- vtype -- slmsk -field io names: - totalSnowDepth: snodl +{% include 'snow_ensemble_output_fms_common.yaml.j2' %} diff --git a/parm/jcb-gdas/model/snow/snow_output_variance_prior_fms.yaml.j2 b/parm/jcb-gdas/model/snow/snow_output_variance_prior_fms.yaml.j2 index 1e9a45223..cc236d0df 100644 --- a/parm/jcb-gdas/model/snow/snow_output_variance_prior_fms.yaml.j2 +++ b/parm/jcb-gdas/model/snow/snow_output_variance_prior_fms.yaml.j2 @@ -1,11 +1,2 @@ -datapath: ./anl/mem%{member}% prefix: snow_ensvariance_prior -filetype: fms restart -filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' -filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' -state variables: -- totalSnowDepth -- vtype -- slmsk -field io names: - totalSnowDepth: snodl +{% include 'snow_ensemble_output_fms_common.yaml.j2' %} diff --git a/parm/jcb-gdas/model/snow/snow_posterior_output_fms.yaml.j2 b/parm/jcb-gdas/model/snow/snow_posterior_output_fms.yaml.j2 index 01ef42626..3bfc4e49b 100644 --- a/parm/jcb-gdas/model/snow/snow_posterior_output_fms.yaml.j2 +++ b/parm/jcb-gdas/model/snow/snow_posterior_output_fms.yaml.j2 @@ -1,11 +1,2 @@ -datapath: ./anl/mem%{member}% prefix: snow_ens_anl -filetype: fms restart -filename_sfcd: '{{ snow_background_time_fv3 }}.sfc_data.nc' -filename_cplr: '{{ snow_background_time_fv3 }}.coupler.res' -state variables: -- totalSnowDepth -- vtype -- slmsk -field io names: - totalSnowDepth: snodl +{% include 'snow_ensemble_output_fms_common.yaml.j2' %} diff --git a/parm/snow/jcb-base.yaml.j2 b/parm/snow/jcb-base.yaml.j2 index 3b32d2dcb..a486e6041 100644 --- a/parm/snow/jcb-base.yaml.j2 +++ b/parm/snow/jcb-base.yaml.j2 @@ -12,6 +12,7 @@ app_path_observation_chronicle: "{{PARMgfs}}/gdas/jcb-gdas/observation_chronicle model_file: model_pseudo initial_condition_file: background # Initial conditions for 4D apps is background final_increment_file: snow_final_increment_fms +output_mean_prior_file: snow_output_mean_prior_fms posterior_output_file: snow_posterior_output_fms output_ensemble_increments_file: snow_ensemble_increments_fms output_increment_file: snow_output_increment_fms #snow_ensemblemean_increment_fms.yaml.j2 @@ -133,7 +134,7 @@ driver_save_posterior_mean_increment: true driver_save_posterior_ensemble_increments: true driver_save_prior_variance: true driver_save_posterior_variance: true -#default driver_save_prior_mean: false +driver_save_prior_mean: true #(default false) #driver_do_test_prints: false (default true) #default driver_do_posterior_observer: true #default driver_use_control_member: false From c5bb2ed8a6679c795e94a2de958118cecdabcc57 Mon Sep 17 00:00:00 2001 From: tsga Date: Wed, 4 Feb 2026 21:27:04 +0000 Subject: [PATCH 08/15] clean up --- parm/snow/ens_apply_incr_nml.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parm/snow/ens_apply_incr_nml.j2 b/parm/snow/ens_apply_incr_nml.j2 index 80ffcba26..36d768247 100644 --- a/parm/snow/ens_apply_incr_nml.j2 +++ b/parm/snow/ens_apply_incr_nml.j2 @@ -3,7 +3,7 @@ hour_str = "{{ current_cycle | strftime('%H') }}", res = {{ CASE_ENS[1:] }}, frac_grid = .true., - rst_path = "{{ DATA }}/anl/mem{{ MYMEM }}", + rst_path = "{{ DATA }}/anl/mem{{ MYMEM }}", inc_path = "{{ DATA }}/anl", orog_path = "{{ HOMEgfs }}/fix/orog/{{ CASE_ENS }}", otype = "{{ CASE_ENS }}.mx{{ OCNRES }}_oro_data", From c5f964524f18102a8504e9eb1253392c435592b5 Mon Sep 17 00:00:00 2001 From: tsga Date: Wed, 4 Feb 2026 21:38:20 +0000 Subject: [PATCH 09/15] fix build --- build.sh | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/build.sh b/build.sh index 80084df1f..35ee9385f 100755 --- a/build.sh +++ b/build.sh @@ -112,19 +112,18 @@ mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR} # Set WORKFLOW_TESTS as CMake option CMAKE_OPTS+=" -DWORKFLOW_TESTS=${WORKFLOW_TESTS:-${WORKFLOW_BUILD}}" -if [[ $WORKFLOW_BUILD == 'ON' ]]; then - # Link MOM6 and Icepack in SOCA to submodules in the UFS repo - rm -rf $dir_root/sorc/soca/external/mom6/MOM6 - rm -rf $dir_root/sorc/soca/external/icepack/Icepack - ln -sf $HOMEgfs/sorc/ufs_model.fd/MOM6-interface/MOM6/ $dir_root/sorc/soca/external/mom6/MOM6 - ln -sf $HOMEgfs/sorc/ufs_model.fd/CICE-interface/CICE/icepack/ $dir_root/sorc/soca/external/icepack/Icepack -else - # Delete forked SOCA NOAA-EMC dev/emc repo and clone the original JCSDA develop repo - rm -rf "$dir_root/sorc/soca/" - git clone https://github.com/jcsda/soca "$dir_root/sorc/soca" --recurse-submodules - cd "$dir_root/sorc/soca" - git checkout 733ac0177ad0b45e04586f2ead5aa67137da332c - cd ${BUILD_DIR} +if [[ $BUILD_SOCA == 'ON' ]]; then + if [[ $WORKFLOW_BUILD == 'ON' ]]; then + # Link MOM6 and Icepack in SOCA to submodules in the UFS repo + rm -rf $dir_root/sorc/soca/external/mom6/MOM6 + rm -rf $dir_root/sorc/soca/external/icepack/Icepack + ln -sf $HOMEgfs/sorc/ufs_model.fd/MOM6-interface/MOM6/ $dir_root/sorc/soca/external/mom6/MOM6 + ln -sf $HOMEgfs/sorc/ufs_model.fd/CICE-interface/CICE/icepack/ $dir_root/sorc/soca/external/icepack/Icepack + else + # Delete forked SOCA NOAA-EMC dev/emc repo and clone the original JCSDA develop repo + rm -rf "$dir_root/sorc/soca/" + git clone https://github.com/jcsda/soca "$dir_root/sorc/soca" --recurse-submodules + fi fi if [[ $BUILD_IODA_CONVERTERS == 'YES' ]]; then From 8a0403481b1dac0812e4926ed8d0fae9daa3b138 Mon Sep 17 00:00:00 2001 From: "Tseganeh Z. Gichamo" Date: Thu, 5 Feb 2026 13:57:48 -0500 Subject: [PATCH 10/15] remove distribution and localization Removed distribution and localization settings from the observation space configuration. --- parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 b/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 index 23828b6e8..28f12582f 100644 --- a/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 +++ b/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 @@ -4,9 +4,6 @@ # ----------------------- obs space: name: {{observation_from_jcb}} - distribution: - name: Halo - halo size: 250e3 obsdatain: engine: type: H5File @@ -24,13 +21,6 @@ obs operator: name: Identity - # localization - # ------------ - obs localizations: - - localization method: Horizontal Box car - lengthscale: 250e3 - max nobs: 50 - # Observation Filters (QC) # ------------------------ obs pre filters: From 6f43724e405eb2a58607f2ba1b29ebc0e645548d Mon Sep 17 00:00:00 2001 From: "Tseganeh Z. Gichamo" Date: Thu, 5 Feb 2026 13:59:20 -0500 Subject: [PATCH 11/15] remove unnecessary change in ghcn obs file --- parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 b/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 index 28f12582f..f1792ccb0 100644 --- a/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 +++ b/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 @@ -20,7 +20,8 @@ # -------------------- obs operator: name: Identity - + # + # Observation Filters (QC) # ------------------------ obs pre filters: From 1e55c6c350bdd1e1247d40e2328084a63a886cea Mon Sep 17 00:00:00 2001 From: "Tseganeh Z. Gichamo" Date: Thu, 5 Feb 2026 14:00:11 -0500 Subject: [PATCH 12/15] Remove extra whitespace in ghcn_snow.yaml.j2 --- parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 b/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 index f1792ccb0..4ad6a7444 100644 --- a/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 +++ b/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 @@ -21,7 +21,7 @@ obs operator: name: Identity # - + # Observation Filters (QC) # ------------------------ obs pre filters: From 5dc85a042516872279977e35a358b2a90ff2fe1e Mon Sep 17 00:00:00 2001 From: "Tseganeh Z. Gichamo" Date: Sun, 8 Feb 2026 07:14:44 -0500 Subject: [PATCH 13/15] Rename snowensanlletkf to snowletkfanl in config --- parm/snow/snow_letkf_config.yaml.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parm/snow/snow_letkf_config.yaml.j2 b/parm/snow/snow_letkf_config.yaml.j2 index e9c8875b1..79930945c 100644 --- a/parm/snow/snow_letkf_config.yaml.j2 +++ b/parm/snow/snow_letkf_config.yaml.j2 @@ -1,5 +1,5 @@ jedi_config: - snowensanlletkf: + snowletkfanl: rundir: '{{ DATA }}' exe_src: '{{ EXECgfs }}/gdas.x' mpi_cmd: '{{ APRUN_SNOWENSANLLETKF }}' From a6956f4fce837542d7e55dc56921aa501a6c2a94 Mon Sep 17 00:00:00 2001 From: "Tseganeh Z. Gichamo" Date: Sun, 8 Feb 2026 07:37:53 -0500 Subject: [PATCH 14/15] Update output configuration file references --- parm/snow/snow_letkf_config.yaml.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parm/snow/snow_letkf_config.yaml.j2 b/parm/snow/snow_letkf_config.yaml.j2 index 79930945c..2757f1e59 100644 --- a/parm/snow/snow_letkf_config.yaml.j2 +++ b/parm/snow/snow_letkf_config.yaml.j2 @@ -146,7 +146,7 @@ data_in: data_out: copy_req: # Configuration files - - ['{{ DATA }}/snowensanlletkf.yaml', '{{ COMOUT_CONF }}/{{ APREFIX_ENS }}snowensanlletkf.yaml'] + - ['{{ DATA }}/snowletkfanl.yaml', '{{ COMOUT_CONF }}/{{ APREFIX_ENS }}snowletkfanl.yaml'] - ['{{ DATA }}/apply_incr_nml', '{{ COMOUT_CONF }}/{{ APREFIX_ENS }}apply_incr_nml'] {% if DO_IMS_SCF %} From 1b49b26ff4cefb1c13d4bd144c9c186e3397f2fa Mon Sep 17 00:00:00 2001 From: tsga Date: Wed, 11 Feb 2026 21:47:58 +0000 Subject: [PATCH 15/15] fix dist and localization --- parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 | 13 +++++++++++++ parm/snow/jcb-prototype_lgetkf.yaml.j2 | 12 ++++++------ parm/snow/snow_letkf_config.yaml.j2 | 2 +- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 b/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 index 4ad6a7444..f8603d587 100644 --- a/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 +++ b/parm/jcb-gdas/observations/snow/ghcn_snow.yaml.j2 @@ -4,6 +4,11 @@ # ----------------------- obs space: name: {{observation_from_jcb}} +{% if algorithm == "local_ensemble_da" %} + distribution: + name: {{distribution_type}} + halo size: "{{halo_size}}" +{% endif %} obsdatain: engine: type: H5File @@ -21,6 +26,14 @@ obs operator: name: Identity # + # localization TODO: generalize this condioned on da algo + # ------------ +{% if algorithm == "local_ensemble_da" %} + obs localizations: + - localization method: {{localization_method}} + lengthscale: {{loc_length_scale}} + max nobs: {{max_nobs}} +{% endif %} # Observation Filters (QC) # ------------------------ diff --git a/parm/snow/jcb-prototype_lgetkf.yaml.j2 b/parm/snow/jcb-prototype_lgetkf.yaml.j2 index d70e66105..46a5f7227 100644 --- a/parm/snow/jcb-prototype_lgetkf.yaml.j2 +++ b/parm/snow/jcb-prototype_lgetkf.yaml.j2 @@ -15,12 +15,12 @@ snow_background_ensemble_path: ./bkg/mem%mem% {% include OBS_LIST_YAML %} # Observation distribution and localization -# TODO: set these through templates -{% set distribution_type = "Halo" %} -{% set localization_method = "Horizontal Box car" %} -{% set halo_size = 250e3 %} -{% set loc_length_scale = 250e3 %} -{% set max_nobs = 50 %} +# TODO: +distribution_type: "Halo" +localization_method: "Horizontal Box car" +halo_size: 250e3 +loc_length_scale: 250e3 +max_nobs: 50 # Testing things # -------------- diff --git a/parm/snow/snow_letkf_config.yaml.j2 b/parm/snow/snow_letkf_config.yaml.j2 index 2757f1e59..930e667a0 100644 --- a/parm/snow/snow_letkf_config.yaml.j2 +++ b/parm/snow/snow_letkf_config.yaml.j2 @@ -2,7 +2,7 @@ jedi_config: snowletkfanl: rundir: '{{ DATA }}' exe_src: '{{ EXECgfs }}/gdas.x' - mpi_cmd: '{{ APRUN_SNOWENSANLLETKF }}' + mpi_cmd: '{{ APRUN_SNOWLETKFANL }}' jedi_args: ['fv3jedi', 'localensembleda'] jcb_base_yaml: '{{ PARMgfs }}/gdas/snow/jcb-base.yaml.j2' jcb_algo_yaml: '{{ PARMgfs }}/gdas/snow/jcb-prototype_lgetkf.yaml.j2'