Skip to content

Conversation

@bhuang95
Copy link

@bhuang95 bhuang95 commented Dec 16, 2025

Description

This PR, along with its three dependent PRs listed below, enables running enkf only for atmosphere in the global-workflow with necessary tasks. It will help test JEDI EnKF capabilities in the global workflow and compare with GSI in support of hybrid 4DEnVar appplication for the atmosphere.

This was further modified based on the original branch from Travis J Elless at NOAA EMC.

Major change summary from three PRs:

This PR:

  • Add DOENKFONLY_ATM (false by default) in the dev/parm/config/gfs/config.base.j2 to activate the GSI and JEDI EnKF-only run.
  • Modify rocoto task generator files for gfs_cycle to keep a few EnKF-only tasks.
  • Add two asks: fetchatmanlbias and prepatmanlbias to fetch operational analysis bias correction files at the previous cycle and process them for JEDI and GSI EnKF use (dev/jobs/JGLOBAL_ATM_PREP_ANL_BIAS)

NOAA-EMC/GDASApp#2010:

  • Rename JEDI increment files generated by enkf-only (without recentering) to be consistent wth ensemble forecast script.
  • Add a parm/atm/atm_ens_obs_dist_localizations.yaml.j2 to define obs distribution and localization for local_ensemble_da atmposphere applicaton. (see more details in the in the following jcb-gdas and jcb PR.)

NOAA-EMC/jcb-gdas#219:

  • Add an if statement to use correct JEDI enkf-only increment filetype (without recentering) to be consistent with ensemble forecast script.
  • Remove observations/atmosphere-lgetkf directory (not used due to changes in jcb below)

NOAA-EMC/jcb#32:

Resolves:

Dependencies:
-NOAA-EMC/GDASApp#2010
-NOAA-EMC/jcb-gdas#219
-NOAA-EMC/jcb#32

Acceptance Criteria

  • With DOENKFONLY_ATM="NO" by default, it should not affect existing applications in the current global workflow. In other words, it should pass all relevant tests following the general guidelines of building the global workflow.
  • With DOENKFONLY_ATM="YES" in the config.base during the workflow setup, it should generate related tasks for GSI and JEDI EnKF-only run with additional variable changes in config.base, respectively, and pass all these tasks through rocoto jobs.

Type of change

  • Bug fix (fixes something broken)
  • New feature (adds functionality)
  • Maintenance (code refactor, clean-up, new CI test, etc.)

Change characteristics

  • Is this a breaking change (a change in existing functionality)? NO
  • Does this change require a documentation update? NO
  • Does this change require an update to any of the following submodules? YES/NO (If YES, please add a link to any PRs that are pending.)
    • EMC verif-global
    • GDAS
    • GFS-utils
    • GSI
    • GSI-monitor
    • GSI-utils
    • UFS-utils
    • UFS-weather-model
    • wxflow

How has this been tested?

-Built and cycled successfully on Ursa as follows.

  • Clone this branch
git clone https://github.com/bhuang95/global-workflow.git
cd global-workflow
git checkout feature/enkf_only_dev
git submodule update --init --recursive
  • Build the branch following step 7.1.3 here
  • IC on Ursa
    /scratch4/BMC/gsienkf/Bo.Huang/expCodes/Workflow/Data/IC/TravisIC-2022010312/
  • Set the workflow following steps 7.3.2 and 7.3.3 here. At "7.3.3. Step 3: Check user and experiment settings", additionally define the following variables
DOENKFONLY_ATM="YES" (for both GSI and JEDI run) to turn on EnKF-only run
DOIAU="NO" (for both GSI and JEDI run) or "YES" (for GSI run only, not ready for JEDI yet) to turn on or off IAU
DO_JEDIATMVAR="YES" (for JEDI run only) to run JEDI
DO_JEDIATMENS="YES"(for JEDI run only) to run JEDI
  • Example of GSI EnKF-only rocoto tasks for the first DA cycle
- gdas_prep                      
- gdas_fetchatmanlbias        
- gdas_prepatmanlbias         
- gdas_prepatmiodaobs         
- enkfgdas_atmensanlinit  
- enkfgdas_atmensanlfv3inc
- enkfgdas_atmensanlfinal 
- enkfgdas_atmensanlobs   
- enkfgdas_atmensanlsol   
- enkfgdas_fcst_mem001-080   
- enkfgdas_epos000-006   
- enkfgdas_esfc               
- enkfgdas_earc_tars_00-01  
- enkfgdas_cleanup 
  • Example of JEDI EnKF-only rocoto tasks for the first DA cycle
