Skip to content
Open
Show file tree
Hide file tree
Changes from 50 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
bf42dd3
first commit
mer-a-o Jan 27, 2026
573df4a
fix failing tests
mer-a-o Feb 3, 2026
128f065
clean up and handling NO
mer-a-o Feb 3, 2026
e40af4f
fix coding norm
mer-a-o Feb 3, 2026
80caed4
fail if obs is not listed in observation_ioda_names.yaml
mer-a-o Feb 4, 2026
51bc473
add tier 1 tests
mer-a-o Feb 4, 2026
5be3656
fix coding norm
mer-a-o Feb 4, 2026
db3dda0
Update src/swell/configuration/jedi/interfaces/geos_cf/task_questions…
mer-a-o Feb 6, 2026
ce8f42c
Update src/swell/configuration/jedi/interfaces/geos_cf/task_questions…
mer-a-o Feb 6, 2026
d5e745e
first commit
Feb 9, 2026
c9df76a
changes for 3d var compo
Feb 24, 2026
5e762e7
Merge branch 'develop' into feature/add-3dvar-cf
Feb 24, 2026
3e5ea35
fix duplicate
Feb 24, 2026
f6f2353
fix stage
Feb 24, 2026
fddcf1e
remove 'very naughty' if statement
jeromebarre Feb 24, 2026
56f7bc5
fix gsi bec specific stuff
Feb 24, 2026
967fbc2
geometry fixes
jeromebarre Feb 24, 2026
933c014
fix mpi
jeromebarre Feb 26, 2026
e9b7c84
fix mpi issues in suite config
jeromebarre Feb 27, 2026
717fe18
fix io
jeromebarre Feb 27, 2026
44807fe
fix field io
jeromebarre Feb 27, 2026
1bfc169
dep eva fix
jeromebarre Mar 2, 2026
f5bd97c
eva names
jeromebarre Mar 2, 2026
885ecb6
eva changes
jeromebarre Mar 2, 2026
0a27a53
coding norms
jeromebarre Mar 3, 2026
fe75a85
PR review 1
jeromebarre Mar 4, 2026
129e704
save
jeromebarre Mar 9, 2026
dd42a94
Merge branch 'develop' into feature/3dvar_cf_bump
jeromebarre Mar 9, 2026
ea37090
update stage b matrix files
jeromebarre Mar 9, 2026
115044e
add params
jeromebarre Mar 9, 2026
b3dee8e
fix params
jeromebarre Mar 9, 2026
97e3c1f
changed my mind fix params
jeromebarre Mar 10, 2026
dbd22af
stage fix
jeromebarre Mar 10, 2026
8f7af3e
add increment output
mer-a-o Mar 11, 2026
7bb1884
Merge remote-tracking branch 'origin/feature/mer-a-o/write-inc-cs' in…
jeromebarre Mar 12, 2026
a7231d2
Merge branch 'develop' into feature/add-3dvar-cf
jeromebarre Mar 12, 2026
649f025
coding norms
jeromebarre Mar 12, 2026
5f8d710
Merge branch 'feature/add-3dvar-cf' into feature/3dvar_cf_bump
jeromebarre Mar 13, 2026
daa393f
fix stdev read
jeromebarre Mar 13, 2026
d548042
improve stage
jeromebarre Mar 13, 2026
f0b247c
fix keys
jeromebarre Mar 13, 2026
86bf901
fix bkg err
jeromebarre Mar 13, 2026
b80e969
saber changes
Mar 17, 2026
041e9be
swell static files
jeromebarre Mar 17, 2026
1f3830b
revert to default
jeromebarre Mar 17, 2026
dca9ca9
Merge branch 'develop' into feature/3dvar_cf_bump
Mar 19, 2026
b35bb42
fix yaml
Mar 20, 2026
be6edb9
coding norms
jeromebarre Mar 20, 2026
4f6ada1
coding norms 2
jeromebarre Mar 20, 2026
9855a36
remove unused var
jeromebarre Mar 20, 2026
2806c42
pr review 1
jeromebarre Mar 30, 2026
4bfe8a7
typo
jeromebarre Mar 30, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,152 @@
# --------------------------------------------------------------------------------------------------

from collections.abc import Mapping
from swell.configuration.jedi.interfaces.geos_cf.model.shared import \
field_io_names


# Central block builders
# --------------------------------------------------------------------------------------------------


def _build_identity_central_block(template_dict: Mapping) -> Mapping:
"""Identity covariance central block"""
return {'saber block name': 'ID'}


def _build_bump_nicas_central_block(template_dict: Mapping) -> Mapping:
"""BUMP/NICAS covariance central block"""
field_aliases = []
for var in template_dict.get('analysis_variables', []):
field_aliases.append({
'in code': var,
'in file': 'fixedlevel_H_500_300_V_00_03'
})

return {
'saber block name': 'BUMP_NICAS',
'read': {
'io': {
'data directory': f"{template_dict['cycle_dir']}/",
'files prefix': 'geos_cf',
'alias': field_aliases
},
'drivers': {
'multivariate strategy': 'univariate',
'read local nicas': True
}
}
}

