Skip to content
Open
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
3da2797
add method to process aerosol analysis to grib2
Jul 21, 2025
3333a7e
fix coding norms
Jul 21, 2025
63e3233
add upp processing to job script
Jul 21, 2025
6c67cf1
add atmos history path
Jul 21, 2025
5e4a341
stage files to run UPP
Jul 21, 2025
33daaf2
update job resource
Jul 22, 2025
6e6ea86
update namelist template with 'nasa_on' parameter
Jul 22, 2025
3757474
set running environment
Jul 22, 2025
2f23293
save the output grib2 file to COMOUT_CHEM_ANALYSIS
Jul 22, 2025
8b26fb8
norm fix
Jul 22, 2025
d27ab35
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Jul 22, 2025
0323953
remove unnecessary lines
Jul 23, 2025
c5333e4
Merge branch 'NOAA-EMC:develop' into feature/aero_postprocess
ypwang19 Jul 29, 2025
51fd3b3
reset to analysis time in input file, and save output to ROTDIR
Jul 30, 2025
91c3338
save grib2 file to ROTDIR
Jul 30, 2025
4332bf5
update gdasapp hash
Jul 30, 2025
3e5e9a2
Merge remote-tracking branch 'upstream/develop' into feature/aero_pos…
Jul 30, 2025
5b34437
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Aug 14, 2025
0018c9f
Merge remote-tracking branch 'upstream/develop' into feature/aero_pos…
Aug 20, 2025
5dcd41b
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Aug 21, 2025
eafddaa
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Aug 25, 2025
8f225d2
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Aug 28, 2025
d5dfc8c
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Sep 4, 2025
cebf39d
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Sep 5, 2025
f0cedc0
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Sep 8, 2025
1156e05
fix conflict
ypwang19 Sep 16, 2025
799423a
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Sep 16, 2025
a296a06
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Sep 16, 2025
bcda940
fix conflict
ypwang19 Sep 16, 2025
8a8cee6
Revert "fix conflict"
ypwang19 Sep 16, 2025
63879af
update submodule
ypwang19 Sep 16, 2025
4291edb
Merge branch 'feature/aero_postprocess' of https://github.com/ypwang1…
ypwang19 Sep 16, 2025
41561d6
fix conflict
ypwang19 Sep 16, 2025
ef9a9eb
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Sep 17, 2025
af28fc6
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Sep 18, 2025
a8ff6ed
add upp config file
Sep 18, 2025
b34ef72
use task number of 96 for aeroanlfinal
Sep 18, 2025
25ac018
link upp/parm/gcafs to workflow ./post
Sep 19, 2025
b5d9759
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Sep 19, 2025
6551e4f
archive aeroanl.grib2
Sep 19, 2025
ccca20c
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Sep 22, 2025
8262265
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Sep 22, 2025
f62921b
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Sep 23, 2025
6c1be3b
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Sep 26, 2025
4c0ee0b
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Sep 29, 2025
4d613f4
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Oct 2, 2025
7109685
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Oct 6, 2025
73a7ea3
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Oct 7, 2025
bd0e5c6
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Oct 28, 2025
3914b30
resolve conflict
Oct 28, 2025
4b44b61
update ufs_model hash
Oct 28, 2025
afb2a25
adjustment for compatibility with the latest workflow changes
Oct 30, 2025
70d48ff
Merge branch 'develop' into feature/aero_postprocess
ypwang19 Oct 30, 2025
860d847
fix norm check
Oct 30, 2025
7375d4e
fix norm check
Oct 30, 2025
426498a
fix
Oct 30, 2025
b01276d
add upp-related configuration in the constructor, instead of in the m…
Oct 31, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions dev/parm/config/gcafs/config.aeroanl.j2
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,16 @@
export STAGE_YAML="${PARMgfs}/gdas/aero/aero_det_stage.yaml.j2"
export SAVE_YAML="${PARMgfs}/gdas/aero/aero_det_save.yaml.j2"

<<<<<<< HEAD
export JEDI_CONFIG_YAML="${PARMgfs}/gdas/aeroanl_jedi_config.yaml.j2"
export UPP_CONFIG_YAML="${PARMgfs}/gdas/aeroanl_upp_config.yaml.j2"

export AERO_STAGE_VARIATIONAL_TMPL="${PARMgfs}/gdas/aero_stage_variational.yaml.j2"
export AERO_FINALIZE_VARIATIONAL_TMPL="${PARMgfs}/gdas/aero_finalize_variational.yaml.j2"
export AERO_BMATRIX_RESCALE_TMPL="aero_gen_bmatrix_rescale_default.yaml.j2"
=======
export AERO_BMATRIX_RESCALE_YAML="aero_gen_bmatrix_rescale_default.yaml.j2"
>>>>>>> upstream/develop

export io_layout_x="{{ IO_LAYOUT_X }}"
export io_layout_y="{{ IO_LAYOUT_Y }}"
Expand Down
4 changes: 2 additions & 2 deletions dev/parm/config/gcafs/config.resources
Original file line number Diff line number Diff line change
Expand Up @@ -520,10 +520,10 @@ case ${step} in
echo "FATAL ERROR: Resources not defined for job ${step} at resolution ${CASE}"
exit 4
esac
ntasks=1
ntasks=120
threads_per_task=1
tasks_per_node=$(( max_tasks_per_node / threads_per_task ))
memory="13072M"
memory=${mem_node_max}
;;

"marineanlinit")
Expand Down
1 change: 1 addition & 0 deletions dev/parm/config/gfs/config.com
Original file line number Diff line number Diff line change
Expand Up @@ -110,5 +110,6 @@ declare -rx COM_CHEM_HISTORY_TMPL=${COM_BASE}'/model/chem/history'
declare -rx COM_CHEM_ANALYSIS_TMPL=${COM_BASE}'/analysis/chem'
declare -rx COM_CHEM_BMAT_TMPL=${COM_CHEM_ANALYSIS_TMPL}'/bmatrix'
declare -rx COM_CHEM_ANLMON_TMPL=${COM_BASE}'/products/chem/anlmon'
declare -rx COM_CHEM_GRIB_TMPL=${COM_BASE}'/products/chem/grib2'

declare -rx COM_MED_RESTART_TMPL=${COM_BASE}'/model/med/restart'
7 changes: 7 additions & 0 deletions env/GAEAC5.env
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ case ${step} in
export NTHREADS_AEROANL=${NTHREADSmax}
export APRUN_AEROANL="${APRUN_default} --cpus-per-task=${NTHREADS_AEROANL}"
;;
"aeroanlfinal")

export APRUNCFP="${launcher} -n \$ncmd ${mpmd_opt}"

export NTHREADS_AEROANLFINAL=${NTHREADSmax}
export APRUN_AEROANLFINAL="${APRUN_default} --cpus-per-task=${NTHREADS_AEROANLFINAL}"
;;
"aeroanlgenb")

export NTHREADS_AEROANLGENB=${NTHREADSmax}
Expand Down
7 changes: 7 additions & 0 deletions env/GAEAC6.env
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ case ${step} in
export NTHREADS_AEROANL=${NTHREADSmax}
export APRUN_AEROANL="${APRUN_default} --cpus-per-task=${NTHREADS_AEROANL}"
;;
"aeroanlfinal")

export APRUNCFP="${launcher} -n \$ncmd ${mpmd_opt}"

export NTHREADS_AEROANLFINAL=${NTHREADSmax}
export APRUN_AEROANLFINAL="${APRUN_default} --cpus-per-task=${NTHREADS_AEROANLFINAL}"
;;
"aeroanlgenb")

export NTHREADS_AEROANLGENB=${NTHREADSmax}
Expand Down
7 changes: 7 additions & 0 deletions env/HERA.env
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ elif [[ "${step}" = "aeroanlvar" ]]; then
export NTHREADS_AEROANL=${NTHREADSmax}
export APRUN_AEROANL="${APRUN_default} --cpus-per-task=${NTHREADS_AEROANL}"

elif [[ "${step}" = "aeroanlfinal" ]]; then

export APRUNCFP="${launcher} -n \$ncmd ${mpmd_opt}"

export NTHREADS_AEROANLFINAL=${NTHREADSmax}
export APRUN_AEROANLFINAL="${APRUN_default} --cpus-per-task=${NTHREADS_AEROANLFINAL}"

