From 1e9d844b0225acc2a0bf913358b1cd8581f9a2a9 Mon Sep 17 00:00:00 2001 From: Guillaume Vernieres Date: Wed, 30 Oct 2024 12:09:46 -0400 Subject: [PATCH] Marine ens. var. (#37) Companion PR to https://github.com/NOAA-EMC/GDASApp/pull/1353 --------- Co-authored-by: Dan Holdaway <27729500+danholdaway@users.noreply.github.com> --- ...d_error_hybrid_diffusion_diffusion.yaml.j2 | 67 +-- .../marine/insitu_profile_argo.yaml.j2 | 542 ------------------ .../gdas-marine-templates.yaml | 2 + 3 files changed, 24 insertions(+), 587 deletions(-) diff --git a/model/marine/marine_background_error_hybrid_diffusion_diffusion.yaml.j2 b/model/marine/marine_background_error_hybrid_diffusion_diffusion.yaml.j2 index 43feedb..b2709aa 100644 --- a/model/marine/marine_background_error_hybrid_diffusion_diffusion.yaml.j2 +++ b/model/marine/marine_background_error_hybrid_diffusion_diffusion.yaml.j2 @@ -3,39 +3,27 @@ components: - covariance: covariance model: SABER saber central block: - saber block name: EXPLICIT_DIFFUSION - active variables: [tocn, socn, ssh, cicen] - geometry: - mom6_input_nml: mom_input.nml - fields metadata: ./fields_metadata.yaml - group mapping: - - name: ocean - variables: - - tocn - - socn - - ssh - - name: ice - variables: - - cicen + saber block name: diffusion read: groups: - - name: ocean + - variables: [tocn, socn, ssh] horizontal: - filename: hz_ocean.nc + filepath: ./staticb/hz_ocean vertical: - filename: vt_ocean.nc - - name: ice + levels: {{marine_vt_levels}} + filepath: ./staticb/vt_ocean + - variables: [cicen] horizontal: - filename: hz_ice.nc + filepath: ./staticb/hz_ice saber outer blocks: - saber block name: StdDev read: model file: - date: '{{marine_window_middle}}' - basename: ./ - ocn_filename: 'ocn.bkgerr_stddev.incr.{{marine_window_middle}}.nc' - ice_filename: 'ice.bkgerr_stddev.incr.{{marine_window_middle}}.nc' + date: '{{marine_stddev_time}}' + basename: ./staticb/ + ocn_filename: 'ocn.bkgerr_stddev.nc' + ice_filename: 'ice.bkgerr_stddev.nc' read_from_file: 3 linear variable change: @@ -43,7 +31,6 @@ components: output variables: [cicen, hicen, hsnon, socn, tocn, uocn, vocn, ssh] linear variable changes: - linear variable change name: BalanceSOCA - weight: value: 1.00 @@ -52,41 +39,31 @@ components: members from template: template: read_from_file: 1 - date: '{{marine_window_middle}}' - basename: ./static_ens/ + date: '{{marine_stddev_time}}' + basename: ../ensdata/ ocn_filename: 'ocn.pert.steric.%mem%.nc' - ice_filename: 'ice.%mem%.nc' + ice_filename: 'ens/ice.%mem%.nc' state variables: [tocn, socn, ssh, uocn, vocn, cicen, hicen, hsnon] pattern: '%mem%' nmembers: '{{marine_number_ensemble_members}}' localization: localization method: SABER saber central block: - saber block name: EXPLICIT_DIFFUSION - active variables: [tocn, socn, ssh] - geometry: - mom6_input_nml: mom_input.nml - fields metadata: ./fields_metadata.yaml - group mapping: - - name: ocean - variables: [tocn, socn, ssh, uocn, vocn] - - name: ice - variables: [cicen, hicen, hsnon] + saber block name: diffusion read: groups: - - name: ocean + - variables: [tocn, socn, ssh] multivariate strategy: duplicated horizontal: - filename: hz_ocean.nc + filepath: ./staticb/hz_ocean vertical: strategy: duplicated - - name: ice + - variables: [cicen] horizontal: - filename: hz_ice.nc - + filepath: ./staticb/hz_ice weight: read_from_file: 3 basename: ./ - ocn_filename: 'ocn.ens_weights.incr.{{marine_window_middle}}.nc' - ice_filename: 'ice.ens_weights.incr.{{marine_window_middle}}.nc' - date: '{{marine_window_middle}}' + ocn_filename: 'ocean.ens_weights.nc' + ice_filename: 'ice.ens_weights.nc' + date: '{{marine_stddev_time}}' diff --git a/observations/marine/insitu_profile_argo.yaml.j2 b/observations/marine/insitu_profile_argo.yaml.j2 index 4a1dbd7..0d121a0 100644 --- a/observations/marine/insitu_profile_argo.yaml.j2 +++ b/observations/marine/insitu_profile_argo.yaml.j2 @@ -15,7 +15,6 @@ obsfile: "{{marine_obsdataout_path}}/{{marine_obsdataout_prefix}}{{observation_from_jcb}}{{marine_obsdataout_suffix}}" simulated variables: [waterTemperature, salinity] observed variables: [waterTemperature, salinity] - derived variables: [waterPressure] io pool: max pool size: 1 obs operator: @@ -60,544 +59,3 @@ minvalue: -2.5 maxvalue: 40.0 - #----------------------------------------------------------------------------- - ### Regional range tests - #----------------------------------------------------------------------------- - - #### Red Sea - #----------------------------------------------------------------------------- - #### - #### the document linked here describes Red sea as the are between 10N, 40E; - #### 20N, 50E; 30N, 30E; 10N, 40E. But that would also include Gulf of Aden. - #### A more reasonable choice seemed to be a box that extends from 10 N to - #### 30 N and 30 E to 45 East . - - - filter: Bounds Check - filter variables: [{name: waterTemperature}] - minvalue: 21.7 - maxvalue: 40.0 - where: - - variable: - name: MetaData/latitude - minvalue: 10 - maxvalue: 30 - - variable: - name: MetaData/longitude - minvalue: 30 - maxvalue: 45 - - #### Mediterranean Sea - #----------------------------------------------------------------------------- - ##### Area 1/3 for Mediterranean Sea - - filter: Bounds Check - filter variables: [{name: waterTemperature}] - minvalue: 10.0 - maxvalue: 40.0 - where: - - variable: - name: MetaData/latitude - minvalue: 30 - maxvalue: 40 - - variable: - name: MetaData/longitude - minvalue: -6 - maxvalue: 40 - ##### Area 2/3 for Mediterranean Sea - - filter: Bounds Check - filter variables: [{name: waterTemperature}] - minvalue: 10.0 - maxvalue: 40.0 - where: - - variable: - name: MetaData/latitude - minvalue: 40 - maxvalue: 41.5 - - variable: - name: MetaData/longitude - minvalue: 20 - maxvalue: 30 - ##### Area 3/3 for Mediterranean Sea - - filter: Bounds Check - filter variables: [{name: waterTemperature}] - minvalue: 10.0 - maxvalue: 40.0 - where: - - variable: - name: MetaData/latitude - minvalue: 40 - maxvalue: 46 - - variable: - name: MetaData/longitude - minvalue: 0 - maxvalue: 20 - - #### Northwestern shelves - #----------------------------------------------------------------------------- - - filter: Bounds Check - filter variables: [{name: waterTemperature}] - minvalue: -2.0 - maxvalue: 24.0 - where: - - variable: - name: MetaData/latitude - minvalue: 50 - maxvalue: 60 - - variable: - name: MetaData/longitude - minvalue: -20 - maxvalue: 10 - #### Southwestern shelves - #----------------------------------------------------------------------------- - - filter: Bounds Check - filter variables: [{name: waterTemperature}] - minvalue: -2.0 - maxvalue: 30 - where: - - variable: - name: MetaData/latitude - minvalue: 25 - maxvalue: 50 - - variable: - name: MetaData/longitude - minvalue: -30 - maxvalue: 0 - - #### Arctic Sea - #----------------------------------------------------------------------------- - - filter: Bounds Check - filter variables: [{name: waterTemperature}] - minvalue: -1.92 - maxvalue: 25.0 - where: - - variable: - name: MetaData/latitude - minvalue: 60 - - - filter: Background Check - filter variables: [{name: waterTemperature}] - threshold: 5.0 - absolute threshold: 5.0 - - #------------------------------------------------------------------------------- - ### Spike test - #----------------------------------------------------------------------------- - - filter: Create Diagnostic Flags - filter variables: - - name: waterTemperature - - name: salinity - flags: - - name: spike - initial value: false - - name: step - initial value: false - - - filter: Spike and Step Check - filter variables: - - name: ObsValue/waterTemperature - dependent: ObsValue/waterTemperature # dy/ - independent: MetaData/depth # dx - count spikes: true - count steps: true - tolerance: - nominal value: 10 # K nominal, in the case of temperature (not really) - gradient: 0.1 # K/m - if dy/dx greater, could be a spike - gradient x resolution: 10 # m - can't know dx to better precision - factors: [1,1,0.5] # multiply tolerance, for ranges bounded by... - x boundaries: [0,500,500] # ...these values of x (depth in m) - boundary layer: - x range: [0.0,300.0] # when bounded by these x values (depth in m)... - step tolerance range: [0.0,-2.0] # ...relax tolerance for steps in boundary layer... - maximum x interval: [50.0,100.0] # ...and ignore level if dx greater than this - action: - name: reject - - #### Count spikes - #----------------------------------------------------------------------------- - - filter: Variable Assignment # create derived obs value containing only T spikes - assignments: - - name: DerivedMetaData/waterTemperature_spikes - type: int - function: - name: IntObsFunction/ProfileLevelCount - options: - where: - - variable: - name: DiagnosticFlags/spike/waterTemperature - value: is_true - - #### Count steps - #----------------------------------------------------------------------------- - - filter: Variable Assignment # create derived obs value containing only T steps - assignments: - - name: DerivedMetaData/waterTemperature_steps - type: int - function: - name: IntObsFunction/ProfileLevelCount - options: - where: - - variable: - name: DiagnosticFlags/step/waterTemperature - value: is_true - #### Count total rejections - #----------------------------------------------------------------------------- - - filter: Variable Assignment # compute sum 2*spikes+steps - assignments: - - name: DerivedMetaData/waterTemperature_rejections - type: int - function: - name: IntObsFunction/LinearCombination - options: - variables: [DerivedMetaData/waterTemperature_spikes, DerivedMetaData/waterTemperature_steps] - coefs: [2,1] - #### Reject entire profile if total rejctions > threshold - #----------------------------------------------------------------------------- - - filter: Perform Action # reject whole profile if 2*spikes+steps>=rejection threshold - where: - - variable: - name: DerivedMetaData/waterTemperature_rejections - minvalue: 3 - action: - name: reject - - #------------------------------------------------------------------------------- - ## Filters for S: - #------------------------------------------------------------------------------- - #----------------------------------------------------------------------------- - ### Global range test - #----------------------------------------------------------------------------- - - filter: Bounds Check - filter variables: [{name: salinity}] - minvalue: 2.0 - maxvalue: 41.0 - - #----------------------------------------------------------------------------- - ### Regional range test - #----------------------------------------------------------------------------- - #### Red Sea - #----------------------------------------------------------------------------- - #### - #### the document linked here describes Red sea as the are between 10N, 40E; - #### 20N, 50E; 30N, 30E; 10N, 40E. But that would also include Gulf of Aden. - #### A more reasonable choice seemed to be a box that extends from 10 N to - #### 30 N and 30 E to 45 East . - - - filter: Bounds Check - filter variables: [{name: salinity}] - minvalue: 2.0 - maxvalue: 41.0 - where: - - variable: - name: MetaData/latitude - minvalue: 10 - maxvalue: 30 - - variable: - name: MetaData/longitude - minvalue: 30 - maxvalue: 45 - - #### Mediterranean Sea - #----------------------------------------------------------------------------- - ##### Area 1/3 for Mediterranean Sea - - filter: Bounds Check - filter variables: [{name: salinity}] - minvalue: 2.0 - maxvalue: 40.0 - where: - - variable: - name: MetaData/latitude - minvalue: 30 - maxvalue: 40 - - variable: - name: MetaData/longitude - minvalue: -6 - maxvalue: 40 - ##### Area 2/3 for Mediterranean Sea - - filter: Bounds Check - filter variables: [{name: salinity}] - minvalue: 2.0 - maxvalue: 40.0 - where: - - variable: - name: MetaData/latitude - minvalue: 40 - maxvalue: 41.5 - - variable: - name: MetaData/longitude - minvalue: 20 - maxvalue: 30 - ##### Area 3/3 for Mediterranean Sea - - filter: Bounds Check - filter variables: [{name: salinity}] - minvalue: 2.0 - maxvalue: 40.0 - where: - - variable: - name: MetaData/latitude - minvalue: 40 - maxvalue: 46 - - variable: - name: MetaData/longitude - minvalue: 0 - maxvalue: 20 - - - #### Northwestern shelves - #----------------------------------------------------------------------------- - - filter: Bounds Check - filter variables: [{name: salinity}] - minvalue: 0.0 - maxvalue: 37.0 - where: - - variable: - name: MetaData/latitude - minvalue: 50 - maxvalue: 60 - - variable: - name: MetaData/longitude - minvalue: -20 - maxvalue: 10 - - #### Southwestern shelves - #----------------------------------------------------------------------------- - - filter: Bounds Check - filter variables: [{name: salinity}] - minvalue: 0.0 - maxvalue: 38 - where: - - variable: - name: MetaData/latitude - minvalue: 25 - maxvalue: 50 - - variable: - name: MetaData/longitude - minvalue: -30 - maxvalue: 0 - - #### Arctic Sea - #----------------------------------------------------------------------------- - - filter: Bounds Check - filter variables: [{name: salinity}] - minvalue: 2.0 - maxvalue: 40.0 - where: - - variable: - name: MetaData/latitude - minvalue: 60 - - - filter: Background Check - filter variables: [{name: salinity}] - threshold: 5.0 - absolute threshold: 5.0 - - #------------------------------------------------------------------------------- - ### Spike test - #----------------------------------------------------------------------------- - - filter: Spike and Step Check - filter variables: - - name: ObsValue/salinity - dependent: ObsValue/salinity # dy/ - independent: MetaData/depth # dx - count spikes: true - count steps: true - tolerance: - nominal value: 1.0 # PSU nominal, in the case of salinity (not really) - threshold: 0.6 # weird salinity thing - factors: [1,1,0.2] # multiply tolerance, for ranges bounded by... - x boundaries: [0,200,600] # ...these values of x (depth in m) - boundary layer: - x range: [0.0,300.0] # when bounded by these x values (depth in m)... - maximum x interval: [50.0,100.0] # ...and ignore level if dx greater than this - action: - name: reject - - #### Count spikes - #----------------------------------------------------------------------------- - - filter: Variable Assignment # create derived obs value containing only S spikes - assignments: - - name: DerivedMetaData/salinity_spikes - type: int - function: - name: IntObsFunction/ProfileLevelCount - options: - where: - - variable: - name: DiagnosticFlags/spike/salinity - value: is_true - #### Count steps - #----------------------------------------------------------------------------- - - filter: Variable Assignment # create derived obs value containing only S steps - assignments: - - name: DerivedMetaData/salinity_steps - type: int - function: - name: IntObsFunction/ProfileLevelCount - options: - where: - - variable: - name: DiagnosticFlags/step/salinity - value: is_true - #### Count total rejections - #----------------------------------------------------------------------------- - - filter: Variable Assignment # compute sum 2*spikes+steps - assignments: - - name: DerivedMetaData/salinity_rejections - type: int - function: - name: IntObsFunction/LinearCombination - options: - variables: [DerivedMetaData/salinity_spikes, DerivedMetaData/salinity_steps] - coefs: [2,1] - #### Reject entire profile if total rejctions > threshold - #----------------------------------------------------------------------------- - - filter: Perform Action # reject whole profile if 2*spikes+steps>=rejection threshold - where: - - variable: - name: DerivedMetaData/salinity_rejections - minvalue: 3 - action: - name: reject - #------------------------------------------------------------------------------- - ### End of Spike test - #----------------------------------------------------------------------------- - - #----------------------------------------------------------------------------- - ## Filters on the whole profile: - #----------------------------------------------------------------------------- - #------------------------------------------------------------------------------- - ### Ocean Vertical stability test - #----------------------------------------------------------------------------- - - #### get pressure from depth - #----------------------------------------------------------------------------- - - filter: Variable Transforms - Transform: OceanDepthToPressure - ocean depth variable: depth - ocean depth group: MetaData - #### Create diagonostic flags for spike step - #----------------------------------------------------------------------------- - - filter: Create Diagnostic Flags - filter variables: - - name: DerivedObsValue/waterPressure - flags: - - name: DensitySpike - initial value: false - - name: DensityStep - initial value: false - - name: Superadiabat - initial value: false - #### - #----------------------------------------------------------------------------- - - filter: Ocean Vertical Stability Check - where: - - variable: - name: ObsValue/waterTemperature - value: is_valid - filter variables: - - name: DerivedObsValue/waterPressure # density spikes/steps --> flag d - variables: - temperature: ObsValue/waterTemperature - salinity: ObsValue/salinity - pressure: DerivedObsValue/waterPressure - count spikes: true - count steps: true - nominal tolerance: -0.05 - threshold: 0.25 - actions: - - name: set - flag: Superadiabat - - name: reject - #### where there are any density inversions, reject temperature only: - #----------------------------------------------------------------------------- - - filter: Perform Action - filter variables: - - name: ObsValue/waterTemperature - where: - - variable: - name: DiagnosticFlags/Superadiabat/waterPressure - value: is_true - action: - name: reject - #### where density spikes, reject all vars (temperature and salinity): - #----------------------------------------------------------------------------- - - filter: Perform Action - filter variables: - - name: ObsValue/waterTemperature - - name: ObsValue/salinity - where: - - variable: - name: DiagnosticFlags/DensitySpike/waterPressure - value: is_true - action: - name: reject - #### create derived metadata counting levels: - #----------------------------------------------------------------------------- - - filter: Variable Assignment - assignments: - - name: DerivedMetaData/number_of_levels - type: int - function: - name: IntObsFunction/ProfileLevelCount - options: - where: - - variable: - name: ObsValue/waterTemperature - value: is_valid - #### create derived metadata counting spikes and steps: - #----------------------------------------------------------------------------- - - filter: Variable Assignment - assignments: - - name: DerivedMetaData/ocean_density_inversions - type: int - function: - name: IntObsFunction/ProfileLevelCount - options: - where: - - variable: - name: DiagnosticFlags/DensitySpike/waterPressure - value: is_true - - variable: - name: DiagnosticFlags/DensityStep/waterPressure - value: is_true - where operator: or - - #### whole profile is rejected if spikes+steps >= numlev/4, so compute - #### 4*( sum spikes+steps ) minus numlev - #### in order to check it against 0: - #----------------------------------------------------------------------------- - - filter: Variable Assignment - assignments: - - name: DerivedMetaData/ocean_density_rejections - type: int - function: - name: IntObsFunction/LinearCombination - options: - variables: [DerivedMetaData/ocean_density_inversions, DerivedMetaData/number_of_levels] - coefs: [4, -1] - #### reject whole profile if spikes+steps >= numlev/4 AND >= 2: - #----------------------------------------------------------------------------- - - filter: Perform Action - filter variables: - - name: ObsValue/waterTemperature - - name: ObsValue/salinity - where: - - variable: - name: DerivedMetaData/ocean_density_rejections - minvalue: 0 - - variable: - name: DerivedMetaData/ocean_density_inversions - minvalue: 2 - where operator: and - action: - name: reject - #------------------------------------------------------------------------------- - ### End of ocean vertical stability test - #----------------------------------------------------------------------------- - - #----------------------------------------------------------------------------- - ### If T was bad, remove S as well regardless - #----------------------------------------------------------------------------- - - filter: RejectList - where: - - variable: QCflagsData/waterTemperature - minvalue: 1 - defer to post: true diff --git a/test/client_integration/gdas-marine-templates.yaml b/test/client_integration/gdas-marine-templates.yaml index 2fe3e79..f258cc9 100644 --- a/test/client_integration/gdas-marine-templates.yaml +++ b/test/client_integration/gdas-marine-templates.yaml @@ -36,6 +36,8 @@ number_of_outer_loops: 1 # Model things # ------------ marine_soca_files_path: DATA/soca +marine_vt_levels: 25 +marine_stddev_time: '2024-01-31T21:00:00Z' # Background marine_background_time: '2024-01-31T21:00:00Z'