diff --git a/.yamllint.yml b/.yamllint.yml index 83f5340c..b5c2671d 100644 --- a/.yamllint.yml +++ b/.yamllint.yml @@ -2,6 +2,9 @@ extends: default +ignore: | + src/swell/configuration/jedi/oops/LocalEnsembleDA.yaml + rules: braces: level: warning @@ -27,3 +30,4 @@ rules: level: warning allow-non-breakable-inline-mappings: true truthy: disable + diff --git a/src/swell/configuration/jedi/interfaces/geos_atmosphere/geos_atmosphere.yaml b/src/swell/configuration/jedi/interfaces/geos_atmosphere/geos_atmosphere.yaml index 402d2544..09fb12b1 100644 --- a/src/swell/configuration/jedi/interfaces/geos_atmosphere/geos_atmosphere.yaml +++ b/src/swell/configuration/jedi/interfaces/geos_atmosphere/geos_atmosphere.yaml @@ -6,3 +6,4 @@ executables: variational3D: fv3jedi_var.x variational4D: fv3jedi_var.x variational4DEnsVar: fv3jedi_var.x + localensembleda: fv3jedi_letkf.x diff --git a/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/background_ensemble.yaml b/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/background_ensemble.yaml new file mode 100755 index 00000000..1657761c --- /dev/null +++ b/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/background_ensemble.yaml @@ -0,0 +1,13 @@ +date: '{{window_begin_iso}}' +members from template: + template: + datetime: '{{local_background_time_iso}}' + filetype: cube sphere history + provider: geos + datapath: '.' + filename: 'geos.mem%mem%.%yyyy%mm%dd_%hh%MM%ssz.nc4' + state variables: [ua,va,t,ps,delp,q,qi,ql,qr,qs,o3ppmv,phis,frocean,frlake,frseaice, + sheleg,ts,soilt,soilm,u10m,v10m] + pattern: '%mem%' + nmembers: {{ensemble_num_members}} + zero padding: 3 diff --git a/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_driver.yaml b/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_driver.yaml new file mode 100644 index 00000000..4c95c81d --- /dev/null +++ b/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_driver.yaml @@ -0,0 +1,4 @@ +save posterior mean: {{local_ensemble_save_posterior_mean}} +save posterior ensemble: {{local_ensemble_save_posterior_ensemble}} +save posterior mean increment: {{local_ensemble_save_posterior_mean_increment}} +save posterior ensemble increments: {{local_ensemble_save_posterior_ensemble_increments}} diff --git a/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_mean_increment_output.yaml b/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_mean_increment_output.yaml new file mode 100644 index 00000000..28cd808d --- /dev/null +++ b/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_mean_increment_output.yaml @@ -0,0 +1,4 @@ +filetype: auxgrid +gridtype: latlon +filename: '{{cycle_dir}}/geos.mean-inc.' + diff --git a/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_mean_output.yaml b/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_mean_output.yaml new file mode 100644 index 00000000..980ae194 --- /dev/null +++ b/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_mean_output.yaml @@ -0,0 +1,3 @@ +filetype: auxgrid +gridtype: latlon +filename: '{{cycle_dir}}/geos.analysis.mean.' diff --git a/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_members_increment_output.yaml b/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_members_increment_output.yaml new file mode 100644 index 00000000..6c8d6cb8 --- /dev/null +++ b/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_members_increment_output.yaml @@ -0,0 +1,4 @@ +filetype: auxgrid +gridtype: latlon +filename: '{{cycle_dir}}/geos.mem%{member}%-inc' + diff --git a/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_members_output.yaml b/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_members_output.yaml new file mode 100644 index 00000000..e2adac3f --- /dev/null +++ b/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_members_output.yaml @@ -0,0 +1,3 @@ +filetype: auxgrid +gridtype: latlon +filename: '{{cycle_dir}}/geos.analysis.mem%{member}%.' diff --git a/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_solver.yaml b/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_solver.yaml new file mode 100644 index 00000000..26ce2664 --- /dev/null +++ b/src/swell/configuration/jedi/interfaces/geos_atmosphere/model/ensemble_solver.yaml @@ -0,0 +1,5 @@ +solver: {{local_ensemble_solver}} +inflation: + rtps: {{local_ensemble_inflation_rtps}} + rtpp: {{local_ensemble_inflation_rtpp}} + mult: {{local_ensemble_inflation_mult}} diff --git a/src/swell/configuration/jedi/interfaces/geos_atmosphere/task_questions.yaml b/src/swell/configuration/jedi/interfaces/geos_atmosphere/task_questions.yaml index 5944b0a0..ca42751a 100644 --- a/src/swell/configuration/jedi/interfaces/geos_atmosphere/task_questions.yaml +++ b/src/swell/configuration/jedi/interfaces/geos_atmosphere/task_questions.yaml @@ -53,6 +53,19 @@ geovals_provider: gradient_norm_reduction: default_value: 10e-5 +horizontal_localization_lengthscale: + default_value: 10000e3 + +horizontal_localization_max_nobs: + default_value: 1000 + +horizontal_localization_method: + default_value: Horizontal Gaspari-Cohn + options: + - Horizontal Gaspari-Cohn + - Horizontal SOAR + - Horizontal Box car + horizontal_resolution: default_value: '361' options: @@ -66,6 +79,21 @@ jedi_forecast_model: options: - pseudo-model +local_ensemble_inflation_mult: + default_value: 1.1 + +local_ensemble_inflation_rtpp: + default_value: 0.6 + +local_ensemble_inflation_rtps: + default_value: 0.5 + +local_ensemble_solver: + default_value: LETKF + options: + - LETKF + - GETKF + minimizer: default_value: DRIPCG options: @@ -157,7 +185,7 @@ observations: - ompsnm_npp path_to_ensemble: - default_value: /discover/nobackup/drholdaw/SwellTestData/letk/ensemble/Y%Y/M%m/D%d/H%H + default_value: /discover/nobackup/drholdaw/SwellTestData/letk/ensemble/Y%Y/M%m/D%d/H%H/geos*%Y%m%d_%H%M%Sz.nc4 path_to_geos_adas_background: default_value: /discover/nobackup/drholdaw/SwellTestData/geosadas/bkg/*bkg_clcv_rst* @@ -174,6 +202,29 @@ produce_geovals: - true - false +vertical_localization_function: + default_value: Gaspari Cohn + options: + - Gaspari Cohn + +vertical_localization_ioda_vertical_coord: + default_value: pressure + options: + - pressure + +vertical_localization_ioda_vertical_coord_group: + default_value: MetaData + options: + - MetaData + +vertical_localization_lengthscale: + default_value: 4 + +vertical_localization_method: + default_value: Vertical localization + options: + - Vertical localization + vertical_resolution: default_value: '72' options: diff --git a/src/swell/configuration/jedi/oops/LocalEnsembleDA.yaml b/src/swell/configuration/jedi/oops/LocalEnsembleDA.yaml new file mode 100644 index 00000000..7dc63ed3 --- /dev/null +++ b/src/swell/configuration/jedi/oops/LocalEnsembleDA.yaml @@ -0,0 +1,36 @@ +geometry: + TASKFILLgeometry + +window begin: '{{window_begin_iso}}' +window length: '{{window_length}}' + +background: + TASKFILLbackground_ensemble + +observations: + observers: + SPECIALobservations + +local ensemble DA: + TASKFILLensemble_solver + +driver: + TASKFILLensemble_driver + +{% if local_ensemble_save_posterior_mean or local_ensemble_save_posterior_ensemble %} +output: + {% if local_ensemble_save_posterior_mean and not local_ensemble_save_posterior_ensemble %} + TASKFILLensemble_mean_output + {% endif %} + {% if not local_ensemble_save_posterior_mean and local_ensemble_save_posterior_ensemble %} + TASKFILLensemble_members_output + {% endif %} +{% endif %} +{% if local_ensemble_save_posterior_mean_increment %} +output increment: + TASKFILLensemble_mean_increment_output +{% endif %} +{% if local_ensemble_save_posterior_ensemble_increments %} +output ensemble increments: + TASKFILLensemble_members_increment_output +{% endif %} diff --git a/src/swell/deployment/create_experiment.py b/src/swell/deployment/create_experiment.py index a384813b..b63a8007 100644 --- a/src/swell/deployment/create_experiment.py +++ b/src/swell/deployment/create_experiment.py @@ -450,8 +450,9 @@ def prepare_cylc_suite_jinja2(logger, swell_suite_path, exp_suite_path, experime 'EvaObservations', 'GenerateBClimatology', 'RunJediHofxExecutable', - 'RunJediVariationalExecutable', + 'RunJediLocalEnsembleDaExecutable', 'RunJediUfoTestsExecutable', + 'RunJediVariationalExecutable', 'RunGeosExecutable', ] diff --git a/src/swell/suites/letkf/flow.cylc b/src/swell/suites/localensembleda/flow.cylc similarity index 73% rename from src/swell/suites/letkf/flow.cylc rename to src/swell/suites/localensembleda/flow.cylc index 2b787151..a29466ca 100644 --- a/src/swell/suites/letkf/flow.cylc +++ b/src/swell/suites/localensembleda/flow.cylc @@ -6,7 +6,7 @@ # -------------------------------------------------------------------------------------------------- -# Cylc suite for executing JEDI-based h(x) +# Cylc suite for executing JEDI-based LocalEnsembleDA Algorithm # -------------------------------------------------------------------------------------------------- @@ -57,17 +57,17 @@ StageJediCycle-{{model_component}} # Run Jedi hofx executable - BuildJediByLinking[^]? | BuildJedi[^] => RunJediLetkfExecutable-{{model_component}} - StageJedi-{{model_component}}[^] => RunJediLetkfExecutable-{{model_component}} - StageJediCycle-{{model_component}} => RunJediLetkfExecutable-{{model_component}} - GetEnsemble-{{model_component}} => RunJediLetkfExecutable-{{model_component}} - GetObservations-{{model_component}} => RunJediLetkfExecutable-{{model_component}} + BuildJediByLinking[^]? | BuildJedi[^] => RunJediLocalEnsembleDaExecutable-{{model_component}} + StageJedi-{{model_component}}[^] => RunJediLocalEnsembleDaExecutable-{{model_component}} + StageJediCycle-{{model_component}} => RunJediLocalEnsembleDaExecutable-{{model_component}} + GetEnsemble-{{model_component}} => RunJediLocalEnsembleDaExecutable-{{model_component}} + GetObservations-{{model_component}} => RunJediLocalEnsembleDaExecutable-{{model_component}} # EvaObservations - RunJediLetkfExecutable-{{model_component}} => EvaObservations-{{model_component}} + RunJediLocalEnsembleDaExecutable-{{model_component}} => EvaObservations-{{model_component}} # Save observations - RunJediLetkfExecutable-{{model_component}} => SaveObsDiags-{{model_component}} + RunJediLocalEnsembleDaExecutable-{{model_component}} => SaveObsDiags-{{model_component}} # Clean up large files EvaObservations-{{model_component}} & SaveObsDiags-{{model_component}} => @@ -127,19 +127,19 @@ [[GetObservations-{{model_component}}]] script = "swell task GetObservations $config -d $datetime -m {{model_component}}" - [[RunJediLetkfExecutable-{{model_component}}]] - script = "swell task RunJediLetkfExecutable $config -d $datetime -m {{model_component}}" + [[RunJediLocalEnsembleDaExecutable-{{model_component}}]] + script = "swell task RunJediLocalEnsembleDaExecutable $config -d $datetime -m {{model_component}}" platform = {{platform}} - execution time limit = {{scheduling["RunJediLetkfExecutable"]["execution_time_limit"]}} + execution time limit = {{scheduling["RunJediLocalEnsembleDaExecutable"]["execution_time_limit"]}} [[[directives]]] - --account = {{scheduling["RunJediLetkfExecutable"]["account"]}} - --qos = {{scheduling["RunJediLetkfExecutable"]["qos"]}} - --job-name = RunJediLetkfExecutable - --nodes={{scheduling["RunJediLetkfExecutable"]["nodes"]}} - --ntasks-per-node={{scheduling["RunJediLetkfExecutable"]["ntasks_per_node"]}} - --constraint={{scheduling["RunJediLetkfExecutable"]["constraint"]}} - {% if scheduling["RunJediLetkfExecutable"]["partition"] %} - --partition={{scheduling["RunJediLetkfExecutable"]["partition"]}} + --account = {{scheduling["RunJediLocalEnsembleDaExecutable"]["account"]}} + --qos = {{scheduling["RunJediLocalEnsembleDaExecutable"]["qos"]}} + --job-name = RunJediLocalEnsembleDaExecutable + --nodes={{scheduling["RunJediLocalEnsembleDaExecutable"]["nodes"]}} + --ntasks-per-node={{scheduling["RunJediLocalEnsembleDaExecutable"]["ntasks_per_node"]}} + --constraint={{scheduling["RunJediLocalEnsembleDaExecutable"]["constraint"]}} + {% if scheduling["RunJediLocalEnsembleDaExecutable"]["partition"] %} + --partition={{scheduling["RunJediLocalEnsembleDaExecutable"]["partition"]}} {% endif %} [[EvaObservations-{{model_component}}]] diff --git a/src/swell/suites/letkf/suite_questions.yaml b/src/swell/suites/localensembleda/suite_questions.yaml similarity index 81% rename from src/swell/suites/letkf/suite_questions.yaml rename to src/swell/suites/localensembleda/suite_questions.yaml index f7598997..3b6376bd 100644 --- a/src/swell/suites/letkf/suite_questions.yaml +++ b/src/swell/suites/localensembleda/suite_questions.yaml @@ -24,3 +24,9 @@ cycle_times: - all prompt: Enter the cycle times for this model. type: string-check-list + +r2d2_local_path: + ask_question: False + default_value: defer_to_platform + prompt: Enter the path where R2D2 will store experiment output + type: string diff --git a/src/swell/tasks/get_ensemble.py b/src/swell/tasks/get_ensemble.py index db99c0e2..627724f9 100644 --- a/src/swell/tasks/get_ensemble.py +++ b/src/swell/tasks/get_ensemble.py @@ -8,10 +8,8 @@ # -------------------------------------------------------------------------------------------------- -import datetime import glob import os -import re from swell.tasks.base.task_base import taskBase @@ -22,14 +20,24 @@ class GetEnsemble(taskBase): def execute(self): - - # Get the path and pattern for the background files + """Acquires ensemble member files for a given experiment and cycle + + Parameters + ---------- + All inputs are extracted from the JEDI experiment file configuration. + See the taskBase constructor for more information. + """ + # Get the path and pattern for the ensemble members # ------------------------------------------------- ensemble_path = self.config.path_to_ensemble() + # Replate ensemble_path with true path + # --------------------------------------------- + ensemble_location = self.cycle_time_dto().strftime(ensemble_path) + # Fetch list of ensemble members # -------------------------------- - ensemble_members = glob.glob(ensemble_path) + ensemble_members = glob.glob(ensemble_location) # Assert at least one ensemble member was found # ----------------------------------------------- @@ -44,17 +52,11 @@ def execute(self): # Get filename from full path member_file = os.path.basename(ensemble_member) - # Extract the datetime part from the string - datetime_part = re.search(r"\d{8}_\d{4}\w", member_file).group() - - # Get datetime for the file from the filename - member_file_datetime = datetime.datetime.strptime(datetime_part, '%Y%m%d_%H%Mz') - - # Create target filename using the datetime format - member_file_target = member_file_datetime.strftime('geos.mem001.%Y%m%d_%H%M%Sz.nc4') + # Extract the member name, excluding path + member_part = member_file.split('/')[-1] # Target path and filename - ensemble_path_file_target = os.path.join(self.cycle_dir(), member_file_target) + ensemble_path_file_target = os.path.join(self.cycle_dir(), member_part) # Remove target file if it exists (might be a link) if os.path.exists(ensemble_path_file_target): diff --git a/src/swell/tasks/run_jedi_letkf_executable.py b/src/swell/tasks/run_jedi_local_ensemble_da_executable.py similarity index 52% rename from src/swell/tasks/run_jedi_letkf_executable.py rename to src/swell/tasks/run_jedi_local_ensemble_da_executable.py index 043bab96..673bd0a4 100644 --- a/src/swell/tasks/run_jedi_letkf_executable.py +++ b/src/swell/tasks/run_jedi_local_ensemble_da_executable.py @@ -18,7 +18,7 @@ # -------------------------------------------------------------------------------------------------- -class RunJediLetkfExecutable(taskBase): +class RunJediLocalEnsembleDaExecutable(taskBase): # ---------------------------------------------------------------------------------------------- @@ -26,7 +26,7 @@ def execute(self): # Jedi application name # --------------------- - jedi_application = 'letkf' + jedi_application = 'localensembleda' # Parse configuration # ------------------- @@ -69,6 +69,51 @@ def execute(self): self.jedi_rendering.add_key('crtm_coeff_dir', self.config.crtm_coeff_dir(None)) self.jedi_rendering.add_key('window_begin', window_begin) + # Ensemble Localizations + self.jedi_rendering.add_key('horizontal_localization_method', + self.config.horizontal_localization_method()) + self.jedi_rendering.add_key('horizontal_localization_lengthscale', + self.config.horizontal_localization_lengthscale()) + self.jedi_rendering.add_key('horizontal_localization_max_nobs', + self.config.horizontal_localization_max_nobs()) + self.jedi_rendering.add_key('vertical_localization_method', + self.config.vertical_localization_method()) + self.jedi_rendering.add_key('vertical_localization_apply_log_transform', + self.config.vertical_localization_apply_log_transform()) + self.jedi_rendering.add_key('vertical_localization_lengthscale', + self.config.vertical_localization_lengthscale()) + self.jedi_rendering.add_key('vertical_localization_ioda_vertical_coord', + self.config.vertical_localization_ioda_vertical_coord()) + self.jedi_rendering.add_key('vertical_localization_ioda_vertical_coord_group', + self.config.vertical_localization_ioda_vertical_coord_group()) + self.jedi_rendering.add_key('vertical_localization_function', + self.config.vertical_localization_function()) + + # Driver + self.jedi_rendering.add_key('local_ensemble_solver', self.config.local_ensemble_solver()) + self.jedi_rendering.add_key('local_ensemble_inflation_rtps', + self.config.local_ensemble_inflation_rtps()) + self.jedi_rendering.add_key('local_ensemble_inflation_rtpp', + self.config.local_ensemble_inflation_rtpp()) + self.jedi_rendering.add_key('local_ensemble_inflation_mult', + self.config.local_ensemble_inflation_mult()) + self.jedi_rendering.add_key('local_ensemble_save_posterior_mean', + self.config.local_ensemble_save_posterior_mean()) + self.jedi_rendering.add_key('local_ensemble_save_posterior_ensemble', + self.config.local_ensemble_save_posterior_ensemble()) + self.jedi_rendering.add_key('local_ensemble_save_posterior_mean_increment', + self.config.local_ensemble_save_posterior_mean_increment()) + self.jedi_rendering.add_key('local_ensemble_save_posterior_ensemble_increments', + self.config.local_ensemble_save_posterior_ensemble_increments()) + + # Prevent both 'local_ensemble_save_posterior_mean' and + # 'local_ensemble_save_posterior_ensemble' from being true + # -------------------------------------------------------- + if not self.config.local_ensemble_save_posterior_mean() ^ \ + self.config.local_ensemble_save_posterior_ensemble(): + raise ValueError("Only one of 'local_ensemble_save_posterior_mean' and\ + 'local_ensemble_save_posterior_ensemble' may be true at once!") + # Jedi configuration file # ----------------------- jedi_config_file = os.path.join(self.cycle_dir(), f'jedi_{jedi_application}_config.yaml') @@ -79,13 +124,37 @@ def execute(self): # Open the JEDI config file and fill initial templates # ---------------------------------------------------- - jedi_config_dict = self.jedi_rendering.render_oops_file(f'{jedi_application}{window_type}') + jedi_config_dict = self.jedi_rendering.render_oops_file('LocalEnsembleDA') # Perform complete template rendering # ----------------------------------- jedi_dictionary_iterator(jedi_config_dict, self.jedi_rendering, window_type, observations, jedi_forecast_model) + # Assemble localizations + # ---------------------- + horizLoc = {'localization method': self.config.horizontal_localization_method(), + 'lengthscale': self.config.horizontal_localization_lengthscale(), + 'max nobs': self.config.horizontal_localization_max_nobs()} + localizations = [horizLoc] + # # Vertical localizations have bug(s) - Commented out for now... + # vertLoc = {'localization method': self.config.vertical_localization_method(), + # 'apply log transformation': + # self.config.vertical_localization_apply_log_transform(), + # 'vertical lengthscale': self.config.vertical_localization_lengthscale(), + # 'ioda vertical coordinate': + # self.config.vertical_localization_ioda_vertical_coord(), + # 'ioda vertical coordinate group': + # self.config.vertical_localization_ioda_vertical_coord_group(), + # 'localization function': self.config.vertical_localization_function()} + # localizations = [horizLoc, vertLoc] if len(vertLoc) != 0 else [horizLoc] + + # Include ensemble localizations and halo types with each observation + # ------------------------------------------------------------------- + for observer in jedi_config_dict['observations']['observers']: + observer.update({'obs localizations': localizations}) + observer['obs space'].update({'distribution': {'name': 'Halo', 'halo size': 5000e3}}) + # Write the expanded dictionary to YAML file # ------------------------------------------ with open(jedi_config_file, 'w') as jedi_config_file_open: @@ -101,7 +170,7 @@ def execute(self): # Jedi executable name # -------------------- - jedi_executable = model_component_meta['executables'][f'{jedi_application}{window_type}'] + jedi_executable = model_component_meta['executables'][f'{jedi_application}'] jedi_executable_path = os.path.join(self.experiment_path(), 'jedi_bundle', 'build', 'bin', jedi_executable) diff --git a/src/swell/tasks/task_questions.yaml b/src/swell/tasks/task_questions.yaml index 26a81ff0..854fdd9c 100644 --- a/src/swell/tasks/task_questions.yaml +++ b/src/swell/tasks/task_questions.yaml @@ -76,7 +76,7 @@ background_time_offset: - GetObservations - GsiBcToIoda - RunJediHofxExecutable - - RunJediLetkfExecutable + - RunJediLocalEnsembleDaExecutable - RunJediUfoTestsExecutable - RunJediVariationalExecutable - SaveObsDiags @@ -128,7 +128,7 @@ crtm_coeff_dir: - GetObservations - GsiBcToIoda - RunJediHofxExecutable - - RunJediLetkfExecutable + - RunJediLocalEnsembleDaExecutable - RunJediUfoTestsExecutable - RunJediVariationalExecutable - SaveObsDiags @@ -141,7 +141,7 @@ ensemble_num_members: - geos_atmosphere prompt: How many members comprise the ensemble? tasks: - - RunJediLetkfExecutable + - RunJediLocalEnsembleDaExecutable type: integer existing_geos_gcm_build_path: @@ -206,7 +206,7 @@ generate_yaml_and_exit: prompt: Generate JEDI executable YAML and exit? tasks: - RunJediHofxExecutable - - RunJediLetkfExecutable + - RunJediLocalEnsembleDaExecutable - RunJediUfoTestsExecutable - RunJediVariationalExecutable type: boolean @@ -313,6 +313,38 @@ gradient_norm_reduction: - RunJediVariationalExecutable type: float +horizontal_localization_lengthscale: + ask_question: false + default_value: defer_to_model + models: + - geos_atmosphere + prompt: What is the length scale for horizontal covariance localization? + tasks: + - RunJediLocalEnsembleDaExecutable + type: float + +horizontal_localization_max_nobs: + ask_question: false + default_value: defer_to_model + models: + - geos_atmosphere + prompt: What is the maximum number of observations to consider for horizontal covariance + localization? + tasks: + - RunJediLocalEnsembleDaExecutable + type: integer + +horizontal_localization_method: + ask_question: false + default_value: defer_to_model + models: + - geos_atmosphere + options: defer_to_model + prompt: Which localization scheme should be applied in the horizontal? + tasks: + - RunJediLocalEnsembleDaExecutable + type: string-drop-list + horizontal_resolution: ask_question: true default_value: defer_to_model @@ -325,7 +357,7 @@ horizontal_resolution: - GenerateBClimatologyByLinking - GetBackground - RunJediHofxExecutable - - RunJediLetkfExecutable + - RunJediLocalEnsembleDaExecutable - RunJediVariationalExecutable - StageJedi - StoreBackground @@ -366,10 +398,103 @@ jedi_forecast_model: prompt: What forecast model should be used within JEDI for 4D window propagation? tasks: - RunJediHofxExecutable - - RunJediLetkfExecutable + - RunJediLocalEnsembleDaExecutable - RunJediVariationalExecutable type: string-drop-list +local_ensemble_inflation_mult: + ask_question: false + default_value: defer_to_model + models: + - geos_atmosphere + prompt: Specify the multiplicative prior inflation coefficient (0, inf]. + tasks: + - RunJediLocalEnsembleDaExecutable + type: float + +local_ensemble_inflation_rtpp: + ask_question: false + default_value: defer_to_model + models: + - geos_atmosphere + prompt: Specify the Relaxation To Prior Perturbation (RTPP) coefficient (0, 1]. + tasks: + - RunJediLocalEnsembleDaExecutable + type: float + +local_ensemble_inflation_rtps: + ask_question: false + default_value: defer_to_model + models: + - geos_atmosphere + prompt: Specify the Relaxation To Prior Spread (RTPS) coefficient (0, 1]. + tasks: + - RunJediLocalEnsembleDaExecutable + type: float + +local_ensemble_save_posterior_ensemble: + ask_question: false + default_value: true + models: + - geos_atmosphere + options: + - true + - false + prompt: Save the posterior ensemble members? + tasks: + - RunJediLocalEnsembleDaExecutable + type: boolean + +local_ensemble_save_posterior_ensemble_increments: + ask_question: true + default_value: false + models: + - geos_atmosphere + options: + - true + - false + prompt: Save the posterior ensemble member increments? + tasks: + - RunJediLocalEnsembleDaExecutable + type: boolean + +local_ensemble_save_posterior_mean: + ask_question: true + default_value: false + models: + - geos_atmosphere + options: + - true + - false + prompt: Save the posterior ensemble mean? + tasks: + - RunJediLocalEnsembleDaExecutable + type: boolean + +local_ensemble_save_posterior_mean_increment: + ask_question: true + default_value: true + models: + - geos_atmosphere + options: + - true + - false + prompt: Save the posterior ensemble mean increment? + tasks: + - RunJediLocalEnsembleDaExecutable + type: boolean + +local_ensemble_solver: + ask_question: true + default_value: defer_to_model + models: + - geos_atmosphere + options: defer_to_model + prompt: Which local ensemble solver type should be implemented? + tasks: + - RunJediLocalEnsembleDaExecutable + type: string-drop-list + minimizer: ask_question: false default_value: defer_to_model @@ -405,7 +530,7 @@ npx_proc: - GenerateBClimatology - GenerateBClimatologyByLinking - RunJediHofxExecutable - - RunJediLetkfExecutable + - RunJediLocalEnsembleDaExecutable - RunJediVariationalExecutable type: integer @@ -419,7 +544,7 @@ npy_proc: - GenerateBClimatology - GenerateBClimatologyByLinking - RunJediHofxExecutable - - RunJediLetkfExecutable + - RunJediLocalEnsembleDaExecutable - RunJediVariationalExecutable type: integer @@ -468,7 +593,7 @@ observations: - GsiBcToIoda - GsiNcdiagToIoda - RunJediHofxExecutable - - RunJediLetkfExecutable + - RunJediLocalEnsembleDaExecutable - RunJediUfoTestsExecutable - RunJediVariationalExecutable - SaveObsDiags @@ -560,10 +685,79 @@ total_processors: - GenerateBClimatologyByLinking - PrepareAnalysis - RunJediHofxExecutable - - RunJediLetkfExecutable + - RunJediLocalEnsembleDaExecutable - RunJediVariationalExecutable type: integer +vertical_localization_apply_log_transform: + ask_question: false + default_value: true + models: + - geos_atmosphere + options: + - true + - false + prompt: Should a log (base 10) transformation be applied to vertical coordinate + when constructing vertical localization? + tasks: + - RunJediLocalEnsembleDaExecutable + type: boolean + +vertical_localization_function: + ask_question: false + default_value: defer_to_model + models: + - geos_atmosphere + options: defer_to_model + prompt: Which localization scheme should be applied in the vertical? + tasks: + - RunJediLocalEnsembleDaExecutable + type: string-drop-list + +vertical_localization_ioda_vertical_coord: + ask_question: false + default_value: defer_to_model + models: + - geos_atmosphere + options: defer_to_model + prompt: Which coordinate should be used in constructing vertical localization? + tasks: + - RunJediLocalEnsembleDaExecutable + type: string + +vertical_localization_ioda_vertical_coord_group: + ask_question: false + default_value: defer_to_model + models: + - geos_atmosphere + options: defer_to_model + prompt: Which vertical coordinate group should be used in constructing vertical + localization? + tasks: + - RunJediLocalEnsembleDaExecutable + type: string + +vertical_localization_lengthscale: + ask_question: false + default_value: defer_to_model + models: + - geos_atmosphere + prompt: What is the length scale for vertical covariance localization? + tasks: + - RunJediLocalEnsembleDaExecutable + type: integer + +vertical_localization_method: + ask_question: false + default_value: defer_to_model + models: + - geos_atmosphere + options: defer_to_model + prompt: What localization scheme should be applied in constructing a vertical localization? + tasks: + - RunJediLocalEnsembleDaExecutable + type: string + vertical_resolution: ask_question: true default_value: defer_to_model @@ -575,7 +769,7 @@ vertical_resolution: - GenerateBClimatology - GenerateBClimatologyByLinking - RunJediHofxExecutable - - RunJediLetkfExecutable + - RunJediLocalEnsembleDaExecutable - RunJediVariationalExecutable - StageJedi type: string-drop-list @@ -593,7 +787,7 @@ window_length: - GetObservations - MoveDaRestart - RunJediHofxExecutable - - RunJediLetkfExecutable + - RunJediLocalEnsembleDaExecutable - RunJediUfoTestsExecutable - RunJediVariationalExecutable - StoreBackground @@ -614,7 +808,7 @@ window_offset: - GsiBcToIoda - GsiNcdiagToIoda - RunJediHofxExecutable - - RunJediLetkfExecutable + - RunJediLocalEnsembleDaExecutable - RunJediUfoTestsExecutable - RunJediVariationalExecutable - SaveObsDiags @@ -634,7 +828,7 @@ window_type: - GenerateBClimatology - GetBackground - RunJediHofxExecutable - - RunJediLetkfExecutable + - RunJediLocalEnsembleDaExecutable - RunJediVariationalExecutable - StoreBackground type: string-drop-list diff --git a/src/swell/test/suite_tests/localensembleda-tier1.yaml b/src/swell/test/suite_tests/localensembleda-tier1.yaml new file mode 100644 index 00000000..32fb9a16 --- /dev/null +++ b/src/swell/test/suite_tests/localensembleda-tier1.yaml @@ -0,0 +1,12 @@ +final_cycle_point: '2021-12-12T00:00:00Z' +jedi_build_method: use_existing +existing_jedi_source_directory: /discover/nobackup/gmao_ci/swell/tier2/stable/build_jedi/jedi_bundle/source/ +existing_jedi_build_directory: /discover/nobackup/gmao_ci/swell/tier2/stable/build_jedi/jedi_bundle/build/ +model_components: ['geos_atmosphere'] +models: + geos_atmosphere: + observations: + - sondes + obs_experiment: x0048v1 + window_type: 3D + horizontal_resolution: 13 diff --git a/src/swell/utilities/render_jedi_interface_files.py b/src/swell/utilities/render_jedi_interface_files.py index 5de19a1e..739fefe2 100644 --- a/src/swell/utilities/render_jedi_interface_files.py +++ b/src/swell/utilities/render_jedi_interface_files.py @@ -47,10 +47,22 @@ def __init__(self, logger, experiment_root, experiment_id, cycle_dir, jedi_inter 'background_frequency', 'background_time', 'crtm_coeff_dir', + 'ensemble_num_members', 'gradient_norm_reduction', + 'horizontal_localization_lengthscale', + 'horizontal_localization_max_nobs', + 'horizontal_localization_method', 'horizontal_resolution', 'local_background_time', 'local_background_time_iso', + 'local_ensemble_inflation_mult', + 'local_ensemble_inflation_rtpp', + 'local_ensemble_inflation_rtps', + 'local_ensemble_save_posterior_ensemble', + 'local_ensemble_save_posterior_ensemble_increments', + 'local_ensemble_save_posterior_mean', + 'local_ensemble_save_posterior_mean_increment', + 'local_ensemble_solver', 'minimizer', 'mom6_iau', 'gsibec_npx_proc', @@ -60,6 +72,12 @@ def __init__(self, logger, experiment_root, experiment_id, cycle_dir, jedi_inter 'number_of_iterations', 'swell_static_files', 'total_processors', + 'vertical_localization_apply_log_transform', + 'vertical_localization_function', + 'vertical_localization_ioda_vertical_coord', + 'vertical_localization_ioda_vertical_coord_group', + 'vertical_localization_lengthscale', + 'vertical_localization_method', 'vertical_resolution', 'window_begin', 'window_begin_iso',