elif [[ "${step}" = "aeroanlgenb" ]]; then

export NTHREADS_AEROANLGENB=${NTHREADSmax}
Expand Down
7 changes: 7 additions & 0 deletions env/HERCULES.env
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,13 @@ case ${step} in

export NTHREADS_AEROANL=${NTHREADSmax}
export APRUN_AEROANL="${APRUN_default} --cpus-per-task=${NTHREADS_AEROANL}"
;;
"aeroanlfinal")

export APRUNCFP="${launcher} -n \$ncmd ${mpmd_opt}"

export NTHREADS_AEROANLFINAL=${NTHREADSmax}
export APRUN_AEROANLFINAL="${APRUN_default} --cpus-per-task=${NTHREADS_AEROANLFINAL}"
;;
"aeroanlgenb")

Expand Down
7 changes: 7 additions & 0 deletions env/ORION.env
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ elif [[ "${step}" = "aeroanlvar" ]]; then
export NTHREADS_AEROANL=${NTHREADSmax}
export APRUN_AEROANL="${APRUN_default} --cpus-per-task=${NTHREADS_AEROANL}"

elif [[ "${step}" = "aeroanlfinal" ]]; then

export APRUNCFP="${launcher} -n \$ncmd ${mpmd_opt}"

export NTHREADS_AEROANLFINAL=${NTHREADSmax}
export APRUN_AEROANLFINAL="${APRUN_default} --cpus-per-task=${NTHREADS_AEROANLFINAL}"

elif [[ "${step}" = "aeroanlgenb" ]]; then

export NTHREADS_AEROANLGENB=${NTHREADSmax}
Expand Down
7 changes: 7 additions & 0 deletions env/WCOSS2.env
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ elif [[ "${step}" = "aeroanlvar" ]]; then
export NTHREADS_AEROANL=${NTHREADSmax}
export APRUN_AEROANL="${APRUN_default}"

elif [[ "${step}" = "aeroanlfinal" ]]; then

export APRUNCFP="${launcher} -np \$ncmd ${mpmd_opt}"

export NTHREADS_AEROANLFINAL=${NTHREADSmax}
export APRUN_AEROANLFINAL="${APRUN_default}"

elif [[ "${step}" = "aeroanlgenb" ]]; then

export NTHREADS_AEROANLGENB=${NTHREADSmax}
Expand Down
3 changes: 2 additions & 1 deletion jobs/JGLOBAL_AERO_ANALYSIS_FINALIZE
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ source "${HOMEgfs}/ush/jjob_header.sh" -e "aeroanlfinal" -c "base aeroanl aeroan
YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \
COMOUT_CHEM_ANALYSIS:COM_CHEM_ANALYSIS_TMPL \
COMOUT_CONF:COM_CONF_TMPL \
COMOUT_ATMOS_RESTART:COM_ATMOS_RESTART_TMPL
COMOUT_ATMOS_RESTART:COM_ATMOS_RESTART_TMPL \
COMOUT_CHEM_GRIB:COM_CHEM_GRIB_TMPL

###############################################################
# Run relevant script
Expand Down
2 changes: 2 additions & 0 deletions jobs/JGLOBAL_AERO_ANALYSIS_INITIALIZE
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ GDUMP="${GDUMP/gcafs/gcdas}"
# Generate COM variables from templates
YMD=${PDY} HH=${cyc} declare_from_tmpl -rx \
COMIN_OBS:COM_OBS_TMPL \
COMIN_ATMOS_ANALYSIS:COM_ATMOS_ANALYSIS_TMPL \
COMOUT_CHEM_ANALYSIS:COM_CHEM_ANALYSIS_TMPL

RUN=${GDUMP} YMD=${gPDY} HH=${gcyc} declare_from_tmpl -rx \
COMIN_ATMOS_RESTART_PREV:COM_ATMOS_RESTART_TMPL \
COMIN_ATMOS_HISTORY_PREV:COM_ATMOS_HISTORY_TMPL \
COMIN_CHEM_BMAT_PREV:COM_CHEM_BMAT_TMPL \
COMIN_CHEM_ANALYSIS_PREV:COM_CHEM_ANALYSIS_TMPL

