Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
98 commits
Select commit Hold shift + click to select a range
cb9c947
write out exceptions
Dooruk Oct 3, 2025
c1f7119
minor changes, make TUI message clearer
Dooruk Oct 3, 2025
3ca20c4
changes in moving files between forecast cycles
Dooruk Oct 3, 2025
10ff584
take out the linking task
Dooruk Oct 3, 2025
79e6153
introduce simplified coupled tasks assuming direct execution of GEOS …
Dooruk Oct 7, 2025
b573f10
forecast suite changes
Dooruk Oct 7, 2025
a1fd030
revamp files, more changes underway
Dooruk Oct 7, 2025
55aeb11
define new coupled model only suite
Dooruk Oct 7, 2025
4c8b9a3
change forecast location and make forecast a static folder
Dooruk Dec 1, 2025
2f8ed47
format and code suggestions
Dooruk Dec 18, 2025
f44ec97
document and codestring
Dooruk Dec 18, 2025
c02bf4d
dont except exception, send exception type to logger
Dooruk Jan 26, 2026
e872e38
background error new form
Dooruk Jan 26, 2026
2aab229
get rid off deprecated keys
Dooruk Feb 2, 2026
a35440d
let go off catching exceptions
Dooruk Feb 2, 2026
4454c92
Merge branch 'develop' into feature/exec_geos_direct_part1
Dooruk Feb 2, 2026
1008a81
revert genB to original
Dooruk Feb 3, 2026
d6e5b99
get rid of unused keys, create alternative method (R2D2, albeit inact…
Dooruk Feb 3, 2026
d081529
minor changes to keep up with PRs
Dooruk Feb 3, 2026
14de66a
changes related to initial restarts
Dooruk Feb 3, 2026
c898ab1
first model specific task
Dooruk Feb 3, 2026
4facad7
Merge branch 'develop' into feature/exec_geos_direct_part1
Dooruk Feb 3, 2026
3ad2722
code style fixes
Dooruk Feb 3, 2026
1d71e1e
adapt to new obs handling
Dooruk Feb 4, 2026
eb4383a
skip save_restart while figuring R2D2 out
Dooruk Feb 4, 2026
6dc3825
deprecated keys related changes and few fixes
Dooruk Feb 4, 2026
23577cf
some changes for geosv12
Dooruk Feb 5, 2026
bad345f
changes in geos class utility for geos v12
Dooruk Feb 5, 2026
c03d9ac
changes for 3dvar_cycle to test get, prep and run
Dooruk Feb 5, 2026
68cea55
make forecast_geos use new method
Dooruk Feb 10, 2026
e6b5643
few fixes, stop using adjacent cycle
Dooruk Feb 10, 2026
cfd44be
clarify homdir expdir logic
Dooruk Feb 10, 2026
3adf0d7
netcdf specify
Dooruk Feb 10, 2026
b9a9a47
Merge branch 'develop' into feature/exec_geos_direct_part1
Dooruk Feb 10, 2026
c2317a3
better statement
Dooruk Feb 12, 2026
ba29005
take out model specific approach from this PR
Dooruk Feb 12, 2026
33a968c
apply minor code improvements
Dooruk Feb 12, 2026
23bc8a5
Merge branch 'develop' into feature/exec_geos_direct_part1
Dooruk Feb 12, 2026
f2e787d
Merge branch 'feature/exec_geos_direct_part1' into feature/exec_geos_…
Dooruk Feb 12, 2026
60b13c5
rename suites, take out obsolete parts and tasks
Dooruk Feb 12, 2026
2cffb0f
add docstrings and proper naming for tasks as forecast directory is n…
Dooruk Feb 13, 2026
b5b61da
version bump
Dooruk Feb 13, 2026
3149f05
suite changes with new task names
Dooruk Feb 18, 2026
dbe0a3f
code improvements
Dooruk Feb 18, 2026
7a2ad5f
make mom6_iau model dependent
Dooruk Feb 20, 2026
f24cd0a
cycle times hack
Dooruk Feb 20, 2026
5094cda
make experiment.yaml non-alphabetical again by using default ruamel
Dooruk Feb 20, 2026
022287b
relevant for experiment.yaml
Dooruk Feb 20, 2026
53ede0e
minor fix for MOM6 IAU
Dooruk Feb 20, 2026
714ecfe
cycle times and overrride fixes
Dooruk Feb 20, 2026
c88b448
add tier2 cycling run
Dooruk Feb 20, 2026
01905d5
Merge branch 'develop' into feature/exec_geos_direct_part2
Dooruk Feb 20, 2026
8127f55
observation changes for new gdas_marine obs
Dooruk Feb 23, 2026
6ec5a39
take csh out, add more observers for tier2
Dooruk Feb 23, 2026
fa72657
experiment.yaml original order
Dooruk Feb 23, 2026
d5b6221
observation yaml, calculate obserror in timeseries
Dooruk Feb 23, 2026
01b13b7
tier2 in 3dvar_marine_cycle
Dooruk Feb 23, 2026
afa338e
update documentation and add another example
Dooruk Feb 23, 2026
2063efa
erase obsolete tasks
Dooruk Feb 23, 2026
0436b08
marine suite configs homdir location
Dooruk Feb 23, 2026
3f82f8e
include hotstart option for model runs, take out unnecessary questions
Dooruk Feb 23, 2026
25ca9ee
fix platform defaults
Dooruk Feb 23, 2026
5396d0b
Merge branch 'feature/exec_geos_direct_part2' into feature/exec_geos_…
Dooruk Feb 23, 2026
ef63eed
erase obsolete methods, add docstrings
Dooruk Feb 23, 2026
b0e948d
pycodestyle
Dooruk Feb 23, 2026
0fdc3db
erase window_offset
Dooruk Feb 23, 2026
5d59260
last changes
Dooruk Feb 23, 2026
70d2c9b
minor fixes
Dooruk Feb 25, 2026
6057a4b
another minot fix
Dooruk Feb 25, 2026
4949606
save forecast with r2d2 option only
Dooruk Feb 26, 2026
488f5d8
save forecast peripheries
Dooruk Feb 26, 2026
0fb4c86
add store for cf and nwp
Dooruk Mar 2, 2026
c65900e
fix forecast conflicts
Dooruk Mar 9, 2026
e84c08d
Merge branch 'develop' into feature/save_tasks/save_forecast
Dooruk Mar 9, 2026
a17a044
conflict fix
Dooruk Mar 11, 2026
4c3bf14
Merge branch 'develop' into feature/save_tasks/save_forecast
Dooruk Mar 11, 2026
13134b0
fix save forecast to work with develop
Dooruk May 18, 2026
7b842b4
Merge branch 'develop' into feature/save_tasks/save_forecast
Dooruk Jun 10, 2026
105d4f6
suite config and flow changes to save forecast
Dooruk Jun 12, 2026
43b072b
use r2d2_experiment_id for store
Dooruk Jun 24, 2026
ce240ed
Merge branch 'develop' into feature/save_tasks/save_forecast
Dooruk Jun 24, 2026
a8c61af
use tar.gz to store, take one
Dooruk Jun 25, 2026
16a46ef
Merge branch 'develop' into feature/save_tasks/save_forecast
Dooruk Jul 21, 2026
0b767b0
Merge branch 'develop' into feature/save_tasks/save_forecast
Dooruk Aug 3, 2026
f916b00
add Furkan's utility
Dooruk Aug 6, 2026
c71e5a8
initial test for using pigz works, except existing files
Dooruk Aug 6, 2026
d286148
migjt need to thinkl further about calling background
Dooruk Aug 6, 2026
3201806
Merge branch 'develop' into feature/save_tasks/save_forecast
Dooruk Aug 6, 2026
5d0a895
create two separate tasks for compressing and storing, as R2D2 doesn'…
Dooruk Aug 10, 2026
61f4c4d
compress utility update
Dooruk Aug 10, 2026
e2396ae
Merge branch 'develop' into feature/save_tasks/save_forecast
Dooruk Aug 10, 2026
63c5521
handle geos_marine background archives separately
Dooruk Aug 10, 2026
3f174f0
workflow and codestyle fixes
Dooruk Aug 10, 2026
7859ad9
final changes, addressing code test issues
Dooruk Aug 10, 2026
029ce47
change pyproject version
Dooruk Aug 10, 2026
205b986
Merge branch 'develop' into feature/save_tasks/save_forecast
Dooruk Aug 17, 2026
d579d22
use stored background
Dooruk Aug 18, 2026
dc0f8f7
Merge branch 'develop' into feature/save_tasks/save_forecast
Dooruk Aug 18, 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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "swell"
version = "20260603"
version = "20260728"
authors = [{name = "NASA Global Modeling and Assimilation Office"}]
description = "Workflow suites, tasks and configuration for coupled data assimilation"
requires-python = ">=3.11"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ def r2d2(template_dict: Mapping) -> Mapping:
'store': {
'fc': [
{'file_type': 'bkg',
'filename': f'{cycle_dir}/bkg.%Y%m%dT%H%M%SZ.nc4',
'r2d2_model': 'geos'}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def r2d2(template_dict: Mapping) -> Mapping:
'store': {
'fc': [
{'file_type': 'bkg',
'filename': f'{cycle_dir}/bkg.%Y%m%dT%H%M%SZ.nc4',
'r2d2_model': 'geos_cf'}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,20 @@


def r2d2(template_dict: Mapping) -> Mapping:
analysis_time_iso = template_dict['analysis_time_iso']
cycle_dir = template_dict['cycle_dir']
local_background_time = template_dict['local_background_time']
experiment_id = template_dict['experiment_id']
analysis_time_iso = template_dict['analysis_time_iso']
local_background_time = template_dict['local_background_time']

fc_list = [{'file_type': 'MOM.res',
'r2d2_model': 'mom6',
'file_extension': 'tar.gz',
'filename': f'{cycle_dir}/MOM6.res.{local_background_time}.nc'}]

if 'cice6' in template_dict['marine_models']:
fc_list.append({'file_type': 'cice.res',
'r2d2_model': 'cice6',
'file_extension': 'tar.gz',
'filename': f'{cycle_dir}/cice.res.{local_background_time}.nc'})

an_list = [{'file_type': 'ocn.incr',
Expand Down
19 changes: 14 additions & 5 deletions src/swell/suites/3dfgat_marine_cycle/flow.cylc
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,11 @@
SaveRestart-{{model_component}} => MoveDaRestart-{{model_component}} => CleanCycle-{{model_component}}

{% if not skip_r2d2 %}
# Save analysis output
# RunJediFgatExecutable-{{model_component}} => SaveAnalysis-{{model_component}}
# Compress forecast on compute node, then store in R2D2 on login node
LinkCoupledGeosOutput-{{model_component}} => RunCompressForecast-{{model_component}} => SaveForecast-{{model_component}} => MoveDaRestart-{{model_component}}
RunJediFgatExecutable-{{model_component}} => SaveObsDiags-{{model_component}} => CleanCycle-{{model_component}}
{% endif %}

# Save model output
# MoveBackground-{{model_component}} => StoreBackground-{{model_component}}

# Clean up large files
EvaObservations-{{model_component}} & EvaJediLog-{{model_component}} & EvaIncrement-{{model_component}} =>
CleanCycle-{{model_component}}
Expand Down Expand Up @@ -246,6 +243,18 @@
--{{key}} = {{value}}
{%- endfor %}

[[RunCompressForecast-{{model_component}}]]
script = "swell task RunCompressForecast $config -d $datetime -m {{model_component}}"
platform = {{platform}}
execution time limit = {{scheduling["RunCompressForecast"]["execution_time_limit"]}}
[[[directives]]]
{%- for key, value in scheduling["RunCompressForecast"]["directives"][model_component].items() %}
--{{key}} = {{value}}
{%- endfor %}

[[SaveForecast-{{model_component}}]]
script = "swell task SaveForecast $config -d $datetime -m {{model_component}}"

[[SaveRestart-{{model_component}}]]
script = "swell task SaveRestart $config -d $datetime -m {{model_component}}"

Expand Down
30 changes: 29 additions & 1 deletion src/swell/suites/3dvar_marine/suite_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ class SuiteConfig(QuestionContainer, Enum):
qd.horizontal_resolution("72x36"),
qd.vertical_resolution("50"),
qd.total_processors(6),
qd.obs_experiment("s2s_v1"),
qd.observations([
"adt_cryosat2n",
"adt_jason3",
Expand All @@ -54,6 +53,7 @@ class SuiteConfig(QuestionContainer, Enum):
"temp_profile_xbt"
]),
qd.background_time_offset("PT18H"),
qd.background_experiment("pr790_test"),
qd.clean_patterns(['*.nc4', '*.txt']),
]
)
Expand All @@ -68,3 +68,31 @@ class SuiteConfig(QuestionContainer, Enum):
)

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

_3dvar_marine_tier2 = QuestionList(
list_name="3dvar_marine_tier2",
questions=[
_3dvar_marine,
qd.start_cycle_point("2023-01-02T12:00:00Z"),
qd.final_cycle_point("2023-01-03T12:00:00Z"),
],
geos_marine=[
qd.cycle_times(['T12']),
qd.marine_models(['mom6', 'cice6']),
qd.analysis_variables([
"sea_water_salinity",
"sea_water_potential_temperature",
"sea_surface_height_above_geoid",
"sea_water_cell_thickness",
"sea_ice_area_fraction",
"sea_ice_thickness",
"sea_ice_snow_thickness"
]),
qd.window_length("P1D"),
qd.horizontal_resolution("1440x1080"),
qd.vertical_resolution("75"),
qd.total_processors(720),
]
)

# --------------------------------------------------------------------------------------------------
19 changes: 14 additions & 5 deletions src/swell/suites/3dvar_marine_cycle/flow.cylc
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,11 @@
SaveRestart-{{model_component}} => MoveDaRestart-{{model_component}} => CleanCycle-{{model_component}}

{% if not skip_r2d2 %}
# Save analysis output
# RunJediVariationalExecutable-{{model_component}} => SaveAnalysis-{{model_component}}
# Compress forecast on compute node, then store in R2D2 on login node
LinkCoupledGeosOutput-{{model_component}} => RunCompressForecast-{{model_component}} => SaveForecast-{{model_component}} => MoveDaRestart-{{model_component}}
RunJediVariationalExecutable-{{model_component}} => SaveObsDiags-{{model_component}} => CleanCycle-{{model_component}}
{% endif %}

# Save model output
# MoveBackground-{{model_component}} => StoreBackground-{{model_component}}

# Clean up large files
EvaObservations-{{model_component}} & EvaJediLog-{{model_component}} & EvaIncrement-{{model_component}} =>
CleanCycle-{{model_component}}
Expand Down Expand Up @@ -217,6 +214,15 @@

{% endif %}

[[RunCompressForecast-{{model_component}}]]
script = "swell task RunCompressForecast $config -d $datetime -m {{model_component}}"
platform = {{platform}}
execution time limit = {{scheduling["RunCompressForecast"]["execution_time_limit"]}}
[[[directives]]]
{%- for key, value in scheduling["RunCompressForecast"]["directives"][model_component].items() %}
--{{key}} = {{value}}
{%- endfor %}

[[RenderJediObservations-{{model_component}}]]
script = "swell task RenderJediObservations $config -d $datetime -m {{model_component}}"

Expand Down Expand Up @@ -245,6 +251,9 @@
--{{key}} = {{value}}
{%- endfor %}

[[SaveForecast-{{model_component}}]]
script = "swell task SaveForecast $config -d $datetime -m {{model_component}}"

[[SaveRestart-{{model_component}}]]
script = "swell task SaveRestart $config -d $datetime -m {{model_component}}"

Expand Down
111 changes: 111 additions & 0 deletions src/swell/tasks/geos_marine/get_background_geos_marine.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# (C) Copyright 2021- United States Government as represented by the Administrator of the
# National Aeronautics and Space Administration. All Rights Reserved.
#
# This software is licensed under the terms of the Apache Licence Version 2.0
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.


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

import os
import tarfile

import r2d2

from swell.tasks.base.task_base import taskBase
from swell.utilities.r2d2 import load_r2d2_credentials

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


def _marine_archive_path(cycle_dir: str, model_name: str, local_background_time: str) -> str:
"""Return the canonical path for a marine background tar.gz archive.

Args:
cycle_dir: Directory where the cycle artifacts are written.
model_name: Name of the marine model, such as "mom6" or "cice6".
local_background_time: Background time string used in the archive name.

Returns:
The full path to the expected archive file.
"""
return os.path.join(cycle_dir, f"{model_name}.{local_background_time}.tar.gz")


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


class GetBackground(taskBase):
"""Fetch marine forecast archives from R2D2 and unpack them into the cycle directory.

This task retrieves the pre-compressed marine background archives produced
by the marine forecast save task and extracts them into the current cycle
directory for downstream use.
"""

def execute(self) -> None:
"""Retrieve the archived marine forecast outputs for the current cycle.

The method loads the R2D2 credentials, resolves the active background
time, fetches the archive for each configured marine model, and unpacks
it into the cycle directory.
"""

load_r2d2_credentials(
self.logger,
self.platform(),
r2d2_server=self.config.r2d2_server(default=None),
)

r2d2_datastore = self.config.r2d2_datastore(default=None)
marine_models = self.config.marine_models(None) or []
window_type = self.config.window_type()
window_length = self.config.window_length()
horizontal_resolution = self.config.horizontal_resolution()
background_experiment = self.config.background_experiment()

local_background_time, local_background_time_dto = \
self.da_window_params.local_background_time(window_length, window_type, dto=True)

os.makedirs(self.cycle_dir(), 0o755, exist_ok=True)

marine_model_configs = [('mom6', 'MOM.res')]
if 'cice6' in marine_models:
marine_model_configs.append(('cice6', 'cice.res'))

for model_name, file_type in marine_model_configs:
archive_path = _marine_archive_path(
self.cycle_dir(), model_name, local_background_time)

self.logger.info(
f'Fetching marine background archive {os.path.basename(archive_path)} '
f'({file_type}) for {model_name}'
)

fetch_kwargs = dict(
item='forecast',
target_file=archive_path,
model=model_name,
experiment=background_experiment,
file_extension='tar.gz',
resolution=horizontal_resolution,
step='PT00',
date=local_background_time_dto.strftime('%Y-%m-%d %H:%M:%S'),
file_type=file_type,
)
if r2d2_datastore:
fetch_kwargs['data_store'] = r2d2_datastore

r2d2.fetch(**fetch_kwargs)

if not os.path.exists(archive_path):
self.logger.abort(f'Marine archive not fetched: {archive_path}')

self.logger.info(f'Unpacking {os.path.basename(archive_path)} into {self.cycle_dir()}')
with tarfile.open(archive_path, 'r:gz') as tar:
tar.extractall(path=self.cycle_dir())

os.remove(archive_path)
self.logger.info(f'Unpacked {os.path.basename(archive_path)} into {self.cycle_dir()}')

# --------------------------------------------------------------------------------------------------
Loading
Loading