- gdas_prep                      
- gdas_fetchatmanlbias        
- gdas_prepatmanlbias         
- enkfgdas_eobs               
- enkfgdas_eupd               
- enkfgdas_ecen000            
- enkfgdas_ediag              
- enkfgdas_fcst_mem001-080 
- enkfgdas_epos000-006   
- enkfgdas_esfc               
- enkfgdas_earc_tars_00-01   
- enkfgdas_cleanup

Checklist

  • Any dependent changes have been merged and published
  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have documented my code, including function, input, and output descriptions
  • My changes generate no new warnings
  • New and existing tests pass with my changes
  • This change is covered by an existing CI test or a new one has been added
  • Any new scripts have been added to the .github/CODEOWNERS file with owners
  • I have made corresponding changes to the system documentation if necessary

Copy link
Contributor

@TravisElless-NOAA TravisElless-NOAA left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for picking up the ball on this @bhuang95. As I'm starting to relearn things, I have a few questions along with some other details I noticed initially.

Comment on lines +18 to +21
# If DOENKFONLY_ATM="YES", skip PROCESS_TROPCY
if [[ "${DOENKFONLY_ATM:-NO}" == "YES" ]] ; then
export PROCESS_TROPCY="NO"
fi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this block actually needed? I haven't run with this enkf setting yet, but in default testing PROCESS_TROPCY=NO gets set 3 lines earlier. Does this default change for enkf only?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TravisElless-NOAA I remember I added this block because PROCESS_TROPCY was set to "YES" somewhere and it failed the task when DOENKFONLY_ATM = "YES". Looks like this block is not needed any more here. I will remove this block and test it in the updated PR.

Comment on lines +31 to +32
'DOLETKF_OCN', 'IAUFHRS_ENKF', 'NET', 'NMEM_ENS_GFS', 'DO_GSISOILDA', 'DO_LAND_IAU',
'DOENKFONLY_ATM']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleans up the format of this block better

Suggested change
'DOLETKF_OCN', 'IAUFHRS_ENKF', 'NET', 'NMEM_ENS_GFS', 'DO_GSISOILDA', 'DO_LAND_IAU',
'DOENKFONLY_ATM']
'DOLETKF_OCN', 'IAUFHRS_ENKF', 'NET', 'NMEM_ENS_GFS',
'DO_GSISOILDA', 'DO_LAND_IAU', 'DOENKFONLY_ATM']

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TravisElless-NOAA Will modify as suggested in the updated PR. Thanks.


# Reset tasks to run enkf-only for atm if do_enkfonly_atm=true
if options['do_enkfonly_atm']:
task_names[run] = []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this clear out the prep jobs you just added/declared previously (line 389)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TravisElless-NOAA Yes. Line 385-390, and Line 429- basically reset task_names[run]. It was meant to only include necessary tasks for enkf-only run and to avoid excessive addition of "if" statements before these lines.

Looking at @aerorahul 's comments suggesting using DO_GSIATMVAR, DO_GSIATMENS, DO_JEDIATMVAR, DO_JEDIATMENS to set up enkf-only run for GSI and JEDI. this may not be preferred and I may need to add if statements instead.

Comment on lines +143 to +144
dep_dict = {'type': 'metatask', 'name': 'gdas_fcst', 'offset': f"-{timedelta_to_HMS(self._base['interval_gdas'])}"}
deps.append(rocoto.add_dependency(dep_dict))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did this need to be in your enkfonly if block? Currently this new dependency is being added to the entire suite of workflow options, where it wasn't before. So asking if this was intended or not.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TravisElless-NOAA Line 143-144 is not necessary to be include in the enkfonly if block. Because the enkfgdas_epmn in the enkfonly if block is dependent on the completion of enkfgdas_fcst on Line 143-144. But we can add them there too.