Expand Down
1 change: 1 addition & 0 deletions parm/post/itag.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
kpo = {{ po | length }},
po = {{ po | join(', ') }},
rdaod = {{ rdaod | to_f90bool }}
nasa_on = {{ nasa_on | to_f90bool }}
/

1 change: 1 addition & 0 deletions parm/post/upp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ upp:
ioform: "netcdfpara"
po: [1000.,975.,950.,925.,900.,875.,850.,825.,800.,775.,750.,725.,700.,675.,650.,625.,600.,575.,550.,525.,500.,475.,450.,425.,400.,375.,350.,325.,300.,275.,250.,225.,200.,175.,150.,125.,100.,70.,50.,40.,30.,20.,15.,10.,7.,5.,3.,2.,1.,0.7,0.4,0.2,0.1,0.07,0.04,0.02,0.01]
rdaod: False
nasa_on: False
fix_data:
mkdir:
- "{{ DATA }}"
Expand Down
4 changes: 4 additions & 0 deletions scripts/exglobal_aero_analysis_finalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from wxflow import Logger, cast_strdict_as_dtypedict
from pygfs.task.aero_analysis import AerosolAnalysis
from pygfs.task.upp import UPP


# Initialize root logger
Expand All @@ -22,5 +23,8 @@
# Instantiate the aerosol analysis task
AeroAnl = AerosolAnalysis(config)

# Process aerosal products through UPP
AeroAnl.upp_anlproc()

# Finalize JEDI aerosol variational analysis
AeroAnl.finalize()
135 changes: 133 additions & 2 deletions ush/python/pygfs/task/aero_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@

from wxflow import (AttrDict,
FileHandler,
add_to_datetime, to_fv3time, to_timedelta,
add_to_datetime, to_timedelta,
to_fv3time,
Task,
Task, Jinja,
YAMLFile, parse_j2yaml,
logit)
from pygfs.jedi import Jedi
import numpy as np
from pygfs.task.upp import UPP

logger = getLogger(__name__.split('.')[-1])

