From 1b07517a22cd569d35ee24d341c15a97fc6ad932 Mon Sep 17 00:00:00 2001 From: Guillaume Vernieres Date: Thu, 25 Apr 2024 11:43:39 -0400 Subject: [PATCH 1/3] Addition of a switch for the cycling type (#1072) Draft because I still need to test this while cycling. - fixes #1071 --- scripts/exgdas_global_marine_analysis_post.py | 9 +++++++-- scripts/exgdas_global_marine_analysis_prep.py | 19 ++++++++++++++----- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/scripts/exgdas_global_marine_analysis_post.py b/scripts/exgdas_global_marine_analysis_post.py index 54cce2363..1376bdd52 100755 --- a/scripts/exgdas_global_marine_analysis_post.py +++ b/scripts/exgdas_global_marine_analysis_post.py @@ -50,6 +50,7 @@ def list_all_files(dir_in, dir_out, wc='*', fh_list=[]): cyc = str(os.getenv('cyc')).zfill(2) bcyc = str((int(cyc) - 3) % 24).zfill(2) gcyc = str((int(cyc) - 6) % 24).zfill(2) # previous cycle +cdatedt = datetime.strptime(cdate, '%Y%m%d%H') bdatedt = datetime.strptime(cdate, '%Y%m%d%H') - timedelta(hours=3) bdate = datetime.strftime(bdatedt, '%Y-%m-%dT%H:00:00Z') mdate = datetime.strftime(datetime.strptime(cdate, '%Y%m%d%H'), '%Y-%m-%dT%H:00:00Z') @@ -93,8 +94,12 @@ def list_all_files(dir_in, dir_out, wc='*', fh_list=[]): os.path.join(com_ocean_analysis, f'{RUN}.t{bcyc}z.ocngrid.nc')]) # Copy the CICE analysis restart -cdateice = pdy + '.' + cyc + '0000' -post_file_list.append([os.path.join(anl_dir, 'Data', f'{cdateice}.cice_model.res.nc'), +if os.getenv('DOIAU') == "YES": + cice_rst_date = bdatedt.strftime('%Y%m%d.%H%M%S') +else: + cice_rst_date = cdatedt.strftime('%Y%m%d.%H%M%S') + +post_file_list.append([os.path.join(anl_dir, 'Data', f'{cice_rst_date}.cice_model.res.nc'), os.path.join(com_ice_restart, f'{cdate}.cice_model_anl.res.nc')]) FileHandler({'copy': post_file_list}).sync() diff --git a/scripts/exgdas_global_marine_analysis_prep.py b/scripts/exgdas_global_marine_analysis_prep.py index d80bfc834..686b4c8e8 100755 --- a/scripts/exgdas_global_marine_analysis_prep.py +++ b/scripts/exgdas_global_marine_analysis_prep.py @@ -70,10 +70,6 @@ def find_clim_ens(input_date): staticsoca_dir = os.getenv('SOCA_INPUT_FIX_DIR') nmem_ens = 0 nmem_ens = int(os.getenv('NMEM_ENS')) -if os.getenv('DOHYBVAR') == "YES": - dohybvar = True -else: - dohybvar = False # create analysis directories diags = os.path.join(anl_dir, 'diags') # output dir for soca DA obs space @@ -89,12 +85,25 @@ def find_clim_ens(input_date): window_begin = datetime.strptime(os.getenv('PDY')+os.getenv('cyc'), '%Y%m%d%H') - half_assim_freq window_begin_iso = window_begin.strftime('%Y-%m-%dT%H:%M:%SZ') window_middle_iso = window_middle.strftime('%Y-%m-%dT%H:%M:%SZ') -fcst_begin = datetime.strptime(os.getenv('PDY')+os.getenv('cyc'), '%Y%m%d%H') RUN = os.getenv('RUN') cyc = os.getenv('cyc') gcyc = os.getenv('gcyc') PDY = os.getenv('PDY') +# hybrid-envar switch +if os.getenv('DOHYBVAR') == "YES": + dohybvar = True +else: + dohybvar = False + +# switch for the cycling type +if os.getenv('DOIAU') == "YES": + # forecast initialized at the begining of the DA window + fcst_begin = window_begin +else: + # forecast initialized at the middle of the DA window + fcst_begin = datetime.strptime(os.getenv('PDY')+os.getenv('cyc'), '%Y%m%d%H') + ################################################################################ # fetch observations From a8daf6a1be634cabce5c923ff6aa442fd206d357 Mon Sep 17 00:00:00 2001 From: Cory Martin Date: Fri, 26 Apr 2024 19:05:16 +0000 Subject: [PATCH 2/3] Add modulefile for Dogwood/Cactus (#1073) While we are technically not supposed to build our own CRTM or FMS, we are asking for forgiveness and forging ahead. This PR should allow GDASApp to compile on WCOSS2 (Dogwood and Cactus) after a minor issue is resolved. That issue being a compile issue in IODA that Ron is already aware of and has a fix that works (https://github.com/JCSDA-internal/ioda/compare/develop...bugfix/read_script_convert_fix). --------- Co-authored-by: cory martin Co-authored-by: cory martin Co-authored-by: cory martin --- build.sh | 2 +- modulefiles/GDAS/wcoss2.intel.lua | 51 +++++++++++++++++++++++++++++++ sorc/ioda | 2 +- 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 modulefiles/GDAS/wcoss2.intel.lua diff --git a/build.sh b/build.sh index a27da74e5..c81b47ae3 100755 --- a/build.sh +++ b/build.sh @@ -71,7 +71,7 @@ while getopts "p:t:c:hvdfa" opt; do done case ${BUILD_TARGET} in - hera | orion | hercules) + hera | orion | hercules | wcoss2) echo "Building GDASApp on $BUILD_TARGET" source $dir_root/ush/module-setup.sh module use $dir_root/modulefiles diff --git a/modulefiles/GDAS/wcoss2.intel.lua b/modulefiles/GDAS/wcoss2.intel.lua new file mode 100644 index 000000000..d21099b2e --- /dev/null +++ b/modulefiles/GDAS/wcoss2.intel.lua @@ -0,0 +1,51 @@ +help([[ +Load environment for running the GDAS application with Intel compilers and MPI. +]]) + +local pkgName = myModuleName() +local pkgVersion = myModuleVersion() +local pkgNameVer = myModuleFullName() + +prepend_path("MODULEPATH", "/apps/dev/lmodules/core") + +load("PrgEnv-intel/8.2.0") +load("cmake/3.20.2") +load("craype") +load("cray-pals") +load("git/2.29.0") +load("intel/19.1.3.304") +load("cray-mpich/8.1.12") +load("hdf5/1.12.2") +load("netcdf/4.7.4") +load("udunits/2.2.28") +load("eigen/3.4.0") +load("boost/1.79.0") +load("gsl-lite/v0.40.0") +load("sp/2.4.0") +load("python/3.8.6") +load("ecbuild/3.7.0") +load("qhull/2020.2") +load("eckit/1.24.4") +load("fckit/0.11.0") +load("atlas/0.35.0") +load("nccmp") + +-- hack for pybind11 +setenv("pybind11_ROOT", "/apps/spack/python/3.8.6/intel/19.1.3.304/pjn2nzkjvqgmjw4hmyz43v5x4jbxjzpk/lib/python3.8/site-packages/pybind11/share/cmake/pybind11") + +-- hack for wxflow +--prepend_path("PYTHONPATH", "/scratch1/NCEPDEV/da/python/gdasapp/wxflow/20240307/src") + +local mpiexec = '/pe/intel/compilers_and_libraries_2020.4.304/linux/mpi/intel64/bin/mpirun' +local mpinproc = '-n' +setenv('MPIEXEC_EXEC', mpiexec) +setenv('MPIEXEC_NPROC', mpinproc) + +setenv("CRTM_FIX","/lfs/h2/emc/da/noscrub/emc.da/GDASApp/fix/crtm/2.4.0") +setenv("GDASAPP_TESTDATA","/lfs/h2/emc/da/noscrub/emc.da/GDASApp/data") +setenv("GDASAPP_UNIT_TEST_DATA_PATH", "/lfs/h2/emc/da/noscrub/emc.da/GDASApp/data/test") + +whatis("Name: ".. pkgName) +whatis("Version: ".. pkgVersion) +whatis("Category: GDASApp") +whatis("Description: Load all libraries needed for GDASApp") diff --git a/sorc/ioda b/sorc/ioda index 91eb2c764..206eba708 160000 --- a/sorc/ioda +++ b/sorc/ioda @@ -1 +1 @@ -Subproject commit 91eb2c7643b33c1af2470d289eefb7aec2667387 +Subproject commit 206eba7084c08a3bc9a1c6ccbbff3e63d7cb602e From 7ecfc17f9df39859b340c8ba81c3c27bfb5f18ac Mon Sep 17 00:00:00 2001 From: Mindo Choi <141867620+apchoiCMD@users.noreply.github.com> Date: Fri, 26 Apr 2024 18:25:52 -0400 Subject: [PATCH 3/3] Using ioda util to convert the datetime in AMSR2 converter (#1077) #### This PR includes: - Replace the method to get datetime from epoch time by using `ioda utils` - `julianDate - 2440588` will make half day off - The above method will avoid dealing with decimal precision. - Closes #1062 --------- Co-authored-by: Guillaume Vernieres --- utils/obsproc/IcecAmsr2Ioda.h | 38 ++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/utils/obsproc/IcecAmsr2Ioda.h b/utils/obsproc/IcecAmsr2Ioda.h index 681bbcd8d..3241d3ae2 100644 --- a/utils/obsproc/IcecAmsr2Ioda.h +++ b/utils/obsproc/IcecAmsr2Ioda.h @@ -13,8 +13,10 @@ #include // NOLINT +#include "ioda/../../../../core/IodaUtils.h" #include "ioda/Group.h" #include "ioda/ObsGroup.h" + #include "oops/util/dateFunctions.h" #include "NetCDFToIodaConverter.h" @@ -83,22 +85,34 @@ namespace gdasapp { int minute = oneTmpdateTimeVal[i+4]; int second = static_cast(oneTmpdateTimeVal[i+5]); - // Replace Fillvalue -9999 to 0 to avoid crash in dateToJulian + // Avoid crash util in ioda::convertDtimeToTimeOffsets if (year == -9999 || month == -9999 || day == -9999 || hour == -9999 || minute == -9999 || second == -9999) { year = month = day = hour = minute = second = 0; } - // Convert a date to Julian date - uint64_t julianDate = util::datefunctions::dateToJulian(year, month, day); - - // Subtract Julian day from January 1, 1970 (convert to epoch) - int daysSinceEpoch = julianDate - 2440588; - - // Calculate seconds only from HHMMSS - int secondsOffset = util::datefunctions::hmsToSeconds(hour, minute, second); - - iodaVars.datetime_(index) = static_cast(daysSinceEpoch*86400.0f) + secondsOffset; + // Construct iso8601 string format for each dateTime + std::stringstream ss; + ss << std::setfill('0') + << std::setw(4) << year << '-' + << std::setw(2) << month << '-' + << std::setw(2) << day << 'T' + << std::setw(2) << hour << ':' + << std::setw(2) << minute << ':' + << std::setw(2) << second << 'Z'; + std::string formattedDateTime = ss.str(); + util::DateTime dateTime(formattedDateTime); + + // Set epoch time for AMSR2_ICEC + util::DateTime epochDtime("1970-01-01T00:00:00Z"); + + // Convert Obs DateTime objects to epoch time offsets in seconds + // 0000-00-00T00:00:00Z will be converterd to negative seconds + int64_t timeOffsets + = ioda::convertDtimeToTimeOffsets(epochDtime, {dateTime})[0]; + + // Update datetime Eigen Arrays + iodaVars.datetime_(index) = timeOffsets; index++; } @@ -106,7 +120,7 @@ namespace gdasapp { for (int i = 0; i < iodaVars.location_; i++) { iodaVars.longitude_(i) = oneDimLonVal[i]; iodaVars.latitude_(i) = oneDimLatVal[i]; - iodaVars.obsVal_(i) = static_cast(oneDimObsVal[i]*0.01f); + iodaVars.obsVal_(i) = static_cast(oneDimObsVal[i]*0.01); iodaVars.obsError_(i) = 0.1; // Do something for obs error iodaVars.preQc_(i) = oneDimFlagsVal[i]; // Store optional metadata, set ocean basins to -999 for now