Comment on lines +39 to +44
{% if not DOENKFONLY_ATM %}
{% for iaufhr in IAUFHRS %}
{% set iaufhr = iaufhr %}
- "{{ COMIN_ATMOS_ANALYSIS_MEM | relpath(ROTDIR) }}/{{ head }}recentered_increment.atm.i{{ '%03d' % iaufhr }}.nc"
{% endfor %} # iaufhr in IAUFHRS
{% endfor %} # iaufhr in IAUFHRS
{% endif %}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section will need to be changed to match the JEDI version in lines 27-32. If running GSI version of ENKFONLY will want to archive increment files for that run as well.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TravisElless-NOAA I see. I will add one block for DOENKFONLY_ATM=YES to match Line 27-29 and add the increment files for GSI enkf-only run as well. Thanks.

@DavidHuber-NOAA
Copy link
Contributor

@bhuang95 Can you look through the items that shfmt flagged here and apply the recommended changes?

@aerorahul
Copy link
Contributor

@bhuang95
Thank you for this contribution.
I have a couple of high-level suggestions:

  1. We have a variable DO_HYBVAR=YES|NO that determines if we run a hybrid EnVar (DO_HYBVAR=YES) or Variational-only (DO_HYBVAR=NO). In addition to that, with DO_HYBVAR=NO always assumes that one wishes to run the variational solver. You wish to choose to update the prior with an ensemble-only via this PR. I assume you wish to only update the ensemble with JEDI (not the GSI-EnKF). We have a variable DO_JEDIATMENS=YES|NO. Should DO_HYBVAR=NO and DO_JEDIATMENS=YES not be sufficient to update the ensemble without executing the variational solver (GSI or JEDI)? What additional value does DO_ATMENSONLY add that is not covered under DO_HYBVAR=YES AND DO_JEDIATMENS=YES?
Variational Ensemble
DO_GSIATMVAR DO_GSIATMENS
DO_JEDIATMVAR DO_JEDIATMENS

With DO_HYBVAR=YES | NO to choose whether it is a hybrid or not (3DVar|EnKF), and the above variables to choose the appropriate update algorithm.

  1. Testing - for each of the options being added, running the GSI-EnKF only and JEDI-EnKF only, we suggest adding 2 separate tests; e.g. C48_gsiatmensDA.yaml and C48_jediatmensDA.yaml

@bhuang95
Copy link
Author

@bhuang95 Thank you for this contribution. I have a couple of high-level suggestions:

  1. We have a variable DO_HYBVAR=YES|NO that determines if we run a hybrid EnVar (DO_HYBVAR=YES) or Variational-only (DO_HYBVAR=NO). In addition to that, with DO_HYBVAR=NO always assumes that one wishes to run the variational solver. You wish to choose to update the prior with an ensemble-only via this PR. I assume you wish to only update the ensemble with JEDI (not the GSI-EnKF). We have a variable DO_JEDIATMENS=YES|NO. Should DO_HYBVAR=NO and DO_JEDIATMENS=YES not be sufficient to update the ensemble without executing the variational solver (GSI or JEDI)? What additional value does DO_ATMENSONLY add that is not covered under DO_HYBVAR=YES AND DO_JEDIATMENS=YES?

Variational Ensemble
DO_GSIATMVAR DO_GSIATMENS
DO_JEDIATMVAR DO_JEDIATMENS
With DO_HYBVAR=YES | NO to choose whether it is a hybrid or not (3DVar|EnKF), and the above variables to choose the appropriate update algorithm.

  1. Testing - for each of the options being added, running the GSI-EnKF only and JEDI-EnKF only, we suggest adding 2 separate tests; e.g. C48_gsiatmensDA.yaml and C48_jediatmensDA.yaml

@aerorahul and @TravisElless-NOAA Thanks for your suggestion. In this PR, we would like to set up enkf-only for both GSI and JEDI so that we can run a comparison of both. I used DO_ATMENSONLY trying to minimize changes to the workflow as it is quite complex. I agree it would be better to use DO_HYBVAR, DO_GSI(JEDI)ATMVAR and DO_GSI(JEDI)ATMENS to achieve this. I will modify this PR as suggested and will look into how to set up the CI tests.

Additionally, I have a another question. The DO_HYBRID run has a lot of tasks (e.g., post-processing tasks). In this PR, do you feel comfortable to only include limited tasks for this enkf-only run as I listed in the description? It would be easier for me to implement.