Expand Down Expand Up @@ -262,3 +263,133 @@ def add_fv3_increments(self, inc_file_YAML: str, bkg_file_YAML: str, incvars: Li
rstfile.variables[vname].delncattr('checksum') # remove the checksum so fv3 does not complain
except (AttributeError, RuntimeError):
pass # checksum is missing, move on

@logit(logger)
def upp_anlproc(self) -> None:
"""Process aerosol analysis to GRIB2

This method processes aerosol analysis products from tracer fields using UPP.
This includes:
- Creating a UPP object
- Staging UPP fix files
- Creating the 'upp_dict' for UPP object
- Generating the upp namelist
- Adding atmos and aerosol increments to the background
- Execute upp.x
"""

local_dict = AttrDict(
{
'UPP_RUN': "analysis",
'FORECAST_HOUR': 0
}
)
self.task_config = AttrDict(**self.task_config, **local_dict)
self.task_config.UPP_CONFIG = self.task_config.UPP_CONFIG_YAML
Copy link
Contributor

Choose a reason for hiding this comment

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

self.task_config should only be changed in the constructor for this class. It's supposed to represent to the configuration for the class, which shouldn't be changed by any of its methods

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I moved these changes to the constructor for this class.

Copy link
Contributor

Choose a reason for hiding this comment

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

I have some follow up comments, but I'm out of the house. I'll update when I get home

Copy link
Contributor

Choose a reason for hiding this comment

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

Will get back to this Sunday or Monday

upp = UPP(self.task_config)

upp_yaml = upp.task_config.upp_yaml
upp.initialize(upp_yaml)

upp_dict = AttrDict()
keys = ['APRUN_AEROANLFINAL', 'forecast_hour',
'atmos_filename', 'flux_filename']

upp_dict = AttrDict()
for key in keys:
upp_dict[key] = upp.task_config[key]

upp_dict['NET'] = 'gfs' # set to 'gfs' so upp can recognize
upp_dict['valid_datetime'] = self.task_config.current_cycle
upp_dict['DATA'] = os.path.join(self.task_config.DATA, 'upp')
upp_dict.update(upp_yaml['upp']['config'])

# Configure the namelist and write to file
logger.info("Creating namelist for upp.x")
nml_template = os.path.join(upp_dict.DATA, "itag.jinja")
nml_data = Jinja(nml_template, upp_dict).render
logger.debug(f"itag:\n{nml_data}")
nml_file = os.path.join(upp_dict.DATA, 'itag')
with open(nml_file, "w") as fho:
fho.write(nml_data)

# ---- add aero increments to atmf000 files
logger.info('Adding aero increments to RESTART files')
bkg_file = os.path.join(upp_dict.DATA, f"{upp_dict.atmos_filename}")
inc_filename = f"aeroinc_gauss.{self.task_config.current_cycle.strftime('%Y-%m-%dT%H:%M:%S')}Z.gaussian.modelLevels.nc"
inc_file = os.path.join(self.task_config.DATA, 'anl', inc_filename)
allvars = upp_yaml['aeroincvars'][:]
bkgvars = [var[0] for var in allvars]
incvars = [var[1] for var in allvars]
self.add_aero_gaussian_increments(inc_file, bkg_file, incvars, bkgvars)

# ---- add atmo increments to atmf000 files
logger.info('Adding atmo increments to RESTART files')
inc_file = os.path.join(upp_dict.DATA, f"{self.task_config.APREFIX}atminc.nc")
allvars = upp_yaml['atmincvars'][:]
bkgvars = [var[0] for var in allvars]
incvars = [var[1] for var in allvars]
self.add_atm_gaussian_increments(inc_file, bkg_file, incvars, bkgvars)

# reset time to 0 (analysis time)
flux_file = os.path.join(upp_dict.DATA, f"{upp_dict.flux_filename}")
with Dataset(flux_file, mode='a') as rstfile:
time = rstfile.variables['time']
time[:] = 0.0
time.setncattr("units", f"hours since {self.task_config.current_cycle.strftime('%Y-%m-%d %H:%M:%S')}")

upp.execute(upp_dict.DATA, upp_dict.APRUN_AEROANLFINAL, upp_dict.forecast_hour)

@logit(logger)
def add_aero_gaussian_increments(self, inc_file: str, bkg_file: str, incvars: List, bkgvars: List) -> None:
"""Add aero gaussian increments to gaussian backgrounds

Parameters
----------
inc_file : str
increment file
bkg_file : str
background file
incvars : List
List of increment variables to add to the background
bkgvars : List
List of background variables to which the increment variables will be added.
"""
with Dataset(inc_file, mode='r') as incfile, Dataset(bkg_file, mode='a') as rstfile:
for incname, bkgname in zip(incvars, bkgvars):
increment = incfile.variables[incname][:]
# reordering the dimensions of increment to macth background
increment_reshape = np.transpose(increment, (2, 0, 1))

bkg = rstfile.variables[bkgname][:]
anl = bkg + increment_reshape[np.newaxis, :, :, :]
rstfile.variables[bkgname][:] = anl[:]
time = rstfile.variables['time']
time[:] = 0.0
time.setncattr("units", f"hours since {self.task_config.current_cycle.strftime('%Y-%m-%d %H:%M:%S')}")

@logit(logger)
def add_atm_gaussian_increments(self, inc_file: str, bkg_file: str, incvars: List, bkgvars: List) -> None:
"""Add atm gaussian increments to gaussian backgrounds

Parameters
----------
inc_file : str
increment file
bkg_file : str
background file
incvars : List
List of increment variables to add to the background
bkgvars : List
List of background variables to which the increment variables will be added.
"""
with Dataset(inc_file, mode='r') as incfile, Dataset(bkg_file, mode='a') as rstfile:
for incname, bkgname in zip(incvars, bkgvars):
increment = incfile.variables[incname][:]
# handel latitude inversion in atminc
lat_axis_index = 1
increment_lat_inversion = np.flip(increment, axis=lat_axis_index)

bkg = rstfile.variables[bkgname][:]
anl = bkg + increment_lat_inversion[np.newaxis, :, :, :]
rstfile.variables[bkgname][:] = anl[:]