From 65e4e93c1377a6d8d80da6e34ed9e4f1a16b9c9d Mon Sep 17 00:00:00 2001 From: PJLevensMO <115472778+PJLevensMO@users.noreply.github.com> Date: Wed, 16 Aug 2023 14:51:02 +0100 Subject: [PATCH] Add CX and varobs for Surfacecloud (#175) * Added namelist files for SurfaceCloud to both varobs and cx, and added varobs writer functionality to provide obs value and relevant obs error * Changes for SurfaceCloud. Updated python script and run it for the new settings. Added Varfield 15 (cloud) and have needed to add Cx field cloud_layer too. Added first attempt at cxwriter and varobswriter yaml files for SurfaceCloud. * Remove files that should not have been changed, and some tweaks to the python script for SurfaceCloud tests * Add files created by running python code * Added yaml files and relevant namelist files for testing * Change list of simulated and observed variables in surfacecloud varobswriter * Changed obs error for cloud fraction column to be in DerivedObsError/CloudError * Added missing ObsValue/stationPressure field to varobs netCDF for surfacecloud * Added Cloud as derived variable * Update to CMakeLists to include tests for varfield 15 and cx upper air field 15 * Small change to CMakeLists in etc directory to change order of namelists * Correction to varobs 15 setup * Change to PLevels * Update cloud_layer in cxfields mod file * Change VarField 15 (cloud) to have use_chans instead of use_levels in unit test * New netCDF file for VarField 15 (cloud) * Fix for the varobswriter for varfield cloud * Updates to cx and varobs writer ctest yamls * Updates to ctest yaml files * Updates for ctest yamls * Update to ctest varobswriter yaml * added derived obs * update 015_VarField_cloud.yaml (issue with missing data in ob value) * Cloud update * working for test_opsinputs_varobswriter_015_VarField_cloud * not sure if any better, but needed to checkout dev * include yaml change (missing in previous commit) * change to surfacecloud namelist for Cx ctest * add to cmakelist * set CXX17 standard * change cloud to cloudAmount * switch off cxx extensions * change name * change in src/opsinputs/opsinputs_varobswriter_mod.F90 * fixed varobswriter_ukvnamelist_surfacecloud --------- Co-authored-by: fabien-mo Co-authored-by: Yaswant Pradhan --- Varfields.md | 2 +- .../code/OpsMod_Varobs/Ops_SetupVarArray.inc | 2 +- etc/ukv/cx/SurfaceCloud.nl | 8 +++ etc/ukv/varobs/SurfaceCloud.nl | 3 + src/opsinputs/opsinputs_cxfields_mod.F90 | 2 +- src/opsinputs/opsinputs_varobswriter_mod.F90 | 4 ++ test/CMakeLists.txt | 15 +++++ test/generate_unittest_netcdfs.py | 21 ++++++- .../015_UpperAirCxField_cloud_layer.nc4 | Bin 0 -> 6240 bytes .../015_UpperAirCxField_cloud_layer.yaml | 40 ++++++++++++ test/testinput/015_VarField_cloud.nc4 | Bin 0 -> 14182 bytes test/testinput/015_VarField_cloud.yaml | 58 ++++++++++++++++++ .../SurfaceCloud.nl | 3 + .../SurfaceCloud.nl | 3 + .../testinput/cx_ukvnamelist_surfacecloud.nc4 | Bin 0 -> 12976 bytes .../cxwriter_ukvnamelist_surfacecloud.yaml | 46 ++++++++++++++ .../varobs_ukvnamelist_surfacecloud.nc4 | Bin 0 -> 10972 bytes ...varobswriter_ukvnamelist_surfacecloud.yaml | 57 +++++++++++++++++ 18 files changed, 260 insertions(+), 4 deletions(-) create mode 100644 etc/ukv/cx/SurfaceCloud.nl create mode 100644 etc/ukv/varobs/SurfaceCloud.nl create mode 100644 test/testinput/015_UpperAirCxField_cloud_layer.nc4 create mode 100644 test/testinput/015_UpperAirCxField_cloud_layer.yaml create mode 100644 test/testinput/015_VarField_cloud.nc4 create mode 100644 test/testinput/015_VarField_cloud.yaml create mode 100644 test/testinput/CxWriterNamelists_015_UpperAirCxField_cloud_layer/SurfaceCloud.nl create mode 100644 test/testinput/VarObsWriterNamelists_015_VarField_cloud/SurfaceCloud.nl create mode 100644 test/testinput/cx_ukvnamelist_surfacecloud.nc4 create mode 100644 test/testinput/cxwriter_ukvnamelist_surfacecloud.yaml create mode 100644 test/testinput/varobs_ukvnamelist_surfacecloud.nc4 create mode 100644 test/testinput/varobswriter_ukvnamelist_surfacecloud.yaml diff --git a/Varfields.md b/Varfields.md index e64813d6..32735449 100644 --- a/Varfields.md +++ b/Varfields.md @@ -17,7 +17,7 @@ | 10 | `VarField_britemp` | `CorBriTemp(:,:)` | bias-corrected brightness temperatures | `BiasCorrObsValue/brightnessTemperature` | | | 11 | `VarField_tskin` | `Tskin(:)` | skin temperature | `OneDVar/skinTemperature` | | | 12 | `VarField_gpstzdelay` | `gpstzdelay(:)`| Ground based GNSS Total Zenith Delay | `BiasCorrObsValue/zenithTotalDelay` | | -| 15 | `VarField_cloud` | | | | Implement | +| 15 | `VarField_cloud` | `cloud(:,:)` | cloud fraction | `DerivedObsValue/cloudAmount`| | | 16 | `VarField_rainrate` | | | | Implement | | 17 | `VarField_mwemiss` | `Emissivity(:,:)` | surface emissivity | `Emiss/emissivity` | | | 18 | `VarField_tcozone` | `TCozone(:)` | total column ozone (Du) | `MetaData/ozoneTotal` | | diff --git a/deps/ops/code/OpsMod_Varobs/Ops_SetupVarArray.inc b/deps/ops/code/OpsMod_Varobs/Ops_SetupVarArray.inc index 76cab3ca..b3aa3f33 100644 --- a/deps/ops/code/OpsMod_Varobs/Ops_SetupVarArray.inc +++ b/deps/ops/code/OpsMod_Varobs/Ops_SetupVarArray.inc @@ -388,7 +388,7 @@ DO Ivar = 1, NumValidVarFields RArrVrbl1d => Ob % AMSUb_Temp CASE (VarField_cloud) ObHdrVrbl = Ob % header % Cloud - ObVrblMulti => Ob % Cloud + ObVrblMulti => Ob % Cloud(:,:) Pge_2D => Pge % Cloud CASE (VarField_rainrate) ObHdrVrbl = Ob % header % Rainrate diff --git a/etc/ukv/cx/SurfaceCloud.nl b/etc/ukv/cx/SurfaceCloud.nl new file mode 100644 index 00000000..44ee703f --- /dev/null +++ b/etc/ukv/cx/SurfaceCloud.nl @@ -0,0 +1,8 @@ +&CXControlNL +! Quantities for which H(x) is not calculated so GeoVaLs are used to produced CX columns. +! - multi-level +! 4 = theta, 10 = q, 12 = qcf, 254 = qcl, 407 = p, 9201 = cloud_layer +! - single-level +! 1 = pstar, 31 = seaice, 33 = orog, 9217 = CloudAmount +CxFields=1,4,10,12,31,33,254,407,9201,9217 +/ diff --git a/etc/ukv/varobs/SurfaceCloud.nl b/etc/ukv/varobs/SurfaceCloud.nl new file mode 100644 index 00000000..a9547200 --- /dev/null +++ b/etc/ukv/varobs/SurfaceCloud.nl @@ -0,0 +1,3 @@ +&VarobsControlNL +Varfields=15 +/ diff --git a/src/opsinputs/opsinputs_cxfields_mod.F90 b/src/opsinputs/opsinputs_cxfields_mod.F90 index f3992624..3ab39838 100644 --- a/src/opsinputs/opsinputs_cxfields_mod.F90 +++ b/src/opsinputs/opsinputs_cxfields_mod.F90 @@ -76,7 +76,7 @@ module opsinputs_cxfields_mod character(len=*), parameter, public :: opsinputs_cxfields_RainRate_layer = opsinputs_cxfields_unknown character(len=*), parameter, public :: opsinputs_cxfields_cloud_conv = opsinputs_cxfields_unknown character(len=*), parameter, public :: opsinputs_cxfields_qc_conv = opsinputs_cxfields_unknown -character(len=*), parameter, public :: opsinputs_cxfields_cloud_layer = opsinputs_cxfields_unknown +character(len=*), parameter, public :: opsinputs_cxfields_cloud_layer = "cloud_layer" character(len=*), parameter, public :: opsinputs_cxfields_ozone = opsinputs_cxfields_unknown character(len=*), parameter, public :: opsinputs_cxfields_qcf = var_cli character(len=*), parameter, public :: opsinputs_cxfields_qcl = var_clw diff --git a/src/opsinputs/opsinputs_varobswriter_mod.F90 b/src/opsinputs/opsinputs_varobswriter_mod.F90 index 78a20089..eeeb995a 100644 --- a/src/opsinputs/opsinputs_varobswriter_mod.F90 +++ b/src/opsinputs/opsinputs_varobswriter_mod.F90 @@ -963,6 +963,10 @@ subroutine opsinputs_varobswriter_populateobservations( & ! TODO(someone): handle this varfield ! call Ops_Alloc(Ob % Header % AMSUb_Temp, "AMSUb_Temp", Ob % Header % NumObsLocal, Ob % AMSUb_Temp) case (VarField_cloud) + call opsinputs_fill_fillelementtype2dfromnormalvariablewithlevels( & + Ob % Header % Cloud, "Cloud", Ob % Header % NumObsLocal, Ob % Cloud, & + ObsSpace, self % modlevs, "cloudAmount_", "DerivedObsValue", self % GeoVaLsAreTopToBottom, & + "cloudAmount_", "DerivedObsError") ! TODO(someone): handle this varfield ! call Ops_Alloc(Ob % Header % Cloud, "Cloud", Ob % Header % NumObsLocal, Ob % Cloud) case (VarField_rainrate) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ba40064d..880e0020 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -144,6 +144,9 @@ ADD_WRITER_TEST(NAME varobswriter_011_VarField_tskin ADD_WRITER_TEST(NAME varobswriter_012_VarField_gpstzdelay YAML 012_VarField_gpstzdelay.yaml DATA 012_VarField_gpstzdelay.nc4) +ADD_WRITER_TEST(NAME varobswriter_015_VarField_cloud + YAML 015_VarField_cloud.yaml + DATA 015_VarField_cloud.nc4) ADD_WRITER_TEST(NAME varobswriter_017_VarField_mwemiss YAML 017_VarField_mwemiss.yaml NAMELIST VarObsWriterNamelists_017_VarField_mwemiss/AMSUB.nl @@ -347,6 +350,10 @@ ADD_WRITER_TEST(NAME varobswriter_ukvnamelist_sonde YAML varobswriter_ukvnamelist_sonde.yaml NAMELIST ../../etc/ukv/varobs/Sonde.nl DATA varobs_ukvnamelist_sonde.nc4) +ADD_WRITER_TEST(NAME varobswriter_ukvnamelist_surfacecloud + YAML varobswriter_ukvnamelist_surfacecloud.yaml + NAMELIST ../../etc/ukv/varobs/SurfaceCloud.nl + DATA varobs_ukvnamelist_surfacecloud.nc4) ### CxWriter tests @@ -429,6 +436,10 @@ ADD_WRITER_TEST(NAME cxwriter_011_UpperAirCxField_P YAML 011_UpperAirCxField_P.yaml NAMELIST CxWriterNamelists_011_UpperAirCxField_P/AMSUB.nl DATA 011_UpperAirCxField_P.nc4 dummy.nc4) +ADD_WRITER_TEST(NAME cxwriter_015_UpperAirCxField_cloud_layer + YAML 015_UpperAirCxField_cloud_layer.yaml + NAMELIST CxWriterNamelists_015_UpperAirCxField_cloud_layer/SurfaceCloud.nl + DATA 015_UpperAirCxField_cloud_layer.nc4 dummy.nc4) ADD_WRITER_TEST(NAME cxwriter_029_UpperAirCxField_qcf YAML 029_UpperAirCxField_qcf.yaml NAMELIST CxWriterNamelists_029_UpperAirCxField_qcf/AMSUB.nl @@ -618,6 +629,10 @@ ADD_WRITER_TEST(NAME cxwriter_ukvnamelist_sonde YAML cxwriter_ukvnamelist_sonde.yaml NAMELIST ../../etc/ukv/cx/Sonde.nl DATA cx_ukvnamelist_sonde.nc4 dummy.nc4) +ADD_WRITER_TEST(NAME cxwriter_ukvnamelist_surfacecloud + YAML cxwriter_ukvnamelist_surfacecloud.yaml + NAMELIST ../../etc/ukv/cx/SurfaceCloud.nl + DATA cx_ukvnamelist_surfacecloud.nc4 dummy.nc4) ### Tests of auxiliary classes diff --git a/test/generate_unittest_netcdfs.py b/test/generate_unittest_netcdfs.py index a04c74ea..480fefd3 100644 --- a/test/generate_unittest_netcdfs.py +++ b/test/generate_unittest_netcdfs.py @@ -651,6 +651,7 @@ def copy_var_to_var(Group, invarname, outvarname, filename): output_1d_simulated_var_to_netcdf('precipitableWater', 'testinput/007_VarField_tcwv.nc4') output_2d_simulated_var_to_netcdf('brightnessTemperature', 'testinput/010_VarField_britemp.nc4', with_bias=True) output_1d_normal_var_to_netcdf ('skinTemperature', 'OneDVar', 'testinput/011_VarField_tskin.nc4') + output_2d_normal_var_to_netcdf ('cloudAmount', 'DerivedObsValue', 'testinput/015_VarField_cloud.nc4', use_chans=True) output_2d_normal_var_to_netcdf ('emissivity', 'Emiss', 'testinput/017_VarField_mwemiss.nc4', use_chans=True) output_1d_normal_var_to_netcdf ('ozoneTotal', 'MetaData', 'testinput/018_VarField_tcozone.nc4') output_1d_normal_var_to_netcdf ('sensorZenithAngle', 'MetaData', 'testinput/019_VarField_satzenith.nc4') @@ -765,6 +766,13 @@ def copy_var_to_var(Group, invarname, outvarname, filename): copy_var_to_var('ObsValue', 'potentialTemperature', 'airTemperature', 'testinput/varobs_ukvnamelist_sonde.nc4') copy_var_to_var('ObsError', 'potentialTemperature', 'airTemperature', 'testinput/varobs_ukvnamelist_sonde.nc4') + # SurfaceCloud - UKV + output_full_varobs_to_netcdf(['MetaData/latitude', + 'MetaData/longitude'], + ['ObsValue/cloud_layer', 'DerivedObsValue/cloudAmount', 'DerivedObsError/cloudAmount'], + [], + 'testinput/varobs_ukvnamelist_surfacecloud.nc4') + # Scatwind output_full_varobs_to_netcdf(['MetaData/latitude', 'MetaData/longitude'], ['ObsValue/windEastward', 'ObsError/windEastward', 'GrossErrorProbability/windEastward', @@ -830,6 +838,7 @@ def copy_var_to_var(Group, invarname, outvarname, filename): output_2d_geoval_to_netcdf ('specific_humidity', 'testinput/005_UpperAirCxField_q.nc4') output_2d_geoval_to_netcdf ('air_pressure', 'testinput/033_UpperAirCxField_p_bar.nc4') output_2d_geoval_to_netcdf ('air_pressure_levels', 'testinput/011_UpperAirCxField_P.nc4') + output_2d_geoval_to_netcdf ('cloud_layer', 'testinput/015_UpperAirCxField_cloud_layer.nc4') output_2d_geoval_to_netcdf ('mass_content_of_cloud_ice_in_atmosphere_layer', 'testinput/029_UpperAirCxField_qcf.nc4') output_2d_geoval_to_netcdf ('mass_content_of_cloud_liquid_water_in_atmosphere_layer', 'testinput/030_UpperAirCxField_qcl.nc4') output_2d_geoval_to_netcdf ('cloud_volume_fraction_in_atmosphere_layer', 'testinput/031_UpperAirCxField_cloud_bulk.nc4') @@ -904,7 +913,7 @@ def copy_var_to_var(Group, invarname, outvarname, filename): 'mass_content_of_cloud_liquid_water_in_atmosphere_layer', 'air_pressure_levels', 'cloud_volume_fraction_in_atmosphere_layer', 'liquid_cloud_volume_fraction_in_atmosphere_layer', 'ice_cloud_volume_fraction_in_atmosphere_layer'], 'testinput/cx_globalnamelist_ssmis.nc4') - + # MWSFY3 output_full_cx_to_netcdf(['skin_temperature','ice_area_fraction','surface_altitude','surface_pressure','uwind_at_10m', 'vwind_at_10m','surface_temperature','relative_humidity_2m','surface_pressure_at_mean_sea_level'], @@ -947,6 +956,16 @@ def copy_var_to_var(Group, invarname, outvarname, filename): 'ice_cloud_volume_fraction_in_atmosphere_layer'], 'testinput/cx_ukvnamelist_sonde.nc4') + # SurfaceCloud - UKV + output_full_cx_to_netcdf(['surface_altitude', + 'surface_pressure', + 'ice_area_fraction', + 'total_cloud_amount'], + ['potential_temperature', 'specific_humidity', 'air_pressure_levels', 'cloud_layer', + 'mass_content_of_cloud_ice_in_atmosphere_layer', + 'mass_content_of_cloud_liquid_water_in_atmosphere_layer'], + 'testinput/cx_ukvnamelist_surfacecloud.nc4') + # SatTCWV output_full_cx_to_netcdf(['surface_altitude', 'surface_pressure', 'ice_area_fraction', 'total_cloud_amount'], ['potential_temperature', 'specific_humidity', 'air_pressure_levels', 'mass_content_of_cloud_ice_in_atmosphere_layer', diff --git a/test/testinput/015_UpperAirCxField_cloud_layer.nc4 b/test/testinput/015_UpperAirCxField_cloud_layer.nc4 new file mode 100644 index 0000000000000000000000000000000000000000..b675353fac6c9a38f708e3d0de8ca8af912106bd GIT binary patch literal 6240 zcmeHI&ubGw6n?Xt#AV&mXj`fxx-C5^NFd^+hi=$xOlg`x(~}4>Z8jQ+i8N_Z@CPU; z6;IyMt03O%f8e#ns~2z5s~!YFkow;2yrjeyJXwT!B>Q&WyqWptoA1qT=CipG`7)r6C)&Gve&(yTrR*CrH%iSu$cQ@}6=ZYLj)&q(+qCxjTM z84V!>Ltt-?6XH`-7Zo@cCM}qJg4uDo7t@aRGNlH*risvaee=lmoy(MGLINzB+b?9w zWf;Q{aYI|n&MyYV@_eaSDf^j10L~5EG!BSI1B#i&K<0ZYfB8RO|^(hRS-Y*%rXAMFpbe^SDS+V_7+$@c$FNg64sy!^Eu zQ368DU;qr1iP{++Mr6Znr5g7T)!3vb^HMb8+e7QLY>U)Taj|}m)~|Du);3`j1%vV( zsHHGpUWT*SM?#v!Kb10Ro9l%=RaZ*YImHgP<<4vj9<*yyWeQdj(L~I+5-}knW6#wcMFF;6G(H}N z$WaOZ4iO`KI=$@^BEG>GDc)f1)y`MOHA^oh*x(RTNJ&`fVzmMh5S@s3C;{JB^Y>}! z-a_Ihd2O13<7D8vUn)rH%MbdXP}QvhEO@?hhU0vJa-2W$yr*}g{HDETKr^5j& zGy|Fe&46Y=GoTsJ3}^;41INWcz5aG?tJj;`-FY>aPLFwS?mgPC*ArekUG{c&3SPaQ O^R{}M=$~WknfDvxGBl;A^gO%*6 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