@bhuang95
Copy link
Author

@bhuang95 Can you look through the items that shfmt flagged here and apply the recommended changes?

@DavidHuber-NOAA I did not see obvious error in the shfmt scan log there. Following the information from Gemini, I installed shfmt and ran shfmt dev/job_cards/rocoto/prep.sh > /dev/null in the front terminal, no error message was printed out either. I probably used "shfmt" command incorrectly?

@DavidHuber-NOAA
Copy link
Contributor

@bhuang95 by default, shfmt writes the corrections to stdout. You can instead run it in place with the -w flag:

shfmt -w dev/job_cards/rocoto/prep.sh

or if you would like to write a new file so you can do your own comparison, you can use the -f flag:

shfmt dev/job_cards/rocoto/prep.sh -f dev/job_cards/rocoto/prep.sh.shfmt

@CoryMartin-NOAA
Copy link
Contributor

@bhuang95 can you start by resolving all the conflicts and then we can go from there on scoping out what is needed for this?

@bhuang95
Copy link
Author

bhuang95 commented Jan 6, 2026

@bhuang95 can you start by resolving all the conflicts and then we can go from there on scoping out what is needed for this?

Thanks very much, @CoryMartin-NOAA. I will fix the conflicts including the jcb repo.

CoryMartin-NOAA added a commit to NOAA-EMC/jcb that referenced this pull request Jan 8, 2026
This PR works along with the following three dependent PRs to enable the
EnKF-only configuration for the atmosphere within the global workflow
(see detailed description
NOAA-EMC/global-workflow#4345)

Dependencies:
-NOAA-EMC/global-workflow#4345
-NOAA-EMC/GDASApp#2010
-NOAA-EMC/jcb-gdas#219

Resolve
- NOAA-EMC/global-workflow#4339

---------

Co-authored-by: Cory Martin <[email protected]>
@bhuang95
Copy link
Author

@bhuang95 can you start by resolving all the conflicts and then we can go from there on scoping out what is needed for this?

@CoryMartin-NOAA I fixed most of shell script failure given what was suggested. I am not sure why the shellcheck still failed and I don't see any obvious issues now (some warning triggered this?). Is there a log file for this shellcheck failure?

@aerorahul
Copy link
Contributor

@bhuang95 can you start by resolving all the conflicts and then we can go from there on scoping out what is needed for this?

@CoryMartin-NOAA I fixed most of shell script failure given what was suggested. I am not sure why the shellcheck still failed and I don't see any obvious issues now (some warning triggered this?). Is there a log file for this shellcheck failure?

@WalterKolczynski-NOAA The shellcheck linter workflow is not posting the non-compliant lines on the PR. The workflow also does not show where it encountered an issue. Can we get some help on this please?

@aerorahul aerorahul mentioned this pull request Jan 14, 2026
11 tasks
@aerorahul
Copy link
Contributor

the bash_code_analysis Github action is not working as expected. @WalterKolczynski-NOAA is working on a fix.

@bhuang95
Copy link
Author

@CoryMartin-NOAA Finally fixed the shellcheck failure and passed all checks. Learnt a lot how this process works, thank you all!

DavidNew-NOAA pushed a commit to NOAA-EMC/jcb-gdas that referenced this pull request Jan 16, 2026
This PR works along with the following three dependent PRs to enable the
EnKF-only configuration for the atmosphere within the global workflow
(see detailed description
NOAA-EMC/global-workflow#4345)

Dependencies:
-NOAA-EMC/global-workflow#4345
-NOAA-EMC/GDASApp#2010
-NOAA-EMC/jcb#32

Resolve
- NOAA-EMC/global-workflow#4339

---------

Co-authored-by: Cory Martin <[email protected]>
DavidNew-NOAA pushed a commit to NOAA-EMC/GDASApp that referenced this pull request Jan 16, 2026
This PR works along with the following three dependent PRs to enable the
EnKF-only configuration for the atmosphere within the global workflow
(see detailed description
NOAA-EMC/global-workflow#4345)

Dependencies:
-NOAA-EMC/global-workflow#4345
-#2010
-NOAA-EMC/jcb#32

Resolve
- NOAA-EMC/global-workflow#4339

---------

Co-authored-by: Cory Martin <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants