diff --git a/ci/driver.sh b/ci/driver.sh index ce6372c59..933b9223b 100755 --- a/ci/driver.sh +++ b/ci/driver.sh @@ -1,6 +1,9 @@ #!/bin/bash --login +echo "Start at $(date)" + my_dir="$( cd "$( dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd )" +echo "Set my_dir ${my_dir}" # ============================================================================== usage() { @@ -51,6 +54,14 @@ esac cd $GDAS_CI_ROOT/repo CI_LABEL="${GDAS_CI_HOST}-RT" gh pr list --label "$CI_LABEL" --state "open" | awk '{print $1;}' > $GDAS_CI_ROOT/open_pr_list + +open_pr=`cat $GDAS_CI_ROOT/open_pr_list | wc -l` +if (( $open_pr == 0 )); then + echo "No open PRs with ${CI_LABEL}, exit." + echo "Finish at $(date)" + exit +fi + open_pr_list=$(cat $GDAS_CI_ROOT/open_pr_list) # ============================================================================== @@ -58,72 +69,86 @@ open_pr_list=$(cat $GDAS_CI_ROOT/open_pr_list) repo_url="https://github.com/NOAA-EMC/GDASApp.git" # loop through all open PRs for pr in $open_pr_list; do - gh pr edit $pr --remove-label $CI_LABEL --add-label ${CI_LABEL}-Running - echo "Processing Pull Request #${pr}" + echo " " + echo "Start processing Pull Request #${pr} at $(date)" # get the branch name used for the PR gdasapp_branch=$(gh pr view $pr --json headRefName -q ".headRefName") - - # get the fork information - pr_details=$(gh pr view $pr --repo ${repo_url} --json headRepository,headRepositoryOwner,headRefName) - # extract the necessary info - fork_owner=$(gh pr view $pr --repo ${repo_url} --json headRepositoryOwner --jq '.headRepositoryOwner.login') - fork_name=$(gh pr view $pr --repo ${repo_url} --json headRepository --jq '.headRepository.name') - - # construct the fork URL - gdasapp_url="https://github.com/$fork_owner/${fork_name}.git" + # get additional branch information + branch_owner=$(gh pr view $pr --repo ${repo_url} --json headRepositoryOwner --jq '.headRepositoryOwner.login') + branch_name=$(gh pr view $pr --repo ${repo_url} --json headRepository --jq '.headRepository.name') + pr_assignees=$(gh pr view $pr --repo ${repo_url} --json assignees --jq '.assignees[].login') + + # check if any assignee is authorized to run CI + authorized_by="" + for str in ${pr_assignees[@]}; do + grep $str /scratch1/NCEPDEV/da/role.jedipara/CI/GDASApp/authorized_users + rc=$? + if (( rc == 0 )); then + authorized_by=${str} + echo "FOUND MATCH $str, rc $rc" + break + fi + done + + # Authorized to run CI + if (( rc == 0 )); then + echo "Run CI" + + # update PR label + gh pr edit $pr --remove-label $CI_LABEL --add-label ${CI_LABEL}-Running + + # construct the fork URL + gdasapp_url="https://github.com/$branch_owner/${branch_name}.git" - echo "Fork URL: $gdasapp_url" - echo "Branch Name: $gdasapp_branch" - - # create PR specific directory - if [ -d $GDAS_CI_ROOT/PR/$pr ]; then - rm -rf $GDAS_CI_ROOT/PR/$pr - fi - mkdir -p $GDAS_CI_ROOT/PR/$pr - cd $GDAS_CI_ROOT/PR/$pr - - # clone copy of repo - git clone --recursive --jobs 8 --branch $gdasapp_branch $gdasapp_url - cd GDASApp - - # checkout pull request - git pull - gh pr checkout $pr - git submodule update --init --recursive - - # get commit hash - commit=$(git log --pretty=format:'%h' -n 1) - echo "$commit" > $GDAS_CI_ROOT/PR/$pr/commit - - # load modules - case ${TARGET} in - hera | orion) - echo "Loading modules on $TARGET" - module purge - module use $GDAS_CI_ROOT/PR/$pr/GDASApp/modulefiles - module load GDAS/$TARGET - module list - ;; - *) - echo "Unsupported platform. Exiting with error." - exit 1 - ;; - esac - - # run build and testing command - $my_dir/run_ci.sh -d $GDAS_CI_ROOT/PR/$pr/GDASApp -o $GDAS_CI_ROOT/PR/$pr/output_${commit} - ci_status=$? - gh pr comment $pr --repo ${repo_url} --body-file $GDAS_CI_ROOT/PR/$pr/output_${commit} - if [ $ci_status -eq 0 ]; then - gh pr edit $pr --repo ${repo_url} --remove-label ${CI_LABEL}-Running --add-label ${CI_LABEL}-Passed + echo "GDASApp URL: $gdasapp_url" + echo "GDASApp branch Name: $gdasapp_branch" + echo "CI authorized by $authorized_by at $(date)" + + # create PR specific directory + if [ -d $GDAS_CI_ROOT/PR/$pr ]; then + rm -rf $GDAS_CI_ROOT/PR/$pr + fi + mkdir -p $GDAS_CI_ROOT/PR/$pr + cd $GDAS_CI_ROOT/PR/$pr + pwd + + # clone copy of repo + git clone --recursive --jobs 8 --branch $gdasapp_branch $gdasapp_url + cd GDASApp + pwd + + # checkout GDASApp pull request + git pull + gh pr checkout $pr + git submodule update --init --recursive + + # get commit hash + commit=$(git log --pretty=format:'%h' -n 1) + echo "$commit" > $GDAS_CI_ROOT/PR/$pr/commit + + # run build and testing command + echo "Execute $my_dir/run_ci.sh for $GDAS_CI_ROOT/PR/$pr/GDASApp at $(date)" + $my_dir/run_ci.sh -d $GDAS_CI_ROOT/PR/$pr/GDASApp -o $GDAS_CI_ROOT/PR/$pr/output_${commit} + ci_status=$? + echo "After run_ci.sh with ci_status ${ci_status} at $(date)" + gh pr comment $pr --repo ${repo_url} --body-file $GDAS_CI_ROOT/PR/$pr/output_${commit} + if [ $ci_status -eq 0 ]; then + gh pr edit $pr --repo ${repo_url} --remove-label ${CI_LABEL}-Running --add-label ${CI_LABEL}-Passed + else + gh pr edit $pr --repo ${repo_url} --remove-label ${CI_LABEL}-Running --add-label ${CI_LABEL}-Failed + fi + + # Not authorized to run CI else - gh pr edit $pr --repo ${repo_url} --remove-label ${CI_LABEL}-Running --add-label ${CI_LABEL}-Failed + echo "Do NOT run CI" fi + + echo "Finish processing Pull Request #{pr} at $(date)" done # ============================================================================== # scrub working directory for older files find $GDAS_CI_ROOT/PR/* -maxdepth 1 -mtime +3 -exec rm -rf {} \; - +echo "Finish at $(date)" diff --git a/ci/gw_driver.sh b/ci/gw_driver.sh index e85684f84..c40ff4026 100755 --- a/ci/gw_driver.sh +++ b/ci/gw_driver.sh @@ -1,6 +1,9 @@ #!/bin/bash --login +echo "Start at $(date)" + my_dir="$( cd "$( dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd )" +echo "Set my_dir ${my_dir}" # ============================================================================== usage() { @@ -32,7 +35,7 @@ done case ${TARGET} in hera | orion) - echo "Running automated testing with workflow on $TARGET" + echo "Running Automated GW Testing on $TARGET" source $MODULESHOME/init/sh source $my_dir/${TARGET}.sh module purge @@ -51,69 +54,116 @@ esac cd $GDAS_CI_ROOT/repo CI_LABEL="${GDAS_CI_HOST}-GW-RT" gh pr list --label "$CI_LABEL" --state "open" | awk '{print $1;}' > $GDAS_CI_ROOT/open_pr_list_gw + +open_pr=`cat $GDAS_CI_ROOT/open_pr_list_gw | wc -l` +if (( $open_pr == 0 )); then + echo "No open PRs with ${CI_LABEL}, exit." + echo "Finish at $(date)" + exit +fi + open_pr_list=$(cat $GDAS_CI_ROOT/open_pr_list_gw) # ============================================================================== # clone, checkout, build, test, etc. repo_url="https://github.com/NOAA-EMC/GDASApp.git" workflow_url="https://github.com/NOAA-EMC/global-workflow.git" +workflow_branch="develop" # loop through all open PRs for pr in $open_pr_list; do - gh pr edit $pr --remove-label $CI_LABEL --add-label ${CI_LABEL}-Running - echo "Processing Pull Request #${pr}" + echo " " + echo "Start processing Pull Request #${pr} at $(date)" # get the branch name used for the PR gdasapp_branch=$(gh pr view $pr --json headRefName -q ".headRefName") - # check for a companion PR in the global-workflow - companion_pr_exists=$(gh pr list --repo ${workflow_url} --head ${gdasapp_branch} --state open) - if [ -n "$companion_pr_exists" ]; then - # get the PR number - companion_pr=$(echo "$companion_pr_exists" | awk '{print $1;}') - - # extract the necessary info - fork_owner=$(gh pr view $companion_pr --repo $workflow_url --json headRepositoryOwner --jq '.headRepositoryOwner.login') - fork_name=$(gh pr view $companion_pr --repo $workflow_url --json headRepository --jq '.headRepository.name') - - # Construct the fork URL - workflow_url="https://github.com/$fork_owner/$fork_name.git" - - echo "Fork URL: $workflow_url" - echo "Branch Name: $gdasapp_branch" - fi - - # create PR specific directory - if [ -d $GDAS_CI_ROOT/workflow/PR/$pr ]; then - rm -rf $GDAS_CI_ROOT/workflow/PR/$pr - fi - mkdir -p $GDAS_CI_ROOT/workflow/PR/$pr - cd $GDAS_CI_ROOT/workflow/PR/$pr + # get additional branch information + branch_owner=$(gh pr view $pr --repo ${repo_url} --json headRepositoryOwner --jq '.headRepositoryOwner.login') + branch_name=$(gh pr view $pr --repo ${repo_url} --json headRepository --jq '.headRepository.name') + pr_assignees=$(gh pr view $pr --repo ${repo_url} --json assignees --jq '.assignees[].login') + + # check if any assignee is authorized to run CI + authorized_by="" + for str in ${pr_assignees[@]}; do + grep $str /scratch1/NCEPDEV/da/role.jedipara/CI/GDASApp/authorized_users + rc=$? + if (( rc == 0 )); then + authorized_by=${str} + echo "FOUND MATCH $str, rc $rc" + break + fi + done + + # Authorized to run CI + if (( rc == 0 )); then + echo "Run CI" + + # update PR label + gh pr edit $pr --remove-label $CI_LABEL --add-label ${CI_LABEL}-Running + + # check for a companion PR in the global-workflow + companion_pr_exists=$(gh pr list --repo ${workflow_url} --head ${gdasapp_branch} --state open) + if [ -n "$companion_pr_exists" ]; then + # get the PR number + companion_pr=$(echo "$companion_pr_exists" | awk '{print $1;}') + + # extract the necessary info + branch_owner=$(gh pr view $companion_pr --repo $workflow_url --json headRepositoryOwner --jq '.headRepositoryOwner.login') + branch_name=$(gh pr view $companion_pr --repo $workflow_url --json headRepository --jq '.headRepository.name') + + # Construct fork URL. Update workflow branch name + workflow_url="https://github.com/$branch_owner/$branch_name.git" + workflow_branch=$gdasapp_branch + + fi + + echo "Workflow URL: $workflow_url" + echo "Workflow branch name: $workflow_branch" + echo "GDASApp branch name: $gdasapp_branch" + echo "CI authorized by $authorized_by at $(date)" + + # create PR specific directory + if [ -d $GDAS_CI_ROOT/workflow/PR/$pr ]; then + rm -rf $GDAS_CI_ROOT/workflow/PR/$pr + fi + mkdir -p $GDAS_CI_ROOT/workflow/PR/$pr + cd $GDAS_CI_ROOT/workflow/PR/$pr + pwd - # clone global workflow develop branch - git clone --recursive --jobs 8 --branch dev/gdasapp $workflow_url - - # checkout pull request - cd $GDAS_CI_ROOT/workflow/PR/$pr/global-workflow/sorc/gdas.cd - git checkout develop - git pull - gh pr checkout $pr - git submodule update --init --recursive - - # get commit hash - commit=$(git log --pretty=format:'%h' -n 1) - echo "$commit" > $GDAS_CI_ROOT/workflow/PR/$pr/commit - - $my_dir/run_gw_ci.sh -d $GDAS_CI_ROOT/workflow/PR/$pr/global-workflow -o $GDAS_CI_ROOT/workflow/PR/$pr/output_${commit} - ci_status=$? - gh pr comment $pr --body-file $GDAS_CI_ROOT/workflow/PR/$pr/output_${commit} - if [ $ci_status -eq 0 ]; then - gh pr edit $pr --remove-label ${CI_LABEL}-Running --add-label ${CI_LABEL}-Passed + # clone global workflow develop branch + git clone --recursive --jobs 8 --branch $workflow_branch $workflow_url + + # checkout GDASApp pull request + cd $GDAS_CI_ROOT/workflow/PR/$pr/global-workflow/sorc/gdas.cd + git pull + gh pr checkout $pr + git submodule update --init --recursive + + # get commit hash + commit=$(git log --pretty=format:'%h' -n 1) + echo "$commit" > $GDAS_CI_ROOT/workflow/PR/$pr/commit + + # run build and testing command + echo "Execute $my_dir/run_gw_ci.sh for $GDAS_CI_ROOT/PR/workflow/PR/$pr/global-workflow at $(date)" + $my_dir/run_gw_ci.sh -d $GDAS_CI_ROOT/workflow/PR/$pr/global-workflow -o $GDAS_CI_ROOT/workflow/PR/$pr/output_${commit} + ci_status=$? + echo "After run_gw_ci.sh with ci_status ${ci_status} at $(date)" + gh pr comment $pr --body-file $GDAS_CI_ROOT/workflow/PR/$pr/output_${commit} + if [ $ci_status -eq 0 ]; then + gh pr edit $pr --remove-label ${CI_LABEL}-Running --add-label ${CI_LABEL}-Passed + else + gh pr edit $pr --remove-label ${CI_LABEL}-Running --add-label ${CI_LABEL}-Failed + fi + + # Not authorized to run CI else - gh pr edit $pr --remove-label ${CI_LABEL}-Running --add-label ${CI_LABEL}-Failed + echo "Do NOT run CI" fi + + echo "Finish processing Pull Request #{pr} at $(date)" done # ============================================================================== # scrub working directory for older files find $GDAS_CI_ROOT/workflow/PR/* -maxdepth 1 -mtime +3 -exec rm -rf {} \; - +echo "Finish at $(date)" diff --git a/ci/run_ci.sh b/ci/run_ci.sh index b62f78a88..1b5f27231 100755 --- a/ci/run_ci.sh +++ b/ci/run_ci.sh @@ -1,5 +1,5 @@ #!/bin/bash -#set -eu +set -u # ============================================================================== usage() { @@ -61,7 +61,7 @@ module use $GDAS_MODULE_USE module load GDAS/$TARGET echo "---------------------------------------------------" >> $outfile rm -rf log.ctest -ctest -E "manual" -R gdasapp --output-on-failure &>> log.ctest +ctest -R gdasapp --output-on-failure &>> log.ctest ctest_status=$? npassed=$(cat log.ctest | grep "tests passed") if [ $ctest_status -eq 0 ]; then diff --git a/ci/run_gw_ci.sh b/ci/run_gw_ci.sh index 59758e37f..ba1874107 100755 --- a/ci/run_gw_ci.sh +++ b/ci/run_gw_ci.sh @@ -1,5 +1,5 @@ #!/bin/bash -#set -eu +set -u # ============================================================================== usage() { @@ -31,7 +31,7 @@ done # ============================================================================== # start output file -echo "Automated Global-Workflow GDASApp Testing Results:" > $outfile +echo "Automated GW GDASApp Testing Results:" > $outfile echo "Machine: ${TARGET}" >> $outfile echo '```' >> $outfile echo "Start: $(date) on $(hostname)" >> $outfile diff --git a/parm/io/fv3jedi_fieldmetadata_fv3inc.yaml b/parm/io/fv3jedi_fieldmetadata_fv3inc.yaml index 2f8acb839..4750967b1 100644 --- a/parm/io/fv3jedi_fieldmetadata_fv3inc.yaml +++ b/parm/io/fv3jedi_fieldmetadata_fv3inc.yaml @@ -9,7 +9,7 @@ field metadata: - long name: air_temperature io name: T_inc -- long name: specific_humidity +- long name: water_vapor_mixing_ratio_wrt_moist_air io name: sphum_inc - long name: cloud_liquid_water diff --git a/parm/io/fv3jedi_fieldmetadata_history.yaml b/parm/io/fv3jedi_fieldmetadata_history.yaml index a8532c32c..2e59dccb1 100644 --- a/parm/io/fv3jedi_fieldmetadata_history.yaml +++ b/parm/io/fv3jedi_fieldmetadata_history.yaml @@ -6,7 +6,7 @@ field metadata: - long name: northward_wind io name: vgrd -- long name: specific_humidity +- long name: water_vapor_mixing_ratio_wrt_moist_air io name: spfh - long name: air_temperature @@ -45,11 +45,11 @@ field metadata: - long name: upward_air_velocity io name: dzdt -- long name: surface_pressure +- long name: air_pressure_at_surface io name: pressfc io file: atmosphere -- long name: surface_geopotential_height +- long name: geopotential_height_at_surface io name: hgtsfc - long name: u_component_of_native_D_grid_wind @@ -74,7 +74,7 @@ field metadata: - long name: sheleg io name: weasd -- long name: sea_surface_temperature +- long name: skin_temperature_at_surface io name: tmpsfc - long name: stype @@ -86,8 +86,8 @@ field metadata: - long name: totalSnowDepthMeters io name: snod -- long name: surface_eastward_wind +- long name: eastward_wind_at_surface io name: ugrd_hyblev1 -- long name: surface_northward_wind +- long name: northward_wind_at_surface io name: vgrd_hyblev1 diff --git a/parm/io/fv3jedi_fieldmetadata_restart.yaml b/parm/io/fv3jedi_fieldmetadata_restart.yaml index d4a4a3a09..ccba447dc 100644 --- a/parm/io/fv3jedi_fieldmetadata_restart.yaml +++ b/parm/io/fv3jedi_fieldmetadata_restart.yaml @@ -10,7 +10,7 @@ field metadata: io name: T - long name: air_pressure_thickness - io name: DELP + io name: delp - long name: layer_thickness io name: DZ diff --git a/parm/jcb-gdas b/parm/jcb-gdas index b8e995a4c..c41e7d7ac 160000 --- a/parm/jcb-gdas +++ b/parm/jcb-gdas @@ -1 +1 @@ -Subproject commit b8e995a4cbf01fa4a662c3da3e7d818f8457ec4e +Subproject commit c41e7d7aca3f4053b177709adaa66488f3643980 diff --git a/parm/soca/fields_metadata.yaml b/parm/soca/fields_metadata.yaml index 586d8557e..444bd8418 100644 --- a/parm/soca/fields_metadata.yaml +++ b/parm/soca/fields_metadata.yaml @@ -1,103 +1,150 @@ # -------------------------------------------------------------------------------------------------- # Field metadata for SOCA. Each field can contain the following information: # -# name: Internal name used by soca code and config files +# name: name used by soca and by the rest of JEDI +# name surface: JEDI variable name for 2D surface of a 3D field (Default: ) # grid: "h", "u", or "v" (Default: h) # masked: use land mask if true (Default: true) # levels: "1" or "full_ocn" (Default: 1) -# getval_name: variable name expected by GetValues (Default: ) -# getval_name_surface: GetValues variable name for 2D surface of a 3D field (Default: ) -# io_file: The restart file domain "ocn", "sfc", or "ice" (Default: ) -# io_name: The variable name used in the restart IO (Default: ) +# io file: The restart file domain "ocn", "sfc", or "ice" (Default: ) +# io name: The variable name used in the restart IO (Default: ) +# constant value: Used for "dummy" fields. Sets the entire field to the given constant globally +# This parameter cannot be used with io_file/io_name +# fill value: If the field is masked, this value will be used for the masked areas. +# (Default: 0.0) +# categories: Number of categories for a field with a category dimension (Default: -1) +# If > 0, then the fields "name", and "io name" can use the +# placeholder "" which will be replaced with the category number # -------------------------------------------------------------------------------------------------- # -------------------------------------------------------------------------------------------------- # Ocean state variables # -------------------------------------------------------------------------------------------------- -- name: tocn +- name: sea_water_potential_temperature + name surface: sea_surface_temperature levels: full_ocn - getval name: sea_water_potential_temperature - getval name surface: sea_surface_temperature io file: ocn io name: Temp - fill value: 0.0 -- name: socn +- name: sea_water_salinity + name surface: sea_surface_salinity levels: full_ocn - getval name: sea_water_salinity - getval name surface: sea_surface_salinity io file: ocn io name: Salt property: positive_definite - fill value: 0.0 -- name: uocn +- name: eastward_sea_water_velocity + name surface: surface_eastward_sea_water_velocity grid: u levels: full_ocn - getval name: eastward_sea_water_velocity - getval name surface: surface_eastward_sea_water_velocity io file: ocn io name: u - fill value: 0.0 -- name: vocn +- name: northward_sea_water_velocity + name surface: surface_northward_sea_water_velocity grid: v levels: full_ocn - getval name: northward_sea_water_velocity - getval name surface: surface_northward_sea_water_velocity io file: ocn io name: v - fill value: 0.0 -- name: hocn +- name: sea_water_cell_thickness levels: full_ocn - getval name: sea_water_cell_thickness io file: ocn io name: h - fill value: 0.001 vert interp: false -- name: ssh - getval name: sea_surface_height_above_geoid +- name: sea_surface_height_above_geoid io file: ocn io name: ave_ssh - fill value: 0.0 - name: mom6_mld io file: ocn io name: MLD fill value: 0.0 + +# -------------------------------------------------------------------------------------------------- +# ice state variables with no categories +# -------------------------------------------------------------------------------------------------- +- name: sea_ice_thickness + io file: ice + io name: hi_h #note, was hicen + property: positive_definite + +- name: sea_ice_area_fraction + io file: ice + io name: aice_h #note, was aicen + +- name: sea_ice_snow_thickness + io file: ice + io name: hs_h #note, was hsnon + property: positive_definite + +- name: snow_ice_surface_temperature + io file: ice + io name: Tsfc_h + +- name: air_temperature + io file: ice + io name: Tair_h + +- name: bulk_ice_salinity + io file: ice + io name: sice_h # -------------------------------------------------------------------------------------------------- -# ice state variables +# ice state variables with category dimension # -------------------------------------------------------------------------------------------------- -- name: hicen - getval name: sea_ice_category_thickness +- name: sea_ice_category_area_fraction + categories: 5 io file: ice - io name: hi_h + io sup name: aicen_h + io name: aice_h property: positive_definite - fill value: 0.0 -- name: cicen - getval name: sea_ice_category_area_fraction - getval name surface: sea_ice_area_fraction # note: not accurate, should be "sum" not "surface" +- name: sea_ice_category_volume + categories: 5 io file: ice - io name: aice_h - fill value: 0.0 + io sup name: vicen_h + io name: vice_h + property: positive_definite -- name: hsnon - getval name: sea_ice_category_snow_thickness +- name: sea_ice_snow_category_volume + categories: 5 io file: ice - io name: hs_h + io sup name: vsnon_h + io name: vsno_h property: positive_definite - fill value: 0.0 + +# -------------------------------------------------------------------------------------------------- +# Thermodynamic ice state variables with category and level dimension +# -------------------------------------------------------------------------------------------------- +- name: sea_ice_category_temperature + categories: 5 + levels: 7 + io file: ice + io sup name: Tinz_h + io name: tiz_h + +- name: sea_ice_category_salinity + categories: 5 + levels: 7 + io file: ice + io sup name: Sinz_h + io name: siz_h + +- name: sea_ice_snow_category_temperature + categories: 5 + levels: 1 + io file: ice + io sup name: Tsnz_h + io name: tsz_h + # -------------------------------------------------------------------------------------------------- # wave state variables # -------------------------------------------------------------------------------------------------- -- name: swh - getval name: sea_surface_wave_significant_height +- name: sea_surface_wave_significant_height io file: wav io name: hs property: positive_definite @@ -105,33 +152,28 @@ # -------------------------------------------------------------------------------------------------- # sea surface variables # -------------------------------------------------------------------------------------------------- -- name: sw +- name: net_downwelling_shortwave_radiation masked: false - getval name: net_downwelling_shortwave_radiation io file: sfc io name: sw_rad -- name: lw +- name: net_downwelling_longwave_radiation masked: false - getval name: net_downwelling_longwave_radiation io file: sfc io name: lw_rad -- name: lhf +- name: upward_latent_heat_flux_in_air masked: false - getval name: upward_latent_heat_flux_in_air io file: sfc io name: latent_heat -- name: shf +- name: upward_sensible_heat_flux_in_air masked: false - getval name: upward_sensible_heat_flux_in_air io file: sfc io name: sens_heat -- name: us +- name: friction_velocity_over_water masked: false - getval name: friction_velocity_over_water io file: sfc io name: fric_vel @@ -139,18 +181,16 @@ # -------------------------------------------------------------------------------------------------- # BGC # -------------------------------------------------------------------------------------------------- -- name: chl +- name: mass_concentration_of_chlorophyll_in_sea_water + name surface: sea_surface_chlorophyll levels: full_ocn - getval name: mass_concentration_of_chlorophyll_in_sea_water - getval name surface: sea_surface_chlorophyll io file: ocn io name: chl property: positive_definite -- name: biop +- name: molar_concentration_of_biomass_in_sea_water_in_p_units + name surface: sea_surface_biomass_in_p_units levels: full_ocn - getval name: molar_concentration_of_biomass_in_sea_water_in_p_units - getval name surface: sea_surface_biomass_in_p_units io file: ocn io name: biomass_p property: positive_definite @@ -161,20 +201,106 @@ - name: distance_from_coast masked: false -- name: layer_depth - levels: full_ocn - vert interp: false - - name: mesoscale_representation_error -- name: mld +- name: ocean_mixed_layer_thickness - name: sea_floor_depth_below_sea_surface - name: sea_area_fraction masked: false -- name: surface_temperature_where_sea +- name: skin_temperature_at_surface_where_sea - name: sea_water_depth levels: full_ocn + +- name: latitude +- name: longitude + +# -------------------------------------------------------------------------------------------------- +# variables that VADER should be responsible for +# -------------------------------------------------------------------------------------------------- +- name: sea_water_temperature + levels: full_ocn + +# -------------------------------------------------------------------------------------------------- +- name: dummy_atm1 + constant value: 5.0 + +- name: ozone_thickness + constant value: 275 #The average amount of ozone in the atm. is 300 Dobson Units + +- name: water_vapor #g/cm^2 + constant value: 1.2 + +- name: wind_speed_at_surface + constant value: 6 + +- name: air_pressure_at_surface + constant value: 999 + +- name: relative_humidity + constant value: 89 + +- name: cloud_liquid_water_path + constant value: 163 + +- name: cloud_area_fraction_in_atmosphere_layer + constant value: 80 + +- name: aerosol_optical_thickness + constant value: 0.16 + +- name: single_scattering_albedo + constant value: 0.71 + +- name: asymmetry_parameter + constant value: 0.97 + +#---------------------ocean bio +- name: Carbon_nitrogen_detritus_concentration + levels: full_ocn + io file: bio + io name: CDET + property: positive_definite + +- name: Particulate_inorganic_carbon + levels: full_ocn + io file: bio + io name: PIC + +- name: colored_dissolved_organic_carbon + levels: full_ocn + io file: bio + io name: CDC + +- name: diatom_concentration + levels: full_ocn + io file: bio + io name: DIATOM + +- name: chlorophyte_concentration + levels: full_ocn + io file: bio + io name: CHLORO + +- name: cyano-bacteria_concentration + levels: full_ocn + io file: bio + io name: CYANO + +- name: coccolithophore_concentration + levels: full_ocn + io file: bio + io name: COCCO + +- name: dinoflagellate_concentration + levels: full_ocn + io file: bio + io name: DINO + +- name: phaeocystis_concentration + levels: full_ocn + io file: bio + io name: PHAEO diff --git a/parm/soca/letkf/letkf.yaml.j2 b/parm/soca/letkf/letkf.yaml.j2 index 1d5e93d7f..ef60c6ec9 100644 --- a/parm/soca/letkf/letkf.yaml.j2 +++ b/parm/soca/letkf/letkf.yaml.j2 @@ -17,7 +17,7 @@ background: ice_filename: "ice.%mem%.nc" read_from_file: 1 basename: {{ ENSPERT_RELPATH }}/ens/ - state variables: [socn, tocn, ssh, hocn, uocn, vocn, cicen] + state variables: [sea_water_salinity, sea_water_potential_temperature, sea_surface_height_above_geoid, sea_water_cell_thickness, eastward_sea_water_velocity, northward_sea_water_velocity, sea_ice_area_fraction] pattern: '%mem%' nmembers: {{ NMEM_ENS }} diff --git a/parm/soca/marine-jcb-base.yaml b/parm/soca/marine-jcb-base.yaml index d07edcd8c..3a9d40223 100644 --- a/parm/soca/marine-jcb-base.yaml +++ b/parm/soca/marine-jcb-base.yaml @@ -24,7 +24,7 @@ minimizer: RPCG final_diagnostics_departures: oman final_prints_frequency: PT3H number_of_outer_loops: 1 -analysis_variables: [cicen, hicen, hsnon, socn, tocn, uocn, vocn, ssh] +analysis_variables: [sea_ice_area_fraction, sea_ice_thickness, sea_ice_snow_thickness, sea_water_salinity, sea_water_potential_temperature, eastward_sea_water_velocity, northward_sea_water_velocity, sea_surface_height_above_geoid] # Model things diff --git a/parm/soca/obs/config/insitu_profile_bathy.yaml b/parm/soca/obs/config/insitu_profile_bathy.yaml index 0dc2db0aa..d78cacdb6 100644 --- a/parm/soca/obs/config/insitu_profile_bathy.yaml +++ b/parm/soca/obs/config/insitu_profile_bathy.yaml @@ -26,3 +26,10 @@ obs filters: - ObsError/waterTemperature coefs: - 1000.0 +obs localizations: +- localization method: Rossby + base value: 100.0e3 + rossby mult: 1.0 + min grid mult: 2.0 + min value: 200.0e3 + max value: 900.0e3 diff --git a/parm/soca/obs/config/insitu_profile_tesac.yaml b/parm/soca/obs/config/insitu_profile_tesac.yaml index 5c966f88a..b2cf1769d 100644 --- a/parm/soca/obs/config/insitu_profile_tesac.yaml +++ b/parm/soca/obs/config/insitu_profile_tesac.yaml @@ -29,3 +29,10 @@ obs filters: - ObsError/waterTemperature coefs: - 1000.0 +obs localizations: +- localization method: Rossby + base value: 100.0e3 + rossby mult: 1.0 + min grid mult: 2.0 + min value: 200.0e3 + max value: 900.0e3 diff --git a/parm/soca/obs/config/insitu_surface_trkob.yaml b/parm/soca/obs/config/insitu_surface_trkob.yaml index 3b058e527..5846b83d6 100644 --- a/parm/soca/obs/config/insitu_surface_trkob.yaml +++ b/parm/soca/obs/config/insitu_surface_trkob.yaml @@ -27,3 +27,10 @@ obs filters: - ObsError/seaSurfaceTemperature coefs: - 1000.0 +obs localizations: +- localization method: Rossby + base value: 100.0e3 + rossby mult: 1.0 + min grid mult: 2.0 + min value: 200.0e3 + max value: 900.0e3 diff --git a/parm/soca/obs/obs_list.yaml b/parm/soca/obs/obs_list.yaml index 0ac8ab5af..c11dc1ace 100644 --- a/parm/soca/obs/obs_list.yaml +++ b/parm/soca/obs/obs_list.yaml @@ -25,15 +25,15 @@ observers: #- !INC ${MARINE_OBS_YAML_DIR}/icec_ssmis_f17_l2.yaml # in situ: monthly -- !INC ${MARINE_OBS_YAML_DIR}/insitu_profile_bathy.yaml +#- !INC ${MARINE_OBS_YAML_DIR}/insitu_profile_bathy.yaml - !INC ${MARINE_OBS_YAML_DIR}/insitu_profile_argo.yaml -- !INC ${MARINE_OBS_YAML_DIR}/insitu_profile_glider.yaml -- !INC ${MARINE_OBS_YAML_DIR}/insitu_profile_tesac.yaml +#- !INC ${MARINE_OBS_YAML_DIR}/insitu_profile_glider.yaml +#- !INC ${MARINE_OBS_YAML_DIR}/insitu_profile_tesac.yaml #- !INC ${MARINE_OBS_YAML_DIR}/insitu_profile_tesac_salinity.yaml #- !INC ${MARINE_OBS_YAML_DIR}/insitu_profile_marinemammal.yaml -- !INC ${MARINE_OBS_YAML_DIR}/insitu_profile_xbtctd.yaml +#- !INC ${MARINE_OBS_YAML_DIR}/insitu_profile_xbtctd.yaml #- !INC ${MARINE_OBS_YAML_DIR}/insitu_surface_altkob.yaml -- !INC ${MARINE_OBS_YAML_DIR}/insitu_surface_trkob.yaml +#- !INC ${MARINE_OBS_YAML_DIR}/insitu_surface_trkob.yaml #- !INC ${MARINE_OBS_YAML_DIR}/insitu_surface_trkob_salinity.yaml # in situ: daily diff --git a/sorc/fv3-jedi b/sorc/fv3-jedi index 88279a632..136dfb9c2 160000 --- a/sorc/fv3-jedi +++ b/sorc/fv3-jedi @@ -1 +1 @@ -Subproject commit 88279a63280c23d6b8974991a8c89380afaf5db7 +Subproject commit 136dfb9c2f8541584e62fa74c616d686602bcdad diff --git a/sorc/ioda b/sorc/ioda index 3fa4a997e..22cd20eae 160000 --- a/sorc/ioda +++ b/sorc/ioda @@ -1 +1 @@ -Subproject commit 3fa4a997e25b3bd018d30e308a26b3e98af0fe6f +Subproject commit 22cd20eae0685914a5b967e13f95779b57bb448c diff --git a/sorc/iodaconv b/sorc/iodaconv index 23e58ed76..6f87a0f27 160000 --- a/sorc/iodaconv +++ b/sorc/iodaconv @@ -1 +1 @@ -Subproject commit 23e58ed76da3628cbd508bd4ac40f8a01c789d7d +Subproject commit 6f87a0f279e836fd604e5b313a25bd1e54bff80e diff --git a/sorc/oops b/sorc/oops index 0d2c235d7..1ba321ff9 160000 --- a/sorc/oops +++ b/sorc/oops @@ -1 +1 @@ -Subproject commit 0d2c235d791e1ba0023ce300103174dddf71aed7 +Subproject commit 1ba321ff912c6338d7362667eff37ddbf569cb18 diff --git a/sorc/saber b/sorc/saber index 1f23a3665..de5015c83 160000 --- a/sorc/saber +++ b/sorc/saber @@ -1 +1 @@ -Subproject commit 1f23a36657f6d10b770348de0f5454e01d377105 +Subproject commit de5015c8328f5b3d64acc99739fbaa64ef571172 diff --git a/sorc/soca b/sorc/soca index 4d7ef21e7..7f2ddb61b 160000 --- a/sorc/soca +++ b/sorc/soca @@ -1 +1 @@ -Subproject commit 4d7ef21e74d78a065156c942a72806ef2e2eb08e +Subproject commit 7f2ddb61bc86796c83dfcd4801c91bffd829ffb4 diff --git a/sorc/ufo b/sorc/ufo index b0cd94558..85ef98cb9 160000 --- a/sorc/ufo +++ b/sorc/ufo @@ -1 +1 @@ -Subproject commit b0cd94558643380ccceea864abac2c34fa291677 +Subproject commit 85ef98cb99f3eae1ed15e39f0cb05046af36fef1 diff --git a/sorc/vader b/sorc/vader index 05eb007e2..3049658d1 160000 --- a/sorc/vader +++ b/sorc/vader @@ -1 +1 @@ -Subproject commit 05eb007e242af3fdc4969c7146a480e12663e452 +Subproject commit 3049658d185c8095caf0e506795d0e5995fa92cf diff --git a/test/fv3jedi/testinput/gdasapp_fv3jedi_fv3inc.yaml b/test/fv3jedi/testinput/gdasapp_fv3jedi_fv3inc.yaml index f59603d92..7ee403ccc 100644 --- a/test/fv3jedi/testinput/gdasapp_fv3jedi_fv3inc.yaml +++ b/test/fv3jedi/testinput/gdasapp_fv3jedi_fv3inc.yaml @@ -1,6 +1,6 @@ variable change: variable change name: Model2GeoVaLs - input variables: &bkgvars [ua,va,t,ps,sphum,ice_wat,liq_wat,o3mr,surface_geopotential_height] + input variables: &bkgvars [ua,va,t,ps,sphum,ice_wat,liq_wat,o3mr,hgtsfc] output variables: &fv3incrvars [ua,va,t,sphum,ice_wat,liq_wat,o3mr,delp,delz] jedi increment variables: [ua,va,t,ps,sphum,ice_wat,liq_wat,o3mr] fv3 increment variables: *fv3incrvars diff --git a/utils/soca/gdas_soca_diagb.h b/utils/soca/gdas_soca_diagb.h index f45ac8313..563d303b9 100644 --- a/utils/soca/gdas_soca_diagb.h +++ b/utils/soca/gdas_soca_diagb.h @@ -261,7 +261,7 @@ namespace gdasapp { // Get the layer thicknesses and convert to layer depth oops::Log::info() << "====================== calculate layer depth" << std::endl; - auto viewHocn = atlas::array::make_view(xbFs["hocn"]); + auto viewHocn = atlas::array::make_view(xbFs["sea_water_cell_thickness"]); atlas::array::ArrayT depth(viewHocn.shape(0), viewHocn.shape(1)); auto viewDepth = atlas::array::make_view(depth); for (atlas::idx_t jnode = 0; jnode < depth.shape(0); ++jnode) { @@ -299,7 +299,7 @@ namespace gdasapp { } // Update the layer thickness halo - nodeColumns.haloExchange(xbFs["hocn"]); + nodeColumns.haloExchange(xbFs["sea_water_cell_thickness"]); // Loop through variables for (auto & var : configD.socaVars.variables()) { @@ -307,7 +307,7 @@ namespace gdasapp { nodeColumns.haloExchange(xbFs[var]); // Skip the layer thickness variable - if (var == "hocn") { + if (var == "sea_water_cell_thickness") { continue; } oops::Log::info() << "====================== std dev for " << var << std::endl; @@ -330,7 +330,7 @@ namespace gdasapp { stdDevFilt(jnode, 0, 0, configD.depthMin, neighbors, 0, viewHocn, bkg, viewBathy, stdDevBkg, false, 4); - if (var == "ssh") { + if (var == "sea_surface_height_above_geoid") { // TODO(G): Extract the unbalanced ssh variance, in the mean time, do this: stdDevBkg(jnode, 0) = std::min(configD.sshMax, stdDevBkg(jnode, 0)); } @@ -353,7 +353,7 @@ namespace gdasapp { if (configD.simpleSmoothing) { for (auto & var : configD.socaVars.variables()) { // Skip the layer thickness variable - if (var == "hocn") { + if (var == "sea_water_cell_thickness") { continue; } @@ -365,7 +365,8 @@ namespace gdasapp { // Loops through nodes and levels for (atlas::idx_t level = 0; level < xbFs[var].shape(1); ++level) { - for (atlas::idx_t jnode = 0; jnode < xbFs["tocn"].shape(0); ++jnode) { + for (atlas::idx_t jnode = 0; + jnode < xbFs["sea_water_potential_temperature"].shape(0); ++jnode) { // Early exit if on a ghost cell if (ghostView(jnode) > 0) { continue; @@ -403,7 +404,8 @@ namespace gdasapp { auto stdDevBkg = atlas::array::make_view(bkgErrFs[var]); auto tmpArray(stdDevBkg); for (int iter = 0; iter < configD.niterVert; ++iter) { - for (atlas::idx_t jnode = 0; jnode < xbFs["tocn"].shape(0); ++jnode) { + for (atlas::idx_t jnode = 0; + jnode < xbFs["sea_water_potential_temperature"].shape(0); ++jnode) { for (atlas::idx_t level = 1; level < xbFs[var].shape(1)-1; ++level) { stdDevBkg(jnode, level) = (tmpArray(jnode, level-1) + tmpArray(jnode, level) + @@ -424,14 +426,15 @@ namespace gdasapp { << std::endl; // Create the diffusion object oops::GeometryData geometryData(geom.functionSpace(), - bkgErrFs["tocn"], true, this->getComm()); + bkgErrFs["sea_water_potential_temperature"], + true, this->getComm()); oops::Diffusion diffuse(geometryData); diffuse.calculateDerivedGeom(geometryData); // Lambda function to construct a field with a constant filtering value auto assignScale = [&](double scale, const std::string& fieldName) { atlas::Field field; - auto levels = xbFs["tocn"].shape(1); + auto levels = xbFs["sea_water_potential_temperature"].shape(1); field = geom.functionSpace().createField(atlas::option::levels(levels) | atlas::option::name(fieldName)); auto viewField = atlas::array::make_view(field);