# Outer block builders
# --------------------------------------------------------------------------------------------------


def _build_stddev_bkg_scaled(template_dict: Mapping) -> Mapping:
"""Standard deviation outer block"""
return {
'saber block name': 'StdDev',
'stddev scale factor': '0.25',
'read': {
'model file': {
'datetime': template_dict['local_background_time_iso'],
'set datetime on read': True,
'filetype': 'cube sphere history',
'max allowable geometry difference': 0.1,
'datapath': template_dict['cycle_dir'],
'filename': 'bkg.%yyyy%mm%ddT%hh%MM%ssZ.nc4',
'field io names': field_io_names,
}
}
}


def _build_stddev_fixed_values(template_dict: Mapping) -> Mapping:
"""Standard deviation outer block with fixed values from analysis variables"""
# Get the stddev values for each analysis variable
# Example: {'volume_mixing_ratio_of_no2': 5e-9, 'volume_mixing_ratio_of_o3': 1e-8}
stddev_dict = {
'volume_mixing_ratio_of_no2': 5e-9,
'volume_mixing_ratio_of_o3': 1e-8,
'volume_mixing_ratio_of_co': 5e-8,
}

# Build the standard deviations list
standard_deviations = [
{'variable': var, 'stddev': value}
for var, value in stddev_dict.items()
]

return {
'saber block name': 'StdDev',
'standard deviations': standard_deviations
}

# Main assembler
# --------------------------------------------------------------------------------------------------


def background_error(template_dict: Mapping) -> Mapping:
"""
Assemble background error covariance configuration from modular components.

Parameters
----------
template_dict : Mapping
Dictionary containing configuration parameters including:
- central_block: Type of central block ('identity', 'bump_nicas', 'diffusion')
- outer_block: add StdDev outer block


Returns
-------
Mapping
JEDI-compatible background error covariance configuration
"""

# Select central block builder
central_block_select = template_dict.get('saber_central_block', 'identity')

central_block_types = {
'identity': _build_identity_central_block,
'bump_nicas': _build_bump_nicas_central_block,
}

background_error = {
# Build the central block
if central_block_select not in central_block_types:
raise ValueError(
f"Unknown background_error_model '{central_block_select}'. "
f"Choose from: {list(central_block_types.keys())}"
)

central_block = central_block_types[central_block_select](template_dict)

# Assemble base configuration
background_error_config = {
'covariance model': 'SABER',
'saber central block': {
'saber block name': 'ID'
},
'saber central block': central_block,
}

return background_error
# Optionally add outer blocks (skip for identity central block)
if central_block_select != 'identity' and 'saber_outer_block' in template_dict:

outer_block_select = template_dict.get('saber_outer_block')

outer_block_types = {
'stddev_bkg_scaled': _build_stddev_bkg_scaled,
'stddev_fixed_values': _build_stddev_fixed_values,
}

if outer_block_select not in outer_block_types:
raise ValueError(
f"Unknown outer_block '{outer_block_select}'. "
f"Choose from: {list(outer_block_types.keys())}"
)

outer_block = outer_block_types[outer_block_select](template_dict)

background_error_config['saber outer blocks'] = [outer_block]

return background_error_config

# --------------------------------------------------------------------------------------------------
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,35 @@ def stage_cycle(template_dict: Mapping) -> Mapping:

cycle_dir = template_dict['cycle_dir']
swell_static_files = template_dict['swell_static_files']
npx_proc = template_dict['npx_proc']
npy_proc = template_dict['npy_proc']

stage_cycle = [
{'copy_files': {
'directories': [
[f'{swell_static_files}/jedi/interfaces/geos_cf/fv3_files/*', f'{cycle_dir}/']
[
f'{swell_static_files}/jedi/interfaces/geos_cf/fv3_files/*',
f'{cycle_dir}/'
]
]
}}
]

# Only link NICAS files when the central block corresponds to BUMP_NICAS
central_block_select = template_dict.get('saber_central_block', 'none')
if central_block_select == 'bump_nicas':
stage_cycle.append({
'link_files': {
'directories': [
[
f'{swell_static_files}/jedi/interfaces/geos_cf/nicas/'
f'layout_{npx_proc}x{npy_proc}x6/*',
f'{cycle_dir}/'
]
]
}
})

return stage_cycle

# --------------------------------------------------------------------------------------------------
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@ analysis_variables:
options:
- volume_mixing_ratio_of_no2

background_error_model:
default_value: identity
saber_central_block:
default_value: bump_nicas
options:
- identity
- bump_nicas

saber_outer_block:
default_value: stddev_bkg_scaled
options:
- stddev_bkg_scaled
- stddev_fixed_values

background_experiment:
default_value: swell_test
Expand Down
7 changes: 6 additions & 1 deletion src/swell/configuration/jedi/oops/variational3D.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,12 @@ def render_oops(self):
},
'prints': {
'frequency': 'PT3H'
}
},
'increment': {
'geometry': self.interface_model('geometry'),
'output': self.interface_model('increment_cs'),
},

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can you make sure the fix from #743 is incorporated?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm testing this PR right now, and it looks like it's already incorporated in line 65-68. So there's no need to make any changes to this file in this PR.

},
'output': self.interface_model('analysis')
}
Expand Down
2 changes: 2 additions & 0 deletions src/swell/suites/3dvar_cf/suite_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class SuiteConfig(QuestionContainer, Enum):
qd.npx_proc(2),
qd.npy_proc(2),
qd.vertical_resolution(72),
qd.saber_central_block('bump_nicas'),
qd.saber_outer_block('stddev_bkg_scaled'),
qd.analysis_variables(["volume_mixing_ratio_of_no2"]),
qd.background_experiment("swell_test"),
qd.observations([
Expand Down
2 changes: 2 additions & 0 deletions src/swell/tasks/run_jedi_variational_executable.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ def execute(self) -> None:
self.jedi_rendering.add_key('minimizer', self.config.minimizer())
self.jedi_rendering.add_key('number_of_iterations', number_of_iterations[0])
self.jedi_rendering.add_key('analysis_variables', self.config.analysis_variables())
self.jedi_rendering.add_key('saber_central_block', self.config.saber_central_block())
self.jedi_rendering.add_key('saber_outer_block', self.config.saber_outer_block())
self.jedi_rendering.add_key('gradient_norm_reduction',
self.config.gradient_norm_reduction())
self.jedi_rendering.add_key('marine_models', self.config.marine_models(None))
Expand Down
6 changes: 6 additions & 0 deletions src/swell/tasks/stage_jedi.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,23 @@ def execute(self) -> None:
swell_static_files = swell_static_files_user

vertical_resolution = self.config.vertical_resolution()
npx_proc = self.config.npx_proc(None)
npy_proc = self.config.npy_proc(None)
gsibec_configuration = self.config.gsibec_configuration(None)
gsibec_nlats = self.config.gsibec_nlats(None)
gsibec_nlons = self.config.gsibec_nlons(None)
saber_central_block = self.config.saber_central_block(None)

# Add jedi interface template keys
self.jedi_rendering.add_key('horizontal_resolution', horizontal_resolution)
self.jedi_rendering.add_key('swell_static_files', swell_static_files)
self.jedi_rendering.add_key('vertical_resolution', vertical_resolution)
self.jedi_rendering.add_key('npx_proc', npx_proc)
self.jedi_rendering.add_key('npy_proc', npy_proc)
self.jedi_rendering.add_key('gsibec_configuration', gsibec_configuration)
self.jedi_rendering.add_key('gsibec_nlats', gsibec_nlats)
self.jedi_rendering.add_key('gsibec_nlons', gsibec_nlons)
self.jedi_rendering.add_key('saber_central_block', saber_central_block)

# Open the stage configuration file
# ---------------------------------
Expand Down
5 changes: 5 additions & 0 deletions src/swell/tasks/task_questions.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ class TaskQuestions(QuestionContainer, Enum):
qd.gsibec_nlons(),
qd.number_of_iterations(),
qd.total_processors(),
qd.saber_central_block(),
qd.saber_outer_block(),
]
)

Expand Down Expand Up @@ -769,10 +771,13 @@ class TaskQuestions(QuestionContainer, Enum):
list_name="StageJedi",
questions=[
swell_static_file_questions,
qd.npx_proc(),
qd.npy_proc(),
qd.gsibec_configuration(),
qd.gsibec_nlats(),
qd.gsibec_nlons(),
qd.horizontal_resolution(),
qd.saber_central_block(),
qd.vertical_resolution()
]
)
Expand Down
28 changes: 28 additions & 0 deletions src/swell/utilities/question_defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,34 @@ class background_error_model(TaskQuestion):

# --------------------------------------------------------------------------------------------------

@dataclass
class saber_central_block(TaskQuestion):
default_value: str = "defer_to_model"
question_name: str = "saber_central_block"
ask_question: bool = True
options: str = "defer_to_model"
models: List[str] = mutable_field([
"all_models"
])
prompt: str = "Which saber central block do you want to use?"
widget_type: WType = WType.STRING

# --------------------------------------------------------------------------------------------------

@dataclass
class saber_outer_block(TaskQuestion):
default_value: str = "defer_to_model"
question_name: str = "saber_outer_block"
ask_question: bool = True
options: str = "defer_to_model"
models: List[str] = mutable_field([
"all_models"
])
prompt: str = "Which saber outer blocks do you want to use?"
widget_type: WType = WType.STRING

# --------------------------------------------------------------------------------------------------

@dataclass
class background_experiment(TaskQuestion):
default_value: str = "defer_to_model"
Expand Down
2 changes: 2 additions & 0 deletions src/swell/utilities/render_jedi_interface_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ def __init__(
'obs_filenames',
'packet_ensemble_members',
'perhost',
'saber_central_block',
'saber_outer_block',
'skip_ensemble_hofx',
'swell_static_files',
'start_cycle_point',
Expand Down
Loading